<commit_before>/* ----------------------------------------------------------
  Utilities
---------------------------------------------------------- */

/* Console log fix
-------------------------- */
if (typeof(console) === 'undefined') {
    var console = {};
    console.log = console.error = console.info = console.debug = console.warn = console.trace = console.dir = console.dirxml = console.group = console.groupEnd = console.time = console.timeEnd = console.assert = console.profile = function() {};
}

/* Array utilities
  https://github.com/Darklg/JavaScriptUtilities/blob/master/assets/js/vanilla-js/libs/vanilla-arrays.js
-------------------------- */
Array.contains = function(needle, haystack) {
    var i = 0,
        length = haystack.length;

    for (; i < length; i++) {
        if (haystack[i] === needle) return true;
    }
    return false;
};
Array.each = function(arrayToParse, callback) {
    var i = 0,
        length = arrayToParse.length;
    for (; i < length; i++) {
        callback(arrayToParse[i]);
    }
};

/* CSS classes utilities
  https://github.com/Darklg/JavaScriptUtilities/blob/master/assets/js/vanilla-js/libs/vanilla-classes.js
-------------------------- */
Element.getClassNames = function(element) {
    var classNames = [],
        elementClassName = element.className;
    if (elementClassName !== '') {
        elementClassName = elementClassName.replace(/\s+/g, ' ');
        classNames = elementClassName.split(' ');
    }
    return classNames;
};
Element.hasClass = function(element, className) {
    if (element.classList) {
        return element.classList.contains(className);
    }
    return Array.contains(className, Element.getClassNames(element));
};
Element.addClass = function(element, className) {
    if (element.classList) {
        element.classList.add(className);
        return;
    }
    if (!Element.hasClass(element, className)) {
        var elementClasses = Element.getClassNames(element);
        elementClasses.push(className);
        element.className = elementClasses.join(' ');
    }
};
Element.removeClass = function(element, className) {
    if (element.classList) {
        element.classList.remove(className);
        return;
    }
    var elementClasses = Element.getClassNames(element);
    var newElementClasses = [];
    var i = 0,
        arLength = elementClasses.length;
    for (; i < arLength; i++) {
        if (elementClasses[i] !== className) {
            newElementClasses.push(elementClasses[i]);
        }
    }
    element.className = newElementClasses.join(' ');
};
Element.toggleClass = function(element, className) {
    if (!Element.hasClass(element, className)) {
        Element.addClass(element, className);
    }
    else {
        Element.removeClass(element, className);
    }
};

/* Add Event
  https://github.com/Darklg/JavaScriptUtilities/blob/master/assets/js/vanilla-js/libs/vanilla-events.js
-------------------------- */
window.addEvent = function(el, eventName, callback, options) {
    if (el == null) { return; }
    if (el.addEventListener) {
        if (!options || typeof(options) !== "object") {
            options = {};
        }

        options.capture = false;
        el.addEventListener(eventName, callback, options);
    }
    else if (el.attachEvent) {
        el.attachEvent("on" + eventName, function(e) {
            return callback.call(el, e);
        });
    }
};
window.eventPreventDefault = function(event) {
    return (event.preventDefault) ? event.preventDefault() : event.returnValue = false;
};

/* Draggable

  Sources :
  http://jsfiddle.net/5t3Ju/
  http://stackoverflow.com/questions/9334084/moveable-draggable-div
  http://jsfiddle.net/tovic/Xcb8d/light/
-------------------------- */

function make_element_draggable(id) {

  // Variables
  this.elem = document.getElementById(id),
  this.selected = null,  // Selected element
  this.dragged = false,  // Dragging status
  this.x_pos = 0, this.y_pos = 0, // Stores x & y coordinates of the mouse pointer
  this.x_elem = 0, this.y_elem = 0; // Stores top, left values (edge) of the element

  var _initDrag = function(e){
    if (e.type === "touchstart"){
      x_pos = e.touches[0].clientX;
      y_pos = e.touches[0].clientY;
    }

    selected = elem;
    x_elem = x_pos - selected.offsetLeft;
    y_elem = y_pos - selected.offsetTop;
  };

  var _shutDrag = function(e){
      selected = null;
  };

  var _onMove = function(e){
    // Get position
    x_pos = document.all ? window.event: e.pageX;
    y_pos = document.all ? window.event : e.pageY;

    if (e.type === "touchmove") {
        x_pos = e.touches[0].clientX;
        y_pos = e.touches[0].clientY;
    }

    if (selected !== null) {
      if (e.type === "touchmove"){
        event.preventDefault();
      }
      dragged = true;
      selected.style.left = (x_pos - x_elem) + 'px';
      selected.style.top = (y_pos - y_elem) + 'px';
    }
  };

  // Prevent native D'n'D behavior
  window.addEvent(elem, 'dragstart', function(e){
    window.eventPreventDefault(e);
  });

  // Start dragging
  window.addEvent(elem, 'mousedown', _initDrag);
  window.addEvent(elem, 'touchstart', _initDrag);

  // Will be called when user dragging an element
  window.addEvent(window, 'mousemove', _onMove);
  window.addEvent(window, 'touchmove', _onMove, {passive: false});

  // Destroy the object when we are done
  window.addEvent(window, 'mouseup', _shutDrag);
  window.addEvent(window, 'touchend', _shutDrag);
  window.addEvent(window, 'touchcancel', _shutDrag);

  // Handle click event
  window.addEvent(elem, 'click', function(e){
      // Prevent default event
      window.eventPreventDefault(e);

      // Do not propagate to other click event if dragged out
      if (dragged) {
        e.stopImmediatePropagation();
      }
      // Reset dragging status
      dragged = false;
  });
};

/* ----------------------------------------------------------
  Main
---------------------------------------------------------- */
window.addEvent(document, 'DOMContentLoaded', function() {

    // 3 different cases :
    // - this script is loaded from inside an app
    // - this script is loaded inside the portal, inside an iframe/overlay activated by clicking the portal button inside an app
    // - this script is loaded inside the "regular" portal when going to /yunohost/sso.

    var in_app = ! document.body.classList.contains('ynh-user-portal');
    var in_overlay_iframe = (window.location != window.parent.location);

    if (in_app)
    {
        init_portal_button_and_overlay();
    }
    else
    {
        init_portal();
        if (in_overlay_iframe) { tweak_portal_when_in_iframe(); }
    }
});

//
// This function is called when ynhpanel.js is included in an app
//
// It will create the small yunohost "portal button" usually in the bottom
// right corner and initialize the portal overlay, shown when clicking the
// portal button meant to make it easier to switch between apps.
//
function init_portal_button_and_overlay()
{
  // Set and store meta viewport
  var meta_viewport = document.querySelector('meta[name="viewport"]');
  if (meta_viewport === null) {
    meta_viewport = document.createElement('meta');
    meta_viewport.setAttribute('name', "viewport");
    meta_viewport.setAttribute('content', "");
    document.getElementsByTagName('head')[0].insertBefore(meta_viewport, null);
  }
  meta_viewport = document.querySelector('meta[name="viewport"]');
  meta_viewport_content = meta_viewport.getAttribute('content');

  // Inject portal button
  var portalButton = document.createElement('a');
  portalButton.setAttribute('id', 'ynh-overlay-switch');
  portalButton.setAttribute('href', '/yunohost/sso/');
  portalButton.setAttribute('class', 'disableAjax');
  document.body.insertBefore(portalButton, null);
  // Make portal button draggable, for user convenience
  make_element_draggable('ynh-overlay-switch');

  // Prepare and inject the portal overlay (what is activated when clicking on the portal button)
  var portalOverlay = document.createElement('iframe');
  portalOverlay.src = "/yunohost/sso/info.html";
  portalOverlay.setAttribute("id","ynh-overlay");
  portalOverlay.setAttribute("style","visibility: hidden;"); // make sure the overlay is invisible already when loading it
  document.body.insertBefore(portalOverlay, null);

  // Inject portal stylesheet
  // (we need it for the portal button to be displayed correctly)
  // FIXME : Really wondering if we shouldn't set this in data/templates/nginx/plain/yunohost_panel.conf.inc ...
  var portalStyle = document.createElement("link");
  portalStyle.setAttribute("rel", "stylesheet");
  portalStyle.setAttribute("type", "text/css");
  portalStyle.setAttribute("href", '/ynhpanel.css');
  document.getElementsByTagName("head")[0].insertBefore(portalStyle, null);
  // Inject custom / theme css
  var customStyle = document.createElement("link");
  customStyle.setAttribute("rel", "stylesheet");
  customStyle.setAttribute("type", "text/css");
  customStyle.setAttribute("href", '/ynhtheme/custom.css');
  document.getElementsByTagName("head")[0].insertBefore(customStyle, null);
  // Inject custom / theme js
  var customScript = document.createElement("script");
  customScript.setAttribute("type", "text/javascript");
  customScript.setAttribute("src", '/ynhtheme/custom.js');
  document.getElementsByTagName("head")[0].insertBefore(customScript, null);

  // Bind portal button
  // FIXME : this somehow prevent the portalButton
  // from being dragged correctly when mouse is moving too fast
  // ... this seem to be okay in the "app" itself, but the bug
  // is happening when *in* the portal overlay inside an app...
  window.addEvent(portalButton, 'click', function(e){
      // Prevent default click
      window.eventPreventDefault(e);
      // Toggle overlay on YNHPortal button click
      Element.toggleClass(portalOverlay, 'visible');
      Element.toggleClass(portalButton, 'visible');
      Element.toggleClass(document.querySelector('html'), 'ynh-panel-active');
      Element.toggleClass(portalOverlay, 'ynh-active');

      if (portalOverlay.classList.contains('ynh-active')) {
          meta_viewport.setAttribute('content', meta_viewport_content);
          Element.addClass(portalOverlay, 'ynh-fadeIn');
          Element.removeClass(portalOverlay, 'ynh-fadeOut');
      } else {
          meta_viewport.setAttribute('content', "width=device-width");
          Element.removeClass(portalOverlay, 'ynh-fadeIn');
          Element.addClass(portalOverlay, 'ynh-fadeOut');
      }
  });
}

