<commit_before>// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2009 by Doug Kearns <dougkearns@gmail.com>
// Copyright (c) 2008-2009 by Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the License.txt file included with this file.

/** @scope modules */

/**
 * @instance browser
 */
const Browser = Module("browser", {
}, {
    // TODO: support 'nrformats'? -> probably not worth it --mst
    incrementURL: function (count) {
        let matches = buffer.URL.match(/(.*?)(\d+)(\D*)$/);
        liberator.assert(matches);

        let [, pre, number, post] = matches;
        let newNumber = parseInt(number, 10) + count;
        let newNumberStr = String(newNumber > 0 ? newNumber : 0);
        if (number.match(/^0/)) { // add 0009<C-a> should become 0010
            while (newNumberStr.length < number.length)
                newNumberStr = "0" + newNumberStr;
        }

        liberator.open(pre + newNumberStr + post);
    }
}, {
    options: function () {
        options.add(["encoding", "enc"],
            "Sets the current buffer's character encoding",
            "string", "UTF-8",
            {
                scope: Option.SCOPE_LOCAL,
                getter: function () config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset,
                setter: function (val) {
                    if (options["encoding"] == val)
                        return val;

                    // Stolen from browser.jar/content/browser/browser.js, more or less.
                    try {
                        config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset = val;
                        PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, val);
                        getWebNavigation().reload(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
                    }
                    catch (e) { liberator.reportError(e); }
                    return null;
                },
                completer: function (context) completion.charset(context)
            });

        // only available in FF 3.5+
        if (services.get("privateBrowsing")) {
            options.add(["private", "pornmode"],
                "Set the 'private browsing' option",
                "boolean", false,
                {
                    setter: function (value) services.get("privateBrowsing").privateBrowsingEnabled = value,
                    getter: function () services.get("privateBrowsing").privateBrowsingEnabled
                });
            let services = modules.services; // Storage objects are global to all windows, 'modules' isn't.
            storage.newObject("private-mode", function () {
                ({
                    init: function () {
                        services.get("observer").addObserver(this, "private-browsing", false);
                        services.get("observer").addObserver(this, "quit-application", false);
                        this.private = services.get("privateBrowsing").privateBrowsingEnabled;
                    },
                    observe: function (subject, topic, data) {
                        if (topic == "private-browsing") {
                            if (data == "enter")
                                storage.privateMode = true;
                            else if (data == "exit")
                                storage.privateMode = false;
                            storage.fireEvent("private-mode", "change", storage.privateMode);
                        }
                        else if (topic == "quit-application") {
                            services.get("observer").removeObserver(this, "quit-application");
                            services.get("observer").removeObserver(this, "private-browsing");
                        }
                    }
                }).init();
            }, { store: false });
            storage.addObserver("private-mode",
                function (key, event, value) {
                    autocommands.trigger("PrivateMode", { state: value });
                }, window);
        }

        options.add(["urlseparator"],
            "Set the separator regex used to separate multiple URL args",
            "string", ",\\s");
    },

    mappings: function () {
        mappings.add([modes.NORMAL],
            ["y"], "Yank current location to the clipboard",
            function () { util.copyToClipboard(util.losslessDecodeURI(buffer.URL, 'conservative'), true); });

        // opening websites
        mappings.add([modes.NORMAL],
            ["o"], "Open one or more URLs",
            function () { commandline.open("", "open ", modes.EX); });

        mappings.add([modes.NORMAL], ["O"],
            "Open one or more URLs, based on current location",
            function () { commandline.open("", "open " + util.losslessDecodeURI(buffer.URL), modes.EX); });

        mappings.add([modes.NORMAL], ["t"],
            "Open one or more URLs in a new tab",
            function () { commandline.open("", "tabopen ", modes.EX); });

        mappings.add([modes.NORMAL], ["T"],
            "Open one or more URLs in a new tab, based on current location",
            function () { commandline.open("", "tabopen " + util.losslessDecodeURI(buffer.URL), modes.EX); });

        mappings.add([modes.NORMAL], ["w"],
            "Open one or more URLs in a new window",
            function () { commandline.open("", "winopen ", modes.EX); });

        mappings.add([modes.NORMAL], ["W"],
            "Open one or more URLs in a new window, based on current location",
            function () { commandline.open("", "winopen " + util.losslessDecodeURI(buffer.URL), modes.EX); });

        mappings.add([modes.NORMAL],
            ["<C-a>"], "Increment last number in URL",
            function (count) { Browser.incrementURL(Math.max(count, 1)); },
            { count: true });

        mappings.add([modes.NORMAL],
            ["<C-x>"], "Decrement last number in URL",
            function (count) { Browser.incrementURL(-Math.max(count, 1)); },
            { count: true });

        mappings.add([modes.NORMAL], ["~"],
            "Open home directory",
            function () { liberator.open("~"); });

        mappings.add([modes.NORMAL], ["gh"],
            "Open homepage",
            function () { BrowserHome(); });

        mappings.add([modes.NORMAL], ["gH"],
            "Open homepage in a new tab",
            function () {
                let homepages = gHomeButton.getHomePage();
                homepages = homepages.replace(/\|/g, options["urlseperator"] || ", "); // we use a different url seperator than Firefox
                liberator.open(homepages, { from: "homepage", where: liberator.NEW_TAB });
            });

        mappings.add([modes.NORMAL], ["gu"],
            "Go to parent directory",
            function (count) {
                function getParent(url, count) {
                    function getParentPath(path) {
                        if (!path)
                            return;

                        path = path.replace(/\/$/, "").replace(/^\/+/, "");
                        if (path.indexOf("#") > 0)
                            return path.replace(/#.*/, "");

                        if (path.indexOf("?") > 0)
                            return path.replace(/\?.*/, "");

                        path = path.replace(/\/+$/, "");
                        if (path.indexOf("/") > 0)
                            return path.replace(/\/[^\/]*$/,"/");
                    }

                    function getParentHost(host) {
                        if (!/\./.test(host) || /^[0-9+.:]+$/.test(host))
                            return host;

                        let hostSuffix = "";
                        let x = host.lastIndexOf(":");
                        if (x > 0) {
                            hostSuffix = host.substr(x);
                            host = host.substr(0, x);
                        }
                        hostSuffix = host.substr(host.length - 6) + hostSuffix;
                        host = host.substr(0, host.length - 6);
                        return host.replace(/[^.]*\./, "") + hostSuffix;
                    }

                    let parent = url;
                    let regexp = new RegExp("([a-z]+:///?)([^/]*)(/.*)");
                    let [, scheme, host, path] = regexp.exec(url);
                    path = path.replace(/\/$/, "").replace(/^\/+/, "");
                    for (let i = 0; i < count; i++) {
                        if (path) {
                            if (path = getParentPath(path))
                                parent = scheme + host + "/" + path;
                            else
                                parent = scheme + host + "/";
                        }
                        else {
                            host = getParentHost(host);
                            parent = scheme + host + "/";
                        }
                    }
                    return parent;
                }

                if (count < 1)
                    count = 1;
                let url = getParent(buffer.URL, count);

                if (url == buffer.URL)
                    liberator.beep();
                else
                    liberator.open(url);
            },
            { count: true });

        mappings.add([modes.NORMAL], ["gU"],
            "Go to the root of the website",
            function () {
                let uri = content.document.location;
                liberator.assert(!/(about|mailto):/.test(uri.protocol)); // exclude these special protocols for now
                liberator.open(uri.protocol + "//" + (uri.host || "") + "/");
            });
    },

    commands: function () {
        commands.add(["downl[oads]", "dl"],
            "Show progress of current downloads",
            function () {
                liberator.open("chrome://mozapps/content/downloads/downloads.xul",
                    { from: "downloads"});
            },
            { argCount: "0" });

        commands.add(["o[pen]"],
            "Open one or more URLs in the current tab",
            function (args) {
                args = args.string;

                if (args)
                    liberator.open(args);
                else
                    liberator.open("about:blank");
            }, {
                completer: function (context) completion.url(context),
                literal: 0,
                privateData: true
            });
    }
});

// vim: set fdm=marker sw=4 ts=4 et:
<commit_msg>fix typo. Thanks Rob<commit_after>// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2009 by Doug Kearns <dougkearns@gmail.com>
// Copyright (c) 2008-2009 by Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the License.txt file included with this file.

/** @scope modules */

/**
 * @instance browser
 */
const Browser = Module("browser", {
}, {
    // TODO: support 'nrformats'? -> probably not worth it --mst
    incrementURL: function (count) {
        let matches = buffer.URL.match(/(.*?)(\d+)(\D*)$/);
        liberator.assert(matches);

        let [, pre, number, post] = matches;
        let newNumber = parseInt(number, 10) + count;
        let newNumberStr = String(newNumber > 0 ? newNumber : 0);
        if (number.match(/^0/)) { // add 0009<C-a> should become 0010
            while (newNumberStr.length < number.length)
                newNumberStr = "0" + newNumberStr;
        }

        liberator.open(pre + newNumberStr + post);
    }
}, {
    options: function () {
        options.add(["encoding", "enc"],
            "Sets the current buffer's character encoding",
            "string", "UTF-8",
            {
                scope: Option.SCOPE_LOCAL,
                getter: function () config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset,
                setter: function (val) {
                    if (options["encoding"] == val)
                        return val;

                    // Stolen from browser.jar/content/browser/browser.js, more or less.
                    try {
                        config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset = val;
                        PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, val);
                        getWebNavigation().reload(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
                    }
                    catch (e) { liberator.reportError(e); }
                    return null;
                },
                completer: function (context) completion.charset(context)
            });

        // only available in FF 3.5+
        if (services.get("privateBrowsing")) {
            options.add(["private", "pornmode"],
                "Set the 'private browsing' option",
                "boolean", false,
                {
                    setter: function (value) services.get("privateBrowsing").privateBrowsingEnabled = value,
                    getter: function () services.get("privateBrowsing").privateBrowsingEnabled
                });
            let services = modules.services; // Storage objects are global to all windows, 'modules' isn't.
            storage.newObject("private-mode", function () {
                ({
                    init: function () {
                        services.get("observer").addObserver(this, "private-browsing", false);
                        services.get("observer").addObserver(this, "quit-application", false);
                        this.private = services.get("privateBrowsing").privateBrowsingEnabled;
                    },
                    observe: function (subject, topic, data) {
                        if (topic == "private-browsing") {
                            if (data == "enter")
                                storage.privateMode = true;
                            else if (data == "exit")
                                storage.privateMode = false;
                            storage.fireEvent("private-mode", "change", storage.privateMode);
                        }
                        else if (topic == "quit-application") {
                            services.get("observer").removeObserver(this, "quit-application");
                            services.get("observer").removeObserver(this, "private-browsing");
                        }
                    }
                }).init();
            }, { store: false });
            storage.addObserver("private-mode",
                function (key, event, value) {
                    autocommands.trigger("PrivateMode", { state: value });
                }, window);
        }

        options.add(["urlseparator"],
            "Set the separator regex used to separate multiple URL args",
            "string", ",\\s");
    },

    mappings: function () {
        mappings.add([modes.NORMAL],
            ["y"], "Yank current location to the clipboard",
            function () { util.copyToClipboard(util.losslessDecodeURI(buffer.URL, 'conservative'), true); });

        // opening websites
        mappings.add([modes.NORMAL],
            ["o"], "Open one or more URLs",
            function () { commandline.open("", "open ", modes.EX); });

        mappings.add([modes.NORMAL], ["O"],
            "Open one or more URLs, based on current location",
            function () { commandline.open("", "open " + util.losslessDecodeURI(buffer.URL), modes.EX); });

        mappings.add([modes.NORMAL], ["t"],
            "Open one or more URLs in a new tab",
            function () { commandline.open("", "tabopen ", modes.EX); });

        mappings.add([modes.NORMAL], ["T"],
            "Open one or more URLs in a new tab, based on current location",
            function () { commandline.open("", "tabopen " + util.losslessDecodeURI(buffer.URL), modes.EX); });

        mappings.add([modes.NORMAL], ["w"],
            "Open one or more URLs in a new window",
            function () { commandline.open("", "winopen ", modes.EX); });

        mappings.add([modes.NORMAL], ["W"],
            "Open one or more URLs in a new window, based on current location",
            function () { commandline.open("", "winopen " + util.losslessDecodeURI(buffer.URL), modes.EX); });

        mappings.add([modes.NORMAL],
            ["<C-a>"], "Increment last number in URL",
            function (count) { Browser.incrementURL(Math.max(count, 1)); },
            { count: true });

        mappings.add([modes.NORMAL],
            ["<C-x>"], "Decrement last number in URL",
            function (count) { Browser.incrementURL(-Math.max(count, 1)); },
            { count: true });

        mappings.add([modes.NORMAL], ["~"],
            "Open home directory",
            function () { liberator.open("~"); });

        mappings.add([modes.NORMAL], ["gh"],
            "Open homepage",
            function () { BrowserHome(); });

        mappings.add([modes.NORMAL], ["gH"],
            "Open homepage in a new tab",
            function () {
                let homepages = gHomeButton.getHomePage();
                homepages = homepages.replace(/\|/g, options["urlseparator"] || ", "); // we use a different url seperator than Firefox
                liberator.open(homepages, { from: "homepage", where: liberator.NEW_TAB });
            });

        mappings.add([modes.NORMAL], ["gu"],
            "Go to parent directory",
            function (count) {
                function getParent(url, count) {
                    function getParentPath(path) {
                        if (!path)
                            return;

                        path = path.replace(/\/$/, "").replace(/^\/+/, "");
                        if (path.indexOf("#") > 0)
                            return path.replace(/#.*/, "");

                        if (path.indexOf("?") > 0)
                            return path.replace(/\?.*/, "");

                        path = path.replace(/\/+$/, "");
                        if (path.indexOf("/") > 0)
                            return path.replace(/\/[^\/]*$/,"/");
                    }

                    function getParentHost(host) {
                        if (!/\./.test(host) || /^[0-9+.:]+$/.test(host))
                            return host;

                        let hostSuffix = "";
                        let x = host.lastIndexOf(":");
                        if (x > 0) {
                            hostSuffix = host.substr(x);
                            host = host.substr(0, x);
                        }
                        hostSuffix = host.substr(host.length - 6) + hostSuffix;
                        host = host.substr(0, host.length - 6);
                        return host.replace(/[^.]*\./, "") + hostSuffix;
                    }

                    let parent = url;
                    let regexp = new RegExp("([a-z]+:///?)([^/]*)(/.*)");
                    let [, scheme, host, path] = regexp.exec(url);
                    path = path.replace(/\/$/, "").replace(/^\/+/, "");
                    for (let i = 0; i < count; i++) {
                        if (path) {
                            if (path = getParentPath(path))
                                parent = scheme + host + "/" + path;
                            else
                                parent = scheme + host + "/";
                        }
                        else {
                            host = getParentHost(host);
                            parent = scheme + host + "/";
                        }
                    }
                    return parent;
                }

                if (count < 1)
                    count = 1;
                let url = getParent(buffer.URL, count);

                if (url == buffer.URL)
                    liberator.beep();
                else
                    liberator.open(url);
            },
            { count: true });

        mappings.add([modes.NORMAL], ["gU"],
            "Go to the root of the website",
            function () {
                let uri = content.document.location;
                liberator.assert(!/(about|mailto):/.test(uri.protocol)); // exclude these special protocols for now
                liberator.open(uri.protocol + "//" + (uri.host || "") + "/");
            });
    },

    commands: function () {
        commands.add(["downl[oads]", "dl"],
            "Show progress of current downloads",
            function () {
                liberator.open("chrome://mozapps/content/downloads/downloads.xul",
                    { from: "downloads"});
            },
            { argCount: "0" });

        commands.add(["o[pen]"],
            "Open one or more URLs in the current tab",
            function (args) {
                args = args.string;

                if (args)
                    liberator.open(args);
                else
                    liberator.open("about:blank");
            }, {
                completer: function (context) completion.url(context),
                literal: 0,
                privateData: true
            });
    }
});

// vim: set fdm=marker sw=4 ts=4 et:
<|endoftext|>


<commit_before>var chai = require('chai');
var assert = chai.assert;

describe('foo', function() {
  it('should bar', function() {
    var alternativeFacts = false;
    assert.isFalse(alternativeFacts);
  });
});
<commit_msg>Testing node_env on travis<commit_after>var chai = require('chai');
var assert = chai.assert;

describe('foo', function() {
  it('should bar', function() {
    var alternativeFacts = false;
    assert.isFalse(alternativeFacts);
  });
  it('BAD UNIT TEST - should have node_env', function() {
    // BAD
    assert.equal(process.env.NODE_ENV, 'TESTING123');
  })
});
<|endoftext|>


<commit_before>import React from 'react'
import sinon from 'sinon'
import { shallow } from 'enzyme'
import { expect } from 'chai'

import { MatchShareWrapper } from './MatchShareWrapper'

describe('MatchShareWrapper', () => {
  let wrapper
  let sandbox
  let spy = {}
  let params = { id: 65, widget_id: 96 }
  let matches = {
    data: {
      first_choice: 'Foo Choice',
      second_choice: 'Bar Choice',
      goal_image: 'foo-bar-image.jpg'
    }
  }
  let props = { matches, params }
  let store = {
    getState() { return matches },
    subscribe: sinon.spy(),
    dispatch: sinon.spy()
  }
  let context = { store }

  before(() => {
    sandbox = sinon.sandbox.create()
    wrapper = shallow(<MatchShareWrapper { ...props } />)
  })

  afterEach(() => {
    sandbox.restore()
  })

  describe('#render', () => {
    before(() => {
      spy.metaData = sandbox.spy(MatchShareWrapper.prototype, 'metaData')
    })

    it('should render one empty  component', () => {
      expect(wrapper.html()).to.equal('')
    })
    it('should calls metaData method', () => {
      expect(spy.metaData).to.have.been.called
    })
  })

  describe('#metaData', () => {
    describe('meta objects', () => {
      const result = MatchShareWrapper.prototype.metaData(props)

      it('should have meta prop', () => {
        expect(result).to.have.key('meta')
      })
      it('meta prop should be an object', () => {
        expect(result.meta).to.be.an.object
      })
      it('should have name prop inside meta object', () => {
        expect(result.meta).to.have.key('name')
      })
      it('name prop should be an object', () => {
        expect(result.meta.name).to.be.an.object
      })
      it('should have all required props inside name prop', () => {
        const keys = ['og:title', 'og:description', 'og:image']
        expect(result.meta.name).to.have.all.keys(keys)
      })
      it('og:title prop should be concatenation of first and second choices', () => {
        const expected = `${matches.data.first_choice} + ${matches.data.second_choice}`
        expect(result.meta.name['og:title']).to.equal(expected)
      })
      it('og:description prop should be equal as passed', () => {
        const expected = 'Subtítulo deve ser configurável.'
        expect(result.meta.name['og:description']).to.equal(expected)
      })
      it('og:image prop should be equal as passed', () => {
        expect(result.meta.name['og:image']).to.equal(matches.data.goal_image)
      })
    })
  })

  describe('#fetchData', () => {
    const result = MatchShareWrapper.fetchData(store, params)

    it('should returns resolved promises', () => {
      expect(result.constructor).to.be.a.Promise
    })
  })
})
<commit_msg>Fix MatchShareWrapper tests.<commit_after>import React from 'react'
import sinon from 'sinon'
import { shallow } from 'enzyme'
import { expect } from 'chai'

import { MatchShareWrapper } from './MatchShareWrapper'

describe('MatchShareWrapper', () => {
  let wrapper
  let sandbox
  let spy = {}
  let params = { id: 65, widget_id: 96 }
  let matches = {
    data: {
      first_choice: 'Foo Choice',
      second_choice: 'Bar Choice',
      goal_image: 'foo-bar-image.jpg',
      widget_title: "Foo Bar Widget Title!"
    }
  }
  let props = { matches, params }
  let store = {
    getState() { return matches },
    subscribe: sinon.spy(),
    dispatch: sinon.spy()
  }
  let context = { store }

  before(() => {
    sandbox = sinon.sandbox.create()
    wrapper = shallow(<MatchShareWrapper { ...props } />)
  })

  afterEach(() => {
    sandbox.restore()
  })

  describe('#render', () => {
    before(() => {
      spy.metaData = sandbox.spy(MatchShareWrapper.prototype, 'metaData')
    })

    it('should render one empty  component', () => {
      expect(wrapper.html()).to.equal('')
    })
    it('should calls metaData method', () => {
      expect(spy.metaData).to.have.been.called
    })
  })

  describe('#metaData', () => {
    describe('meta objects', () => {
      const result = MatchShareWrapper.prototype.metaData(props)

      it('should have meta prop', () => {
        expect(result).to.have.key('meta')
      })
      it('meta prop should be an object', () => {
        expect(result.meta).to.be.an.object
      })
      it('should have name prop inside meta object', () => {
        expect(result.meta).to.have.key('name')
      })
      it('name prop should be an object', () => {
        expect(result.meta.name).to.be.an.object
      })
      it('should have all required props inside name prop', () => {
        const keys = ['og:title', 'og:description', 'og:image']
        expect(result.meta.name).to.have.all.keys(keys)
      })
      it('og:title prop should be concatenation of first and second choices', () => {
        const expected = `${matches.data.first_choice} + ${matches.data.second_choice}`
        expect(result.meta.name['og:title']).to.equal(expected)
      })
      it('og:description prop should be equal as passed', () => {
        expect(result.meta.name['og:description']).to.equal(matches.data.widget_title)
      })
      it('og:image prop should be equal as passed', () => {
        expect(result.meta.name['og:image']).to.equal(matches.data.goal_image)
      })
    })
  })

  describe('#fetchData', () => {
    const result = MatchShareWrapper.fetchData(store, params)

    it('should returns resolved promises', () => {
      expect(result.constructor).to.be.a.Promise
    })
  })
})
<|endoftext|>


<commit_before>function isPlainObject(obj) {
  return obj ? typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype : false;
}

function handleProperties(sourceProperties, mergeProperties){
  if(!isPlainObject(mergeProperties)){
    return mergeProperties
  }
  if(! isPlainObject(sourceProperties)){
    return mergeProperties
  }
  Object.keys(mergeProperties).forEach(key=>{
    if(key === 'field_1'){
      console.log(1)
    }
    mergeProperties[key]= handleSchema(sourceProperties[key], mergeProperties[key])
  })
  return mergeProperties;
}

function handleSchema(source, merge){
  if(!isPlainObject(source)) return merge;
  if(!isPlainObject(merge)) return merge;
  let result = {}
  Object.assign(result, source, merge)
  if(merge.type === 'object'){
    result.properties = handleProperties(source.properties, merge.properties);
  }else if(merge.type === 'array'){
    result.items = handleSchema(source.items, merge.items);
  }
  return result;
}

module.exports = function(sourceJsonSchema, mergeJsonSchema){
  return handleSchema(sourceJsonSchema, mergeJsonSchema)
}<commit_msg>opti: 删除调试代码<commit_after>function isPlainObject(obj) {
  return obj ? typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype : false;
}

function handleProperties(sourceProperties, mergeProperties){
  if(!isPlainObject(mergeProperties)){
    return mergeProperties
  }
  if(! isPlainObject(sourceProperties)){
    return mergeProperties
  }
  Object.keys(mergeProperties).forEach(key=>{
    mergeProperties[key]= handleSchema(sourceProperties[key], mergeProperties[key])
  })
  return mergeProperties;
}

function handleSchema(source, merge){
  if(!isPlainObject(source)) return merge;
  if(!isPlainObject(merge)) return merge;
  let result = {}
  Object.assign(result, source, merge)
  if(merge.type === 'object'){
    result.properties = handleProperties(source.properties, merge.properties);
  }else if(merge.type === 'array'){
    result.items = handleSchema(source.items, merge.items);
  }
  return result;
}

module.exports = function(sourceJsonSchema, mergeJsonSchema){
  return handleSchema(sourceJsonSchema, mergeJsonSchema)
}<|endoftext|>


<commit_before>import React, {Component} from 'react';
import {
    View,
    Text,
    TouchableOpacity,
    Modal,
    StyleSheet,
    Alert,
    Platform,
}  from 'react-native';
import { RNCamera } from 'react-native-camera';
import CameraRoll from "@react-native-community/cameraroll";
import KeepAwake from 'react-native-keep-awake';
import * as Device from 'app/utility/Device';
import Icon from 'react-native-vector-icons/FontAwesome';

class VideoRecorder extends Component {

    componentDidUpdate(prevProps) {
        if (prevProps.isRecording !== this.props.isRecording) {
            if (this.props.isRecording) {
                this._record();
            } else {
                this._stopRecording();
            }
        }
    }

    componentWillUnmount() {
        if (this.timer) {
            clearTimeout(this.timer);
            this.timer = null;
        }
    }

    // actions

    _closeModal() {
        if (!this.timer) {
            this.props.closeModal(this.props.setID);
        }
    }

    // toggle
    _toggleCameraType() {
        this.props.toggleCameraType();
    }

    // record

    async _record() {
        try {
            // record
            const data = await this.camera.recordAsync({
                mute: false,
                mirrorVideo: this.props.cameraType === 'front',
                // quality: RNCamera.Constants.VideoQuality['288p'],
                // quality?: keyof VideoQuality;
                // orientation?: keyof Orientation | OrientationNumber;
                // maxDuration?: number;
                // maxFileSize?: number;
                // mute?: boolean;
                // mirrorVideo?: boolean;
                // path?: string;
                // videoBitrate?: number;

                // /** iOS only */
                // codec?: keyof VideoCodec | VideoCodec[keyof VideoCodec];
            });

            // save to gallery
            console.tron.log(`have data, what do with it? ${JSON.stringify(data)}`);
            const uri = await CameraRoll.saveToCameraRoll(data.uri);

            // dispatch information
            if (this.props.setID) {
                console.tron.log(`should be saving to ${uri}`);
                this.props.saveVideo(this.props.setID, uri, this.props.videoType);
            }
            // TODO: share options can be here, but for now just finish
        } catch (err) {
            console.tron.log("ERROR " + err);
            this.props.saveVideoError(this.props.setID, err);
            Alert.alert('There was an issue saving your video. Please try again');
        }
    }

    _stopRecording() {
        // cancelled a recording
        if (!this.props.isModalShowing) {
            return;
        }

        if (Platform.OS === 'ios') {
            // TODO: remove timer hack, this was necessary to prevent weird behavior when ending too quickly
            this.timer = setTimeout(() => {
                this.camera.stopRecording();
                clearTimeout(this.timer);
                this.timer = null;
            }, 1000);
        } else {
            this.camera.stopRecording();
        }
    }

    // render

    _renderActionButton() {
        if (this.props.isSaving) {
            return (
                <View style={[styles.actionButton, styles.savingButton]}>
                    <Text style={styles.buttonText}>SAVING</Text>
                </View>
            );
        } else if (this.props.isRecording) {
            return (
                <TouchableOpacity onPress={()=>this.props.tappedStop()}>
                    <View style={[styles.actionButton, styles.stopButton]}>
                        <Text style={styles.buttonText}>END</Text>
                    </View>
                </TouchableOpacity>
            );
        } else {
            return (
                <TouchableOpacity onPress={()=>this.props.tappedStart(this.props.setID)}>
                    <View style={[styles.actionButton, styles.startButton]}>
                        <Text style={styles.buttonText}>START</Text>
                    </View>
                </TouchableOpacity>
            );
        }
    }

    _renderToggleCameraTypeButton() {
        // TODO: enable camera after fixing Android's slow front facing camera
        return <View></View>

        // need to return empty view as button remains but is not clickable if not returning anything
        if (this.props.isRecording || this.props.isSaving) {
            return <View></View>
        } else {
            return (
                <View style={styles.flipButton}>
                    <TouchableOpacity onPress={()=>this._toggleCameraType()}>
                        <View>
                            <Icon name="repeat" size={30} style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)', padding: 10, borderRadius: 22.5, overflow: 'hidden' }} color='white' />
                        </View>
                    </TouchableOpacity>
                </View>
            );
        }
    }

    _renderCamera() {
        if (this.props.isModalShowing) {
            return (
                <View style={[{flex: 1}, styles.container]}>
                    <RNCamera
                        ref={(cam) => {this.camera = cam}}
                        style={{flex: 1}}
                        type={this.props.cameraType}
                    >
                        <View style={styles.cancelButton}>
                            <View>
                            <TouchableOpacity onPress={()=>this._closeModal()}>
                                <View><Text style={styles.cancelText}>Cancel</Text></View>
                            </TouchableOpacity>
                            </View>
                        </View>

                        <View style={{position: 'absolute', bottom: 50, left: 0, right: 0, alignItems: 'center'}}>
                            { this._renderActionButton() }
                        </View>

                        {this._renderToggleCameraTypeButton()}

                    </RNCamera>
                    <KeepAwake />
                </View>
            );
        } else {
            return null;
        }
    }

    render() {
        return (
            <Modal visible={this.props.isModalShowing} animationType='fade'>
                { this._renderCamera() }
            </Modal>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        backgroundColor: 'black'
    },
    actionButton: {
        width: 70,
        height: 70,
        borderRadius: 70,
        alignItems: 'center',
        justifyContent: 'center'
    },
    startButton: {
        backgroundColor: 'green',
    },
    stopButton: {
        backgroundColor: 'red',
    },
    savingButton: {
        backgroundColor: 'darkgray'
    },
    buttonText: {
        color: 'white',
        fontWeight: 'bold',
    },
    cancelButton: {
        marginTop: Device.isiPhoneX() ? 50 : 30,
        marginLeft: 20,
        width: 100,
        backgroundColor: '#333333',
        justifyContent: 'center',
        alignItems: 'center',
        borderRadius: 8
    },
    cancelText: {
        color: 'white',
        fontWeight: 'bold',
        width: 50,
        height: 30,
        paddingTop: 5,
        textAlign: 'center'
    },
    flipButton: {
        alignItems: 'flex-end',
        marginRight: 20,
        backgroundColor: '#00000000',
        position: 'absolute',
        bottom: 60,
        right: 0
    },
    flipIcon: {
        backgroundColor: 'rgba(0, 0, 0, 0.5)',
        padding: 10,
        borderRadius: 22.5,
        overflow: 'hidden',
    },
});

export default VideoRecorder;
<commit_msg>delete temp vid from cache<commit_after>import React, {Component} from 'react';
import {
    View,
    Text,
    TouchableOpacity,
    Modal,
    StyleSheet,
    Alert,
    Platform,
}  from 'react-native';
import { RNCamera } from 'react-native-camera';
import CameraRoll from "@react-native-community/cameraroll";
import RNFetchBlob from 'rn-fetch-blob';
import KeepAwake from 'react-native-keep-awake';
import * as Device from 'app/utility/Device';
import Icon from 'react-native-vector-icons/FontAwesome';

class VideoRecorder extends Component {

    componentDidUpdate(prevProps) {
        if (prevProps.isRecording !== this.props.isRecording) {
            if (this.props.isRecording) {
                this._record();
            } else {
                this._stopRecording();
            }
        }
    }

    componentWillUnmount() {
        if (this.timer) {
            clearTimeout(this.timer);
            this.timer = null;
        }
    }

    // actions

    _closeModal() {
        if (!this.timer) {
            this.props.closeModal(this.props.setID);
        }
    }

    // toggle
    _toggleCameraType() {
        this.props.toggleCameraType();
    }

    // record

    async _record() {
        try {
            // record
            const data = await this.camera.recordAsync({
                mute: false,
                mirrorVideo: this.props.cameraType === 'front',
                // quality: RNCamera.Constants.VideoQuality['288p'],
                // quality?: keyof VideoQuality;
                // orientation?: keyof Orientation | OrientationNumber;
                // maxDuration?: number;
                // maxFileSize?: number;
                // mute?: boolean;
                // mirrorVideo?: boolean;
                // path?: string;
                // videoBitrate?: number;

                // /** iOS only */
                // codec?: keyof VideoCodec | VideoCodec[keyof VideoCodec];
            });

            // save to gallery
            console.tron.log(`have data, what do with it? ${JSON.stringify(data)}`);
            const uri = await CameraRoll.saveToCameraRoll(data.uri);

            // delete from cache
            await RNFetchBlob.fs.unlink(data.uri);

            // dispatch information
            if (this.props.setID) {
                console.tron.log(`should be saving to ${uri}`);
                this.props.saveVideo(this.props.setID, uri, this.props.videoType);
            }
            // TODO: share options can be here, but for now just finish
        } catch (err) {
            console.tron.log("ERROR " + err);
            this.props.saveVideoError(this.props.setID, err);
            Alert.alert('There was an issue saving your video. Please try again');
        }
    }

    _stopRecording() {
        // cancelled a recording
        if (!this.props.isModalShowing) {
            return;
        }

        if (Platform.OS === 'ios') {
            // TODO: remove timer hack, this was necessary to prevent weird behavior when ending too quickly
            this.timer = setTimeout(() => {
                this.camera.stopRecording();
                clearTimeout(this.timer);
                this.timer = null;
            }, 1000);
        } else {
            this.camera.stopRecording();
        }
    }

    // render

    _renderActionButton() {
        if (this.props.isSaving) {
            return (
                <View style={[styles.actionButton, styles.savingButton]}>
                    <Text style={styles.buttonText}>SAVING</Text>
                </View>
            );
        } else if (this.props.isRecording) {
            return (
                <TouchableOpacity onPress={()=>this.props.tappedStop()}>
                    <View style={[styles.actionButton, styles.stopButton]}>
                        <Text style={styles.buttonText}>END</Text>
                    </View>
                </TouchableOpacity>
            );
        } else {
            return (
                <TouchableOpacity onPress={()=>this.props.tappedStart(this.props.setID)}>
                    <View style={[styles.actionButton, styles.startButton]}>
                        <Text style={styles.buttonText}>START</Text>
                    </View>
                </TouchableOpacity>
            );
        }
    }

    _renderToggleCameraTypeButton() {
        // TODO: enable camera after fixing Android's slow front facing camera
        return <View></View>

        // need to return empty view as button remains but is not clickable if not returning anything
        if (this.props.isRecording || this.props.isSaving) {
            return <View></View>
        } else {
            return (
                <View style={styles.flipButton}>
                    <TouchableOpacity onPress={()=>this._toggleCameraType()}>
                        <View>
                            <Icon name="repeat" size={30} style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)', padding: 10, borderRadius: 22.5, overflow: 'hidden' }} color='white' />
                        </View>
                    </TouchableOpacity>
                </View>
            );
        }
    }

    _renderCamera() {
        if (this.props.isModalShowing) {
            return (
                <View style={[{flex: 1}, styles.container]}>
                    <RNCamera
                        ref={(cam) => {this.camera = cam}}
                        style={{flex: 1}}
                        type={this.props.cameraType}
                    >
                        <View style={styles.cancelButton}>
                            <View>
                            <TouchableOpacity onPress={()=>this._closeModal()}>
                                <View><Text style={styles.cancelText}>Cancel</Text></View>
                            </TouchableOpacity>
                            </View>
                        </View>

                        <View style={{position: 'absolute', bottom: 50, left: 0, right: 0, alignItems: 'center'}}>
                            { this._renderActionButton() }
                        </View>

                        {this._renderToggleCameraTypeButton()}

                    </RNCamera>
                    <KeepAwake />
                </View>
            );
        } else {
            return null;
        }
    }

    render() {
        return (
            <Modal visible={this.props.isModalShowing} animationType='fade'>
                { this._renderCamera() }
            </Modal>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        backgroundColor: 'black'
    },
    actionButton: {
        width: 70,
        height: 70,
        borderRadius: 70,
        alignItems: 'center',
        justifyContent: 'center'
    },
    startButton: {
        backgroundColor: 'green',
    },
    stopButton: {
        backgroundColor: 'red',
    },
    savingButton: {
        backgroundColor: 'darkgray'
    },
    buttonText: {
        color: 'white',
        fontWeight: 'bold',
    },
    cancelButton: {
        marginTop: Device.isiPhoneX() ? 50 : 30,
        marginLeft: 20,
        width: 100,
        backgroundColor: '#333333',
        justifyContent: 'center',
        alignItems: 'center',
        borderRadius: 8
    },
    cancelText: {
        color: 'white',
        fontWeight: 'bold',
        width: 50,
        height: 30,
        paddingTop: 5,
        textAlign: 'center'
    },
    flipButton: {
        alignItems: 'flex-end',
        marginRight: 20,
        backgroundColor: '#00000000',
        position: 'absolute',
        bottom: 60,
        right: 0
    },
    flipIcon: {
        backgroundColor: 'rgba(0, 0, 0, 0.5)',
        padding: 10,
        borderRadius: 22.5,
        overflow: 'hidden',
    },
});

