<commit_before>// Future versions of Hyper may add additional config options,
// which will not automatically be merged into this file.
// See https://hyper.is#cfg for all currently supported options.

module.exports = {
  config: {
    // choose either `'stable'` for receiving highly polished,
    // or `'canary'` for less polished but more frequent updates
    updateChannel: 'stable',

    // default font size in pixels for all tabs
    fontSize: 14,

    // font family with optional fallbacks
    fontFamily: 'Menlo, "DejaVu Sans Mono", Consolas, "Lucida Console", monospace',

    // default font weight: 'normal' or 'bold'
    fontWeight: 'normal',

    // font weight for bold characters: 'normal' or 'bold'
    fontWeightBold: 'bold',

    // terminal cursor background color and opacity (hex, rgb, hsl, hsv, hwb or cmyk)
    cursorColor: 'rgba(248,28,229,0.8)',

    // terminal text color under BLOCK cursor
    cursorAccentColor: '#000',

    // `'BEAM'` for |, `'UNDERLINE'` for _, `'BLOCK'` for █
    cursorShape: 'BEAM',

    // set to `true` (without backticks and without quotes) for blinking cursor
    cursorBlink: true,

    // color of the text
    foregroundColor: '#fff',

    // terminal background color
    // opacity is only supported on macOS
    backgroundColor: '#000',

    // terminal selection color
    selectionColor: 'rgba(248,28,229,0.3)',

    // border color (window, tabs)
    borderColor: '#333',

    // custom CSS to embed in the main window
    css: '',

    // custom CSS to embed in the terminal window
    termCSS: '',

    // if you're using a Linux setup which show native menus, set to false
    // default: `true` on Linux, `true` on Windows, ignored on macOS
    showHamburgerMenu: '',

    // set to `false` (without backticks and without quotes) if you want to hide the minimize, maximize and close buttons
    // additionally, set to `'left'` if you want them on the left, like in Ubuntu
    // default: `true` (without backticks and without quotes) on Windows and Linux, ignored on macOS
    showWindowControls: '',

    // custom padding (CSS format, i.e.: `top right bottom left`)
    padding: '12px 14px',

    // the full list. if you're going to provide the full color palette,
    // including the 6 x 6 color cubes and the grayscale map, just provide
    // an array here instead of a color map object
    colors: {
      black: '#000000',
      red: '#C51E14',
      green: '#1DC121',
      yellow: '#C7C329',
      blue: '#0A2FC4',
      magenta: '#C839C5',
      cyan: '#20C5C6',
      white: '#C7C7C7',
      lightBlack: '#686868',
      lightRed: '#FD6F6B',
      lightGreen: '#67F86F',
      lightYellow: '#FFFA72',
      lightBlue: '#6A76FB',
      lightMagenta: '#FD7CFC',
      lightCyan: '#68FDFE',
      lightWhite: '#FFFFFF',
    },

    // the shell to run when spawning a new session (i.e. /usr/local/bin/fish)
    // if left empty, your system's login shell will be used by default
    //
    // Windows
    // - Make sure to use a full path if the binary name doesn't work
    // - Remove `--login` in shellArgs
    //
    // Bash on Windows
    // - Example: `C:\\Windows\\System32\\bash.exe`
    //
    // PowerShell on Windows
    // - Example: `C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`
    shell: '',

    // for setting shell arguments (i.e. for using interactive shellArgs: `['-i']`)
    // by default `['--login']` will be used
    shellArgs: ['--login'],

    // for environment variables
    env: {},

    // set to `false` for no bell
    bell: 'SOUND',

    // if `true` (without backticks and without quotes), selected text will automatically be copied to the clipboard
    copyOnSelect: false,

    // if `true` (without backticks and without quotes), hyper will be set as the default protocol client for SSH
    defaultSSHApp: true,

    // if `true` (without backticks and without quotes), on right click selected text will be copied or pasted if no
    // selection is present (`true` by default on Windows and disables the context menu feature)
    // quickEdit: true,

    // URL to custom bell
    // bellSoundURL: 'http://example.com/bell.mp3',

    // for advanced config flags please refer to https://hyper.is/#cfg
  },

  // a list of plugins to fetch and install from npm
  // format: [@org/]project[#version]
  // examples:
  //   `hyperpower`
  //   `@company/project`
  //   `project#1.0.1`
  plugins: ['hyper-snazzy'],

  // in development, you can create a directory under
  // `~/.hyper_plugins/local/` and include it here
  // to load it and avoid it being `npm install`ed
  localPlugins: [],

  keymaps: {
    // Example
    // 'window:devtools': 'cmd+alt+o',
  },
};
<commit_msg>Update hyper config<commit_after>// Future versions of Hyper may add additional config options,
// which will not automatically be merged into this file.
// See https://hyper.is#cfg for all currently supported options.

module.exports = {
  config: {
    // choose either `'stable'` for receiving highly polished,
    // or `'canary'` for less polished but more frequent updates
    updateChannel: 'stable',

    // default font size in pixels for all tabs
    fontSize: 16,

    // font family with optional fallbacks
    fontFamily: '"Dank Mono", "Victor Mono", Menlo, "DejaVu Sans Mono", Consolas, "Lucida Console", monospace',

    // default font weight: 'normal' or 'bold'
    fontWeight: 'normal',

    // font weight for bold characters: 'normal' or 'bold'
    fontWeightBold: 'bold',

    // terminal cursor background color and opacity (hex, rgb, hsl, hsv, hwb or cmyk)
    cursorColor: 'rgba(248,28,229,0.8)',

    // terminal text color under BLOCK cursor
    cursorAccentColor: '#000',

    // `'BEAM'` for |, `'UNDERLINE'` for _, `'BLOCK'` for █
    cursorShape: 'BEAM',

    // set to `true` (without backticks and without quotes) for blinking cursor
    cursorBlink: true,

    // color of the text
    foregroundColor: '#fff',

    // terminal background color
    // opacity is only supported on macOS
    backgroundColor: '#000',

    // terminal selection color
    selectionColor: 'rgba(248,28,229,0.3)',

    // border color (window, tabs)
    borderColor: '#333',

    // custom CSS to embed in the main window
    css: '',

    // custom CSS to embed in the terminal window
    termCSS: '',

    // if you're using a Linux setup which show native menus, set to false
    // default: `true` on Linux, `true` on Windows, ignored on macOS
    showHamburgerMenu: '',

    // set to `false` (without backticks and without quotes) if you want to hide the minimize, maximize and close buttons
    // additionally, set to `'left'` if you want them on the left, like in Ubuntu
    // default: `true` (without backticks and without quotes) on Windows and Linux, ignored on macOS
    showWindowControls: '',

    // custom padding (CSS format, i.e.: `top right bottom left`)
    padding: '12px 14px',

    // the full list. if you're going to provide the full color palette,
    // including the 6 x 6 color cubes and the grayscale map, just provide
    // an array here instead of a color map object
    colors: {
      black: '#000000',
      red: '#C51E14',
      green: '#1DC121',
      yellow: '#C7C329',
      blue: '#0A2FC4',
      magenta: '#C839C5',
      cyan: '#20C5C6',
      white: '#C7C7C7',
      lightBlack: '#686868',
      lightRed: '#FD6F6B',
      lightGreen: '#67F86F',
      lightYellow: '#FFFA72',
      lightBlue: '#6A76FB',
      lightMagenta: '#FD7CFC',
      lightCyan: '#68FDFE',
      lightWhite: '#FFFFFF',
    },

    // the shell to run when spawning a new session (i.e. /usr/local/bin/fish)
    // if left empty, your system's login shell will be used by default
    //
    // Windows
    // - Make sure to use a full path if the binary name doesn't work
    // - Remove `--login` in shellArgs
    //
    // Bash on Windows
    // - Example: `C:\\Windows\\System32\\bash.exe`
    //
    // PowerShell on Windows
    // - Example: `C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`
    shell: '',

    // for setting shell arguments (i.e. for using interactive shellArgs: `['-i']`)
    // by default `['--login']` will be used
    shellArgs: ['--login'],

    // for environment variables
    env: {},

    // set to `false` for no bell
    bell: 'SOUND',

    // if `true` (without backticks and without quotes), selected text will automatically be copied to the clipboard
    copyOnSelect: false,

    // if `true` (without backticks and without quotes), hyper will be set as the default protocol client for SSH
    defaultSSHApp: true,

    // if `true` (without backticks and without quotes), on right click selected text will be copied or pasted if no
    // selection is present (`true` by default on Windows and disables the context menu feature)
    // quickEdit: true,

    // URL to custom bell
    // bellSoundURL: 'http://example.com/bell.mp3',

    // for advanced config flags please refer to https://hyper.is/#cfg
  },

  // a list of plugins to fetch and install from npm
  // format: [@org/]project[#version]
  // examples:
  //   `hyperpower`
  //   `@company/project`
  //   `project#1.0.1`
  plugins: ['hyper-snazzy'],

  // in development, you can create a directory under
  // `~/.hyper_plugins/local/` and include it here
  // to load it and avoid it being `npm install`ed
  localPlugins: [],

  keymaps: {
    // Example
    // 'window:devtools': 'cmd+alt+o',
  },
};
<|endoftext|>


<commit_before>// @flow
import React, { Component } from 'react';
import classnames from 'classnames';

import ParameterList from '../ParameterList';
import * as utils from '../../../utils';

import styles from './json-doc.css';
import type { Service } from '../../../generated/version/ServiceType';

const defaultView =
  (

    <-- Hover over JSON example for documentation

);

type Props = {
  documentationFullType: string,
  service: Service,
  importedServices: Service[],
};

class Documentation extends Component {
  props: Props;
  state: {
    height: number,
  };
  constructor(props: props) {
    super(props);
    this.state = { height: 0 };
    this.updateContainerHeight = this.updateContainerHeight.bind(this);
  }

  componentDidUpdate() {
    this.updateContainerHeight();
  }

  updateContainerHeight() {
    const container = this.container;
    if (container) {
      const height = container.clientHeight;
      if (height > this.state.height) {
        this.setState({ height });
      }
    }
  }

  render() {
    const { documentationFullType, service, importedServices } = this.props;
    const { height } = this.state;
    if (!documentationFullType) return defaultView;

    const modelName = documentationFullType.substring(0, documentationFullType.lastIndexOf('.'));
    const fieldName = documentationFullType.substring(documentationFullType.lastIndexOf('.') + 1);
    const model = utils.getModel(modelName, service, importedServices);
    const field = model ? model.fields.find(f => f.name === fieldName) : null;

    return (

 { this.container = el; }}
        className={classnames(styles.documentation)}
        style={{ minHeight: `${height}px` }}
      >
        <ParameterList {...field} service={service} importedServices={importedServices} parentModel={modelName} />

    );
  }
}