//
// This function is called to initialize elements like the app tile colors and other things ...
//
function init_portal()
{

  window.addEvent(document.getElementById('add-mailalias'), "click", function() {
    // Clone last input.
    var inputAliasClone = document.querySelector('.mailalias-input').cloneNode(true);
    // Empty value.
    inputAliasClone.value = '';
    // Append to form-group.
    this.parentNode.insertBefore(inputAliasClone, this);
  });

  window.addEvent(document.getElementById('add-maildrop'), "click", function() {
    // Clone last input.
    var inputDropClone = document.querySelector('.maildrop-input').cloneNode(true);
    // Empty value.
    inputDropClone.value = '';
    // Append to form-group.
    this.parentNode.insertBefore(inputDropClone, this);
  });

  Array.each(document.getElementsByClassName("app-tile"), function(el) {
        // Set first-letter data attribute.
        el.querySelector('.first-letter').innerHTML = el.getAttribute("data-appname").substring(0, 2);
        // handle app links so they work both in plain info page and in the info iframe called from ynhpanel.js
        window.addEvent(el, 'click', function(event) {
            // if asked to open in new tab
            if (event.ctrlKey || event.shiftKey || event.metaKey
                || (event.button && event.button == 1)) {
                return
            }
            // if asked in current tab
            else {
                event.preventDefault();
                parent.location.href=this.href;
                return false;
            };
        });
  });
}

function tweak_portal_when_in_iframe()
{
    // Set class to body to show we're in overlay
    document.body.classList.add('in_app_overlay');
    let userContainer = document.querySelector('a.user-container');
    if (userContainer) {
        userContainer.classList.replace('user-container-info', 'user-container-edit');
        userContainer.setAttribute('href', userContainer
            .getAttribute('href')
            .replace('edit.html', ''));
        window.addEvent(userContainer, 'click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            window.parent.location.href = userContainer.getAttribute('href');
        });
    }
    let logoutButton = document.getElementById('ynh-logout');
    if (logoutButton)
    {
        // We force to do the logout "globally", not just in the
        // iframe, otherwise after login out the url might still be
        // domain.tld/app which is weird ...
        window.addEvent(logoutButton, 'click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            window.parent.location.href = logoutButton.getAttribute("href");
        });
    }
}
<commit_msg>Don't load additional css and js using js itself ... instead, instead include those directly from data/templates/nginx/plain/yunohost_panel.conf.inc<commit_after>/* ----------------------------------------------------------
  Utilities
---------------------------------------------------------- */

/* Console log fix
-------------------------- */
if (typeof(console) === 'undefined') {
    var console = {};
    console.log = console.error = console.info = console.debug = console.warn = console.trace = console.dir = console.dirxml = console.group = console.groupEnd = console.time = console.timeEnd = console.assert = console.profile = function() {};
}

/* Array utilities
  https://github.com/Darklg/JavaScriptUtilities/blob/master/assets/js/vanilla-js/libs/vanilla-arrays.js
-------------------------- */
Array.contains = function(needle, haystack) {
    var i = 0,
        length = haystack.length;

    for (; i < length; i++) {
        if (haystack[i] === needle) return true;
    }
    return false;
};
Array.each = function(arrayToParse, callback) {
    var i = 0,
        length = arrayToParse.length;
    for (; i < length; i++) {
        callback(arrayToParse[i]);
    }
};

/* CSS classes utilities
  https://github.com/Darklg/JavaScriptUtilities/blob/master/assets/js/vanilla-js/libs/vanilla-classes.js
-------------------------- */
Element.getClassNames = function(element) {
    var classNames = [],
        elementClassName = element.className;
    if (elementClassName !== '') {
        elementClassName = elementClassName.replace(/\s+/g, ' ');
        classNames = elementClassName.split(' ');
    }
    return classNames;
};
Element.hasClass = function(element, className) {
    if (element.classList) {
        return element.classList.contains(className);
    }
    return Array.contains(className, Element.getClassNames(element));
};
Element.addClass = function(element, className) {
    if (element.classList) {
        element.classList.add(className);
        return;
    }
    if (!Element.hasClass(element, className)) {
        var elementClasses = Element.getClassNames(element);
        elementClasses.push(className);
        element.className = elementClasses.join(' ');
    }
};
Element.removeClass = function(element, className) {
    if (element.classList) {
        element.classList.remove(className);
        return;
    }
    var elementClasses = Element.getClassNames(element);
    var newElementClasses = [];
    var i = 0,
        arLength = elementClasses.length;
    for (; i < arLength; i++) {
        if (elementClasses[i] !== className) {
            newElementClasses.push(elementClasses[i]);
        }
    }
    element.className = newElementClasses.join(' ');
};
Element.toggleClass = function(element, className) {
    if (!Element.hasClass(element, className)) {
        Element.addClass(element, className);
    }
    else {
        Element.removeClass(element, className);
    }
};

/* Add Event
  https://github.com/Darklg/JavaScriptUtilities/blob/master/assets/js/vanilla-js/libs/vanilla-events.js
-------------------------- */
window.addEvent = function(el, eventName, callback, options) {
    if (el == null) { return; }
    if (el.addEventListener) {
        if (!options || typeof(options) !== "object") {
            options = {};
        }

        options.capture = false;
        el.addEventListener(eventName, callback, options);
    }
    else if (el.attachEvent) {
        el.attachEvent("on" + eventName, function(e) {
            return callback.call(el, e);
        });
    }
};
window.eventPreventDefault = function(event) {
    return (event.preventDefault) ? event.preventDefault() : event.returnValue = false;
};

/* Draggable

  Sources :
  http://jsfiddle.net/5t3Ju/
  http://stackoverflow.com/questions/9334084/moveable-draggable-div
  http://jsfiddle.net/tovic/Xcb8d/light/
-------------------------- */

function make_element_draggable(id) {

  // Variables
  this.elem = document.getElementById(id),
  this.selected = null,  // Selected element
  this.dragged = false,  // Dragging status
  this.x_pos = 0, this.y_pos = 0, // Stores x & y coordinates of the mouse pointer
  this.x_elem = 0, this.y_elem = 0; // Stores top, left values (edge) of the element

  var _initDrag = function(e){
    if (e.type === "touchstart"){
      x_pos = e.touches[0].clientX;
      y_pos = e.touches[0].clientY;
    }

    selected = elem;
    x_elem = x_pos - selected.offsetLeft;
    y_elem = y_pos - selected.offsetTop;
  };

  var _shutDrag = function(e){
      selected = null;
  };

  var _onMove = function(e){
    // Get position
    x_pos = document.all ? window.event: e.pageX;
    y_pos = document.all ? window.event : e.pageY;

    if (e.type === "touchmove") {
        x_pos = e.touches[0].clientX;
        y_pos = e.touches[0].clientY;
    }

    if (selected !== null) {
      if (e.type === "touchmove"){
        event.preventDefault();
      }
      dragged = true;
      selected.style.left = (x_pos - x_elem) + 'px';
      selected.style.top = (y_pos - y_elem) + 'px';
    }
  };

  // Prevent native D'n'D behavior
  window.addEvent(elem, 'dragstart', function(e){
    window.eventPreventDefault(e);
  });

  // Start dragging
  window.addEvent(elem, 'mousedown', _initDrag);
  window.addEvent(elem, 'touchstart', _initDrag);

  // Will be called when user dragging an element
  window.addEvent(window, 'mousemove', _onMove);
  window.addEvent(window, 'touchmove', _onMove, {passive: false});

  // Destroy the object when we are done
  window.addEvent(window, 'mouseup', _shutDrag);
  window.addEvent(window, 'touchend', _shutDrag);
  window.addEvent(window, 'touchcancel', _shutDrag);

  // Handle click event
  window.addEvent(elem, 'click', function(e){
      // Prevent default event
      window.eventPreventDefault(e);

      // Do not propagate to other click event if dragged out
      if (dragged) {
        e.stopImmediatePropagation();
      }
      // Reset dragging status
      dragged = false;
  });
};

/* ----------------------------------------------------------
  Main
---------------------------------------------------------- */
window.addEvent(document, 'DOMContentLoaded', function() {

    // 3 different cases :
    // - this script is loaded from inside an app
    // - this script is loaded inside the portal, inside an iframe/overlay activated by clicking the portal button inside an app
    // - this script is loaded inside the "regular" portal when going to /yunohost/sso.

    var in_app = ! document.body.classList.contains('ynh-user-portal');
    var in_overlay_iframe = (window.location != window.parent.location);

    if (in_app)
    {
        init_portal_button_and_overlay();
    }
    else
    {
        init_portal();
        if (in_overlay_iframe) { tweak_portal_when_in_iframe(); }
    }
});