export default VideoRecorder;
<|endoftext|>


<commit_before>'use strict';
//
// module.exports = function(Gtrends) {
//
// };

var request = require("request");
const googleTrends = require('google-trends-api');

module.exports = function(Gtrends) {
  Gtrends.find = function(msg, cb) {
    process.nextTick(function() {
      msg = msg ? msg : 'ibm';
      // googleTrends.interestOverTime({keyword: msg})
      // .then(function(result){
      //   cb(null, result);
      // })
      // .catch(function(err){
      //   cb(null, err);
      // });
      // cb(null, 'Sender says ' + msg + ' to YOU!!!');

      googleTrends.relatedTopics({keyword: msg})
      .then(function(result){
        var respData = [];
        var data = JSON.parse(result).default.rankedList[0].rankedKeyword;
        for (var i = 0; i < data.length; i++) {
          respData.push({"description" : data[i].topic.type, "title" : data[i].topic.title});
        }
        cb(null, respData);
      })
      .catch(function(err){
        cb(null, err);
      });
    });
  };
};
<commit_msg>change response format to array, another try<commit_after>'use strict';
//
// module.exports = function(Gtrends) {
//
// };

var request = require("request");
const googleTrends = require('google-trends-api');

module.exports = function(Gtrends) {
  Gtrends.find = function(msg, cb) {
    process.nextTick(function() {
      msg = msg ? msg : 'ibm';
      // googleTrends.interestOverTime({keyword: msg})
      // .then(function(result){
      //   cb(null, result);
      // })
      // .catch(function(err){
      //   cb(null, err);
      // });
      // cb(null, 'Sender says ' + msg + ' to YOU!!!');

      googleTrends.relatedTopics({keyword: msg})
      .then(function(result){
        var respData = [];
        var data = JSON.parse(result).default.rankedList[0].rankedKeyword;
        for (var i = 0; i < data.length; i++) {
          respData.push({"description" : data[i].topic.type, "title" : data[i].topic.title, "location" : "None", "link" : data[i].link, "date" : "2012-11-03T07:00:00"});
        }
        cb(null, respData);
      })
      .catch(function(err){
        cb(null, err);
      });
    });
  };
};
<|endoftext|>