export default Documentation;
<commit_msg>fix flow types<commit_after>// @flow
import React, { Component } from 'react';
import classnames from 'classnames';

import ParameterList from '../ParameterList';
import * as utils from '../../../utils';

import styles from './json-doc.css';
import type { Service } from '../../../generated/version/ServiceType';

const defaultView =
  (

    <-- Hover over JSON example for documentation

);

type Props = {
  documentationFullType: string,
  service: Service,
  importedServices: Service[],
};

class Documentation extends Component {
  props: Props;
  state: {
    height: number,
  };

  constructor(props: Props) {
    super(props);
    this.state = { height: 0 };
    this.updateContainerHeight = this.updateContainerHeight.bind(this);
  }

  componentDidUpdate() {
    this.updateContainerHeight();
  }

  container: HTMLDivElement;
  updateContainerHeight: () => void;

  updateContainerHeight() {
    const container = this.container;
    if (container) {
      const height = container.clientHeight;
      if (height > this.state.height) {
        this.setState({ height });
      }
    }
  }

  render() {
    const { documentationFullType, service, importedServices } = this.props;
    const { height } = this.state;
    if (!documentationFullType) return defaultView;

    const modelName = documentationFullType.substring(0, documentationFullType.lastIndexOf('.'));
    const fieldName = documentationFullType.substring(documentationFullType.lastIndexOf('.') + 1);
    const model = utils.getModel(modelName, service, importedServices);
    const field = model ? model.fields.find(f => f.name === fieldName) : null;

    return (

 { this.container = el; }}
        className={classnames(styles.documentation)}
        style={{ minHeight: `${height}px` }}
      >
        <ParameterList {...field} service={service} importedServices={importedServices} parentModel={modelName} />

    );
  }
}

export default Documentation;
<|endoftext|>


<commit_before>angular.module("proBebe.services")
.factory('ObserverMicrodonation', function(storage) {

  function Observer() {}

  Observer.start = function(state){
    var dateShowPopup = storage.get('dateShowPopup');
    if(dateShowPopup == null){
      var current = new Date;
      current.setMonth(current.getMonth() + 1);
      storage.set('dateShowPopup', current);
    }
  }

  Observer.updateDateShowPopup = function(){
    var current = new Date;
    current.setDate(current.getDate() + 14); // 2 weeks
    storage.set('dateShowPopup',current);
  }

  Observer._isTimeToShow = function(current){
    var dateShowPopup = new Date(storage.get('dateShowPopup'));
    if((dateShowPopup.getMonth() == current.getMonth()) && (dateShowPopup.getDate() == current.getDate())){
      dateShowPopup.setMonth(dateShowPopup.getMonth() -2);
      storage.set('dateShowPopup',dateShowPopup);
      return true;
    } else return false;
  }

  Observer.isTimeToShowPopup = function(){
    var current =  new Date;
    return Observer._isTimeToShow(current)
  }

  return Observer;

});
<commit_msg>Define to show microdonation popup now<commit_after>angular.module("proBebe.services")
.factory('ObserverMicrodonation', function(storage) {

  function Observer() {}

  Observer.start = function(){
    var dateShowPopup = storage.get('dateShowPopup');
    if(dateShowPopup == null){
      var current = new Date;
      // current.setMonth(current.getMonth() + 1);
      storage.set('dateShowPopup', current);
    }
  }

  Observer.updateDateShowPopup = function(){
    var current = new Date;
    current.setDate(current.getDate() + 14); // 2 weeks
    storage.set('dateShowPopup',current);
  }

  Observer._isTimeToShow = function(current){
    var dateShowPopup = new Date(storage.get('dateShowPopup'));
    if((dateShowPopup.getMonth() <= current.getMonth())
      && (dateShowPopup.getDate() <= current.getDate())
      && (dateShowPopup.getFullYear() == current.getFullYear()))
    {
      dateShowPopup.setFullYear(dateShowPopup.getFullYear() -1);
      storage.set('dateShowPopup',dateShowPopup);
      return true;
    } else return false;
  }

  Observer.isTimeToShowPopup = function(){
    var current =  new Date;
    return Observer._isTimeToShow(current)
  }

  return Observer;

});
<|endoftext|>


<commit_before>import { isElement, eventOn, eventOff } from './dom'

const eventListenerSupported = window.addEventListener
const MutationObserver =
  window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver

// Fallback observation for legacy browsers
// Emulate observer disconnect() method so that we can detach the events later
const fakeObserverFactory = (el, callback) => /* istanbul ignore next: hard to test in JSDOM */ {
  eventOn(el, 'DOMNodeInserted', callback, false)
  eventOn(el, 'DOMNodeRemoved', callback, false)
  return {
    disconnect: () => {
      eventOff(el, 'DOMNodeInserted', callback, false)
      eventOff(el, 'DOMNodeRemoved', callback, false)
    }
  }
}

/**
 * Observe a DOM element changes, falls back to eventListener mode
 * @param {Element} el The DOM element to observe
 * @param {Function} callback callback to be called on change
 * @param {object} [opts={childList: true, subtree: true}] observe options
 * @see http://stackoverflow.com/questions/3219758
 */
const observeDom = (el, callback, opts) => /* istanbul ignore next: difficult to test in JSDOM */ {
  // Handle case where we might be passed a vue instance
  el = el ? el.$el || el : null
  /* istanbul ignore next: difficult to test in JSDOM */
  if (!isElement(el)) {
    // We can't observe something that isn't an element
    return null
  }

  let obs = null

  if (MutationObserver) {
    // Define a new observer
    obs = new MutationObserver(mutations => {
      let changed = false
      // A Mutation can contain several change records, so we loop through them to see what has changed.
      // We break out of the loop early if any "significant" change has been detected
      for (let i = 0; i < mutations.length && !changed; i++) {
        // The mutation record
        const mutation = mutations[i]
        // Mutation Type
        const type = mutation.type
        // DOM Node (could be any DOM Node type - HTMLElement, Text, comment, etc)
        const target = mutation.target
        if (type === 'characterData' && target.nodeType === Node.TEXT_NODE) {
          // We ignore nodes that are not TEXT (i.e. comments, etc) as they don't change layout
          changed = true
        } else if (type === 'attributes') {
          changed = true
        } else if (
          type === 'childList' &&
          (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0)
        ) {
          // This includes HTMLElement and Text Nodes being added/removed/re-arranged
          changed = true
        }
      }
      if (changed) {
        // We only call the callback if a change that could affect layout/size truely happened.
        callback()
      }
    })

    // Have the observer observe foo for changes in children, etc
    obs.observe(el, { childList: true, subtree: true, ...opts })
  } else if (eventListenerSupported) {
    // Legacy interface. most likely not used in modern browsers
    obs = fakeObserverFactory(el, callback)
  }

  // We return a reference to the observer so that obs.disconnect() can be called if necessary
  // To reduce overhead when the root element is hidden
  return obs
}