//
// This function is called when ynhpanel.js is included in an app
//
// It will create the small yunohost "portal button" usually in the bottom
// right corner and initialize the portal overlay, shown when clicking the
// portal button meant to make it easier to switch between apps.
//
function init_portal_button_and_overlay()
{
  // Set and store meta viewport
  var meta_viewport = document.querySelector('meta[name="viewport"]');
  if (meta_viewport === null) {
    meta_viewport = document.createElement('meta');
    meta_viewport.setAttribute('name', "viewport");
    meta_viewport.setAttribute('content', "");
    document.getElementsByTagName('head')[0].insertBefore(meta_viewport, null);
  }
  meta_viewport = document.querySelector('meta[name="viewport"]');
  meta_viewport_content = meta_viewport.getAttribute('content');

  // Inject portal button
  var portalButton = document.createElement('a');
  portalButton.setAttribute('id', 'ynh-overlay-switch');
  portalButton.setAttribute('href', '/yunohost/sso/');
  portalButton.setAttribute('class', 'disableAjax');
  document.body.insertBefore(portalButton, null);
  // Make portal button draggable, for user convenience
  make_element_draggable('ynh-overlay-switch');

  // Prepare and inject the portal overlay (what is activated when clicking on the portal button)
  var portalOverlay = document.createElement('iframe');
  portalOverlay.src = "/yunohost/sso/info.html";
  portalOverlay.setAttribute("id","ynh-overlay");
  portalOverlay.setAttribute("style","visibility: hidden;"); // make sure the overlay is invisible already when loading it
  document.body.insertBefore(portalOverlay, null);

  // Bind portal button
  // FIXME : this somehow prevent the portalButton
  // from being dragged correctly when mouse is moving too fast
  // ... this seem to be okay in the "app" itself, but the bug
  // is happening when *in* the portal overlay inside an app...
  window.addEvent(portalButton, 'click', function(e){
      // Prevent default click
      window.eventPreventDefault(e);
      // Toggle overlay on YNHPortal button click
      Element.toggleClass(portalOverlay, 'visible');
      Element.toggleClass(portalButton, 'visible');
      Element.toggleClass(document.querySelector('html'), 'ynh-panel-active');
      Element.toggleClass(portalOverlay, 'ynh-active');

      if (portalOverlay.classList.contains('ynh-active')) {
          meta_viewport.setAttribute('content', meta_viewport_content);
          Element.addClass(portalOverlay, 'ynh-fadeIn');
          Element.removeClass(portalOverlay, 'ynh-fadeOut');
      } else {
          meta_viewport.setAttribute('content', "width=device-width");
          Element.removeClass(portalOverlay, 'ynh-fadeIn');
          Element.addClass(portalOverlay, 'ynh-fadeOut');
      }
  });
}

//
// This function is called to initialize elements like the app tile colors and other things ...
//
function init_portal()
{

  window.addEvent(document.getElementById('add-mailalias'), "click", function() {
    // Clone last input.
    var inputAliasClone = document.querySelector('.mailalias-input').cloneNode(true);
    // Empty value.
    inputAliasClone.value = '';
    // Append to form-group.
    this.parentNode.insertBefore(inputAliasClone, this);
  });

  window.addEvent(document.getElementById('add-maildrop'), "click", function() {
    // Clone last input.
    var inputDropClone = document.querySelector('.maildrop-input').cloneNode(true);
    // Empty value.
    inputDropClone.value = '';
    // Append to form-group.
    this.parentNode.insertBefore(inputDropClone, this);
  });

  Array.each(document.getElementsByClassName("app-tile"), function(el) {
        // Set first-letter data attribute.
        el.querySelector('.first-letter').innerHTML = el.getAttribute("data-appname").substring(0, 2);
        // handle app links so they work both in plain info page and in the info iframe called from ynhpanel.js
        window.addEvent(el, 'click', function(event) {
            // if asked to open in new tab
            if (event.ctrlKey || event.shiftKey || event.metaKey
                || (event.button && event.button == 1)) {
                return
            }
            // if asked in current tab
            else {
                event.preventDefault();
                parent.location.href=this.href;
                return false;
            };
        });
  });
}

function tweak_portal_when_in_iframe()
{
    // Set class to body to show we're in overlay
    document.body.classList.add('in_app_overlay');
    let userContainer = document.querySelector('a.user-container');
    if (userContainer) {
        userContainer.classList.replace('user-container-info', 'user-container-edit');
        userContainer.setAttribute('href', userContainer
            .getAttribute('href')
            .replace('edit.html', ''));
        window.addEvent(userContainer, 'click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            window.parent.location.href = userContainer.getAttribute('href');
        });
    }
    let logoutButton = document.getElementById('ynh-logout');
    if (logoutButton)
    {
        // We force to do the logout "globally", not just in the
        // iframe, otherwise after login out the url might still be
        // domain.tld/app which is weird ...
        window.addEvent(logoutButton, 'click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            window.parent.location.href = logoutButton.getAttribute("href");
        });
    }
}
<|endoftext|>


<commit_before>'use strict';

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

stoke('foo');
/* [
 *   {
 *     type: 'unquoted',
 *     body: 'foo'
 *   }
 * ]
 */

stoke('echo "foo `echo \'bar baz\'`"');
/* [
 *   {
 *     type: 'unquoted',
 *     body: 'echo'
 *   },
 *   {
 *     type: 'double-quoted',
 *     body: [
 *       {
 *         type: 'unquoted',
 *         body: 'foo '
 *       },
 *       {
 *         type: 'back-quoted',
 *         body: [
 *           {
 *             type: 'unquoted',
 *             body: 'echo'
 *           },
 *           {
 *             type: 'single-quoted',
 *             body: 'bar baz'
 *           }
 *         ]
 *       }
 *     ]
 *   }
 * ]
 */
<commit_msg>Edit example<commit_after>'use strict';

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

stoke('echo "foo `echo \'bar baz\'`"');
/* [
 *   {
 *     type: 'unquoted',
 *     body: 'echo'
 *   },
 *   {
 *     type: 'double-quoted',
 *     body: [
 *       {
 *         type: 'unquoted',
 *         body: 'foo '
 *       },
 *       {
 *         type: 'back-quoted',
 *         body: [
 *           {
 *             type: 'unquoted',
 *             body: 'echo'
 *           },
 *           {
 *             type: 'single-quoted',
 *             body: 'bar baz'
 *           }
 *         ]
 *       }
 *     ]
 *   }
 * ]
 */
<|endoftext|>


<commit_before>import chai from 'chai';
import thunk from 'redux-thunk';
import { nodes } from '../../app/reducers/nodes';
import { pins } from '../../app/reducers/pins';
import { links } from '../../app/reducers/links';
import { nodeTypes } from '../../app/reducers/nodetypes';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import * as Actions from '../../app/actions';

// const middlewares = [thunk];
// const mockStore = configureStore(middlewares);
const mockStore = (state) => createStore(combineReducers({
  project: combineReducers({
    nodes,
    pins,
    links,
  }),
  nodeTypes,
}), state, applyMiddleware(thunk));

describe('Node deleting with dependecies', () => {
  const mockState = {
    project: {
      nodes: {
        1: {
          id: 1,
        },
        2: {
          id: 2,
        },
      },
      pins: {
        1: {
          id: 1,
          nodeId: 1,
        },
        2: {
          id: 2,
          nodeId: 1,
        },
        3: {
          id: 3,
          nodeId: 2,
        },
      },
      links: {
        1: {
          id: 1,
          fromPinId: 2,
          toPinId: 3,
        },
      },
    },
  };

  let store;
  beforeEach(() => {
    store = mockStore(mockState);
  });

  it('should delete node, children pins and link', () => {
    const expectedState = {
      project: {
        nodes: {
          2: { id: 2 },
        },
        pins: {
          3: { id: 3, nodeId: 2 },
        },
        links: {},
      },
      nodeTypes: {},
    };

    store.dispatch(Actions.deleteNodeWithDependencies(1));

    chai.expect(store.getState()).to.deep.equal(expectedState);
  });
});

describe('Node add with dependencies', () => {
  const mockState = {
    project: {
      nodes: {},
      pins: {},
    },
    nodeTypes: {
      1: {
        id: 1,
        pins: {
          input: [{
            key: 'in',
            label: 'in',
          }],
          output: [{
            key: 'out',
            label: 'out',
          }],
        },
      },
    },
  };

  let store;
  beforeEach(() => {
    store = mockStore(mockState);
  });
  it('should add children pins', () => {
    const expectedState = {
      project: {
        nodes: {
          0: {
            id: 0,
            typeId: 1,
            position: {
              x: 10,
              y: 10,
            },
          },
        },
        pins: {
          0: {
            id: 0,
            nodeId: 0,
            type: 'input',
            name: 'in',
          },
          1: {
            id: 1,
            nodeId: 0,
            type: 'output',
            name: 'out',
          },
        },
        links: {},
      },
      nodeTypes: {
        1: {
          id: 1,
          pins: {
            input: [{
              key: 'in',
              label: 'in',
            }],
            output: [{
              key: 'out',
              label: 'out',
            }],
          },
        },
      },
    };

    store.dispatch(Actions.addNodeWithDependencies(1, { x: 10, y: 10 }));

    chai.expect(store.getState()).to.deep.equal(expectedState);
  });
});
<commit_msg>fix(tests): fix test for node add/delete with dependencies<commit_after>import chai from 'chai';
import thunk from 'redux-thunk';
import { nodes } from '../../app/reducers/nodes';
import { pins } from '../../app/reducers/pins';
import { links } from '../../app/reducers/links';
import { nodeTypes } from '../../app/reducers/nodetypes';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import * as Actions from '../../app/actions';
import * as PIN_TYPE from '../../app/constants/pinType';

// const middlewares = [thunk];
// const mockStore = configureStore(middlewares);
const mockStore = (state) => createStore(combineReducers({
  project: combineReducers({
    nodes,
    pins,
    links,
  }),
  nodeTypes,
}), state, applyMiddleware(thunk));

describe('Node deleting with dependecies', () => {
  const mockState = {
    project: {
      nodes: {
        1: {
          id: 1,
        },
        2: {
          id: 2,
        },
      },
      pins: {
        1: {
          id: 1,
          nodeId: 1,
        },
        2: {
          id: 2,
          nodeId: 1,
        },
        3: {
          id: 3,
          nodeId: 2,
        },
      },
      links: {
        1: {
          id: 1,
          fromPinId: 2,
          toPinId: 3,
        },
      },
    },
  };

  let store;
  beforeEach(() => {
    store = mockStore(mockState);
  });

  it('should delete node, children pins and link', () => {
    const expectedState = {
      project: {
        nodes: {
          2: { id: 2 },
        },
        pins: {
          3: { id: 3, nodeId: 2 },
        },
        links: {},
      },
      nodeTypes: {},
    };

    store.dispatch(Actions.deleteNodeWithDependencies(1));

    chai.expect(store.getState()).to.deep.equal(expectedState);
  });
});