<commit_before>///
/// utility functions for computing progress of complex tasks
///
/// State callback here is an object with these keys:
///   done: bool, true if done
///   current: number, the current progress value
///   end: number, optional, the value of current where we expect to be done
///
/// If end is not set, we'll display a spinner instead of a progress bar
///

var _ = require('underscore');
var Future = require('fibers/future');
var consolejs = require('./console.js');

var Progress = function (options) {
  var self = this;

  options = options || {};

  self._lastState = null;
  self._parent = options.parent;
  self._watchers = options.watchers || [];

  self._title = options.title;

  // XXX: Should we have a strict/mdg mode that enables this test?
  //if (!self._title && self._parent) {
  //  throw new Error("No title passed");
  //}

  self._forkJoin = options.forkJoin;

  self._allTasks = [];

  self._selfState = { current: 0, done: false };
  self._state = _.clone(self._selfState);

  self._isDone = false;

  // Set this to true to stop displaying a progress bar/spinner.
  self.suppressDisplay = false;

  self.startTime = +(new Date);
};

_.extend(Progress.prototype, {
  toString: function() {
    var self = this;
    return "Progress [state=" + JSON.stringify(self._state) + "]";
  },

  reportProgressDone: function () {
    var self = this;

    var state = _.clone(self._selfState);
    state.done = true;
    if (state.end !== undefined) {
      if (state.current > state.end) {
        state.end = state.current;
      }
      state.current = state.end;
    }
    self.reportProgress(state);
  },

  // Tries to determine which is the 'current' job in the tree
  // This is very heuristical... we use some hints, like:
  // don't descend into fork-join jobs; we know these execute concurrently,
  // so we assume the top-level task has the title
  // i.e. "Downloading packages", not "downloading supercool-1.0"
  getCurrentProgress: function () {
    var self = this;

    var isRoot = !self._parent;

    if (self._isDone) {
      // A done task cannot be the active task
      return null;
    }

    if (!self._state.done && (self._state.current != 0) && !isRoot) {
      // We are not done and we have interesting state to report
      return self;
    }

    if (self._forkJoin) {
      // Don't descend into fork-join tasks (by choice)
      return self;
    }

    if (self._allTasks.length) {
      var candidates = _.map(self._allTasks, function (task) {
        return task.getCurrentProgress();
      });
      var active = _.filter(candidates, function (s) {
        return !!s;
      });
      if (active.length == 1) {
        return active[0];
      }
      // No single active task, return self
      return self;
    }

    return self;
  },

  // Creates a subtask that must be completed as part of this (bigger) task
  addChildTask: function (options) {
    var self = this;
    options = _.extend({ parent: self }, options || {});
    var child = new Progress(options);
    self._allTasks.push(child);
    self._reportChildState(child, child._state);
    return child;
  },

  // Dumps the tree, for debug
  dump: function (stream, options, prefix) {
    var self = this;

    options = options || {};
    if (options.skipDone && self._isDone) {
      return;
    }

    if (prefix) {
      stream.write(prefix);
    }
    var end = self._state.end;
    if (!end) {
      end = '?';
    }
    stream.write("Task [" + self._title + "] " + self._state.current + "/" + end
      + (self._isDone ? " done" : "") +"\n");
    if (self._allTasks.length) {
      _.each(self._allTasks, function (child) {
        child.dump(stream, options, (prefix || '') + '  ');
      });
    }
  },

  // Receives a state report indicating progress of self
  reportProgress: function (state) {
    var self = this;

    self._selfState = state;

    self._updateTotalState();

    // Nudge the spinner/progress bar, but don't yield (might not be safe to yield)
    consolejs.Console.nudge(false);

    self._notifyState();
  },

  // Subscribes a watcher to changes
  addWatcher: function (watcher) {
    var self = this;

    self._watchers.push(watcher);
  },

  // Notifies watchers & parents
  _notifyState: function () {
    var self = this;

    if (self._parent) {
      self._parent._reportChildState(self, self._state);
    }

    if (self._watchers.length) {
      _.each(self._watchers, function (watcher) {
        watcher(self._state);
      });
    }
  },

  // Recomputes state, incorporating children's states
  _updateTotalState: function () {
    var self = this;

    var state = _.clone(self._selfState);

    var allChildrenDone = true;
    var state = _.clone(self._selfState);
    _.each(self._allTasks, function (child) {
      var childState = child._state;

      if (!child._isDone) {
        allChildrenDone = false;
      }

      state.current += childState.current;
      if (state.end !== undefined) {
        if (childState.done) {
          state.end += childState.current;
        } else if (childState.end !== undefined) {
          state.end += childState.end;
        } else {
          state.end = undefined;
        }
      }
    });
    self._isDone = allChildrenDone && !!self._selfState.done;
    if (!allChildrenDone) {
      state.done = false;
    }

    if (!state.done && self._state.done) {
      // This shouldn't happen
      throw new Error("Progress transition from done => !done");
    }

    self._state = state;
  },

  // Called by a child when its state changes
  _reportChildState: function (child, state) {
    var self = this;

    self._updateTotalState();
    self._notifyState();
  },

  getState: function() {
    return this._state;
  }
});