export default observeDom
<commit_msg>fix(utisl/observeDom): make sure to check for browser enviroment (#2838)<commit_after>import { isElement, eventOn, eventOff } from './dom'
import { inBrowser } from './env'

const eventListenerSupported = inBrowser && window.addEventListener
const MutationObserver =
  inBrowser &&
  (window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver)

// Fallback observation for legacy browsers
// Emulate observer disconnect() method so that we can detach the events later
const fakeObserverFactory = (el, callback) => /* istanbul ignore next: hard to test in JSDOM */ {
  eventOn(el, 'DOMNodeInserted', callback, false)
  eventOn(el, 'DOMNodeRemoved', callback, false)
  return {
    disconnect: () => {
      eventOff(el, 'DOMNodeInserted', callback, false)
      eventOff(el, 'DOMNodeRemoved', callback, false)
    }
  }
}

/**
 * Observe a DOM element changes, falls back to eventListener mode
 * @param {Element} el The DOM element to observe
 * @param {Function} callback callback to be called on change
 * @param {object} [opts={childList: true, subtree: true}] observe options
 * @see http://stackoverflow.com/questions/3219758
 */
const observeDom = (el, callback, opts) => /* istanbul ignore next: difficult to test in JSDOM */ {
  // Handle case where we might be passed a vue instance
  el = el ? el.$el || el : null
  /* istanbul ignore next: difficult to test in JSDOM */
  if (!isElement(el)) {
    // We can't observe something that isn't an element
    return null
  }

  let obs = null

  if (MutationObserver) {
    // Define a new observer
    obs = new MutationObserver(mutations => {
      let changed = false
      // A Mutation can contain several change records, so we loop through them to see what has changed.
      // We break out of the loop early if any "significant" change has been detected
      for (let i = 0; i < mutations.length && !changed; i++) {
        // The mutation record
        const mutation = mutations[i]
        // Mutation Type
        const type = mutation.type
        // DOM Node (could be any DOM Node type - HTMLElement, Text, comment, etc)
        const target = mutation.target
        if (type === 'characterData' && target.nodeType === Node.TEXT_NODE) {
          // We ignore nodes that are not TEXT (i.e. comments, etc) as they don't change layout
          changed = true
        } else if (type === 'attributes') {
          changed = true
        } else if (
          type === 'childList' &&
          (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0)
        ) {
          // This includes HTMLElement and Text Nodes being added/removed/re-arranged
          changed = true
        }
      }
      if (changed) {
        // We only call the callback if a change that could affect layout/size truely happened.
        callback()
      }
    })

    // Have the observer observe foo for changes in children, etc
    obs.observe(el, { childList: true, subtree: true, ...opts })
  } else if (eventListenerSupported) {
    // Legacy interface. most likely not used in modern browsers
    obs = fakeObserverFactory(el, callback)
  }

  // We return a reference to the observer so that obs.disconnect() can be called if necessary
  // To reduce overhead when the root element is hidden
  return obs
}

export default observeDom
<|endoftext|>


<commit_before>NEWSBLUR.ReaderMarkRead = function(options) {
    var defaults = {
        days: 1,
        modal_container_class: "NB-full-container"
    };

    this.flags = {};
    this.values = {
        0: 0,
        1: 1,
        2: 3,
        3: 7,
        4: 14,
        5: 30
    };
    if (NEWSBLUR.Globals.is_archive) {
        this.values = {
            0: 0,
            1: 1,
            2: 3,
            3: 7,
            4: 14,
            5: 30,
            6: 60,
            7: 90,
            8: 120,
            9: 180,
            10: 365,
        };
    }
    this.options = $.extend({}, defaults, options);
    this.model = NEWSBLUR.assets;
    this.runner();
};

NEWSBLUR.ReaderMarkRead.prototype = new NEWSBLUR.Modal;
NEWSBLUR.ReaderMarkRead.prototype.constructor = NEWSBLUR.ReaderMarkRead;

_.extend(NEWSBLUR.ReaderMarkRead.prototype, {

    runner: function() {
        this.make_modal();
        this.load_slider();
        this.generate_explanation(this.options['days']);
        this.handle_cancel();
        this.open_modal();

        this.$modal.bind('click', $.rescope(this.handle_click, this));
        $(document).bind('keydown.mark_read', 'return', _.bind(this.save_mark_read, this));
        $(document).bind('keydown.mark_read', 'ctrl+return', _.bind(this.save_mark_read, this));
        $(document).bind('keydown.mark_read', 'meta+return', _.bind(this.save_mark_read, this));
    },

    make_modal: function() {
        var self = this;

        this.$modal = $.make('div', { className: 'NB-modal-markread NB-modal' }, [
            $.make('h2', { className: 'NB-modal-title' }, [
                $.make('div', { className: 'NB-icon' }),
                'Mark old stories as read',
                $.make('div', { className: 'NB-icon-dropdown' })
            ]),
            $.make('form', { className: 'NB-markread-form' }, [
                $.make('div', { className: 'NB-markread-slider'}),
                $.make('div', { className: 'NB-markread-explanation'}),
                $.make('div', { className: 'NB-modal-submit' }, [
                    $.make('input', { type: 'submit', className: 'NB-modal-submit-button NB-modal-submit-green', value: 'Do it' })
                ])
            ]).bind('submit', function(e) {
                e.preventDefault();
                self.save_mark_read();
                return false;
            })
        ]);
    },

    load_slider: function() {
        var self = this;
        var $slider = $('.NB-markread-slider', this.$modal);

        $slider.slider({
            range: 'min',
            min: 0,
            max: 4,
            step: 1,
            value: _.indexOf(_.values(this.values), this.options['days']),
            slide: function(e, ui) {
                var value = self.values[ui.value];
                self.update_dayofweek(value);
                self.generate_explanation(value);
            },
            stop: function(e, ui) {

            }
        });

    },

    update_dayofweek: function(value) {

    },

    generate_explanation: function(value) {
        var $button = $('.NB-modal-submit-button', this.$modal);
        var explanation;

        if (value == 0) {
            explanation = "Mark every story as read";
        } else if (value >= 1) {
            explanation = "Mark all stories older than " + value + " day" + (value==1?'':'s') + " old as read";
        }

        $button.val(explanation);
    },

    save_mark_read: function() {
        if (this.flags.saving) return;

        var $save = $('.NB-modal input[type=submit]');
        var $slider = $('.NB-markread-slider', this.$modal);
        var days = this.values[$slider.slider('option', 'value')];

        this.flags.saving = true;
        $save.attr('value', 'Marking as read...').addClass('NB-disabled').attr('disabled', true);
        if (NEWSBLUR.Globals.is_authenticated) {
            this.model.save_mark_read(days, _.bind(function() {
                NEWSBLUR.reader.start_count_unreads_after_import();
                $.modal.close();
                NEWSBLUR.reader.force_feeds_refresh(function() {
                    NEWSBLUR.reader.finish_count_unreads_after_import();
                }, true);
                this.flags.saving = false;
            }, this));
        } else {
            this.flags.saving = false;
            $.modal.close();
        }
    },

    // ===========
    // = Actions =
    // ===========

    handle_click: function(elem, e) {
        var self = this;

        $.targetIs(e, { tagSelector: '.NB-add-url-submit' }, function($t, $p) {
            e.preventDefault();
        });
    },

    handle_cancel: function() {
        var $cancel = $('.NB-modal-cancel', this.$modal);

        $cancel.click(function(e) {
            e.preventDefault();
            $.modal.close();
        });
    }

});
<commit_msg>Maxing out mark read dates.<commit_after>NEWSBLUR.ReaderMarkRead = function(options) {
    var defaults = {
        days: 1,
        modal_container_class: "NB-full-container"
    };

    this.flags = {};
    this.values = {
        0: 0,
        1: 1,
        2: 3,
        3: 7,
        4: 14,
        5: 30
    };
    if (NEWSBLUR.Globals.is_archive) {
        this.values = {
            0: 0,
            1: 1,
            2: 3,
            3: 7,
            4: 14,
            5: 30,
            6: 60,
            7: 90,
            8: 120,
            9: 180,
            10: 365,
        };
    }
    this.options = $.extend({}, defaults, options);
    this.model = NEWSBLUR.assets;
    this.runner();
};

NEWSBLUR.ReaderMarkRead.prototype = new NEWSBLUR.Modal;
NEWSBLUR.ReaderMarkRead.prototype.constructor = NEWSBLUR.ReaderMarkRead;

_.extend(NEWSBLUR.ReaderMarkRead.prototype, {

    runner: function() {
        this.make_modal();
        this.load_slider();
        this.generate_explanation(this.options['days']);
        this.handle_cancel();
        this.open_modal();

        this.$modal.bind('click', $.rescope(this.handle_click, this));
        $(document).bind('keydown.mark_read', 'return', _.bind(this.save_mark_read, this));
        $(document).bind('keydown.mark_read', 'ctrl+return', _.bind(this.save_mark_read, this));
        $(document).bind('keydown.mark_read', 'meta+return', _.bind(this.save_mark_read, this));
    },

    make_modal: function() {
        var self = this;

        this.$modal = $.make('div', { className: 'NB-modal-markread NB-modal' }, [
            $.make('h2', { className: 'NB-modal-title' }, [
                $.make('div', { className: 'NB-icon' }),
                'Mark old stories as read',
                $.make('div', { className: 'NB-icon-dropdown' })
            ]),
            $.make('form', { className: 'NB-markread-form' }, [
                $.make('div', { className: 'NB-markread-slider'}),
                $.make('div', { className: 'NB-markread-explanation'}),
                $.make('div', { className: 'NB-modal-submit' }, [
                    $.make('input', { type: 'submit', className: 'NB-modal-submit-button NB-modal-submit-green', value: 'Do it' })
                ])
            ]).bind('submit', function(e) {
                e.preventDefault();
                self.save_mark_read();
                return false;
            })
        ]);
    },

    load_slider: function() {
        var self = this;
        var $slider = $('.NB-markread-slider', this.$modal);

        $slider.slider({
            range: 'min',
            min: 0,
            max: Object.keys(this.values).length-1,
            step: 1,
            value: _.indexOf(_.values(this.values), this.options['days']),
            slide: function(e, ui) {
                var value = self.values[ui.value];
                self.update_dayofweek(value);
                self.generate_explanation(value);
            },
            stop: function(e, ui) {

            }
        });

    },

    update_dayofweek: function(value) {

    },

    generate_explanation: function(value) {
        var $button = $('.NB-modal-submit-button', this.$modal);
        var explanation;

        if (value == 0) {
            explanation = "Mark every story as read";
        } else if (value >= 1) {
            explanation = "Mark all stories older than " + value + " day" + (value==1?'':'s') + " old as read";
        }

        $button.val(explanation);
    },

    save_mark_read: function() {
        if (this.flags.saving) return;

        var $save = $('.NB-modal input[type=submit]');
        var $slider = $('.NB-markread-slider', this.$modal);
        var days = this.values[$slider.slider('option', 'value')];

        this.flags.saving = true;
        $save.attr('value', 'Marking as read...').addClass('NB-disabled').attr('disabled', true);
        if (NEWSBLUR.Globals.is_authenticated) {
            this.model.save_mark_read(days, _.bind(function() {
                NEWSBLUR.reader.start_count_unreads_after_import();
                $.modal.close();
                NEWSBLUR.reader.force_feeds_refresh(function() {
                    NEWSBLUR.reader.finish_count_unreads_after_import();
                }, true);
                this.flags.saving = false;
            }, this));
        } else {
            this.flags.saving = false;
            $.modal.close();
        }
    },

    // ===========
    // = Actions =
    // ===========

    handle_click: function(elem, e) {
        var self = this;

        $.targetIs(e, { tagSelector: '.NB-add-url-submit' }, function($t, $p) {
            e.preventDefault();
        });
    },

    handle_cancel: function() {
        var $cancel = $('.NB-modal-cancel', this.$modal);

        $cancel.click(function(e) {
            e.preventDefault();
            $.modal.close();
        });
    }

});
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

'use strict';

module.exports = {
  opts: {
    readme: './README.md',
    package: './package.json',
    template: './node_modules/jsdoc-fresh',
    recurse: true,
    verbose: true,
    destination: './docs/'
  },
  plugins: [
    'plugins/markdown',
    'jsdoc-region-tag'
  ],
  source: {
    excludePattern: '(^|\\/|\\\\)[._]',
    include: [
      'src',
      'protos'
    ],
    includePattern: '\\.js$'
  },
  templates: {
    copyright: 'Copyright 2019 Google, LLC.',
    includeDate: false,
    sourceFiles: false,
    systemName: 'gtoken',
    theme: 'lumen',
    default: {
      outputSourceFiles: false
    }
  },
  markdown: {
    idInHeadings: true
  }
};
<commit_msg>chore: correct .jsdoc.js protos and double quotes (#274)<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

'use strict';

module.exports = {
  opts: {
    readme: './README.md',
    package: './package.json',
    template: './node_modules/jsdoc-fresh',
    recurse: true,
    verbose: true,
    destination: './docs/'
  },
  plugins: [
    'plugins/markdown',
    'jsdoc-region-tag'
  ],
  source: {
    excludePattern: '(^|\\/|\\\\)[._]',
    include: [
      'src',
    ],
    includePattern: '\\.js$'
  },
  templates: {
    copyright: 'Copyright 2019 Google, LLC.',
    includeDate: false,
    sourceFiles: false,
    systemName: 'gtoken',
    theme: 'lumen',
    default: {
      outputSourceFiles: false
    }
  },
  markdown: {
    idInHeadings: true
  }
};
<|endoftext|>


<commit_before>import isFunction from 'lodash/lang/isFunction';
import isArray from 'lodash/lang/isArray';
import isObject from 'lodash/lang/isObject';
import isString from 'lodash/lang/isString';

import RegisterException from './exceptions/register';

let validate = (controller) => {
  let errors = [];

  // --- VALIDATE NAME -----
  let name = controller.getName();
  if (!name || name.indexOf(' ') != -1) {
    errors.push('controller\'s name could not be empty or contain spaces');
  }

  // --- VALIDATE CONTROLLER CONSTRUCTOR -----
  let Controller = controller.getController(); // :(
  if (!isFunction(Controller)) {
    errors.push('controller should be a constructor');
  }

  return errors;
};

export default class ValentController {
  route = null;

  constructor(name, Controller, options) {
    this.name = name;
    this.options = options;
    this.Controller = Controller;

    let errors = validate(this);
    if (errors.length) {
      throw new RegisterException(name, 'valent-controller', errors);
    }

    if (this.options.url) {
      let routeOptions = this.options.routeOptions || {};

      Object.assign(routeOptions,{
        url:  this.getUrl(),
        struct:  this.getStruct()
      });

      let module = this.options.module;
      if (module) {
        routeOptions.module = module;
      }

      if (this.hasResolvers()) {
        routeOptions.resolve = this.getResolvers();
      }

      if (this.hasTemplate()) {

        // set template
        routeOptions.template = this.getTemplate();
      } else if (this.hasTemplateUrl()) {

        // set templateUrl
        routeOptions.templateUrl = this.getTemplateUrl();
      } else if (this.hasTemplateMethod()) {

        // set template using Components method
        let method = this.getTemplateMethod();
        let template = method(this);

        if (!isString(template)) {
          throw new RuntimeException(name, 'result of Component.render() should be a string');
        }

        routeOptions.template = template;
      }

      valent.route(this.name, this.options.url, routeOptions);
    }
  }

  getName() {
    return this.name;
  }

  getController() {
    return this.Controller;
  }

  hasTemplate() {
    return !!this.options.template;
  }

  getTemplate() {
    return this.options.template;
  }

  hasTemplateUrl() {
    return !!this.options.templateUrl;
  }

  getTemplateUrl() {
    return this.options.templateUrl;
  }

  hasTemplateMethod() {
    return isFunction(this.Controller.render);
  }

  getTemplateMethod() {
    return this.Controller.render;
  }

  withoutTemplate() {
    return !this.hasTemplate() && !this.hasTemplateUrl() && !this.hasTemplateMethod();
  }

  hasUrl() {
    return !!this.options.url || !!this.options.url.length;
  }

  getUrl() {
    return this.options.url;
  }

  getStruct() {
    return this.options.struct || {};
  }

  hasResolvers() {
    return this.options.resolve && !!Object.keys(this.options.resolve).length;
  }

  getResolvers() {
    return this.options.resolve;
  }
}
<commit_msg>Valent controller - RuntimeException -> RegisterException<commit_after>import isFunction from 'lodash/lang/isFunction';
import isArray from 'lodash/lang/isArray';
import isObject from 'lodash/lang/isObject';
import isString from 'lodash/lang/isString';

import RegisterException from './exceptions/register';

let validate = (controller) => {
  let errors = [];

  // --- VALIDATE NAME -----
  let name = controller.getName();
  if (!name || name.indexOf(' ') != -1) {
    errors.push('controller\'s name could not be empty or contain spaces');
  }

  // --- VALIDATE CONTROLLER CONSTRUCTOR -----
  let Controller = controller.getController(); // :(
  if (!isFunction(Controller)) {
    errors.push('controller should be a constructor');
  }

  return errors;
};

export default class ValentController {
  route = null;

  constructor(name, Controller, options) {
    this.name = name;
    this.options = options;
    this.Controller = Controller;

    let errors = validate(this);
    if (errors.length) {
      throw new RegisterException(name, 'valent-controller', errors);
    }

    if (this.options.url) {
      let routeOptions = this.options.routeOptions || {};

      Object.assign(routeOptions,{
        url:  this.getUrl(),
        struct:  this.getStruct()
      });

      let module = this.options.module;
      if (module) {
        routeOptions.module = module;
      }

      if (this.hasResolvers()) {
        routeOptions.resolve = this.getResolvers();
      }

      if (this.hasTemplate()) {

        // set template
        routeOptions.template = this.getTemplate();
      } else if (this.hasTemplateUrl()) {

        // set templateUrl
        routeOptions.templateUrl = this.getTemplateUrl();
      } else if (this.hasTemplateMethod()) {

        // set template using Components method
        let method = this.getTemplateMethod();
        let template = method(this);

        if (!isString(template)) {
          throw new RegisterException(name, 'result of Component.render() should be a string');
        }

        routeOptions.template = template;
      }

      valent.route(this.name, this.options.url, routeOptions);
    }
  }

  getName() {
    return this.name;
  }

  getController() {
    return this.Controller;
  }

  hasTemplate() {
    return !!this.options.template;
  }

  getTemplate() {
    return this.options.template;
  }

  hasTemplateUrl() {
    return !!this.options.templateUrl;
  }

  getTemplateUrl() {
    return this.options.templateUrl;
  }

  hasTemplateMethod() {
    return isFunction(this.Controller.render);
  }

  getTemplateMethod() {
    return this.Controller.render;
  }

  withoutTemplate() {
    return !this.hasTemplate() && !this.hasTemplateUrl() && !this.hasTemplateMethod();
  }

  hasUrl() {
    return !!this.options.url || !!this.options.url.length;
  }

  getUrl() {
    return this.options.url;
  }

  getStruct() {
    return this.options.struct || {};
  }

  hasResolvers() {
    return this.options.resolve && !!Object.keys(this.options.resolve).length;
  }

  getResolvers() {
    return this.options.resolve;
  }
}
<|endoftext|>


<commit_before>// list of mocks that should include *all* plotly.js trace modules

var svgMockList = [
    ['1', require('@mocks/1.json')],
    ['4', require('@mocks/4.json')],
    ['5', require('@mocks/5.json')],
    ['10', require('@mocks/10.json')],
    ['11', require('@mocks/11.json')],
    ['17', require('@mocks/17.json')],
    ['21', require('@mocks/21.json')],
    ['22', require('@mocks/22.json')],
    ['airfoil', require('@mocks/airfoil.json')], // important to keep because it's the only mock with config options
    ['annotations-autorange', require('@mocks/annotations-autorange.json')],
    ['axes_enumerated_ticks', require('@mocks/axes_enumerated_ticks.json')],
    ['axes_visible-false', require('@mocks/axes_visible-false.json')],
    ['bar_and_histogram', require('@mocks/bar_and_histogram.json')],
    ['waterfall', require('@mocks/waterfall_profit-loss_2018_colorscale.json')],
    ['basic_error_bar', require('@mocks/basic_error_bar.json')],
    ['binding', require('@mocks/binding.json')],
    ['cheater_smooth', require('@mocks/cheater_smooth.json')],
    ['finance_style', require('@mocks/finance_style.json')],
    ['geo_first', require('@mocks/geo_first.json')],
    ['layout_image', require('@mocks/layout_image.json')],
    ['layout-colorway', require('@mocks/layout-colorway.json')],
    ['multicategory', require('@mocks/multicategory.json')],
    ['polar_categories', require('@mocks/polar_categories.json')],
    ['polar_direction', require('@mocks/polar_direction.json')],
    ['polar_wind-rose', require('@mocks/polar_wind-rose.json')],
    ['range_selector_style', require('@mocks/range_selector_style.json')],
    ['range_slider_multiple', require('@mocks/range_slider_multiple.json')],
    ['sankey_energy', require('@mocks/sankey_energy.json')],
    ['parcats_bad-displayindex', require('@mocks/parcats_bad-displayindex.json')],
    ['scattercarpet', require('@mocks/scattercarpet.json')],
    ['shapes', require('@mocks/shapes.json')],
    ['splom_iris', require('@mocks/splom_iris.json')],
    ['table_wrapped_birds', require('@mocks/table_wrapped_birds.json')],
    ['ternary_fill', require('@mocks/ternary_fill.json')],
    ['text_chart_arrays', require('@mocks/text_chart_arrays.json')],
    ['transforms', require('@mocks/transforms.json')],
    ['updatemenus', require('@mocks/updatemenus.json')],
    ['violin_side-by-side', require('@mocks/violin_side-by-side.json')],
    ['world-cals', require('@mocks/world-cals.json')],
    ['typed arrays', {
        data: [{
            x: new Float32Array([1, 2, 3]),
            y: new Float32Array([1, 2, 1])
        }]
    }]
];

var glMockList = [
    ['gl2d_heatmapgl', require('@mocks/gl2d_heatmapgl.json')],
    ['gl2d_line_dash', require('@mocks/gl2d_line_dash.json')],
    ['gl2d_parcoords_2', require('@mocks/gl2d_parcoords_2.json')],
    ['gl2d_pointcloud-basic', require('@mocks/gl2d_pointcloud-basic.json')],
    ['gl3d_annotations', require('@mocks/gl3d_annotations.json')],
    ['gl3d_set-ranges', require('@mocks/gl3d_set-ranges.json')],
    ['gl3d_world-cals', require('@mocks/gl3d_world-cals.json')],
    ['gl3d_cone-autorange', require('@mocks/gl3d_cone-autorange.json')],
    ['gl3d_streamtube-simple', require('@mocks/gl3d_streamtube-simple.json')],
    ['glpolar_style', require('@mocks/glpolar_style.json')],
    ['gl3d_isosurface_multiple-traces', require('@mocks/gl3d_isosurface_out_of_iso_range_case.json')]
];

var mapboxMockList = [
    ['scattermapbox', require('@mocks/mapbox_bubbles-text.json')]
];

module.exports = {
    svg: svgMockList,
    gl: glMockList,
    mapbox: mapboxMockList,
    all: svgMockList.concat(glMockList).concat(mapboxMockList)
};
<commit_msg>fixup mock list<commit_after>// list of mocks that should include *all* plotly.js trace modules

var svgMockList = [
    ['1', require('@mocks/1.json')],
    ['4', require('@mocks/4.json')],
    ['5', require('@mocks/5.json')],
    ['10', require('@mocks/10.json')],
    ['11', require('@mocks/11.json')],
    ['17', require('@mocks/17.json')],
    ['21', require('@mocks/21.json')],
    ['22', require('@mocks/22.json')],
    ['airfoil', require('@mocks/airfoil.json')], // important to keep because it's the only mock with config options
    ['annotations-autorange', require('@mocks/annotations-autorange.json')],
    ['axes_enumerated_ticks', require('@mocks/axes_enumerated_ticks.json')],
    ['axes_visible-false', require('@mocks/axes_visible-false.json')],
    ['bar_and_histogram', require('@mocks/bar_and_histogram.json')],
    ['waterfall', require('@mocks/waterfall_profit-loss_2018vs2019_rectangle.json')],
    ['basic_error_bar', require('@mocks/basic_error_bar.json')],
    ['binding', require('@mocks/binding.json')],
    ['cheater_smooth', require('@mocks/cheater_smooth.json')],
    ['finance_style', require('@mocks/finance_style.json')],
    ['geo_first', require('@mocks/geo_first.json')],
    ['layout_image', require('@mocks/layout_image.json')],
    ['layout-colorway', require('@mocks/layout-colorway.json')],
    ['multicategory', require('@mocks/multicategory.json')],
    ['polar_categories', require('@mocks/polar_categories.json')],
    ['polar_direction', require('@mocks/polar_direction.json')],
    ['polar_wind-rose', require('@mocks/polar_wind-rose.json')],
    ['range_selector_style', require('@mocks/range_selector_style.json')],
    ['range_slider_multiple', require('@mocks/range_slider_multiple.json')],
    ['sankey_energy', require('@mocks/sankey_energy.json')],
    ['parcats_bad-displayindex', require('@mocks/parcats_bad-displayindex.json')],
    ['scattercarpet', require('@mocks/scattercarpet.json')],
    ['shapes', require('@mocks/shapes.json')],
    ['splom_iris', require('@mocks/splom_iris.json')],
    ['table_wrapped_birds', require('@mocks/table_wrapped_birds.json')],
    ['ternary_fill', require('@mocks/ternary_fill.json')],
    ['text_chart_arrays', require('@mocks/text_chart_arrays.json')],
    ['transforms', require('@mocks/transforms.json')],
    ['updatemenus', require('@mocks/updatemenus.json')],
    ['violin_side-by-side', require('@mocks/violin_side-by-side.json')],
    ['world-cals', require('@mocks/world-cals.json')],
    ['typed arrays', {
        data: [{
            x: new Float32Array([1, 2, 3]),
            y: new Float32Array([1, 2, 1])
        }]
    }]
];

var glMockList = [
    ['gl2d_heatmapgl', require('@mocks/gl2d_heatmapgl.json')],
    ['gl2d_line_dash', require('@mocks/gl2d_line_dash.json')],
    ['gl2d_parcoords_2', require('@mocks/gl2d_parcoords_2.json')],
    ['gl2d_pointcloud-basic', require('@mocks/gl2d_pointcloud-basic.json')],
    ['gl3d_annotations', require('@mocks/gl3d_annotations.json')],
    ['gl3d_set-ranges', require('@mocks/gl3d_set-ranges.json')],
    ['gl3d_world-cals', require('@mocks/gl3d_world-cals.json')],
    ['gl3d_cone-autorange', require('@mocks/gl3d_cone-autorange.json')],
    ['gl3d_streamtube-simple', require('@mocks/gl3d_streamtube-simple.json')],
    ['glpolar_style', require('@mocks/glpolar_style.json')],
    ['gl3d_isosurface_multiple-traces', require('@mocks/gl3d_isosurface_out_of_iso_range_case.json')]
];

var mapboxMockList = [
    ['scattermapbox', require('@mocks/mapbox_bubbles-text.json')]
];

module.exports = {
    svg: svgMockList,
    gl: glMockList,
    mapbox: mapboxMockList,
    all: svgMockList.concat(glMockList).concat(mapboxMockList)
};
<|endoftext|>


<commit_before>// use this file to automate the running of tests.
var runr     = require('./src/task/runr')
var execa    = require('./src/cli/execa-commands')
var spawn    = require('./src/cli/spawn-commands')
var concur   = require('./src/async/concurrent').each
var painless = require('./src/bin/painless')

function execute (dir) {
  execa([{cmd: './src/bin/painless', args: [`test/${dir}/*.js`]}])
}

function arr () {
  execute('array')
}

function async1 () {
  execute('async')
}

function func () {
  execute('function')
}

function gen () {
  execute('generator')
}

function lang () {
  execute('lang')
}

function num () {
  execute('number')
}

function obj () {
  execute('object')
}

function stamp () {
  execute('stamp')
}

function lint () {
  spawn([
    {cmd: 'node', args: ['lint.js', '-a']}
  ], {cwd: 'array', concurrent: true})

  // spawn([
  //   {cmd: 'node', args: ['lint.js', '-a']}
  // ], {cwd: 'lang', concurrent: true})
}

function defs () {
  arr()
  async1()
  func()
  gen()
  lang()
  num()
  obj()
  stamp()
}

function all () {
  defs()
  lint()
}

runr
  .task('default' , defs)
  .task('arr'     , arr)
  .task('async'   , async1)
  .task('func'    , func)
  .task('gen'     , gen)
  .task('lang'    , lang)
  .task('num'     , num)
  .task('obj'     , obj)
  .task('stamp'   , stamp)
  .task('lint'    , lint)
  .task('all'     , all)
<commit_msg>update test-runner —  pass argv from runr to allow choice. implement ability to lint files in a collection by passing `—-lint` as an argument.<commit_after>// use this file to automate the running of tests.
var runr     = require('./src/task/runr')
var execa    = require('./src/cli/execa-commands')
var spawn    = require('./src/cli/spawn-commands')
var painless = require('./src/bin/painless')

function execute (dir) {
  execa([{cmd: './src/bin/painless', args: [`test/${dir}/*.js`]}], () => {
    if (runr.args.lint) {
      process.nextTick(() => {
        spawn([{cmd: './src/bin/painless', args: [`test/lint/${dir}.js`, '-a']}])
      })
    }
  })
}

function arr () {
  execute('array')
}

function async1 () {
  execute('async')
}

function func () {
  execute('function')
}

function gen () {
  execute('generator')
}

function lang () {
  execute('lang')
}

function num () {
  execute('number')
}

function obj () {
  execute('object')
}

function stamp () {
  execute('stamp')
}

function defs () {
  arr()
  async1()
  func()
  gen()
  lang()
  num()
  obj()
  stamp()
}

function all () {
  defs()
}

runr
  .task('default' , defs)
  .task('arr'     , arr)
  .task('async'   , async1)
  .task('func'    , func)
  .task('gen'     , gen)
  .task('lang'    , lang)
  .task('num'     , num)
  .task('obj'     , obj)
  .task('stamp'   , stamp)
<|endoftext|>


<commit_before><commit_msg>fix wrong usage of affiliation and state in getRooms()<commit_after><|endoftext|>


<commit_before>'use strict'

// (ECHU): Trying a new style for exporting modules.
module.exports = (function() {
  var db = require('../../databases'),
      mysql = require('mysql'),
      config = require('../../config/environment'),
      _ = require('lodash');

  var _search = function(query, size, page) {
    var starting_from = (page - 1) * size;

    return db.elasticsearch.search({
      index: config.elasticsearch.index,
      type: 'entity',
      size: size,
      from: starting_from,
      body: {
        query: {
          match: {
            "_all": query
          }
        }
      }
    }).then(function (body) {
      var hits = body.hits.hits;
      return {status: 200, payload: hits}
      // res.json({
      //   _num: size,
      //   _page: page,
      //   entities: hits
      // })
    }, function (error) {
      return {status: 400, payload: error};
      //res.status(400).json(error);
    });
  }

  var _count = function(query) {
    return db.elasticsearch.count({
      index: config.elasticsearch.index,
      type: 'entity',
      body: {
        query: {
          match: {
            "_all": query
          }
        }
      }
    }).then(function (body) {
      return {status: 200, payload: body.count}
      // res.json({
      //   total: body.count
      // })
    }, function (error) {
      return {status: 400, payload: error}
      //res.status(400).json(error);
    });
  }

  /** _getEntity
   *
   * _getEntity is a private function to get all the ads associated
   * with a given entity. Since the entity contains username fields for
   * the ads added by each user and a `base` field, those ads are
   * concatenated together, sorted, and then sliced before returning.
   *
   * A different solution might attempt to connect directly to the SQL
   * db for pagination instead of the manual one in this case.
   */
  var _getEntity = function(entity_id, size, page) {
    var starting_from = (page - 1) * size;

    return db.elasticsearch.getSource({
      index: config.elasticsearch.index,
      type: 'entity',
      id: entity_id
    }).then(function (source) {
      var ads = [];
      for (var key in source) {
        // other than the 'entity' key, all other keys are lists of ads
        if (key != 'entity') {
          var record = source[key];
          record.user = key;
          ads = ads.concat(record);
        }
      }
      ads.sort();
      return {status: 200, payload: {
        total: ads.length,
        ads: ads.slice(starting_from, starting_from + size)
      }};
    }, function (error) {
      return {status: 400, payload: error};
    });
  }

  /** _update
   *
   * This updates the elasticsearch instance.
   * Takes an entity_id, a username, a blob object, the operation,
   * and the http response object.
   *
   * The operation is one of 'add' or 'remove'.
   */
  var _update = function(entity_id, user, blob, operation, res) {
    var script;
    switch(operation) {
      case 'add':
        script = "if (ctx._source.containsKey(key)) { ctx._source[key] += blob } else { ctx._source[key] = [blob] }";
        break;
      case 'remove':
        script = "if (ctx._source.containsKey(key)) { ctx._source[key] -= blob }";
        break;
      default:
        throw new Error("Invalid operation '"+operation+"' requested.")
    }

    db.elasticsearch.update({
      index: config.elasticsearch.index,
      type: 'entity',
      id: entity_id,
      retryOnConflict: 5,
      body: {
        script: script,
        params: {
          key: user,
          blob: blob
        }
      }
    }).then(function(response) {
      res.json(response)
    }, function(error) {
      return res.status(400).json({error: error});
    })
  }

  var _construct_link = function(entity_id, linker, column_name, reason) {
      return "(SELECT t2.ad_id as id, json, "+mysql.escape(reason)+" as reason " +
        "FROM entities as e "+
        "JOIN "+mysql.escapeId(linker)+" as t1 ON e.ad_id = t1.ad_id " +
        "JOIN "+mysql.escapeId(linker)+" as t2 ON t2."+mysql.escapeId(column_name)+"=t1."+mysql.escapeId(column_name)+" AND NOT t2.ad_id IN (SELECT ad_id from entities where entity_id="+mysql.escape(entity_id)+") " +
        "JOIN ads ON t2.ad_id=ads.id " +
        "WHERE e.entity_id="+mysql.escape(entity_id)+")"
  }

  var search = function(req, res) {
    var number_per_page = req.query.size || 10,
        page = req.query.page || 1,
        count = req.query.count || "no";
    var query_string = req.body.query;
    if (query_string) {
      var search_deferred = _search(query_string, number_per_page, page),
          count_deferred = {status: 200, payload: undefined};
      if (count === "yes") {
        count_deferred = _count(query_string);
      }
      Promise.all([search_deferred, count_deferred])
        .then(function (results) {
          var search_result = results[0],
              count_result = results[1],
              return_result = {_max_num: number_per_page, _page: page};

          // handle any errors
          if (search_result.status == 400) {
            res.status(400).json({error: search_result.payload})
            return
          }
          if (count_result.status == 400) {
            res.status(400).json({error: count_result.payload})
            return
          }

          // merge the two results into one struct
          return_result.entities = search_result.payload;
          return_result.total = count_result.payload;
          res.json(return_result);
      })
    } else {
      res.status(400).json({error: "Expected 'query' in body."})
    }
  }

  var getEntity = function(req, res) {
    var entity_id = req.params.id,
        number_per_page = req.query.size || 10,
        page = req.query.page || 1,
        count = req.query.count || "no";

    _getEntity(entity_id, number_per_page, page)
      .then(function(result) {
        var return_result = {_max_num: number_per_page, _page: page};
        if (result.status == 400) {
          res.status(400).json({error: result.payload})
          return
        }
        return_result.ads = result.payload.ads;
        if (count === "yes") {
          return_result.total = result.payload.total;
        }
        res.json(return_result);
      });
  }

  var attachAd = function(req, res) {
    var entity_id = req.params.id,
        ad_id = req.params.ad_id,
        user = req.query.user || "auto";

    // first, insert into the table
    var query = "INSERT INTO entities (ad_id, entity_id, user) VALUES (?, ?, ?)";
    db.mysql.query(query, [ad_id, entity_id, user], function(err, rows) {
      if (err) {
        return res.status(400).json({error: err});
      }

      // upon a successful insert, let's find the json for the matching ad
      db.mysql.query("SELECT json FROM ads WHERE id=?", ad_id, function(err, rows) {
        if (err) {
          return res.status(400).json({error: err});
        }

        // once we have successfully written into the entities table, we
        // also have to update elasticsearch
        var blob = JSON.parse(rows[0].json);
        _update(entity_id, user, blob, 'add', res);
      });
    });
  }

  var detachAd = function(req, res) {
    var entity_id = req.params.id,
        ad_id = req.params.ad_id,
        user = req.query.user || "auto";

    // first, insert into the table
    var query = "DELETE FROM entities WHERE ad_id=? AND entity_id=? AND user=?";
    db.mysql.query(query, [ad_id, entity_id, user], function(err, rows) {
      if (err) {
        return res.status(400).json({error: err});
      }

      // upon a successful delete, let's find the json for the matching ad
      db.mysql.query("SELECT json FROM ads WHERE id=?", ad_id, function(err, rows) {
        if (err) {
          return res.status(400).json({error: err});
        }

        // once we have successfully deleted from the entities table, we
        // also have to update elasticsearch
        var blob = JSON.parse(rows[0].json);
        _update(entity_id, user, blob, 'remove', res);
      });
    });
  }

  var suggestAd = function(req, res) {
    var entity_id = req.params.id,
        number_per_page = parseInt(req.query.size) || 10,
        page = parseInt(req.query.page) || 1,
        count = req.query.count || "no";
    var starting_from = (page - 1) * number_per_page;

    var query = "SELECT id, json, group_concat(reason) as reasons FROM ("+
      _construct_link(entity_id, 'phone_link', 'phone_id', 'phone') +
      " UNION ALL " +
      _construct_link(entity_id, 'text_link', 'text_id', 'text') +
      ") as t GROUP BY id ORDER BY id LIMIT ?,?"

    var count_query = "SELECT count(distinct id) as total FROM ("+
      _construct_link(entity_id, 'phone_link', 'phone_id', 'phone') +
      " UNION ALL " +
      _construct_link(entity_id, 'text_link', 'text_id', 'text') +
      ") as t"

    db.mysql.query(query, [starting_from, number_per_page], function(err, rows) {
      if (err) {
        return res.status(400).json({error: err});
      }
      var payload = {suggestions: rows}
      if (count === "yes") {
        db.mysql.query(count_query, function(err, rows) {
          payload.total = rows[0].total;
          res.json(payload)
        })
      } else {
        res.json(payload)
      }
    })
  }

  return {
    search: search,
    suggestAd: suggestAd,
    getEntity: getEntity,
    attachAd: attachAd,
    detachAd: detachAd
  }
})();
<commit_msg>added function to find similar images<commit_after>'use strict'

// (ECHU): Trying a new style for exporting modules.
module.exports = (function() {
  var db = require('../../databases'),
      mysql = require('mysql'),
      config = require('../../config/environment'),
      https = require('https'),
      querystring = require('querystring'),
      _ = require('lodash');

  var _search = function(query, size, page) {
    var starting_from = (page - 1) * size;

    return db.elasticsearch.search({
      index: config.elasticsearch.index,
      type: 'entity',
      size: size,
      from: starting_from,
      body: {
        query: {
          match: {
            "_all": query
          }
        }
      }
    }).then(function (body) {
      var hits = body.hits.hits;
      return {status: 200, payload: hits}
      // res.json({
      //   _num: size,
      //   _page: page,
      //   entities: hits
      // })
    }, function (error) {
      return {status: 400, payload: error};
      //res.status(400).json(error);
    });
  }

  var _count = function(query) {
    return db.elasticsearch.count({
      index: config.elasticsearch.index,
      type: 'entity',
      body: {
        query: {
          match: {
            "_all": query
          }
        }
      }
    }).then(function (body) {
      return {status: 200, payload: body.count}
      // res.json({
      //   total: body.count
      // })
    }, function (error) {
      return {status: 400, payload: error}
      //res.status(400).json(error);
    });
  }

  /** _getEntity
   *
   * _getEntity is a private function to get all the ads associated
   * with a given entity. Since the entity contains username fields for
   * the ads added by each user and a `base` field, those ads are
   * concatenated together, sorted, and then sliced before returning.
   *
   * A different solution might attempt to connect directly to the SQL
   * db for pagination instead of the manual one in this case.
   */
  var _getEntity = function(entity_id, size, page) {
    var starting_from = (page - 1) * size;

    return db.elasticsearch.getSource({
      index: config.elasticsearch.index,
      type: 'entity',
      id: entity_id
    }).then(function (source) {
      var ads = [];
      for (var key in source) {
        // other than the 'entity' key, all other keys are lists of ads
        if (key != 'entity') {
          var record = source[key];
          record.user = key;
          ads = ads.concat(record);
        }
      }
      ads.sort();
      return {status: 200, payload: {
        total: ads.length,
        ads: ads.slice(starting_from, starting_from + size)
      }};
    }, function (error) {
      return {status: 400, payload: error};
    });
  }

  /** _update
   *
   * This updates the elasticsearch instance.
   * Takes an entity_id, a username, a blob object, the operation,
   * and the http response object.
   *
   * The operation is one of 'add' or 'remove'.
   */
  var _update = function(entity_id, user, blob, operation, res) {
    var script;
    switch(operation) {
      case 'add':
        script = "if (ctx._source.containsKey(key)) { ctx._source[key] += blob } else { ctx._source[key] = [blob] }";
        break;
      case 'remove':
        script = "if (ctx._source.containsKey(key)) { ctx._source[key] -= blob }";
        break;
      default:
        throw new Error("Invalid operation '"+operation+"' requested.")
    }

    db.elasticsearch.update({
      index: config.elasticsearch.index,
      type: 'entity',
      id: entity_id,
      retryOnConflict: 5,
      body: {
        script: script,
        params: {
          key: user,
          blob: blob
        }
      }
    }).then(function(response) {
      res.json(response)
    }, function(error) {
      return res.status(400).json({error: error});
    })
  }

  var _construct_link = function(entity_id, linker, column_name, reason) {
      return "(SELECT t2.ad_id as id, json, "+mysql.escape(reason)+" as reason " +
        "FROM entities as e "+
        "JOIN "+mysql.escapeId(linker)+" as t1 ON e.ad_id = t1.ad_id " +
        "JOIN "+mysql.escapeId(linker)+" as t2 ON t2."+mysql.escapeId(column_name)+"=t1."+mysql.escapeId(column_name)+" AND NOT t2.ad_id IN (SELECT ad_id from entities where entity_id="+mysql.escape(entity_id)+") " +
        "JOIN ads ON t2.ad_id=ads.id " +
        "WHERE e.entity_id="+mysql.escape(entity_id)+")"
  }

  var _get_json = function(ad_id) {
    if (ad_id) {
      return new Promise(function(resolve, reject) {
        db.mysql.query("SELECT json FROM ads WHERE id=?", ad_id, function(err, rows) {
          if (err) {
            return reject(err)
          }

          // once we have the blob, we'll put it in the response
          var blob = {}
          if (rows.length > 0) {
            blob = JSON.parse(rows[0].json);
          }
          return resolve(blob);
        })
      })
    } else {
      return {}
    }
  }

  var search = function(req, res) {
    var number_per_page = req.query.size || 10,
        page = req.query.page || 1,
        count = req.query.count || "no";
    var query_string = req.body.query;
    if (query_string) {
      var search_deferred = _search(query_string, number_per_page, page),
          count_deferred = {status: 200, payload: undefined};
      if (count === "yes") {
        count_deferred = _count(query_string);
      }
      Promise.all([search_deferred, count_deferred])
        .then(function (results) {
          var search_result = results[0],
              count_result = results[1],
              return_result = {_max_num: number_per_page, _page: page};

          // handle any errors
          if (search_result.status == 400) {
            res.status(400).json({error: search_result.payload})
            return
          }
          if (count_result.status == 400) {
            res.status(400).json({error: count_result.payload})
            return
          }

          // merge the two results into one struct
          return_result.entities = search_result.payload;
          return_result.total = count_result.payload;
          res.json(return_result);
      })
    } else {
      res.status(400).json({error: "Expected 'query' in body."})
    }
  }

  var getEntity = function(req, res) {
    var entity_id = req.params.id,
        number_per_page = req.query.size || 10,
        page = req.query.page || 1,
        count = req.query.count || "no";

    _getEntity(entity_id, number_per_page, page)
      .then(function(result) {
        var return_result = {_max_num: number_per_page, _page: page};
        if (result.status == 400) {
          res.status(400).json({error: result.payload})
          return
        }
        return_result.ads = result.payload.ads;
        if (count === "yes") {
          return_result.total = result.payload.total;
        }
        res.json(return_result);
      });
  }

  var attachAd = function(req, res) {
    var entity_id = req.params.id,
        ad_id = req.params.ad_id,
        user = req.query.user || "auto";

    // first, insert into the table
    var query = "INSERT INTO entities (ad_id, entity_id, user) VALUES (?, ?, ?)";
    db.mysql.query(query, [ad_id, entity_id, user], function(err, rows) {
      if (err) {
        return res.status(400).json({error: err});
      }

      // upon a successful insert, let's find the json for the matching ad
      db.mysql.query("SELECT json FROM ads WHERE id=?", ad_id, function(err, rows) {
        if (err) {
          return res.status(400).json({error: err});
        }

        // once we have successfully written into the entities table, we
        // also have to update elasticsearch
        var blob = JSON.parse(rows[0].json);
        _update(entity_id, user, blob, 'add', res);
      });
    });
  }

  var detachAd = function(req, res) {
    var entity_id = req.params.id,
        ad_id = req.params.ad_id,
        user = req.query.user || "auto";

    // first, insert into the table
    var query = "DELETE FROM entities WHERE ad_id=? AND entity_id=? AND user=?";
    db.mysql.query(query, [ad_id, entity_id, user], function(err, rows) {
      if (err) {
        return res.status(400).json({error: err});
      }

      // upon a successful delete, let's find the json for the matching ad
      _get_json(ad_id).then(
        function(blob) {
          // once we have successfully deleted from the entities table, we
          // also have to update elasticsearch (we need to json to delete
          // the exact object)
          _update(entity_id, user, blob, 'remove', res);
        },
        function(err) {
          return res.status(400).json({error: err});
        });
    });
  }

  var suggestAd = function(req, res) {
    var entity_id = req.params.id,
        number_per_page = parseInt(req.query.size) || 10,
        page = parseInt(req.query.page) || 1,
        count = req.query.count || "no";
    var starting_from = (page - 1) * number_per_page;

    var query = "SELECT id, json, group_concat(reason) as reasons FROM ("+
      _construct_link(entity_id, 'phone_link', 'phone_id', 'phone') +
      " UNION ALL " +
      _construct_link(entity_id, 'text_link', 'text_id', 'text') +
      ") as t GROUP BY id ORDER BY id LIMIT ?,?"

    var count_query = "SELECT count(distinct id) as total FROM ("+
      _construct_link(entity_id, 'phone_link', 'phone_id', 'phone') +
      " UNION ALL " +
      _construct_link(entity_id, 'text_link', 'text_id', 'text') +
      ") as t"

    db.mysql.query(query, [starting_from, number_per_page], function(err, rows) {
      if (err) {
        return res.status(400).json({error: err});
      }
      var payload = {suggestions: rows}
      if (count === "yes") {
        db.mysql.query(count_query, function(err, rows) {
          payload.total = rows[0].total;
          res.json(payload)
        })
      } else {
        res.json(payload)
      }
    })
  }

  var findSimilarImage = function(req, res) {
    var url = req.query.url;
    if (!url) {
      return res.status(400).json({error: "must provide an image URL"})
    }

    var query = {
      url: req.query.url,
      nodup: req.query.nodup,
      num: req.query.num,
      neardup: req.query.neardup,
      neardup_type: req.query.neardup_type,
      visualize: 0
    }

    var s = querystring.stringify(query)

/** !! IMPORTANT !!
 *
 * The isi memexproxy currently serves an invalid cert and thus should
 * be rejected. But in order to actually access the service, we have to
 * ignore the cert. While this offers a secure transport, it does not
 * verify the identity of the server. This can be extremely dangerous!
 *
 * Once ISI fixes this (hopefully), we should set `rejectUnauthorized`
 * to true. The cert is authorized for memexproxy.com and
 * www.memexproxy.com, but not isi.memexproxy.com.
 */
    var options = {
      hostname: 'isi.memexproxy.com',
      path: '/ColumbiaUimgSearch.php?' + s,
      auth: config.imagesearch.user + ":" + config.imagesearch.pass,
      rejectUnauthorized: false
    }

    https.request(options, function(isi_res) {
      var body = '';
      isi_res.on('data', function(chunk) {
        body += chunk;
      });

      isi_res.on('end', function() {
        var result = {}
        if (body) {
          var similar_images = JSON.parse(body)
            .images[0]
            .similar_images;
          Promise.all(_.map(similar_images.ht_ads_id, _get_json)).then(
            function(blobs) {
              // group together image_urls, cached image urls, page urls, and distance
              result = _.map(
                _.zip(
                  similar_images.image_urls,
                  similar_images.cached_image_urls,
                  similar_images.page_urls,
                  similar_images.distance,
                  blobs),
                function(elem) {
                  return {
                    image_urls: elem[0],
                    cached_image_urls: elem[1],
                    page_urls: elem[2],
                    distance: elem[3],
                    ad: elem[4]
                  }
                })
              return res.json(result)
            },
            function(error) {
              return res.status(400).json({error: error})
            });
        }
      });
    }).on('error', function(e) {
      return res.status(400).json({error: e})
    }).end()
  }

  return {
    search: search,
    suggestAd: suggestAd,
    getEntity: getEntity,
    attachAd: attachAd,
    detachAd: detachAd,
    findSimilarImage: findSimilarImage
  }
})();
<|endoftext|>


<commit_before>var growl;
try {
	growl = require('growl');
} catch (e) {
	growl = function() {};
	console.warn('Unable to load the "growl" module, will not define any Growl support.');
}

/** Notifies the user of the result of a Runner evaluation.
*
*@class
*/
var RunnerGrowl = new Class({
	Extends: require('../PromiseView'),

	showFailure: function showFailure() {
		growl('Test failed  :(', { priority: 4 });
	},

	showSuccess: function showSuccess() {
		growl('Test succeeded!  :)', { priority: 3 });
	}
});

module.exports = RunnerGrowl;	// CommonJS export
<commit_msg>Improve Growl view Add failure details Use browser icon<commit_after>var growl;
try {
	growl = require('growl');
} catch (e) {
	growl = function() {};
	console.warn('Unable to load the "growl" module, will not define any Growl support.');
}

/** Notifies the user of the result of a Runner evaluation.
*
*@class
*/
var RunnerGrowl = new Class({
	Extends: require('../PromiseView'),

	showFailure: function showFailure(reason) {
		this.show(reason.toString(), {
			title:		'Test failed',
			priority:	4
		});
	},

	showSuccess: function showSuccess() {
		this.show(this.model.features.length + ' features passed', {
			title: 'Test succeeded'
		});
	},

	show: function show(content, options) {
		var defaults = {
			name:		'Watai',
			image:		this.model.config.driverCapabilities.browserName.capitalize(),
			priority:	3
		};

		growl(content, Object.merge(defaults, options));
	}
});

module.exports = RunnerGrowl;	// CommonJS export
<|endoftext|>


<commit_before>(function(root) {
    'use strict';

    var slice = Array.prototype.slice;

    var Testr = function(group) {
        var tests = {};

        this.group = group;

        this.addTest = function(test, fn) {
            var args = slice.call(arguments, 2);

            if (Testr.type(fn) !== '[object Function]') {
                console.warn('Ignoring non-callable test "' + test + '"');
            } else {
                tests[test] = function() {
                    return fn.apply(null, args);
                };
            }
        };

        this.run = function() {
            var results = {},
                test;

            for(test in tests) {
                try {
                    results[test] = tests[test]() ? 'pass' : 'fail';
                } catch(e) {
                    results[test] = 'error';
                    console.error(e.name + ' in test "' + test + '" : ' + e.message);
                }
            }

            return results;
        };

        this.report = function() {
            var results = this.run(),
                container = document.createElement('div'),
                reportdiv = document.createElement('div'),
                title = document.createElement('h1'),
                result,
                resultdiv;

            reportdiv.className = 'report';
            title.innerHTML = this.group;

            for(result in results) {
                resultdiv = document.createElement('div');
                resultdiv.className = 'result ' + results[result];
                resultdiv.innerHTML = result;
                reportdiv.appendChild(resultdiv);
            }

            container.appendChild(title);
            container.appendChild(reportdiv);

            return container;
        };
    };

    // See http://wiki.ecmascript.org/doku.php?id=harmony:egal
    Testr.egal = function(x, y) {
        if (x === y) {
            // 0 === -0, but they are not identical
            return x !== 0 || 1 / x === 1 / y;
        }

        // NaN !== NaN, but they are identical.
        // NaNs are the only non-reflexive value, i.e., if x !== x,
        // then x is a NaN.
        // isNaN is broken: it converts its argument to number, so
        // isNaN("foo") => true
        return x !== x && y !== y;
    };

    Testr.is = Testr.egal;

    Testr.isnt = function(x, y) {
        return !Testr.is(x, y);
    };

    Testr.type = function(obj) {
        return Object.prototype.toString.call(obj);
    };

    Testr.isArguments = function(obj) {
        return Testr.type(obj) == '[object Arguments]';
    };

    Testr.isArray = function(obj) {
        return Testr.type(obj) == '[object Array]';
    };

    Testr.isBoolean = function(obj) {
        return Testr.type(obj) == '[object Boolean]';
    };

    Testr.isDate = function(obj) {
        return Testr.type(obj) == '[object Date]';
    };

    Testr.isFunction = function(obj) {
        return Testr.type(obj) == '[object Function]';
    };

    Testr.isNaN = function(obj) {
        return obj !== obj;
    };

    Testr.isNull = function(obj) {
        return obj === null;
    };

    Testr.isNumber = function(obj) {
        return Testr.type(obj) == '[object Number]';
    };

    Testr.isRegExp = function(obj) {
        return Testr.type(obj) == '[object RegExp]';
    };

    Testr.isString = function(obj) {
        return Testr.type(obj) == '[object String]';
    };

    Testr.isUndefined = function(obj) {
        return obj === void 0;
    };

    root.Testr = Testr;

})(this, undefined);
<commit_msg>Removed type check when adding tests<commit_after>(function(root) {
    'use strict';

    var slice = Array.prototype.slice;

    var Testr = function(group) {
        var tests = {};

        this.group = group;

        this.addTest = function(test, fn) {
            var args = slice.call(arguments, 2);

            tests[test] = function() {
                return fn.apply(null, args);
            };
        };

        this.run = function() {
            var results = {},
                test;

            for(test in tests) {
                try {
                    results[test] = tests[test]() ? 'pass' : 'fail';
                } catch(e) {
                    results[test] = 'error';
                    console.error(e.name + ' in test "' + test + '" : ' + e.message);
                }
            }

            return results;
        };

        this.report = function() {
            var results = this.run(),
                container = document.createElement('div'),
                reportdiv = document.createElement('div'),
                title = document.createElement('h1'),
                result,
                resultdiv;

            reportdiv.className = 'report';
            title.innerHTML = this.group;

            for(result in results) {
                resultdiv = document.createElement('div');
                resultdiv.className = 'result ' + results[result];
                resultdiv.innerHTML = result;
                reportdiv.appendChild(resultdiv);
            }

            container.appendChild(title);
            container.appendChild(reportdiv);

            return container;
        };
    };

    // See http://wiki.ecmascript.org/doku.php?id=harmony:egal
    Testr.egal = function(x, y) {
        if (x === y) {
            // 0 === -0, but they are not identical
            return x !== 0 || 1 / x === 1 / y;
        }

        // NaN !== NaN, but they are identical.
        // NaNs are the only non-reflexive value, i.e., if x !== x,
        // then x is a NaN.
        // isNaN is broken: it converts its argument to number, so
        // isNaN("foo") => true
        return x !== x && y !== y;
    };

    Testr.is = Testr.egal;

    Testr.isnt = function(x, y) {
        return !Testr.is(x, y);
    };

    Testr.type = function(obj) {
        return Object.prototype.toString.call(obj);
    };

    Testr.isArguments = function(obj) {
        return Testr.type(obj) == '[object Arguments]';
    };

    Testr.isArray = function(obj) {
        return Testr.type(obj) == '[object Array]';
    };

    Testr.isBoolean = function(obj) {
        return Testr.type(obj) == '[object Boolean]';
    };

    Testr.isDate = function(obj) {
        return Testr.type(obj) == '[object Date]';
    };

    Testr.isFunction = function(obj) {
        return Testr.type(obj) == '[object Function]';
    };

    Testr.isNaN = function(obj) {
        return obj !== obj;
    };

    Testr.isNull = function(obj) {
        return obj === null;
    };

    Testr.isNumber = function(obj) {
        return Testr.type(obj) == '[object Number]';
    };

    Testr.isRegExp = function(obj) {
        return Testr.type(obj) == '[object RegExp]';
    };

    Testr.isString = function(obj) {
        return Testr.type(obj) == '[object String]';
    };

    Testr.isUndefined = function(obj) {
        return obj === void 0;
    };

    root.Testr = Testr;

})(this, undefined);
<|endoftext|>


<commit_before>import axios from 'axios'

	const BASE_URL="http://0.0.0.0:3000/"
  const COMPONENTS_READ ="w_components"

export default {

  getData(url, config={}, responseBehavior = (response) => response.data){
    return axios
      .get(url, config)
      .then(responseBehavior)
      .catch((error) => this.onError(error))
  },
  urlBuilder(apiurl,params){
    return `${BASE_URL}${apiurl}${this.paramsToUrl(params)}`
  },
  paramsToUrl(params){
    return Object.keys(params).reduce( (acc, pk) => `${acc}${pk}=${params[pk]}&` , '?')
  },
  configForRange(from,to){
    let conf = {
      headers:
      {
        'Prefer': 'count=exact',
        'Range-Unit': 'w_components',
        'Range': `${from}-${to}`
      }
    }
    return conf
  },
  configForSingleObject(){
    let conf = {
      headers: {
        'Accept': 'application/vnd.pgrst.object+json'
      }
    }
    return conf
  },
  constructResponseAsPage(response){
    const [current,total] = response.headers['content-range'].split('/')
    const [to, from] = current.split('-')
    const page = {from, to, total: Number(total), content: response.data}
    return page
  },

  //TODO move search serverside, then we will not have to fetch the full component list anymore
  //currently we are getting in the headers only with information necessary to search
  fetchTechComponents() {
    return this.getData(this.urlBuilder(COMPONENTS_READ, {select: 'uid,name,status,tags'}))
  },
  fetchTechComponentsHeadersPage(from=0, to=10){
    return this.getData(
      this.urlBuilder(COMPONENTS_READ, {select: 'name,status,tags'}),
      this.configForRange(from, to),
      this.constructResponseAsPage)
  },
  fetchTechComponentDetails(id) {
    return this.getData(
      this.urlBuilder(COMPONENTS_READ, {uid:`eq.${id}`}),
      this.configForSingleObject())
  },
  fetchTechComponentsSize() {
    return this.getData(
      this.urlBuilder(COMPONENTS_READ, {select: 'name'}),
      this.configForRange(0,0),
      (response) => {
        console.log(`We are interested in ${response.headers['content-range']} `)
        const [current,total] = response.headers['content-range'].split('/')
        return Number(total)
      })
  },

  fetchMeritocracy () {
  	return this.notImplemented("fetchMeritocracy")
  },

  fetchServices () {
  	return this.notImplemented("fetchServices")
  },

  fetchTaxonomy () {
    let config = {headers: {'Accept': 'application/vnd.pgrst.object+json'}}

  	 return axios
      .get(`${BASE_URL}w_taxonomy`, config)
      .then(response => response.data)
      .catch((error) => onError(error))
  },
  fetchUsecases () {
    return this.getData('w_usecases')
  },

  editTechComponent(techComponent){
      return this.notImplemented("editTechComponent")
  },
  createTechComponent(techComponent){
    return this.notImplemented("createTechComponent")
  },

  notImplemented(name){
    console.log(`Not implemented ${name} in the backend - returning empty data`)
    return new Promise((resolve) => {
      resolve([])
    })
  },

  onError( error ){
    console.log(`Application encountered an error when communicating with backend:\n${error.message}`)
    if (error.response) {
      console.log('>>> error in response >>>')
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
      this.$router.push({name: 'not-found', params: {code: error.response.status, asset: url}})
    } else if (error.request) {
      console.log('>>> error in request >>>')
       console.log(error.request)
       this.$router.push({name: 'not-found', params: {code: error.request.status, asset: url}})
    } else {
      console.log('Something happened in setting up the request that triggered an Error')
      this.$router.push({name: 'error', params: {code: 500}})

    }
  }
}
<commit_msg>added post call to api<commit_after>import axios from 'axios'

	const BASE_URL="http://0.0.0.0:3000/"
  const COMPONENTS_READ ="w_components"

export default {

  getData(url, config={}, responseBehavior = (response) => response.data){
    return axios
      .get(url, config)
      .then(responseBehavior)
      .catch((error) => this.onError(error))
  },
  postData(url, toPost){
    return axios
      .post( url, toPost)
      .then( (response) => {console.log(response.data); return response.data})
      .catch( (error) => this.onError(error))
  },
  urlBuilder(apiurl,params){
    return `${BASE_URL}${apiurl}${this.paramsToUrl(params)}`
  },
  paramsToUrl(params){
    return Object.keys(params).reduce( (acc, pk) => `${acc}${pk}=${params[pk]}&` , '?')
  },
  configForRange(from,to){
    let conf = {
      headers:
      {
        'Prefer': 'count=exact',
        'Range-Unit': 'w_components',
        'Range': `${from}-${to}`
      }
    }
    return conf
  },
  configForSingleObject(){
    let conf = {
      headers: {
        'Accept': 'application/vnd.pgrst.object+json'
      }
    }
    return conf
  },
  configForResponseOnChange(){
    const conf = {
      headers: {
        'Prefer': 'return=representation'
      }
    }
    return conf
  },
  constructResponseAsPage(response){
    const [current,total] = response.headers['content-range'].split('/')
    const [to, from] = current.split('-')
    const page = {from, to, total: Number(total), content: response.data}
    return page
  },

  //TODO move search serverside, then we will not have to fetch the full component list anymore
  //currently we are getting in the headers only with information necessary to search
  fetchTechComponents() {
    return this.getData(this.urlBuilder(COMPONENTS_READ, {select: 'uid,name,status,tags'}))
  },
  fetchTechComponentsHeadersPage(from=0, to=10){
    return this.getData(
      this.urlBuilder(COMPONENTS_READ, {select: 'name,status,tags'}),
      this.configForRange(from, to),
      this.constructResponseAsPage)
  },
  fetchTechComponentDetails(id) {
    return this.getData(
      this.urlBuilder(COMPONENTS_READ, {uid:`eq.${id}`}),
      this.configForSingleObject())
  },
  fetchTechComponentsSize() {
    return this.getData(
      this.urlBuilder(COMPONENTS_READ, {select: 'name'}),
      this.configForRange(0,0),
      (response) => {
        console.log(`We are interested in ${response.headers['content-range']} `)
        const [current,total] = response.headers['content-range'].split('/')
        return Number(total)
      })
  },

  fetchMeritocracy () {
  	return this.notImplemented("fetchMeritocracy")
  },

  fetchServices () {
  	return this.notImplemented("fetchServices")
  },

  fetchTaxonomy () {
    let config = {headers: {'Accept': 'application/vnd.pgrst.object+json'}}

  	 return axios
      .get(`${BASE_URL}w_taxonomy`, config)
      .then(response => response.data)
      .catch((error) => onError(error))
  },
  fetchUsecases () {
    return this.getData('w_usecases')
  },

  editTechComponent(techComponent){
      return this.postData(this.urlBuilder(COMPONENTS_READ), techComponent, configForResponseOnChange())
  },
  createTechComponent(techComponent){
    return this.notImplemented("createTechComponent")
  },

  notImplemented(name){
    console.log(`Not implemented ${name} in the backend - returning empty data`)
    return new Promise((resolve) => {
      resolve([])
    })
  },

  onError( error ){
    console.log(`Application encountered an error when communicating with backend:\n${error.message}`)
    if (error.response) {
      console.log('>>> error in response >>>')
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
      this.$router.push({name: 'not-found', params: {code: error.response.status, asset: url}})
    } else if (error.request) {
      console.log('>>> error in request >>>')
       console.log(error.request)
       this.$router.push({name: 'not-found', params: {code: error.request.status, asset: url}})
    } else {
      console.log('Something happened in setting up the request that triggered an Error')
      this.$router.push({name: 'error', params: {code: 500}})

    }
  }
}
<|endoftext|>


<commit_before><commit_msg>Fix linting issues for 014489c489c57b394e25e22a2e2017e439bb39f4<commit_after><|endoftext|>