describe('Node add with dependencies', () => {
  const mockState = {
    project: {
      nodes: {},
      pins: {},
    },
    nodeTypes: {
      1: {
        id: 1,
        pins: {
          in: {
            key: 'in',
            type: PIN_TYPE.INPUT,
            label: 'in',
          },
          out: {
            key: 'out',
            type: PIN_TYPE.OUTPUT,
            label: 'out',
          },
        },
      },
    },
  };

  let store;
  beforeEach(() => {
    store = mockStore(mockState);
  });
  it('should add children pins', () => {
    const expectedState = {
      project: {
        nodes: {
          0: {
            id: 0,
            typeId: 1,
            position: {
              x: 10,
              y: 10,
            },
          },
        },
        pins: {
          0: {
            id: 0,
            nodeId: 0,
            key: 'in',
          },
          1: {
            id: 1,
            nodeId: 0,
            key: 'out',
          },
        },
        links: {},
      },
      nodeTypes: {
        1: {
          id: 1,
          pins: {
            in: {
              key: 'in',
              type: PIN_TYPE.INPUT,
              label: 'in',
            },
            out: {
              key: 'out',
              type: PIN_TYPE.OUTPUT,
              label: 'out',
            },
          },
        },
      },
    };

    store.dispatch(Actions.addNodeWithDependencies(1, { x: 10, y: 10 }));

    chai.expect(store.getState()).to.deep.equal(expectedState);
  });
});
<|endoftext|>


<commit_before>

// This is mostly so that no errors occur when executing
// the script stand-alone.
parent.wl_inst = {}

///////////////////////////////////////////////////////////////
//
// WEBLAB PSEUDO-CLASS
// The following class-like function provides the JavaScript
// API that Weblab provides to enable simple interaction for
// its experiments. The interface relies heavily on callbacks,
// to receive the events that the experiment requires to function,
// including but not limited to interaction start notifications,
// message responses, etc.
//
///////////////////////////////////////////////////////////////
Weblab = new function () {

    ///////////////////////////////////////////////////////////////
    //
    // PRIVATE ATTRIBUTES AND FUNCTIONS
    // The API uses these internally to provide an easier to use,
    // higher level API. Users of this class do not need to be
    // aware of them.
    //
    ///////////////////////////////////////////////////////////////

    var mCommandsSentMap = {};
    var mCommandsSentCounter = 0;

    var mFilesSentMap = {};
    var mFilesSentCounter = 0;

    var mOnTimeCallback;
    var mOnEndCallback;
    var mOnStartInteractionCallback;

    var mDefaultFileHandlerSuccessCallback;
    var mDefaultFileHandlerErrorCallback;

    var mIsExperimentActive;

    // Exception thrown when trying to use a WebLab-provided function while offline.
    // (Such as when this script is used stand-alone).
    var mNotOnline = { name: "WeblabJS Error", level: "high", message: "Tried to call WebLab method. WebLab-provided methods are not available." }

    // For experiments debugging purposes. Allows fixed responses when
    // not connected to the real WebLab, thus allowing stand-alone
    // debugging of user-experiments.
    var mSendCommandDbg = false;
    var mSendCommandResponse;
    var mSendCommandResult;

    ///////////////////////////////////////////////////////////////
    //
    // INTERNAL CALLBACKS
    // Those are set on the parent's wl_inst object.
    // They are callbacks invoked by the Weblab GWT client itself.
    // Users of this class do not need to be aware of them.
    //
    ///////////////////////////////////////////////////////////////

    parent.wl_inst.version = "1.1";

    parent.wl_inst.setTime = function (time) {
        mOnTimeCallback();
    }

    parent.wl_inst.startInteraction = function () {
        mIsExperimentActive = true;
        mOnStartInteractionCallback();
    }

    parent.wl_inst.end = function () {
        mIsExperimentActive = false;
        mOnEndCallback();
    }

    parent.wl_inst.handleCommandResponse = function (msg, id) {
        if (id in mCommandsSentMap) {
            mCommandsSentMap[id][0](msg);
            delete mCommandsSentMap[id];
        }
    };

    parent.wl_inst.handleCommandError = function (msg, id) {
        if (id in mCommandsSentMap) {
            mCommandsSentMap[id][1](msg);
            delete mCommandsSentMap[id];
        }
    };

    parent.wl_inst.handleFileResponse = function (msg, id) {
        if (id in mFilesSentMap) {
            mFilesSentMap[id][0](msg);
            delete mFilesSentMap[id];
        }
    };

    parent.wl_inst.handleFileError = function (msg, id) {
        if (id in mFilesSentMap) {
            mFilesSentMap[id][0](msg);
            delete mFilesSentMap[id];
        }
    }

    ///////////////////////////////////////////////////////////////
    //
    // PUBLIC INTERFACE
    // The following methods are part of the public interface of this
    // class. They can be used freely. Several of them rely on callbacks.
    // They might not work properly if they are run stand-alone, on a
    // context different than Weblab-Deusto.
    //
    ///////////////////////////////////////////////////////////////

    //! Sends a command to the experiment server.
    //!
    //! @param text Text of the command.
    //! @param successHandler Callback that will receive the response for the command.
    //! Takes a single string as argument.
    //! @param errorHandler Callback that will receive the response for the command.
    //! Takes a single string as argument.
    //!
    this.sendCommand = function (text, successHandler, errorHandler) {
        mCommandsSentCounter++;

        if (this.checkOnline() == false) {
            if (mSendCommandDbg)
                setTimeout(mSendCommandResult ? successHandler : errorHandler, 100, mSendCommandResponse);
            else
                throw mNotOnline;
        }
        else {
            mCommandsSentMap[mCommandsSentCounter] = [successHandler, errorHandler];
            return parent.wl_sendCommand(text, mCommandsSentCounter);
        }
    };

    //! Sets the callback that will be invoked when the experiment finishes. Generally,
    //! an experiment finishes when it runs out of allocated time, but it may also
    //! be finished explicitly by the user or the experiment code, or by errors and
    //! and disconnections.
    //!
    this.setOnEndCallback = function (onEndCallback) {
        mOnEndCallback = onEndCallback;
    }

    //! Sets the callbacks that will be invoked by default when a sendfile request
    //! finishes. The appropriate callback specified here will be invoked if no
    //! callback was specified in the sendFile call, or if the sendFile was done
    //! from GWT itself and not through this API.
    //!
    //! @param onSuccess Callback invoked when the sendFile request succeeds. Takes
    //! the return message as argument.
    //! @param onError Callback invoked when the sendFile request fails. Takes the
    //! return message as argument.
    this.setFileHandlerCallbacks = function (onSuccess, onError) {
        mDefaultFileHandlerErrorCallback = onError;
        mDefaultFileHandlerSuccessCallback = onSuccess;
    }

    //! Sets the startInteractionCallback. This is the callback that will be invoked
    //! after the Weblab experiment is successfully reserved, and the user can start
    //! interacting with the experiment.
    this.setOnStartInteractionCallback = function (onStartInteractionCallback) {
        mOnStartInteractionCallback = onStartInteractionCallback;
    }

    //! Sets the setTime callback. This is the callback that Weblab invokes when it defines
    //! the time that the experiment has left. Currently, the Weblab system only invokes
    //! this once, on startup. Hence, from the moment setTime is invoked, the experiment
    //! can take for granted that that is indeed the time it has left. Unless, of course,
    //! the experiment itself chooses to finish, or the user finishes early.
    //!
    //! @param onTimeCallback The callback to invoke when Weblab sets the time left for
    //! the experiment.
    //!
    this.setOnTimeCallback = function (onTimeCallback) {
        mOnTimeCallback = onTimeCallback;
    }

    //! Sets the three Weblab callbacks at once.
    //!
    //! @param onStartInteraction Start Interaction callback.
    //! @param onTime On Time callback.
    //! @param onEnd On End callback.
    //!
    //! @see setOnStartInteraction
    //! @see setOnTimeCallback
    //! @see setOnEndCallback
    this.setCallbacks = function (onStartInteraction, onTime, onEnd) {
        this.setOnStartInteractionCallback(onStartInteraction);
        this.setOnTimeCallback(onTime);
        this.setOnEndCallback(onEnd);
    }

    //! Retrieves a configuration property.
    //!
    //! @param name Name of the property.
    this.getProperty = function (name) {
        return parent.wl_getProperty(name);
    };

    //! Retrieves a configuration property.
    //!
    //! @param name Name of the property.
    //! @param def Default value to return if the configuration property
    //! is not found.
    this.getPropertyDef = function (name, def) {
        return parent.wl_getPropertyDef(name, def);
    };

    //! Retrieves an integer configuration property.
    //!
    //! @param name Name of the property.
    this.getIntProperty = function (name) {
        return parent.wl_getIntProperty(name);
    };

    //! Retrieves an integer configuration property.
    //!
    //! @param name Name of the property.
    //! @param def Default value to return if the configuration property
    //! is not found.
    this.getIntPropertyDef = function (name, def) {
        return parent.wl_getIntPropertyDef(name, def);
    };

    //! Finishes the experiment.
    //!
    this.clean = function () {
        return parent.wl_onClean();
    };

    //! Returns true if the experiment is active, false otherwise.
    //! An experiment is active if it has started and not finished.
    //! That is, if the server, supposedly, should be able to receive
    //! commands.
    //!
    this.isExperimentActive = function () {
        return mIsExperimentActive;
    }

    //! Checks whether this interface is actually connected to the real
    //! WebLab client.
    //!
    //! @return True, if connected to the real WL client. False otherwise.
    this.checkOnline = function () {
        return parent.wl_sendCommand != undefined;
    }

    //! This method is for debugging purposes. When the WeblabJS interface is used stand-alone,
    //! offline from the real Weblab client, then the response to SendCommand will be as specified.
    //!
    //! @param response Text in the response.
    //! @param result If true, SendCommand will invoke the success handler.
    //! @param result If false, SendCommand will invoke the failure handler.
    this.dbgSetOfflineSendCommandResponse = function (response, result) {
        mSendCommandDbg = true;
        mSendCommandResult = result == undefined ? true : result;
        mSendCommandResponse = response;
    }

}; //! end-of class-like Weblab function

<commit_msg>[jsxilinx]: Minor changes<commit_after>