exports.Progress = Progress;
<commit_msg>Display progress message in case of multiple jobs<commit_after>///
/// utility functions for computing progress of complex tasks
///
/// State callback here is an object with these keys:
///   done: bool, true if done
///   current: number, the current progress value
///   end: number, optional, the value of current where we expect to be done
///
/// If end is not set, we'll display a spinner instead of a progress bar
///

var _ = require('underscore');
var Future = require('fibers/future');
var consolejs = require('./console.js');

var Progress = function (options) {
  var self = this;

  options = options || {};

  self._lastState = null;
  self._parent = options.parent;
  self._watchers = options.watchers || [];

  self._title = options.title;

  // XXX: Should we have a strict/mdg mode that enables this test?
  //if (!self._title && self._parent) {
  //  throw new Error("No title passed");
  //}

  self._forkJoin = options.forkJoin;

  self._allTasks = [];

  self._selfState = { current: 0, done: false };
  self._state = _.clone(self._selfState);

  self._isDone = false;

  // Set this to true to stop displaying a progress bar/spinner.
  self.suppressDisplay = false;

  self.startTime = +(new Date);
};

_.extend(Progress.prototype, {
  toString: function() {
    var self = this;
    return "Progress [state=" + JSON.stringify(self._state) + "]";
  },

  reportProgressDone: function () {
    var self = this;

    var state = _.clone(self._selfState);
    state.done = true;
    if (state.end !== undefined) {
      if (state.current > state.end) {
        state.end = state.current;
      }
      state.current = state.end;
    }
    self.reportProgress(state);
  },

  // Tries to determine which is the 'current' job in the tree
  // This is very heuristical... we use some hints, like:
  // don't descend into fork-join jobs; we know these execute concurrently,
  // so we assume the top-level task has the title
  // i.e. "Downloading packages", not "downloading supercool-1.0"
  getCurrentProgress: function () {
    var self = this;

    var isRoot = !self._parent;

    if (self._isDone) {
      // A done task cannot be the active task
      return null;
    }

    if (!self._state.done && (self._state.current != 0) && !isRoot) {
      // We are not done and we have interesting state to report
      return self;
    }

    if (self._forkJoin) {
      // Don't descend into fork-join tasks (by choice)
      return self;
    }

    if (self._allTasks.length) {
      var candidates = _.map(self._allTasks, function (task) {
        return task.getCurrentProgress();
      });
      var active = _.filter(candidates, function (s) {
        return !!s;
      });
      if (active.length) {
        // pick one to display, somewhat arbitrarily
        return active[active.length - 1];
      }
      // No single active task, return self
      return self;
    }

    return self;
  },

  // Creates a subtask that must be completed as part of this (bigger) task
  addChildTask: function (options) {
    var self = this;
    options = _.extend({ parent: self }, options || {});
    var child = new Progress(options);
    self._allTasks.push(child);
    self._reportChildState(child, child._state);
    return child;
  },

  // Dumps the tree, for debug
  dump: function (stream, options, prefix) {
    var self = this;

    options = options || {};
    if (options.skipDone && self._isDone) {
      return;
    }

    if (prefix) {
      stream.write(prefix);
    }
    var end = self._state.end;
    if (!end) {
      end = '?';
    }
    stream.write("Task [" + self._title + "] " + self._state.current + "/" + end
      + (self._isDone ? " done" : "") +"\n");
    if (self._allTasks.length) {
      _.each(self._allTasks, function (child) {
        child.dump(stream, options, (prefix || '') + '  ');
      });
    }
  },

  // Receives a state report indicating progress of self
  reportProgress: function (state) {
    var self = this;

    self._selfState = state;

    self._updateTotalState();

    // Nudge the spinner/progress bar, but don't yield (might not be safe to yield)
    consolejs.Console.nudge(false);

    self._notifyState();
  },

  // Subscribes a watcher to changes
  addWatcher: function (watcher) {
    var self = this;

    self._watchers.push(watcher);
  },

  // Notifies watchers & parents
  _notifyState: function () {
    var self = this;

    if (self._parent) {
      self._parent._reportChildState(self, self._state);
    }

    if (self._watchers.length) {
      _.each(self._watchers, function (watcher) {
        watcher(self._state);
      });
    }
  },

  // Recomputes state, incorporating children's states
  _updateTotalState: function () {
    var self = this;

    var state = _.clone(self._selfState);

    var allChildrenDone = true;
    var state = _.clone(self._selfState);
    _.each(self._allTasks, function (child) {
      var childState = child._state;

      if (!child._isDone) {
        allChildrenDone = false;
      }

      state.current += childState.current;
      if (state.end !== undefined) {
        if (childState.done) {
          state.end += childState.current;
        } else if (childState.end !== undefined) {
          state.end += childState.end;
        } else {
          state.end = undefined;
        }
      }
    });
    self._isDone = allChildrenDone && !!self._selfState.done;
    if (!allChildrenDone) {
      state.done = false;
    }

    if (!state.done && self._state.done) {
      // This shouldn't happen
      throw new Error("Progress transition from done => !done");
    }

    self._state = state;
  },

  // Called by a child when its state changes
  _reportChildState: function (child, state) {
    var self = this;

    self._updateTotalState();
    self._notifyState();
  },

  getState: function() {
    return this._state;
  }
});

exports.Progress = Progress;
<|endoftext|>


<commit_before>// var _ = require('underscore')
var app = require('../../server/server')
var dsConfig = require('../../server/datasources.json')

// 12 hours in milliseconds
// var EMAILINTERVAL = 43200000

// 10 seconds for testing
var EMAILINTERVAL = 10000

module.exports = function (UsedCode) {

  // this is the logic for taking in a request, removing an access code,
  // and sending the code to both the client and the used code table

  UsedCode.process = function (requestObject, cb) {

    var yourEmailAddress = dsConfig.emailDs.transports[0].auth.user

    var response = requestObject.instance
    // grab the object representing the SQL data
    var availableCodes = app.datasources.rethinkdb.models.availableCodes
    var contacts = app.datasources.rethinkdb.models.contact
    var products = app.datasources.rethinkdb.models.product

    var prodId = requestObject.instance.productId
    // search the SQL data for the correct model using the productId
    // maybe move thise to the before save function below?? that way we can avoid
    // writing to the db if there's no codes
    availableCodes.findOne({where: {productId: prodId}}, function (err, row) {
      if (err) {console.log(err)}
      if (row) {
        // add our new code to our response
        response.code = row.code
        // add the date
        var date = new Date().toDateString()
        response.date = date
        // delete the row
        availableCodes.destroyById(row.id, function (err2) {
          if (!err2) {
            // send the callback
            cb(null, response)
          }
        })

        products.findOne({where: {productId: prodId}}, function (err2, product) {
          if (err2) {console.log(err2)}
          var nProduct = product
          nProduct.popularity = nProduct.popularity += 1
          products.upsert(nProduct, function (err3, obj) {
            if (err3) {throw err3}
            console.log(obj)
          })
        })

        availableCodes.count({productId: prodId}, function (err2, count) {
          if (err) {console.log(err)}
          if (count < 9) {
            console.log('productId ' + prodId + ' has ' + count + ' codes left')
            contacts.findOne({where: {productId: prodId}}, function (err3, contact) {
              if (err3) {console.log(err3)}
              var now = Date.now()
              if (now - contact.lastEmailed > EMAILINTERVAL) {
                var updated = contact
                updated.lastEmailed = now
                app.models.Email.send({
                  to: contact.mainEmail,
                  // cc: 'chrcollier@wiley.comgbuhler@wiley.com',
                  from: yourEmailAddress,
                  subject: 'The email subject',
                  text: 'Need More Codes For: (PRODUCT)\n\nWe only have ' + count + ' left'
                  // html: 'HTML tags are converted'
                }, function (err4) {
                    if (err4) {throw err4}
                    console.log('> email sent successfully')
                  }
                )

                contacts.upsert(updated, function (err4, instance) {
                  if (err4) {console.log(err4)}
                  console.log('updated', instance)
                })
              } else {
                console.log('Contact has already been emailed within 12 hours')
              }
            })
          }
        })
      } else {
        cb(true, null)
      }
    })
  }

  // commented for testing usedCode searching -- uncomment when done

  UsedCode.observe('before save', function (modelInstance, next) {

    if (modelInstance.instance.code) {
      next()
    } else {
      UsedCode.process(modelInstance, function (err, res) {
        if (err) {console.log(err)}
        modelInstance = res
        next()
      })
    }

  })

  // register our 'process' function as a remote method
  // available via our web api
  // UsedCode.remoteMethod(
  //     'process',
  //     {
  //       accepts: {arg: 'requestObject', type: 'Object'},
  //       returns: {arg: 'receivedCode', type: 'Object'}
  //     }
  // )

}
<commit_msg>update number number of available codes on product when code is generated<commit_after>// var _ = require('underscore')
var app = require('../../server/server')
var dsConfig = require('../../server/datasources.json')