// This is mostly so that no errors occur when executing
// the script stand-alone.
parent.wl_inst = {}

///////////////////////////////////////////////////////////////
//
// WEBLAB PSEUDO-CLASS
// The following class-like function provides the JavaScript
// API that Weblab provides to enable simple interaction for
// its experiments. The interface relies heavily on callbacks,
// to receive the events that the experiment requires to function,
// including but not limited to interaction start notifications,
// message responses, etc.
//
///////////////////////////////////////////////////////////////
Weblab = new function () {

    ///////////////////////////////////////////////////////////////
    //
    // PRIVATE ATTRIBUTES AND FUNCTIONS
    // The API uses these internally to provide an easier to use,
    // higher level API. Users of this class do not need to be
    // aware of them.
    //
    ///////////////////////////////////////////////////////////////

    var mCommandsSentMap = {};
    var mCommandsSentCounter = 0;

    var mFilesSentMap = {};
    var mFilesSentCounter = 0;

    var mOnTimeCallback;
    var mOnEndCallback;
    var mOnStartInteractionCallback;

    var mDefaultFileHandlerSuccessCallback;
    var mDefaultFileHandlerErrorCallback;

    var mIsExperimentActive = false;

    // Exception thrown when trying to use a WebLab-provided function while offline.
    // (Such as when this script is used stand-alone).
    var mNotOnline = { name: "WeblabJS Error", level: "high", message: "Tried to call WebLab method. WebLab-provided methods are not available." }

    // For experiments debugging purposes. Allows fixed responses when
    // not connected to the real WebLab, thus allowing stand-alone
    // debugging of user-experiments.
    var mSendCommandDbg = false;
    var mSendCommandResponse;
    var mSendCommandResult;

    ///////////////////////////////////////////////////////////////
    //
    // INTERNAL CALLBACKS
    // Those are set on the parent's wl_inst object.
    // They are callbacks invoked by the Weblab GWT client itself.
    // Users of this class do not need to be aware of them.
    //
    ///////////////////////////////////////////////////////////////

    parent.wl_inst.version = "1.1";

    parent.wl_inst.setTime = function (time) {
        mOnTimeCallback();
    }

    parent.wl_inst.startInteraction = function () {
        mIsExperimentActive = true;
        mOnStartInteractionCallback();
    }

    parent.wl_inst.end = function () {
        mIsExperimentActive = false;
        mOnEndCallback();
    }

    parent.wl_inst.handleCommandResponse = function (msg, id) {
        if (id in mCommandsSentMap) {
            mCommandsSentMap[id][0](msg);
            delete mCommandsSentMap[id];
        }
    };

    parent.wl_inst.handleCommandError = function (msg, id) {
        if (id in mCommandsSentMap) {
            mCommandsSentMap[id][1](msg);
            delete mCommandsSentMap[id];
        }
    };

    parent.wl_inst.handleFileResponse = function (msg, id) {
        if (id in mFilesSentMap) {
            mFilesSentMap[id][0](msg);
            delete mFilesSentMap[id];
        }
    };

    parent.wl_inst.handleFileError = function (msg, id) {
        if (id in mFilesSentMap) {
            mFilesSentMap[id][0](msg);
            delete mFilesSentMap[id];
        }
    }

    ///////////////////////////////////////////////////////////////
    //
    // PUBLIC INTERFACE
    // The following methods are part of the public interface of this
    // class. They can be used freely. Several of them rely on callbacks.
    // They might not work properly if they are run stand-alone, on a
    // context different than Weblab-Deusto.
    //
    ///////////////////////////////////////////////////////////////

    //! Sends a command to the experiment server.
    //!
    //! @param text Text of the command.
    //! @param successHandler Callback that will receive the response for the command.
    //! Takes a single string as argument.
    //! @param errorHandler Callback that will receive the response for the command.
    //! Takes a single string as argument.
    //!
    this.sendCommand = function (text, successHandler, errorHandler) {
        mCommandsSentCounter++;

        if (this.checkOnline() == false) {
            if (mSendCommandDbg)
                setTimeout(mSendCommandResult ? successHandler : errorHandler, 100, mSendCommandResponse);
            else
                throw mNotOnline;
        }
        else {
            mCommandsSentMap[mCommandsSentCounter] = [successHandler, errorHandler];
            return parent.wl_sendCommand(text, mCommandsSentCounter);
        }
    };

    //! Sets the callback that will be invoked when the experiment finishes. Generally,
    //! an experiment finishes when it runs out of allocated time, but it may also
    //! be finished explicitly by the user or the experiment code, or by errors and
    //! and disconnections.
    //!
    this.setOnEndCallback = function (onEndCallback) {
        mOnEndCallback = onEndCallback;
    }

    //! Sets the callbacks that will be invoked by default when a sendfile request
    //! finishes. The appropriate callback specified here will be invoked if no
    //! callback was specified in the sendFile call, or if the sendFile was done
    //! from GWT itself and not through this API.
    //!
    //! @param onSuccess Callback invoked when the sendFile request succeeds. Takes
    //! the return message as argument.
    //! @param onError Callback invoked when the sendFile request fails. Takes the
    //! return message as argument.
    this.setFileHandlerCallbacks = function (onSuccess, onError) {
        mDefaultFileHandlerErrorCallback = onError;
        mDefaultFileHandlerSuccessCallback = onSuccess;
    }

    //! Sets the startInteractionCallback. This is the callback that will be invoked
    //! after the Weblab experiment is successfully reserved, and the user can start
    //! interacting with the experiment.
    this.setOnStartInteractionCallback = function (onStartInteractionCallback) {
        mOnStartInteractionCallback = onStartInteractionCallback;
    }

    //! Sets the setTime callback. This is the callback that Weblab invokes when it defines
    //! the time that the experiment has left. Currently, the Weblab system only invokes
    //! this once, on startup. Hence, from the moment setTime is invoked, the experiment
    //! can take for granted that that is indeed the time it has left. Unless, of course,
    //! the experiment itself chooses to finish, or the user finishes early.
    //!
    //! @param onTimeCallback The callback to invoke when Weblab sets the time left for
    //! the experiment.
    //!
    this.setOnTimeCallback = function (onTimeCallback) {
        mOnTimeCallback = onTimeCallback;
    }

    //! Sets the three Weblab callbacks at once.
    //!
    //! @param onStartInteraction Start Interaction callback.
    //! @param onTime On Time callback.
    //! @param onEnd On End callback.
    //!
    //! @see setOnStartInteraction
    //! @see setOnTimeCallback
    //! @see setOnEndCallback
    this.setCallbacks = function (onStartInteraction, onTime, onEnd) {
        this.setOnStartInteractionCallback(onStartInteraction);
        this.setOnTimeCallback(onTime);
        this.setOnEndCallback(onEnd);
    }

    //! Retrieves a configuration property.
    //!
    //! @param name Name of the property.
    this.getProperty = function (name) {
        return parent.wl_getProperty(name);
    };

    //! Retrieves a configuration property.
    //!
    //! @param name Name of the property.
    //! @param def Default value to return if the configuration property
    //! is not found.
    this.getPropertyDef = function (name, def) {
        return parent.wl_getPropertyDef(name, def);
    };

    //! Retrieves an integer configuration property.
    //!
    //! @param name Name of the property.
    this.getIntProperty = function (name) {
        return parent.wl_getIntProperty(name);
    };

    //! Retrieves an integer configuration property.
    //!
    //! @param name Name of the property.
    //! @param def Default value to return if the configuration property
    //! is not found.
    this.getIntPropertyDef = function (name, def) {
        return parent.wl_getIntPropertyDef(name, def);
    };

    //! Finishes the experiment.
    //!
    this.clean = function () {
        return parent.wl_onClean();
    };

    //! Returns true if the experiment is active, false otherwise.
    //! An experiment is active if it has started and not finished.
    //! That is, if the server, supposedly, should be able to receive
    //! commands.
    //!
    this.isExperimentActive = function () {
        return mIsExperimentActive;
    }

    //! Checks whether this interface is actually connected to the real
    //! WebLab client.
    //!
    //! @return True, if connected to the real WL client. False otherwise.
    this.checkOnline = function () {
        return parent.wl_sendCommand != undefined;
    }

    //! This method is for debugging purposes. When the WeblabJS interface is used stand-alone,
    //! offline from the real Weblab client, then the response to SendCommand will be as specified.
    //!
    //! @param response Text in the response.
    //! @param result If true, SendCommand will invoke the success handler.
    //! @param result If false, SendCommand will invoke the failure handler.
    this.dbgSetOfflineSendCommandResponse = function (response, result) {
        mSendCommandDbg = true;
        mSendCommandResult = result == undefined ? true : result;
        mSendCommandResponse = response;
    }

}; //! end-of class-like Weblab function

<|endoftext|>


<commit_before>hqDefine("export/js/export_list_main", function () {
    'use strict';

    /* Angular; to be deprecated */
    var initial_page_data = hqImport("hqwebapp/js/initial_page_data").get,
        listExportsApp = window.angular.module('listExportsApp', ['hq.list_exports']);
    listExportsApp.config(["$httpProvider", function ($httpProvider) {
        $httpProvider.defaults.xsrfCookieName = 'csrftoken';
        $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
        $httpProvider.defaults.headers.common["X-CSRFToken"] = $("#csrfTokenContainer").val();
    }]);
    listExportsApp.config(["djangoRMIProvider", function (djangoRMIProvider) {
        djangoRMIProvider.configure(initial_page_data("djng_current_rmi"));
    }]);
    listExportsApp.constant('bulk_download_url', initial_page_data("bulk_download_url"));
    listExportsApp.constant('modelType', initial_page_data("model_type"));
    listExportsApp.constant('staticModelType', initial_page_data("static_model_type"));
    listExportsApp.constant('filterFormElements', {
        emwf_form_filter: function () {
            return $('#id_emwf_form_filter');
        },
        emwf_case_filter: function () {
            return $('#id_emwf_case_filter');
        },
    });
    listExportsApp.constant('filterFormModalElement', function () {
        return $('#setFeedFiltersModal');
    });

    /* Knockout */
    var exportModel = function(options) {
        options.isAutoRebuildEnabled = options.isAutoRebuildEnabled || false;
        options.isDailySaved = options.isDailySaved || false;
        options.isFeed = options.isFeed || false;
        options.showLink = options.showLink || false;
        options.emailedExport = options.emailedExport || {};

        var mapping = {
            'copy': ["emailedExport"]
        };
        var self = ko.mapping.fromJS(options, mapping);

        self.isLocationSafeForUser = function () {
            return _.isEmpty(self.emailedExport) || self.emailedExport.isLocationSafeForUser;
        };

        self.downloadRequested = function (model, e) {
            var $btn = $(e.target);
            $btn.addClass('disabled');
            $btn.text(gettext('Download Requested'));
            return true;    // allow default click action to process so file is downloaded
        };
        self.copyLinkRequested = function (model, e) {
            model.showLink(true);
            var clipboard = new Clipboard(e.target, {
                target: function (trigger) {
                    return trigger.nextElementSibling;
                },
            });
            clipboard.onClick(e);
            clipboard.destroy();
        };

        self.updateEmailedExportData = function (model) {
            var component = model.emailedExport;
            $('#modalRefreshExportConfirm-' + model.id() + '-' + component.groupId).modal('hide');
            component.updatingData = true;
            $.ajax({
                method: 'POST',
                url: hqImport("hqwebapp/js/initial_page_data").reverse('update_emailed_export_data'),
                data: {
                    export_id: model.id(),
                    is_deid: self.isDeid,
                    model_type: self.modelType,
                },
                success: function (data) {
                    if (data.success) {
                        var exportType = hqImport('export/js/utils').capitalize(model.exportType());
                        hqImport('analytix/js/google').track.event(exportType + " Exports", "Update Saved Export", "Saved");
                        self.pollProgressBar(model);
                    }
                },
            });
        };

        self.updateDisabledState = function (model, e) {
            var component = model.emailedExport,
                $button = $(e.currentTarget);

            $button.disableButton();
            $.ajax({
                method: 'POST',
                url: hqImport("hqwebapp/js/initial_page_data").reverse('toggle_saved_export_enabled'),
                data: {
                    export_id: model.id(),
                    is_auto_rebuild_enabled: model.isAutoRebuildEnabled(),
                    is_deid: self.isDeid,
                    model_type: self.modelType,
                },
                success: function (data) {
                    if (data.success) {
                        var exportType = hqImport('export/js/utils').capitalize(model.exportType());
                        var event = (model.isAutoRebuildEnabled() ? "Disable" : "Enable") + " Saved Export";
                        hqImport('analytix/js/google').track.event(exportType + " Exports", event, "Saved");
                        model.isAutoRebuildEnabled(data.isAutoRebuildEnabled);
                    }
                    $button.enableButton();
                    $('#modalEnableDisableAutoRefresh-' + model.id() + '-' + component.groupId).modal('hide');
                },
            });
        };

        return self;
    };

    var exportListModel = function(options) {
        hqImport("hqwebapp/js/assert_properties").assert(options, ['exports', 'isDeid', 'modelType']);

        var self = {};

        self.modelType = options.modelType;
        self.isDeid = options.isDeid;
        self.exports = _.map(options.exports, function (e) { return exportModel(e); });
        self.myExports = _.filter(self.exports, function (e) { return !!e.my_export; });
        self.notMyExports = _.filter(self.exports, function (e) { return !e.my_export; });

        self.sendExportAnalytics = function () {
            hqImport('analytix/js/kissmetrix').track.event("Clicked Export button");
            return true;
        };

        // TODO: test
        // Polling
        self.pollProgressBar = function (exp) {
            exp.emailedExport.updatingData = false;
            exp.emailedExport.taskStatus = {
                'percentComplete': 0,
                'inProgress': true,
                'success': false,
            };
            var tick = function () {
                $.ajax({
                    method: 'GET',
                    url: hqImport("hqwebapp/js/initial_page_data").reverse("get_saved_export_progress"),
                    data: {
                        export_instance_id: exp.id(),
                        is_deid: self.isDeid,
                        model_type: self.modelType,
                    },
                    success: function (data) {
                        exp.emailedExport.taskStatus = data.taskStatus;
                        if (!data.taskStatus.success) {
                            // The first few ticks don't yet register the task
                            exp.emailedExport.taskStatus.inProgress = true;
                            setTimeout(tick, 1500);
                        } else {
                            exp.emailedExport.taskStatus.justFinished = true;
                        }
                    },
                });
            };
            tick();
        };
        _.each(self.exports, function (exp) {
            if (exp.emailedExport && exp.emailedExport.taskStatus && exp.emailedExport.taskStatus.inProgress) {
                self.pollProgressBar(exp);
            }
        });

        // Bulk export handling
        self.selectAll = function() {
            _.each(self.exports, function (e) { e.addedToBulk(true); });
        };
        self.selectNone = function() {
            _.each(self.exports, function (e) { e.addedToBulk(false); });
        };
        self.showBulkExportDownload = ko.observable(false);
        self.bulkExportList = ko.observable('');
        _.each(self.exports, function (e) {
            e.addedToBulk.subscribe(function (newValue) {
                // Determine whether or not to show bulk export download button & message
                if (newValue !== self.showBulkExportDownload()) {
                    self.showBulkExportDownload(!!_.find(self.exports, function (e) {
                        return e.addedToBulk();
                    }));
                }

                // Update hidden value of exports to download
                if (self.showBulkExportDownload()) {
                    self.bulkExportList(JSON.stringify(_.map(_.filter(self.exports, function (e) {
                        return e.addedToBulk();
                    }), function (e) {
                        return ko.mapping.toJS(e);
                    })));
                }
            });
        });

        // HTML elements from filter form - it's not very knockout-y to manipulate directly
        self.$filterModal = $("#setFeedFiltersModal");
        self.$emwfCaseFilter = $("#id_emwf_case_filter");
        self.$emwfFormFilter = $("#id_emwf_form_filter");

        // Editing filters for a saved export
        self.formData = {};
        self.filterModalExportId = ko.observable();
        self.locationRestrictions = ko.observableArray([]);  // List of location names. Export will be restricted to these locations.
        self.formSubmitErrorMessage = ko.observable('');
        self.dateRegex = '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]';
        self.isSubmittingForm = ko.observable(false);

        self.hasLocationRestrictions = ko.computed(function () {
            return self.locationRestrictions().length;
        });

        self.filterModalExportId.subscribe(function (newValue) {
            if (!newValue) {
                return;
            }
            var newSelectedExport = _.find(self.exports, function (e) { return e.id() === newValue; });
            self.$filterModal.find("form")[0].reset();
            self.formData = newSelectedExport.emailedExport.filters;
            self.locationRestrictions(newSelectedExport.emailedExport.locationRestrictions);
            // select2s require programmatic update
            self.$emwfCaseFilter.select2("data", newSelectedExport.emailedExport.filters.emwf_case_filter);
            self.$emwfFormFilter.select2("data", newSelectedExport.emailedExport.filters.emwf_form_filter);
        });
        // TODO
        /*$scope.$watch("formData.date_range", function (newDateRange) {
            if (!newDateRange) {
                $scope.formData.date_range = "since";
            } else {
                self.formSubmitErrorMessage('');
            }
        });*/
        self.commitFilters = function () {
            var export_ = _.find(self.exports, function (e) { return e.id() === self.filterModalExportId(); });
            self.isSubmittingForm(true);

            // Put the data from the select2 into the formData object
            var exportType = export_.exportType;
            if (exportType === 'form') {
                self.formData.emwf_form_filter = self.$emwfFormFilter.select2("data");
                self.formData.emwf_case_filter = null;
            } else if (exportType === 'case') {
                self.formData.emwf_case_filter = self.$emwfCaseFilter.select2("data");
                self.formData.emwf_form_filter = null;
            }

            // TODO: test
            $.ajax({
                method: 'POST',
                url: hqImport("hqwebapp/js/initial_page_data").reverse("commit_filters"),
                data: {
                    export_id: export_.id(),
                    form_data: self.formData,
                    is_deid: hqImport("hqwebapp/js/initial_page_data").get("is_deid"),
                    model_type: self.modelType,
                },
                success: function (data) {
                    self.isSubmittingForm(false);
                    if (data.success) {
                        self.formSubmitErrorMessage('');
                        export_.emailedExport.filters = self.formData;
                        self.pollProgressBar(export_);
                        self.$filterModal.modal('hide');
                    } else {
                        self.formSubmitErrorMessage(data.error);
                    }
                },
                error: function () {
                    self.isSubmittingForm(false);
                    self.formSubmitErrorMessage(gettext("Problem saving dashboard feed filters"));
                },
            });
        };

        return self;
    };

    $(function () {
        var initialPageData = hqImport("hqwebapp/js/initial_page_data");

        $("#create-export").koApplyBindings(hqImport("export/js/create_export").createExportModel({
            model_type: initialPageData.get("model_type", true),
            drilldown_fetch_url: initialPageData.reverse('get_app_data_drilldown_values'),
            drilldown_submit_url: initialPageData.reverse('submit_app_data_drilldown_form'),
            page: {
                is_daily_saved_export: initialPageData.get('is_daily_saved_export', true),
                is_feed: initialPageData.get('is_feed', true),
                is_deid: initialPageData.get('is_deid', true),
                model_type: initialPageData.get('model_type', true),
            },
        }));
        $('#createExportOptionsModal').on('show.bs.modal', function () {
            hqImport('analytix/js/kissmetrix').track.event("Clicked New Export");
        });

        var modelType = initialPageData.get("model_type");
        $("#export-list").koApplyBindings(exportListModel({
            exports: initialPageData.get("exports"),
            modelType: modelType,
            isDeid: initialPageData.get('is_deid'),
        }));

        if (modelType === 'form') {
            hqImport('analytix/js/kissmetrix').track.event('Visited Export Forms Page');
        } else if (modelType === 'case') {
            hqImport('analytix/js/kissmetrix').track.event('Visited Export Cases Page');
        }
    });
});
<commit_msg>Not all exports have a formname (case exports)<commit_after>hqDefine("export/js/export_list_main", function () {
    'use strict';

    /* Angular; to be deprecated */
    var initial_page_data = hqImport("hqwebapp/js/initial_page_data").get,
        listExportsApp = window.angular.module('listExportsApp', ['hq.list_exports']);
    listExportsApp.config(["$httpProvider", function ($httpProvider) {
        $httpProvider.defaults.xsrfCookieName = 'csrftoken';
        $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
        $httpProvider.defaults.headers.common["X-CSRFToken"] = $("#csrfTokenContainer").val();
    }]);
    listExportsApp.config(["djangoRMIProvider", function (djangoRMIProvider) {
        djangoRMIProvider.configure(initial_page_data("djng_current_rmi"));
    }]);
    listExportsApp.constant('bulk_download_url', initial_page_data("bulk_download_url"));
    listExportsApp.constant('modelType', initial_page_data("model_type"));
    listExportsApp.constant('staticModelType', initial_page_data("static_model_type"));
    listExportsApp.constant('filterFormElements', {
        emwf_form_filter: function () {
            return $('#id_emwf_form_filter');
        },
        emwf_case_filter: function () {
            return $('#id_emwf_case_filter');
        },
    });
    listExportsApp.constant('filterFormModalElement', function () {
        return $('#setFeedFiltersModal');
    });

    /* Knockout */
    var exportModel = function(options) {
        _.each(['isAutoRebuildEnabled', 'isDailySaved', 'isFeed', 'showLink'], function (key) {
            options[key] = options[key] || false;
        });
        options.emailedExport = options.emailedExport || {};
        options.formname = options.formname || '';

        var mapping = {
            'copy': ["emailedExport"]
        };
        var self = ko.mapping.fromJS(options, mapping);

        self.isLocationSafeForUser = function () {
            return _.isEmpty(self.emailedExport) || self.emailedExport.isLocationSafeForUser;
        };

        self.downloadRequested = function (model, e) {
            var $btn = $(e.target);
            $btn.addClass('disabled');
            $btn.text(gettext('Download Requested'));
            return true;    // allow default click action to process so file is downloaded
        };
        self.copyLinkRequested = function (model, e) {
            model.showLink(true);
            var clipboard = new Clipboard(e.target, {
                target: function (trigger) {
                    return trigger.nextElementSibling;
                },
            });
            clipboard.onClick(e);
            clipboard.destroy();
        };

        self.updateEmailedExportData = function (model) {
            var component = model.emailedExport;
            $('#modalRefreshExportConfirm-' + model.id() + '-' + component.groupId).modal('hide');
            component.updatingData = true;
            $.ajax({
                method: 'POST',
                url: hqImport("hqwebapp/js/initial_page_data").reverse('update_emailed_export_data'),
                data: {
                    export_id: model.id(),
                    is_deid: self.isDeid,
                    model_type: self.modelType,
                },
                success: function (data) {
                    if (data.success) {
                        var exportType = hqImport('export/js/utils').capitalize(model.exportType());
                        hqImport('analytix/js/google').track.event(exportType + " Exports", "Update Saved Export", "Saved");
                        self.pollProgressBar(model);
                    }
                },
            });
        };

        self.updateDisabledState = function (model, e) {
            var component = model.emailedExport,
                $button = $(e.currentTarget);

            $button.disableButton();
            $.ajax({
                method: 'POST',
                url: hqImport("hqwebapp/js/initial_page_data").reverse('toggle_saved_export_enabled'),
                data: {
                    export_id: model.id(),
                    is_auto_rebuild_enabled: model.isAutoRebuildEnabled(),
                    is_deid: self.isDeid,
                    model_type: self.modelType,
                },
                success: function (data) {
                    if (data.success) {
                        var exportType = hqImport('export/js/utils').capitalize(model.exportType());
                        var event = (model.isAutoRebuildEnabled() ? "Disable" : "Enable") + " Saved Export";
                        hqImport('analytix/js/google').track.event(exportType + " Exports", event, "Saved");
                        model.isAutoRebuildEnabled(data.isAutoRebuildEnabled);
                    }
                    $button.enableButton();
                    $('#modalEnableDisableAutoRefresh-' + model.id() + '-' + component.groupId).modal('hide');
                },
            });
        };

        return self;
    };

    var exportListModel = function(options) {
        hqImport("hqwebapp/js/assert_properties").assert(options, ['exports', 'isDeid', 'modelType']);

        var self = {};

        self.modelType = options.modelType;
        self.isDeid = options.isDeid;
        self.exports = _.map(options.exports, function (e) { return exportModel(e); });
        self.myExports = _.filter(self.exports, function (e) { return !!e.my_export; });
        self.notMyExports = _.filter(self.exports, function (e) { return !e.my_export; });

        self.sendExportAnalytics = function () {
            hqImport('analytix/js/kissmetrix').track.event("Clicked Export button");
            return true;
        };

        // TODO: test
        // Polling
        self.pollProgressBar = function (exp) {
            exp.emailedExport.updatingData = false;
            exp.emailedExport.taskStatus = {
                'percentComplete': 0,
                'inProgress': true,
                'success': false,
            };
            var tick = function () {
                $.ajax({
                    method: 'GET',
                    url: hqImport("hqwebapp/js/initial_page_data").reverse("get_saved_export_progress"),
                    data: {
                        export_instance_id: exp.id(),
                        is_deid: self.isDeid,
                        model_type: self.modelType,
                    },
                    success: function (data) {
                        exp.emailedExport.taskStatus = data.taskStatus;
                        if (!data.taskStatus.success) {
                            // The first few ticks don't yet register the task
                            exp.emailedExport.taskStatus.inProgress = true;
                            setTimeout(tick, 1500);
                        } else {
                            exp.emailedExport.taskStatus.justFinished = true;
                        }
                    },
                });
            };
            tick();
        };
        _.each(self.exports, function (exp) {
            if (exp.emailedExport && exp.emailedExport.taskStatus && exp.emailedExport.taskStatus.inProgress) {
                self.pollProgressBar(exp);
            }
        });

        // Bulk export handling
        self.selectAll = function() {
            _.each(self.exports, function (e) { e.addedToBulk(true); });
        };
        self.selectNone = function() {
            _.each(self.exports, function (e) { e.addedToBulk(false); });
        };
        self.showBulkExportDownload = ko.observable(false);
        self.bulkExportList = ko.observable('');
        _.each(self.exports, function (e) {
            e.addedToBulk.subscribe(function (newValue) {
                // Determine whether or not to show bulk export download button & message
                if (newValue !== self.showBulkExportDownload()) {
                    self.showBulkExportDownload(!!_.find(self.exports, function (e) {
                        return e.addedToBulk();
                    }));
                }

                // Update hidden value of exports to download
                if (self.showBulkExportDownload()) {
                    self.bulkExportList(JSON.stringify(_.map(_.filter(self.exports, function (e) {
                        return e.addedToBulk();
                    }), function (e) {
                        return ko.mapping.toJS(e);
                    })));
                }
            });
        });

        // HTML elements from filter form - it's not very knockout-y to manipulate directly
        self.$filterModal = $("#setFeedFiltersModal");
        self.$emwfCaseFilter = $("#id_emwf_case_filter");
        self.$emwfFormFilter = $("#id_emwf_form_filter");

        // Editing filters for a saved export
        self.formData = {};
        self.filterModalExportId = ko.observable();
        self.locationRestrictions = ko.observableArray([]);  // List of location names. Export will be restricted to these locations.
        self.formSubmitErrorMessage = ko.observable('');
        self.dateRegex = '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]';
        self.isSubmittingForm = ko.observable(false);

        self.hasLocationRestrictions = ko.computed(function () {
            return self.locationRestrictions().length;
        });

        self.filterModalExportId.subscribe(function (newValue) {
            if (!newValue) {
                return;
            }
            var newSelectedExport = _.find(self.exports, function (e) { return e.id() === newValue; });
            self.$filterModal.find("form")[0].reset();
            self.formData = newSelectedExport.emailedExport.filters;
            self.locationRestrictions(newSelectedExport.emailedExport.locationRestrictions);
            // select2s require programmatic update
            self.$emwfCaseFilter.select2("data", newSelectedExport.emailedExport.filters.emwf_case_filter);
            self.$emwfFormFilter.select2("data", newSelectedExport.emailedExport.filters.emwf_form_filter);
        });
        // TODO
        /*$scope.$watch("formData.date_range", function (newDateRange) {
            if (!newDateRange) {
                $scope.formData.date_range = "since";
            } else {
                self.formSubmitErrorMessage('');
            }
        });*/
        self.commitFilters = function () {
            var export_ = _.find(self.exports, function (e) { return e.id() === self.filterModalExportId(); });
            self.isSubmittingForm(true);

            // Put the data from the select2 into the formData object
            var exportType = export_.exportType;
            if (exportType === 'form') {
                self.formData.emwf_form_filter = self.$emwfFormFilter.select2("data");
                self.formData.emwf_case_filter = null;
            } else if (exportType === 'case') {
                self.formData.emwf_case_filter = self.$emwfCaseFilter.select2("data");
                self.formData.emwf_form_filter = null;
            }

            // TODO: test
            $.ajax({
                method: 'POST',
                url: hqImport("hqwebapp/js/initial_page_data").reverse("commit_filters"),
                data: {
                    export_id: export_.id(),
                    form_data: self.formData,
                    is_deid: hqImport("hqwebapp/js/initial_page_data").get("is_deid"),
                    model_type: self.modelType,
                },
                success: function (data) {
                    self.isSubmittingForm(false);
                    if (data.success) {
                        self.formSubmitErrorMessage('');
                        export_.emailedExport.filters = self.formData;
                        self.pollProgressBar(export_);
                        self.$filterModal.modal('hide');
                    } else {
                        self.formSubmitErrorMessage(data.error);
                    }
                },
                error: function () {
                    self.isSubmittingForm(false);
                    self.formSubmitErrorMessage(gettext("Problem saving dashboard feed filters"));
                },
            });
        };

        return self;
    };

    $(function () {
        var initialPageData = hqImport("hqwebapp/js/initial_page_data");

        $("#create-export").koApplyBindings(hqImport("export/js/create_export").createExportModel({
            model_type: initialPageData.get("model_type", true),
            drilldown_fetch_url: initialPageData.reverse('get_app_data_drilldown_values'),
            drilldown_submit_url: initialPageData.reverse('submit_app_data_drilldown_form'),
            page: {
                is_daily_saved_export: initialPageData.get('is_daily_saved_export', true),
                is_feed: initialPageData.get('is_feed', true),
                is_deid: initialPageData.get('is_deid', true),
                model_type: initialPageData.get('model_type', true),
            },
        }));
        $('#createExportOptionsModal').on('show.bs.modal', function () {
            hqImport('analytix/js/kissmetrix').track.event("Clicked New Export");
        });

        var modelType = initialPageData.get("model_type");
        $("#export-list").koApplyBindings(exportListModel({
            exports: initialPageData.get("exports"),
            modelType: modelType,
            isDeid: initialPageData.get('is_deid'),
        }));

        if (modelType === 'form') {
            hqImport('analytix/js/kissmetrix').track.event('Visited Export Forms Page');
        } else if (modelType === 'case') {
            hqImport('analytix/js/kissmetrix').track.event('Visited Export Cases Page');
        }
    });
});
<|endoftext|>