// 12 hours in milliseconds
// var EMAILINTERVAL = 43200000

// 10 seconds for testing
var EMAILINTERVAL = 10000

module.exports = function (UsedCode) {

  // this is the logic for taking in a request, removing an access code,
  // and sending the code to both the client and the used code table

  UsedCode.process = function (requestObject, cb) {

    var yourEmailAddress = dsConfig.emailDs.transports[0].auth.user

    var response = requestObject.instance
    // grab the object representing the SQL data
    var availableCodes = app.datasources.rethinkdb.models.availableCodes
    var contacts = app.datasources.rethinkdb.models.contact
    var products = app.datasources.rethinkdb.models.product

    var prodId = requestObject.instance.productId
    // search the SQL data for the correct model using the productId
    // maybe move thise to the before save function below?? that way we can avoid
    // writing to the db if there's no codes
    availableCodes.findOne({where: {productId: prodId}}, function (err, row) {
      if (err) {console.log(err)}
      if (row) {
        // add our new code to our response
        response.code = row.code
        // add the date
        var date = new Date().toDateString()
        response.date = date
        // delete the row
        availableCodes.destroyById(row.id, function (err2) {
          if (!err2) {
            products.findOne({where: {productId: prodId}}, function (err3, product) {
              if (err3) {console.log(err3)}
              var nProduct = product
              availableCodes.count({productId: prodId}, function (err4, count) {
                nProduct.nCodes = count
                nProduct.popularity = nProduct.popularity += 1
                products.upsert(nProduct, function (err4, obj) {
                  if (err4) {throw err4}
                })
              })
            })
            // send the callback
            cb(null, response)
          }
        })

        availableCodes.count({productId: prodId}, function (err2, count) {
          if (err) {console.log(err)}
          if (count < 9) {
            console.log('productId ' + prodId + ' has ' + count + ' codes left')
            contacts.findOne({where: {productId: prodId}}, function (err3, contact) {
              if (err3) {console.log(err3)}
              var now = Date.now()
              if (now - contact.lastEmailed > EMAILINTERVAL) {
                var updated = contact
                updated.lastEmailed = now
                app.models.Email.send({
                  to: contact.mainEmail,
                  // cc: 'chrcollier@wiley.comgbuhler@wiley.com',
                  from: yourEmailAddress,
                  subject: 'The email subject',
                  text: 'Need More Codes For: (PRODUCT)\n\nWe only have ' + count + ' left'
                  // html: 'HTML tags are converted'
                }, function (err4) {
                    if (err4) {throw err4}
                    console.log('> email sent successfully')
                  }
                )

                contacts.upsert(updated, function (err4, instance) {
                  if (err4) {console.log(err4)}
                  console.log('updated', instance)
                })
              } else {
                console.log('Contact has already been emailed within 12 hours')
              }
            })
          }
        })
      } else {
        cb(true, null)
      }
    })
  }

  // commented for testing usedCode searching -- uncomment when done

  UsedCode.observe('before save', function (modelInstance, next) {

    if (modelInstance.instance.code) {
      next()
    } else {
      UsedCode.process(modelInstance, function (err, res) {
        if (err) {console.log(err)}
        modelInstance = res
        next()
      })
    }

  })

  // register our 'process' function as a remote method
  // available via our web api
  // UsedCode.remoteMethod(
  //     'process',
  //     {
  //       accepts: {arg: 'requestObject', type: 'Object'},
  //       returns: {arg: 'receivedCode', type: 'Object'}
  //     }
  // )

}
<|endoftext|>


<commit_before>var test = require('tape')
var error = require('../')

test('inheritance', function(t) {
  t.plan(10)

  var MyError = error('MyError')

  t.ok(MyError() instanceof Error, 'MyError instances should inherit Error')
  t.ok(new MyError() instanceof Error, 'MyError instances should inherit Error')

  t.ok(MyError() instanceof MyError, 'MyError instances should inherit MyError')
  t.ok(new MyError() instanceof MyError, 'MyError instances should inherit MyError')

  var OtherError = error('OtherError', MyError)

  t.ok(OtherError() instanceof Error, 'OtherError instances should inherit Error')
  t.ok(new OtherError() instanceof Error, 'OtherError instances should inherit Error')

  t.ok(OtherError() instanceof MyError, 'OtherError instances should inherit MyError')
  t.ok(new OtherError() instanceof MyError, 'OtherError instances should inherit MyError')

  t.ok(OtherError() instanceof OtherError, 'OtherError instances should inherit OtherError')
  t.ok(new OtherError() instanceof OtherError, 'OtherError instances should inherit OtherError')
})

<commit_msg>Add test for custom prototype attribute inheritance<commit_after>var test = require('tape')
var error = require('../')

test('inheritance', function(t) {
  t.plan(11)

  var MyError = error('MyError')
  MyError.prototype.code = 77

  t.ok(MyError() instanceof Error, 'MyError instances should inherit Error')
  t.ok(new MyError() instanceof Error, 'MyError instances should inherit Error')

  t.ok(MyError() instanceof MyError, 'MyError instances should inherit MyError')
  t.ok(new MyError() instanceof MyError, 'MyError instances should inherit MyError')

  t.equals(MyError().code, 77, 'MyError instances should inherit MyError.prototype properties')

  var OtherError = error('OtherError', MyError)

  t.ok(OtherError() instanceof Error, 'OtherError instances should inherit Error')
  t.ok(new OtherError() instanceof Error, 'OtherError instances should inherit Error')

  t.ok(OtherError() instanceof MyError, 'OtherError instances should inherit MyError')
  t.ok(new OtherError() instanceof MyError, 'OtherError instances should inherit MyError')

  t.ok(OtherError() instanceof OtherError, 'OtherError instances should inherit OtherError')
  t.ok(new OtherError() instanceof OtherError, 'OtherError instances should inherit OtherError')

  t.equals(OtherError().code, 77, 'OtherError instances should inherit MyError.prototype properties')
})

<|endoftext|>


<commit_before>// Copyright 2020 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.

// Sets the page to always display the first two elements when loading the page.
let currentPage = 0;

google.charts.load('current', {'packages': ['bar', 'table']});

// Retrieves a list of avaliable keyword campaigns the user has stored and is
// used in dropdown menu.
function getKeywordCampaigns() {
  const keywordCampaignList = document.getElementById('keyword-campaigns');
  keywordCampaignList.innerHTML = '<option value=0>Select a keyword' +
    'campaign</option>';

  fetch('/keyword-campaigns').then((response) =>
    response.json()).then((keywordCampaigns) => {
    keywordCampaigns.forEach((keywordCampaign) => {
      keywordCampaignList.innerHTML += '<option value=' +
        keywordCampaign.keywordCampaignId + '>' + keywordCampaign.name  +
        '</option>';
    });

    if (keywordCampaigns.length == 0) {
      const dsaCampaignsList = document.getElementById('DSA-campaigns');
      dsaCampaignsList.innerHTML = '
There are no keyword campaigns.' +
        'Please create one.
';
    }
  });
}

// Checks if user has selected a keyword campaign. If the user has selected a
// keyword then the for loop draws 2 graphs and creates pagination to explore
// other charts.
function drawDsaCampaignCharts() {
  const numChartsPerPage = 2;
  const dsaCampaignsList = document.getElementById('DSA-campaigns');
  dsaCampaignsList.innerHTML = '
First select a keyword campaign.
';
  const keywordCampaignId = document.getElementById('keyword-campaigns').value;

  if (keywordCampaignId != 0) {
    dsaCampaignsList.innerHTML = '';

    fetch('/DSA-campaigns?keywordCampaignId=' +
      keywordCampaignId).then((response) =>
      response.json()).then((DSACampaigns) => {
      const isNumberOfChartsOdd = (DSACampaigns.length % numChartsPerPage);

      // chartsToShow checks what the active page and give a starting
      // point to display the next two charts.
      let chartsToShow = currentPage * numChartsPerPage;

      // chartCounter keeps track of which number each chart displayed is
      // (useful for drawing the graph) and is used as a flag to check if
      // two charts have been processed.
      let chartCounter = 1;

      if (DSACampaigns.length == 0) {
        dsaCampaignsList.innerHTML = '
There are no DSA campaigns. ' +
          'Please create one.
';
        dsaCampaignsList.innerHTML += 'Here';
      }
      else {
        while (chartCounter <= numChartsPerPage) {
          drawDSACampaignBarGraph(DSACampaigns[chartsToShow], chartCounter);
          hideDiv(isNumberOfChartsOdd, DSACampaigns.length, chartsToShow);
          chartsToShow++;
          chartCounter++;
        }
        makePagination((DSACampaigns.length / numChartsPerPage) +
          (DSACampaigns.length % numChartsPerPage), (currentPage));
      }
    });
  }
}

// Hides the second chart if the last pair of charts only contains one
// chart left to display.
function hideDiv(isNumberOfChartsOdd, numberOfCharts, currentChart) {
  const secondBarChart = document.getElementById('Chart2');

  if (isNumberOfChartsOdd == 1 && currentChart == numberOfCharts - 1 ||
    numberOfCharts == 0) {
    secondBarChart.style.visibility = 'hidden';
  }
  else {
    secondBarChart.style.visibility = 'visible';
  }
}

// Creates pagination html for the user to see other charts by taking the
// existing number of pages and the active page the user is on.
function makePagination(numberOfPages, activePageNumber) {
  const pagination = document.getElementById('pagination');
  let paginationString = '';
  paginationString += '
<input type=\"button\" ' +
    'id=\"previous\" onclick=\"previousPage()\" value=\"previous\" />';
  paginationString += '  ' + (activePageNumber +
    1)  +'  ';
  paginationString += '<input type=\"button\" id=\"next\" ' +
    'onclick=\"nextPage(' + numberOfPages + ')\" value=\"next\" />
';
  pagination.innerHTML = paginationString;
}

// Increases the page forward by increasing the active page by one and letting
// the display charts increase to the next two and rerunning getDSACampaigns to
// retrieve the charts.
function nextPage(numberOfPages) {
  const activePage = document.getElementById('activePageNumber');
  let increasePage = parseInt(activePage.innerText);

  // The if statement checks if the user clicks nextpage but there is
  // no more charts to look at using numberOfPages.
  if (increasePage + 1 <= numberOfPages) {
    increasePage++;
    currentPage++;
    drawDsaCampaignCharts();
  }
  activePage.innerText = increasePage;
}

// Decreases the page backward by decreasing the active page by one and letting
// the display charts decrease to the previous two and rerunning
// getDSACampaigns to retrieve the charts.
function previousPage() {
  const activePage = document.getElementById('activePageNumber');
  let decreasePage = parseInt(activePage.innerText);

  // The if statement checks if the user clicks previousPage but there is
  // no more charts to look at using 0 because there are no negative pages.
  if (decreasePage - 1 > 0) {
    decreasePage--;
    currentPage--;
    drawDsaCampaignCharts();
  }
  activePage.innerText = decreasePage;
}

function drawDSACampaignBarGraph(DSACampaign, chartNumber) {
  const data = new google.visualization.DataTable();
  data.addColumn('string', 'DSA Campaign');
  data.addColumn('number', 'Impressions');
  data.addColumn('number', 'Clicks');
  data.addColumn('number', 'Cost (USD)');

  data.addRow([DSACampaign.name, DSACampaign.impressions,
    DSACampaign.clicks, DSACampaign.cost]);

  const options = {
    chart: {
      title: DSACampaign.name + ' ' + 'DSA Campaign Metrics',
      subtitle: 'Impressions, Clicks, and Cost',
    },
    bars: 'horizontal', // Required for Material Bar Charts.
  };

  const chart = new google.charts.Bar(document.getElementById('bar-chart' +
    chartNumber));
  chart.draw(data, google.charts.Bar.convertOptions(options));
  console.log('Drew bar graph.');

  drawDSACampaignTable(DSACampaign, chartNumber);
}

function drawDSACampaignTable(DSACampaign, chartNumber) {
  const data = new google.visualization.DataTable();
  const data2 = new google.visualization.DataTable();
  data.addColumn('string', 'DSA Campaign');
  data.addColumn('string', 'Start Date');
  data.addColumn('string', 'End Date');
  data.addColumn('number', 'Manual CPC');
  data.addColumn('number', 'Daily Budget');
  data.addColumn('string', 'Location');
  data.addColumn('string', 'Domain');

  data2.addColumn('string', 'Target');
  data2.addColumn('string', 'Ad Text');
  data2.addColumn('number', 'Impressions');
  data2.addColumn('number', 'Clicks');
  data2.addColumn('number', 'Cost (USD)');

  data.addRow([DSACampaign.name, DSACampaign.startDate, DSACampaign.endDate,
    DSACampaign.manualCPC, DSACampaign.dailyBudget, DSACampaign.locations,
    DSACampaign.domain]);

  data2.addRow([DSACampaign.targets, DSACampaign.adText,
    DSACampaign.impressions, DSACampaign.clicks, DSACampaign.cost]);

  const table = new google.visualization.Table(document.getElementById('table' +
    chartNumber));

  table.draw(data, {showRowNumber: false, width: '100%', height: '50%'});

  const table2 = new google.visualization.Table(document.getElementById(
      'secondtable' + chartNumber));

  table2.draw(data2, {showRowNumber: false, width: '100%', height: '100%'});

  createThirdRow(DSACampaign, chartNumber);

  console.log('Drew table.');
}

function createThirdRow(DSACampaign, chartNumber) {
  const data = new google.visualization.DataTable();

  data.addColumn('string', 'Status');
  data.addColumn('string', 'SQR');
  data.addColumn('string', 'Delete');

  data.addRow([DSACampaign.campaignStatus, ' SQR ',
    '<button onclick=\"deleteDSACampaign(' + DSACampaign.DSACampaignId +
  ')\" class=\"deleteCampaign\"> Delete </button>']);

  const table = new google.visualization.Table(document.getElementById(
      'deletebutton' + chartNumber));
  table.draw(data, {allowHtml: true, showRowNumber: false, width: '100%',
    height: '50%'});
}

function deleteDSACampaign(id) {
  console.log('Start Deleting DSA');

  const params = new URLSearchParams();
  params.append('id', id);
  fetch('/delete-DSACampaign', {method: 'POST', body: params});

  if (currentPage == 0) {
    location.reload();
  }

  currentPage = 0;
  drawDsaCampaignCharts();
}
<commit_msg>More linting fixes.<commit_after>// Copyright 2020 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.

// Sets the page to always display the first two elements when loading the page.
let currentPage = 0;

google.charts.load('current', {'packages': ['bar', 'table']});

// Retrieves a list of avaliable keyword campaigns the user has stored and is
// used in dropdown menu.
function getKeywordCampaigns() {
  const keywordCampaignList = document.getElementById('keyword-campaigns');
  keywordCampaignList.innerHTML = '<option value=0>Select a keyword' +
    'campaign</option>';

  fetch('/keyword-campaigns').then((response) =>
    response.json()).then((keywordCampaigns) => {
    keywordCampaigns.forEach((keywordCampaign) => {
      keywordCampaignList.innerHTML += '<option value=' +
        keywordCampaign.keywordCampaignId + '>' + keywordCampaign.name  +
        '</option>';
    });

    if (keywordCampaigns.length == 0) {
      const dsaCampaignsList = document.getElementById('DSA-campaigns');
      dsaCampaignsList.innerHTML = '
There are no keyword campaigns.' +
        'Please create one.
';
    }
  });
}

// Checks if user has selected a keyword campaign. If the user has selected a
// keyword then the for loop draws 2 graphs and creates pagination to explore
// other charts.
function drawDsaCampaignCharts() {
  const numChartsPerPage = 2;
  const dsaCampaignsList = document.getElementById('DSA-campaigns');
  dsaCampaignsList.innerHTML = '
First select a keyword campaign.
';
  const keywordCampaignId = document.getElementById('keyword-campaigns').value;

  if (keywordCampaignId != 0) {
    dsaCampaignsList.innerHTML = '';

    fetch('/DSA-campaigns?keywordCampaignId=' +
      keywordCampaignId).then((response) =>
      response.json()).then((DSACampaigns) => {
      const isNumberOfChartsOdd = (DSACampaigns.length % numChartsPerPage);

      // chartsToShow checks what the active page and give a starting
      // point to display the next two charts.
      let chartsToShow = currentPage * numChartsPerPage;

      // chartCounter keeps track of which number each chart displayed is
      // (useful for drawing the graph) and is used as a flag to check if
      // two charts have been processed.
      let chartCounter = 1;

      if (DSACampaigns.length == 0) {
        dsaCampaignsList.innerHTML = '
There are no DSA campaigns. ' +
          'Please create one.
';
        dsaCampaignsList.innerHTML += 'Here';
      }
      else {
        while (chartCounter <= numChartsPerPage) {
          drawDSACampaignBarGraph(DSACampaigns[chartsToShow], chartCounter);
          hideDiv(isNumberOfChartsOdd, DSACampaigns.length, chartsToShow);
          chartsToShow++;
          chartCounter++;
        }
        makePagination((DSACampaigns.length / numChartsPerPage) +
          (DSACampaigns.length % numChartsPerPage), (currentPage));
      }
    });
  }
}

// Hides the second chart if the last pair of charts only contains one
// chart left to display.
function hideDiv(isNumberOfChartsOdd, numberOfCharts, currentChart) {
  const secondBarChart = document.getElementById('Chart2');

  if (isNumberOfChartsOdd == 1 && currentChart == numberOfCharts - 1 ||
    numberOfCharts == 0) {
      secondBarChart.style.visibility = 'hidden';
    }
  else {
      secondBarChart.style.visibility = 'visible';
    }
}

// Creates pagination html for the user to see other charts by taking the
// existing number of pages and the active page the user is on.
function makePagination(numberOfPages, activePageNumber) {
  const pagination = document.getElementById('pagination');
  let paginationString = '';
  paginationString += '
<input type=\"button\" ' +
    'id=\"previous\" onclick=\"previousPage()\" value=\"previous\" />';
  paginationString += '  ' + (activePageNumber +
    1)  +'  ';
  paginationString += '<input type=\"button\" id=\"next\" ' +
    'onclick=\"nextPage(' + numberOfPages + ')\" value=\"next\" />
';
  pagination.innerHTML = paginationString;
}