<commit_before>var express = require('express');
var app = express();

var serialPort = require("serialport");
serialPort.list(function (err, ports) {
	console.log('Available ports:');
	ports.forEach(function(port) {
		console.log("comName: " + port.comName);
		console.log("\tpnpId: " + port.pnpId);
		console.log("\tmanufacturer: " + port.manufacturer);
	});
});

app.use(express.static(__dirname + '/public'));

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

var server = app.listen(process.env.PORT || 3000, function () {
	var host = server.address().address;
	var port = server.address().port;
	console.log('Listening at http://%s:%s', host, port);
});

var SerialPort = require("serialport").SerialPort
var serialPort = new SerialPort("/dev/cu.usbmodem1411", {
  baudrate: 115200,
  disconnectedCallback: function() {
  	// todo: need to reconnect here
  }
});

function tellRobo(command) {
	serialPort.write(command + '\r\n', function(err, results) {
		if(err) console.log('err ' + err);
		if(results) console.log('results ' + results);
	});
}

var revolutionsPerMeter = 16.818;
var encoderResolution = 256;
var countsPerMeter = revolutionsPerMeter * encoderResolution;
var top = countsPerMeter * 9.75; // 14.16meters from floor at 120,000 = ~8611 counts per meter
var bottom = countsPerMeter * 0.10;
var slows = "800";
var fasts = "1300"; // 1300 seemed quite reliable, 1400 and 1350 crashed on first attempt
var downac = "15000"; // 15000
var downdc = "12000"; // 12000