// Increases the page forward by increasing the active page by one and letting
// the display charts increase to the next two and rerunning getDSACampaigns to
// retrieve the charts.
function nextPage(numberOfPages) {
  const activePage = document.getElementById('activePageNumber');
  let increasePage = parseInt(activePage.innerText);

  // The if statement checks if the user clicks nextpage but there is
  // no more charts to look at using numberOfPages.
  if (increasePage + 1 <= numberOfPages) {
    increasePage++;
    currentPage++;
    drawDsaCampaignCharts();
  }
  activePage.innerText = increasePage;
}

// Decreases the page backward by decreasing the active page by one and letting
// the display charts decrease to the previous two and rerunning
// getDSACampaigns to retrieve the charts.
function previousPage() {
  const activePage = document.getElementById('activePageNumber');
  let decreasePage = parseInt(activePage.innerText);

  // The if statement checks if the user clicks previousPage but there is
  // no more charts to look at using 0 because there are no negative pages.
  if (decreasePage - 1 > 0) {
    decreasePage--;
    currentPage--;
    drawDsaCampaignCharts();
  }
  activePage.innerText = decreasePage;
}

function drawDSACampaignBarGraph(DSACampaign, chartNumber) {
  const data = new google.visualization.DataTable();
  data.addColumn('string', 'DSA Campaign');
  data.addColumn('number', 'Impressions');
  data.addColumn('number', 'Clicks');
  data.addColumn('number', 'Cost (USD)');

  data.addRow([DSACampaign.name, DSACampaign.impressions,
    DSACampaign.clicks, DSACampaign.cost]);

  const options = {
    chart: {
      title: DSACampaign.name + ' ' + 'DSA Campaign Metrics',
      subtitle: 'Impressions, Clicks, and Cost',
    },
    bars: 'horizontal', // Required for Material Bar Charts.
  };

  const chart = new google.charts.Bar(document.getElementById('bar-chart' +
    chartNumber));
  chart.draw(data, google.charts.Bar.convertOptions(options));
  console.log('Drew bar graph.');

  drawDSACampaignTable(DSACampaign, chartNumber);
}

function drawDSACampaignTable(DSACampaign, chartNumber) {
  const data = new google.visualization.DataTable();
  const data2 = new google.visualization.DataTable();
  data.addColumn('string', 'DSA Campaign');
  data.addColumn('string', 'Start Date');
  data.addColumn('string', 'End Date');
  data.addColumn('number', 'Manual CPC');
  data.addColumn('number', 'Daily Budget');
  data.addColumn('string', 'Location');
  data.addColumn('string', 'Domain');

  data2.addColumn('string', 'Target');
  data2.addColumn('string', 'Ad Text');
  data2.addColumn('number', 'Impressions');
  data2.addColumn('number', 'Clicks');
  data2.addColumn('number', 'Cost (USD)');

  data.addRow([DSACampaign.name, DSACampaign.startDate, DSACampaign.endDate,
    DSACampaign.manualCPC, DSACampaign.dailyBudget, DSACampaign.locations,
    DSACampaign.domain]);

  data2.addRow([DSACampaign.targets, DSACampaign.adText,
    DSACampaign.impressions, DSACampaign.clicks, DSACampaign.cost]);

  const table = new google.visualization.Table(document.getElementById('table' +
    chartNumber));

  table.draw(data, {showRowNumber: false, width: '100%', height: '50%'});

  const table2 = new google.visualization.Table(document.getElementById(
      'secondtable' + chartNumber));

  table2.draw(data2, {showRowNumber: false, width: '100%', height: '100%'});

  createThirdRow(DSACampaign, chartNumber);

  console.log('Drew table.');
}

function createThirdRow(DSACampaign, chartNumber) {
  const data = new google.visualization.DataTable();

  data.addColumn('string', 'Status');
  data.addColumn('string', 'SQR');
  data.addColumn('string', 'Delete');

  data.addRow([DSACampaign.campaignStatus, ' SQR ',
  '<button onclick=\"deleteDSACampaign(' + DSACampaign.DSACampaignId +
  ')\" class=\"deleteCampaign\"> Delete </button>']);

  const table = new google.visualization.Table(document.getElementById(
      'deletebutton' + chartNumber));
  table.draw(data, {allowHtml: true, showRowNumber: false, width: '100%',
    height: '50%'});
}

function deleteDSACampaign(id) {
  console.log('Start Deleting DSA');

  const params = new URLSearchParams();
  params.append('id', id);
  fetch('/delete-DSACampaign', {method: 'POST', body: params});

  if (currentPage == 0) {
    location.reload();
  }

  currentPage = 0;
  drawDsaCampaignCharts();
}
<|endoftext|>


<commit_before>'use strict';

describe('The CLI called with', function () {
    var run = require('../src/run.js');
    var args;

    require('chai').should();

    var stdMocks = require('std-mocks');

    function stdout() {
        return stdMocks.flush().stdout.join('');
    }

    beforeEach(function () {
        args = {K: null, T: 'xdot', V: false, o: null, files: [], prog: 'dot'};

        stdMocks.use();
    });

    afterEach(function () {
        stdMocks.restore();
        stdMocks.flush();
    });
});
<commit_msg>add -V tests<commit_after>'use strict';

describe('The CLI called with', function () {
    var run = require('../src/run.js');
    var args;

    require('chai').should();

    var stdMocks = require('std-mocks');

    function stdout() {
        return stdMocks.flush().stdout.join('');
    }

    beforeEach(function () {
        args = {K: null, T: 'xdot', V: false, o: null, files: [], prog: 'dot'};

        stdMocks.use();
    });

    afterEach(function () {
        stdMocks.restore();
        stdMocks.flush();
    });

    describe('-V', function () {
        beforeEach(function () {
            args.V = true;
        });

        it('should print version information', function () {
            run(args);
            stdout().should.equal('dot - graphviz version 2.38.0 (20140413.2041)\n');
        });
        it('should print the called executable name', function () {
            args.prog = 'circo';
            run(args);
            stdout().should.equal('circo - graphviz version 2.38.0 (20140413.2041)\n');
        });
    });
});
<|endoftext|>


<commit_before>function dumpModernizr(){
  var str = '';
  dumpModernizr.old = dumpModernizr.old || {};

    for (var prop in Modernizr) {

      // skip previously done ones.
      if (dumpModernizr.old[prop]) continue;
      else dumpModernizr.old[prop] = true;

      if (typeof Modernizr[prop] === 'function') continue;
      // skip unit test items
      if (/^test/.test(prop)) continue;

      if (~TEST.inputs.indexOf(prop)) {
        str += '
'+prop+'{}
';
        for (var field in Modernizr[prop]) {
          str += '
' + field + ': ' + Modernizr[prop][field] + '
';
        }
        str += '

';
      } else {
        str += '
' + prop + ': ' + Modernizr[prop] + '
';
      }
  }
  return str;
}

function grabFeatDetects(){
  // thx github.js
  gh.object("Modernizr", "Modernizr").blobAll('master', function (data) {

    var filenames = [];

    for (var file in data.blobs){
      var match = file.match(/^feature-detects\/(.*)/);
      if (!match) continue;

      var relpath = location.host == "modernizr.github.com" ?
                      'https://raw.github.com/Modernizr/Modernizr/master/' : '../';

      filenames.push(relpath + match[0]);
    }

    var jqxhrs = filenames.map(function(filename){
      return jQuery.getScript(filename);
    });

    jQuery.when.apply(jQuery, jqxhrs).done(resultsToDOM);

  });
}

function resultsToDOM(){
  var modOutput = document.createElement('div'),
      ref = document.getElementById('qunit-testresult') || document.getElementById('qunit-tests');

  modOutput.className = 'output';
  modOutput.innerHTML = dumpModernizr();
  if (Modernizr.csscolumns) ref.parentNode.insertBefore(modOutput, ref);

  // Modernizr object as text
  document.getElementsByTagName('textarea')[0].value = JSON.stringify(Modernizr);
}

/* uno  */ resultsToDOM();
/* dos  */ grabFeatDetects();
/* tres */ setTimeout(resultsToDOM, 5e3);

<commit_msg>webkit likes textarea value like innerHTML but only after you force a reflow. this is crazy.<commit_after>function dumpModernizr(){
  var str = '';
  dumpModernizr.old = dumpModernizr.old || {};

    for (var prop in Modernizr) {

      // skip previously done ones.
      if (dumpModernizr.old[prop]) continue;
      else dumpModernizr.old[prop] = true;

      if (typeof Modernizr[prop] === 'function') continue;
      // skip unit test items
      if (/^test/.test(prop)) continue;

      if (~TEST.inputs.indexOf(prop)) {
        str += '
'+prop+'{}
';
        for (var field in Modernizr[prop]) {
          str += '
' + field + ': ' + Modernizr[prop][field] + '
';
        }
        str += '

';
      } else {
        str += '
' + prop + ': ' + Modernizr[prop] + '
';
      }
  }
  return str;
}

function grabFeatDetects(){
  // thx github.js
  gh.object("Modernizr", "Modernizr").blobAll('master', function (data) {

    var filenames = [];

    for (var file in data.blobs){
      var match = file.match(/^feature-detects\/(.*)/);
      if (!match) continue;

      var relpath = location.host == "modernizr.github.com" ?
                      'https://raw.github.com/Modernizr/Modernizr/master/' : '../';

      filenames.push(relpath + match[0]);
    }

    var jqxhrs = filenames.map(function(filename){
      return jQuery.getScript(filename);
    });

    jQuery.when.apply(jQuery, jqxhrs).done(resultsToDOM);

  });
}

function resultsToDOM(){

  var modOutput = document.createElement('div'),
      ref = document.getElementById('qunit-testresult') || document.getElementById('qunit-tests');

  modOutput.className = 'output';
  modOutput.innerHTML = dumpModernizr();
  if (Modernizr.csscolumns) ref.parentNode.insertBefore(modOutput, ref);

  // Modernizr object as text
  document.getElementsByTagName('textarea')[0].innerHTML = JSON.stringify(Modernizr);

}

/* uno  */ resultsToDOM();
/* dos  */ grabFeatDetects();
/* tres */ setTimeout(resultsToDOM, 5e3);

<|endoftext|>