app.get('/goDownFast', function(req, res) {
	tellRobo('!s 1 ' + fasts);
	tellRobo('!ac 1 ' + downac);
	tellRobo('!dc 1 ' + downdc);
	tellRobo('!p 1 ' + bottom);
	res.send('done');
})

app.get('/goUpSlow', function(req, res) {
	tellRobo('!s 1 ' + slows);
	tellRobo('!ac 1 2000');
	tellRobo('!dc 1 2000');
	tellRobo('!p 1 ' + top);
	res.send('done');
})

app.get('/goDownSlow', function(req, res) {
	tellRobo('!s 1 ' + slows);
	tellRobo('!ac 1 2000');
	tellRobo('!dc 1 2000');
	tellRobo('!p 1 ' + bottom);
	res.send('done');
})

app.get('/inch', function(req, res) {
	tellRobo('!p 1 1000');
	res.send('done');
})<commit_msg>new lower top with carriage attached<commit_after>var express = require('express');
var app = express();

var serialPort = require("serialport");
serialPort.list(function (err, ports) {
	console.log('Available ports:');
	ports.forEach(function(port) {
		console.log("comName: " + port.comName);
		console.log("\tpnpId: " + port.pnpId);
		console.log("\tmanufacturer: " + port.manufacturer);
	});
});

app.use(express.static(__dirname + '/public'));

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

var server = app.listen(process.env.PORT || 3000, function () {
	var host = server.address().address;
	var port = server.address().port;
	console.log('Listening at http://%s:%s', host, port);
});

var SerialPort = require("serialport").SerialPort
var serialPort = new SerialPort("/dev/cu.usbmodem1421", {
  baudrate: 115200,
  disconnectedCallback: function() {
  	// todo: need to reconnect here
  }
});

function tellRobo(command) {
	serialPort.write(command + '\r\n', function(err, results) {
		if(err) console.log('err ' + err);
		if(results) console.log('results ' + results);
	});
}

var revolutionsPerMeter = 16.818;
var encoderResolution = 256;
var countsPerMeter = revolutionsPerMeter * encoderResolution;
var top = countsPerMeter * 9.25; // 14.16meters from floor at 120,000 = ~8611 counts per meter
var bottom = countsPerMeter * 0.10;
var slows = "800";
var fasts = "1300"; // 1300 seemed quite reliable, 1400 and 1350 crashed on first attempt
var downac = "15000"; // 15000
var downdc = "12000"; // 12000

app.get('/goDownFast', function(req, res) {
	tellRobo('!s 1 ' + fasts);
	tellRobo('!ac 1 ' + downac);
	tellRobo('!dc 1 ' + downdc);
	tellRobo('!p 1 ' + bottom);
	res.send('done');
})

app.get('/goUpSlow', function(req, res) {
	tellRobo('!s 1 ' + slows);
	tellRobo('!ac 1 2000');
	tellRobo('!dc 1 2000');
	tellRobo('!p 1 ' + top);
	res.send('done');
})

app.get('/goDownSlow', function(req, res) {
	tellRobo('!s 1 ' + slows);
	tellRobo('!ac 1 2000');
	tellRobo('!dc 1 2000');
	tellRobo('!p 1 ' + bottom);
	res.send('done');
})

app.get('/inch', function(req, res) {
	tellRobo('!p 1 1000');
	res.send('done');
})<|endoftext|>


<commit_before>/** @jsx React.DOM */

// Helpers
var Events = require('./Events');

// Classes
var AccountListComponent = require('./components/AccountListComponent');
var BankListComponent = require('./components/BankListComponent');
var CategoryComponent = require('./components/CategoryComponent');
var ChartComponent = require('./components/ChartComponent');
var OperationListComponent = require('./components/OperationListComponent');
var SimilarityComponent = require('./components/SimilarityComponent');

// Global variables
var store = require('./store');

// Now this really begins.
var Kresus = React.createClass({

    getInitialState: function() {
        return {
            showing: 'reports'
        }
    },

    componentDidMount: function() {
        // Let's go.
        store.getCategories();
        store.once(Events.CATEGORIES_LOADED, function() {
            store.getAllBanks();
        });
    },

    _show: function(name) {
        return function() {
            this.setState({ showing: name });
        }.bind(this);
    },

    render: function() {

        var mainComponent;
        switch(this.state.showing) {
            case "reports":
                mainComponent = <OperationListComponent/>
                break;
            case "charts":
                mainComponent = <ChartComponent/>
                break;
            case "categories":
                mainComponent = <CategoryComponent/>
                break;
            case "similarities":
                mainComponent = <SimilarityComponent/>
                break;
            case "settings":
                // TODO
                alert('NYI, showing operations list instead');
                mainComponent = <OperationListComponent/>
                break;
            default:
                alert('unknown component to render: '  + this.state.showing + '!');
                break;
        }

        return (

                    KRESUS

                             Report

                             Charts

                             Categories

                             Similarities

                             Settings

 Banks

                <BankListComponent />
                <AccountListComponent />

                    {mainComponent}

        );
    }
});

React.renderComponent(<Kresus />, document.querySelector('#main'));
<commit_msg>Change class name with respect to current module.<commit_after>/** @jsx React.DOM */

// Helpers
var Events = require('./Events');

// Classes
var AccountListComponent = require('./components/AccountListComponent');
var BankListComponent = require('./components/BankListComponent');
var CategoryComponent = require('./components/CategoryComponent');
var ChartComponent = require('./components/ChartComponent');
var OperationListComponent = require('./components/OperationListComponent');
var SimilarityComponent = require('./components/SimilarityComponent');

// Global variables
var store = require('./store');

// Now this really begins.
var Kresus = React.createClass({

    getInitialState: function() {
        return {
            showing: 'reports'
        }
    },

    componentDidMount: function() {
        // Let's go.
        store.getCategories();
        store.once(Events.CATEGORIES_LOADED, function() {
            store.getAllBanks();
        });
    },

    _show: function(name) {
        return function() {
            this.setState({ showing: name });
        }.bind(this);
    },

    render: function() {

        var mainComponent;
        var showing = this.state.showing;
        switch(showing) {
            case "reports":
                mainComponent = <OperationListComponent/>
                break;
            case "charts":
                mainComponent = <ChartComponent/>
                break;
            case "categories":
                mainComponent = <CategoryComponent/>
                break;
            case "similarities":
                mainComponent = <SimilarityComponent/>
                break;
            case "settings":
                // TODO
                alert('NYI, showing operations list instead');
                mainComponent = <OperationListComponent/>
                break;
            default:
                alert('unknown component to render: '  + showing + '!');
                break;
        }

        function IsActive(which) {
            return showing === which ? 'active' : '';
        }

        return (

                    KRESUS

                             Report

                             Charts

                             Categories

                             Similarities

                             Settings

 Banks

                <BankListComponent />
                <AccountListComponent />

                    {mainComponent}

        );
    }
});

React.renderComponent(<Kresus />, document.querySelector('#main'));
<|endoftext|>