<commit_before>/*

stacking xml parser

*/

'use strict';

const sInitial = 0;
const sDeclaration = 1;
const sPreElement = 2;
const sElement = 3;
const sAttribute = 5;
const sAttrNML = 6;
const sValue = 7;
const sEndElement = 9;
const sNML = 10;
const sContent = 11;
const sElementBoundary = 12;
const sAttributeSpacer = 14;
const sComment = 16;

var state = sInitial;
var boundary;
var token;
var attributeCount;
var depth;

function reset() {
	state = sInitial;
	token = '';
	boundary = '<';
	attributeCount = 0;
	depth = 0;
	attributeCount = [0];
}

function staxParse(s,callback) {

	//comments, processing instructions, CDATA segments

	var c;
	reset();

	for (var i=0;i<s.length;i++) {
		c = s.charAt(i);

		if ((c == '\t') || (c == '\r') || (c == '\n')) {
			c = ' ';
		}

		if (boundary.indexOf(c)>=0) {

			token = token.trim();
			if (((state & 1) == 1) && (token != '')) {
				callback(state,token); // nonstandard space handling
			}
			if ((state == sAttribute) || (state == sElement)) {
				attributeCount[depth]++;
			}

			if (state == sInitial) {
				state = sDeclaration;
				boundary = '>';
			}
			else if (state == sDeclaration) {
				state = sPreElement;
				boundary = '<';
			}
			else if (state == sPreElement) {
				state = sElement;
				boundary = ' />';
			}
			else if (state == sElement) {
				depth++;
				attributeCount.push(0);
				if (c == '/') {
					state = sEndElement;
					boundary = '>';
				}
				else if (c == ' ') {
					state = sAttribute;
					boundary = '/=>';
				}
				else if (c == '>') {
					state = sContent;
					boundary = '<';
				}
			}
			else if (state == sAttribute) {
				if (c == '=' ) {
					state = sAttrNML;
					boundary = '\'"';
				}
				else if (c == '>') {
					state = sContent;
					boundary = '<';
				}
			}
			else if (state == sAttrNML) {
				state = sValue;
				boundary = c;
			}
			else if (state == sValue) {
				state = sAttribute;
				boundary = '=/>';
			}
			else if (state == sEndElement) {
				attributeCount.pop();
				depth--;
				state = sPreElement;
				boundary = '<';
			}
			else if (state == sContent) {
				state = sElement;
				boundary = ' />';
			}
			else if (state == sElementBoundary) {
				attributeCount = 0;
				state = sPreElement;
				boundary = '<';
			}

			token = '';
		}
		else {
			token += c;
		}

	}
}

module.exports = {
	parse : function(s,callback) {
		return staxParse(s,callback);
	},
	sInitial : sInitial,
	Declaration : sDeclaration,
	sPreElement : sPreElement,
	sElement : sElement,
	sAttribute : sAttribute,
	sAttrNML : sAttrNML,
	sValue : sValue,
	sEndElement : sEndElement,
	sNML : sNML,
	sContent : sContent,
	sElementBoundary : sElementBoundary,
	sAttributeSpacer : sAttributeSpacer
}<commit_msg>Support <empty/> elements<commit_after>/*

stacking xml parser

*/

'use strict';

const sInitial = 0;
const sDeclaration = 1;
const sPreElement = 2;
const sElement = 3;
const sAttribute = 5;
const sAttrNML = 6;
const sValue = 7;
const sEndElement = 9;
const sNML = 10;
const sContent = 11;
const sElementBoundary = 12;
const sAttributeSpacer = 14;
const sComment = 16;

var state = sInitial;
var boundary;
var token;
var attributeCount;
var depth;

function reset() {
	state = sInitial;
	token = '';
	boundary = '<';
	attributeCount = 0;
	depth = 0;
	attributeCount = [0];
}

function staxParse(s,callback) {

	//comments, processing instructions, CDATA segments

	var c;
	var keepToken = false;
	reset();

	for (var i=0;i<s.length;i++) {
		c = s.charAt(i);

		if ((c == '\t') || (c == '\r') || (c == '\n')) {
			c = ' ';
		}

		if (boundary.indexOf(c)>=0) {

			token = token.trim();
			keepToken = false;
			if (((state & 1) == 1) && (token != '')) {
				callback(state,token); // nonstandard space handling
			}
			if ((state == sAttribute) || (state == sElement)) {
				attributeCount[depth]++;
			}

			if (state == sInitial) {
				state = sDeclaration;
				boundary = '>';
			}
			else if (state == sDeclaration) {
				state = sPreElement;
				boundary = '<';
			}
			else if (state == sPreElement) {
				state = sElement;
				boundary = ' />';
			}
			else if (state == sElement) {
				depth++;
				attributeCount.push(0);
				if (c == '/') {
					state = sEndElement;
					boundary = '>';
					callback(sContent,'');
					keepToken = true;
				}
				else if (c == ' ') {
					state = sAttribute;
					boundary = '/=>';
				}
				else if (c == '>') {
					state = sContent;
					boundary = '<';
				}
			}
			else if (state == sAttribute) {
				if (c == '=' ) {
					state = sAttrNML;
					boundary = '\'"';
				}
				else if (c == '>') {
					state = sContent;
					boundary = '<';
				}
			}
			else if (state == sAttrNML) {
				state = sValue;
				boundary = c;
			}
			else if (state == sValue) {
				state = sAttribute;
				boundary = '=/>';
			}
			else if (state == sEndElement) {
				attributeCount.pop();
				depth--;
				state = sPreElement;
				boundary = '<';
			}
			else if (state == sContent) {
				state = sElement;
				boundary = ' />';
			}
			else if (state == sElementBoundary) {
				attributeCount = 0;
				state = sPreElement;
				boundary = '<';
			}

			if (!keepToken) token = '';
		}
		else {
			token += c;
		}

	}
}

module.exports = {
	parse : function(s,callback) {
		return staxParse(s,callback);
	},
	sInitial : sInitial,
	Declaration : sDeclaration,
	sPreElement : sPreElement,
	sElement : sElement,
	sAttribute : sAttribute,
	sAttrNML : sAttrNML,
	sValue : sValue,
	sEndElement : sEndElement,
	sNML : sNML,
	sContent : sContent,
	sElementBoundary : sElementBoundary,
	sAttributeSpacer : sAttributeSpacer
}<|endoftext|>


<commit_before>import * as t from './action-types';

// todo: remove these links
// Flux Standard Actions: https://github.com/acdlite/flux-standard-action
// Redux Standard API-calling Action:
//   https://github.com/agraboso/redux-api-middleware#redux-standard-api-calling-actions

export const action = () => ({
  type: t.ACTION,
  payload: { /* todo: add or remove payload */ },
});

// redux-api-middleware action creators
// import { CALL_API } from 'redux-api-middleware';

// export const apiAction = () => ({
//   [CALL_API]: {
//     endpoint: '/api-end-point',
//     method: 'GET', // POST, PUT, DELETE, PATCH
//     types: [t.ACTION_REQUEST, t.ACTION_SUCCESS, t.ACTION_FAILURE],
//   }
// });

// thunk middleware action creators
// import fetch from 'isomorphic-fetch';

// export const apiAction = () => {
//   return dispatch => {
//     dispatch(actionRequest());

//     return fetch('api-endpoint-url')
//       .then(data => data.json())
//       .then(data => dispatch(actionSuccess(data)))
//       .catch(err => dispatch(actionFailure(err)));
//   }
// };

// export const actionRequest = () => ({
//   type: t.ACTION_REQUEST,
//   payload: { /* todo: add or remove payload */ },
// });

// export const actionSuccess = (data) => ({
//   type: t.ACTION_SUCCESS,
//   payload: data,
// });

// export const actionFailure = (err) => ({
//   type: t.ACTION_FAILURE,
//   payload: err,
//   error: true,
// });
<commit_msg>Reorder thunk style action creators<commit_after>import * as t from './action-types';

// todo: remove these links
// Flux Standard Actions: https://github.com/acdlite/flux-standard-action
// Redux Standard API-calling Action:
//   https://github.com/agraboso/redux-api-middleware#redux-standard-api-calling-actions

export const action = () => ({
  type: t.ACTION,
  payload: { /* todo: add or remove payload */ },
});

// redux-api-middleware action creators
// import { CALL_API } from 'redux-api-middleware';

// export const apiAction = () => ({
//   [CALL_API]: {
//     endpoint: '/api-end-point',
//     method: 'GET', // POST, PUT, DELETE, PATCH
//     types: [t.ACTION_REQUEST, t.ACTION_SUCCESS, t.ACTION_FAILURE],
//   }
// });

// thunk middleware action creators
// import fetch from 'isomorphic-fetch';

// export const actionRequest = () => ({
//   type: t.ACTION_REQUEST,
//   payload: { /* todo: add or remove payload */ },
// });

// export const actionSuccess = (data) => ({
//   type: t.ACTION_SUCCESS,
//   payload: data,
// });

// export const actionFailure = (err) => ({
//   type: t.ACTION_FAILURE,
//   payload: err,
//   error: true,
// });

// export const apiAction = () => {
//   return dispatch => {
//     dispatch(actionRequest());

//     return fetch('api-endpoint-url')
//       .then(data => data.json())
//       .then(data => dispatch(actionSuccess(data)))
//       .catch(err => dispatch(actionFailure(err)));
//   }
// };
<|endoftext|>


<commit_before>Kwf.EyeCandy.List.Plugins.ActiveListener.LargeContentAjax = Ext.extend(Kwf.EyeCandy.List.Plugins.Abstract, {
    init: function() {
        this.activeItem = null;
        this.list.on('activeChanged', function(item) {
            this._activate(item);
        }, this);

        this.largeContainer = this.list.el.child(this.largeContainerSelector);
        this.largeContent = {};
        this.fetchedItems = {};
    },

    _loadItem: function(item, options)
    {
        if (this.largeContent[item.id]) return; //already loaded/loading

        this.largeContent[item.id] = this.largeContainer.createChild({
            html: '

'
        });
        this.largeContent[item.id].enableDisplayMode('block');
        if (!options.visible) {
            this.largeContent[item.id].hide();
        }

        var url = '/kwf/util/kwc/render';
        if (Kwf.Debug.rootFilename) url = Kwf.Debug.rootFilename + url;

        Ext.Ajax.request({
            params: { url: item.el.child('a').dom.href },
            url: url,
            success: function(response) {
                var contentEl = this.largeContent[item.id].createChild();
                this.largeContent[item.id].setStyle('position', 'absolute');
                this.fetchedItems[item.id] = true;
                contentEl.update(response.responseText);

                if (this.largeContent[item.id].isVisible()) {

                    var previousHeight = this.largeContainer.getHeight();
                    this.largeContainer.setHeight(this.largeContent[item.id].getHeight()); //set to new height, not animated
                    Kwf.callOnContentReady(contentEl.dom, {newRender: true});
                    contentEl.hide(); //hide after callOnContentReady, will be faded in after images loaded
                    this.largeContainer.setHeight(previousHeight, false); //set back to previous height, not animated
                    this.largeContainer.setHeight(this.largeContent[item.id].getHeight(), true); //animate to new height

                    var showContent = function() {
                        this.largeContent[item.id].child('.loading').remove();
                        contentEl.fadeIn();
                        if (options && options.success) {
                            options.success.call(options.scope || this);
                        }
                    };

                    var imagesToLoad = 0;
                    contentEl.query('img').each(function(imgEl) {
                        imagesToLoad++;
                        imgEl.onload = (function() {
                            imagesToLoad--;
                            if (imagesToLoad <= 0) showContent.call(this);
                        }).createDelegate(this);
                    }, this);

                    if (imagesToLoad == 0) showContent.call(this);

                } else {
                    this.largeContent[item.id].child('.loading').remove();
                    this.largeContent[item.id].show();
                    this.largeContent[item.id].hide();
                    Kwf.callOnContentReady(this.largeContent[item.id].dom, {newRender: true});
                }
            },
            scope: this
        });

    },
    _activate: function(item)
    {
        var nextItem = this.list.getItem(item.listIndex+1);
        if (nextItem && !this.largeContent[nextItem.id]) {
            //preload
            this._loadItem.defer(1000, this, [nextItem, {visible: false}]);
        }

        if (!this.activeItem) {
            //the first one activated must be already shown in largeContainer
            this.largeContent[item.id] = this.largeContainer.child('div');
            this.largeContent[item.id].enableDisplayMode('block');
            this.largeContent[item.id].setStyle('position', 'absolute');
            this.largeContainer.setHeight(this.largeContent[item.id].getHeight());
            this.activeItem = item;
            return;
        }

        this._loadItem(item, {visible: true});

        var activeEl = this.largeContent[this.activeItem.id];
        var nextEl = this.largeContent[item.id];

        if (this.fetchedItems[item.id]) {
            nextEl.show();
            var oldHeight = this.largeContainer.getHeight();
            this.largeContainer.setHeight(nextEl.getHeight()); //set new height without animation
            Kwf.callOnContentReady(nextEl.dom, {newRender: false});
            this.largeContainer.setHeight(oldHeight); //set previous height without animation
            this.largeContainer.setHeight(nextEl.getHeight(), true); //and now animate to new height
            nextEl.hide();
        }

        if (this.transition == 'fade') {
            activeEl.dom.style.zIndex = 2;

            nextEl.dom.style.zIndex = 1;
            nextEl.show();

            activeEl.fadeOut(Ext.applyIf({
                useDisplay: true
            }, this.transitionConfig));
        } else if (this.transition == 'slide') {
            activeEl.slideOut(
                this.activeItem.listIndex < item.listIndex ? 'l' : 'r',
                Ext.applyIf({
                    remove: false,
                    useDisplay: true
                }, this.transitionConfig)
            );
            nextEl.slideIn(
                this.activeItem.listIndex < item.listIndex ? 'r' : 'l',
                Ext.applyIf({
                    remove: false,
                    useDisplay: true
                }, this.transitionConfig)
            );
        } else {
            //default, no fx; switch hard
            activeEl.hide();
            nextEl.show();
        }

        Kwf.Statistics.count(item.el.child('a').dom.href);

        this.activeItem = item;
    }
});
<commit_msg>fade in new element above old instead of fading out old above new<commit_after>Kwf.EyeCandy.List.Plugins.ActiveListener.LargeContentAjax = Ext.extend(Kwf.EyeCandy.List.Plugins.Abstract, {
    init: function() {
        this.activeItem = null;
        this.list.on('activeChanged', function(item) {
            this._activate(item);
        }, this);

        this.largeContainer = this.list.el.child(this.largeContainerSelector);
        this.largeContent = {};
        this.fetchedItems = {};
    },

    _loadItem: function(item, options)
    {
        if (this.largeContent[item.id]) return; //already loaded/loading

        this.largeContent[item.id] = this.largeContainer.createChild({
            html: '

'
        });
        this.largeContent[item.id].enableDisplayMode('block');
        if (!options.visible) {
            this.largeContent[item.id].hide();
        }

        var url = '/kwf/util/kwc/render';
        if (Kwf.Debug.rootFilename) url = Kwf.Debug.rootFilename + url;

        Ext.Ajax.request({
            params: { url: item.el.child('a').dom.href },
            url: url,
            success: function(response) {
                var contentEl = this.largeContent[item.id].createChild();
                this.largeContent[item.id].setStyle('position', 'absolute');
                this.fetchedItems[item.id] = true;
                contentEl.update(response.responseText);

                if (this.largeContent[item.id].isVisible()) {

                    var previousHeight = this.largeContainer.getHeight();
                    this.largeContainer.setHeight(this.largeContent[item.id].getHeight()); //set to new height, not animated
                    Kwf.callOnContentReady(contentEl.dom, {newRender: true});
                    contentEl.hide(); //hide after callOnContentReady, will be faded in after images loaded
                    this.largeContainer.setHeight(previousHeight, false); //set back to previous height, not animated
                    this.largeContainer.setHeight(this.largeContent[item.id].getHeight(), true); //animate to new height

                    var showContent = function() {
                        this.largeContent[item.id].child('.loading').remove();
                        contentEl.fadeIn();
                        if (options && options.success) {
                            options.success.call(options.scope || this);
                        }
                    };

                    var imagesToLoad = 0;
                    contentEl.query('img').each(function(imgEl) {
                        imagesToLoad++;
                        imgEl.onload = (function() {
                            imagesToLoad--;
                            if (imagesToLoad <= 0) showContent.call(this);
                        }).createDelegate(this);
                    }, this);

                    if (imagesToLoad == 0) showContent.call(this);

                } else {
                    this.largeContent[item.id].child('.loading').remove();
                    this.largeContent[item.id].show();
                    this.largeContent[item.id].hide();
                    Kwf.callOnContentReady(this.largeContent[item.id].dom, {newRender: true});
                }
            },
            scope: this
        });

    },
    _activate: function(item)
    {
        var nextItem = this.list.getItem(item.listIndex+1);
        if (nextItem && !this.largeContent[nextItem.id]) {
            //preload
            this._loadItem.defer(1000, this, [nextItem, {visible: false}]);
        }

        if (!this.activeItem) {
            //the first one activated must be already shown in largeContainer
            this.largeContent[item.id] = this.largeContainer.child('div');
            this.largeContent[item.id].enableDisplayMode('block');
            this.largeContent[item.id].setStyle('position', 'absolute');
            this.largeContainer.setHeight(this.largeContent[item.id].getHeight());
            this.activeItem = item;
            return;
        }

        this._loadItem(item, {visible: true});

        var activeEl = this.largeContent[this.activeItem.id];
        var nextEl = this.largeContent[item.id];

        if (this.fetchedItems[item.id]) {
            nextEl.show();
            var oldHeight = this.largeContainer.getHeight();
            this.largeContainer.setHeight(nextEl.getHeight()); //set new height without animation
            Kwf.callOnContentReady(nextEl.dom, {newRender: false});
            this.largeContainer.setHeight(oldHeight); //set previous height without animation
            this.largeContainer.setHeight(nextEl.getHeight(), true); //and now animate to new height
            nextEl.hide();
        }

        if (this.transition == 'fade') {
            activeEl.dom.style.zIndex = 1;
            nextEl.dom.style.zIndex = 2;

            nextEl.fadeIn(Ext.applyIf({
                useDisplay: true,
                callback: function() {
                    activeEl.hide();
                },
                scope: this
            }, this.transitionConfig));
        } else if (this.transition == 'slide') {
            activeEl.slideOut(
                this.activeItem.listIndex < item.listIndex ? 'l' : 'r',
                Ext.applyIf({
                    remove: false,
                    useDisplay: true
                }, this.transitionConfig)
            );
            nextEl.slideIn(
                this.activeItem.listIndex < item.listIndex ? 'r' : 'l',
                Ext.applyIf({
                    remove: false,
                    useDisplay: true
                }, this.transitionConfig)
            );
        } else {
            //default, no fx; switch hard
            activeEl.hide();
            nextEl.show();
        }

        Kwf.Statistics.count(item.el.child('a').dom.href);

        this.activeItem = item;
    }
});
<|endoftext|>


<commit_before>module.exports = {
    id: "android",
    initialize:function() {
        var channel = require("cordova/channel"),
            cordova = require('cordova'),
            callback = require('cordova/plugin/android/callback'),
            polling = require('cordova/plugin/android/polling'),
            exec = require('cordova/exec');

        channel.onDestroy.subscribe(function() {
            cordova.shuttingDown = true;
        });

        // Start listening for XHR callbacks
        // Figure out which bridge approach will work on this Android
        // device: polling or XHR-based callbacks
        setTimeout(function() {
            if (cordova.UsePolling) {
                polling();
            }
            else {
                var isPolling = prompt("usePolling", "gap_callbackServer:");
                cordova.UsePolling = isPolling;
                if (isPolling == "true") {
                    cordova.UsePolling = true;
                    polling();
                } else {
                    cordova.UsePolling = false;
                    callback();
                }
            }
        }, 1);

        // Inject a listener for the backbutton on the document.
        var backButtonChannel = cordova.addDocumentEventHandler('backbutton', {
            onSubscribe:function() {
                // If we just attached the first handler, let native know we need to override the back button.
                if (this.numHandlers === 1) {
                    exec(null, null, "App", "overrideBackbutton", [true]);
                }
            },
            onUnsubscribe:function() {
                // If we just detached the last handler, let native know we no longer override the back button.
                if (this.numHandlers === 0) {
                    exec(null, null, "App", "overrideBackbutton", [false]);
                }
            }
        });

        // Add hardware MENU and SEARCH button handlers
        cordova.addDocumentEventHandler('menubutton');
        cordova.addDocumentEventHandler('searchbutton');

        // Figure out if we need to shim-in localStorage and WebSQL
        // support from the native side.
        var storage = require('cordova/plugin/android/storage');

        // First patch WebSQL if necessary
        if (typeof window.openDatabase == 'undefined') {
            // Not defined, create an openDatabase function for all to use!
            window.openDatabase = storage.openDatabase;
        } else {
            // Defined, but some Android devices will throw a SECURITY_ERR -
            // so we wrap the whole thing in a try-catch and shim in our own
            // if the device has Android bug 16175.
            var originalOpenDatabase = window.openDatabase;
            window.openDatabase = function(name, version, desc, size) {
                var db = null;
                try {
                    db = originalOpenDatabase(name, version, desc, size);
                }
                catch (ex) {
                    if (ex.code === 18) {
                        db = null;
                    } else {
                        throw ex;
                    }
                }

                if (db === null) {
                    return storage.openDatabase(name, version, desc, size);
                }
                else {
                    return db;
                }

            };
        }

        // Patch localStorage if necessary
        if (typeof window.localStorage == 'undefined' || window.localStorage === null) {
            window.localStorage = new storage.CupcakeLocalStorage();
        }

        // Let native code know we are all done on the JS side.
        // Native code will then un-hide the WebView.
        channel.join(function() {
            prompt("", "gap_init:");
        }, [channel.onCordovaReady]);
    },
    objects: {
        cordova: {
            children: {
                JSCallback:{
                    path:"cordova/plugin/android/callback"
                },
                JSCallbackPolling:{
                    path:"cordova/plugin/android/polling"
                }
            }
        },
        navigator: {
            children: {
                app:{
                    path: "cordova/plugin/android/app"
                }
            }
        },
        device:{
            path: "cordova/plugin/android/device"
        },
        File: { // exists natively on Android WebView, override
            path: "cordova/plugin/File"
        },
        FileReader: { // exists natively on Android WebView, override
            path: "cordova/plugin/FileReader"
        },
        FileError: { //exists natively on Android WebView on Android 4.x
            path: "cordova/plugin/FileError"
        },
        MediaError: { // exists natively on Android WebView on Android 4.x
            path: "cordova/plugin/MediaError"
        }
    },
    merges: {
        navigator: {
            children: {
                notification: {
                    path: 'cordova/plugin/android/notification'
                }
            }
        }
    }
};
<commit_msg>[CB-481] showing webview on init.. this got removed in the CordovaWebView merge. This also means all cordova android apps got introduced a 1-2 second delay on initialization recently...<commit_after>module.exports = {
    id: "android",
    initialize:function() {
        var channel = require("cordova/channel"),
            cordova = require('cordova'),
            callback = require('cordova/plugin/android/callback'),
            polling = require('cordova/plugin/android/polling'),
            exec = require('cordova/exec');

        channel.onDestroy.subscribe(function() {
            cordova.shuttingDown = true;
        });

        // Start listening for XHR callbacks
        // Figure out which bridge approach will work on this Android
        // device: polling or XHR-based callbacks
        setTimeout(function() {
            if (cordova.UsePolling) {
                polling();
            }
            else {
                var isPolling = prompt("usePolling", "gap_callbackServer:");
                cordova.UsePolling = isPolling;
                if (isPolling == "true") {
                    cordova.UsePolling = true;
                    polling();
                } else {
                    cordova.UsePolling = false;
                    callback();
                }
            }
        }, 1);

        // Inject a listener for the backbutton on the document.
        var backButtonChannel = cordova.addDocumentEventHandler('backbutton', {
            onSubscribe:function() {
                // If we just attached the first handler, let native know we need to override the back button.
                if (this.numHandlers === 1) {
                    exec(null, null, "App", "overrideBackbutton", [true]);
                }
            },
            onUnsubscribe:function() {
                // If we just detached the last handler, let native know we no longer override the back button.
                if (this.numHandlers === 0) {
                    exec(null, null, "App", "overrideBackbutton", [false]);
                }
            }
        });

        // Add hardware MENU and SEARCH button handlers
        cordova.addDocumentEventHandler('menubutton');
        cordova.addDocumentEventHandler('searchbutton');

        // Figure out if we need to shim-in localStorage and WebSQL
        // support from the native side.
        var storage = require('cordova/plugin/android/storage');

        // First patch WebSQL if necessary
        if (typeof window.openDatabase == 'undefined') {
            // Not defined, create an openDatabase function for all to use!
            window.openDatabase = storage.openDatabase;
        } else {
            // Defined, but some Android devices will throw a SECURITY_ERR -
            // so we wrap the whole thing in a try-catch and shim in our own
            // if the device has Android bug 16175.
            var originalOpenDatabase = window.openDatabase;
            window.openDatabase = function(name, version, desc, size) {
                var db = null;
                try {
                    db = originalOpenDatabase(name, version, desc, size);
                }
                catch (ex) {
                    if (ex.code === 18) {
                        db = null;
                    } else {
                        throw ex;
                    }
                }

                if (db === null) {
                    return storage.openDatabase(name, version, desc, size);
                }
                else {
                    return db;
                }

            };
        }

        // Patch localStorage if necessary
        if (typeof window.localStorage == 'undefined' || window.localStorage === null) {
            window.localStorage = new storage.CupcakeLocalStorage();
        }

        // Let native code know we are all done on the JS side.
        // Native code will then un-hide the WebView.
        channel.join(function() {
            exec(null, null, "App", "show", []);
        }, [channel.onCordovaReady]);
    },
    objects: {
        cordova: {
            children: {
                JSCallback:{
                    path:"cordova/plugin/android/callback"
                },
                JSCallbackPolling:{
                    path:"cordova/plugin/android/polling"
                }
            }
        },
        navigator: {
            children: {
                app:{
                    path: "cordova/plugin/android/app"
                }
            }
        },
        device:{
            path: "cordova/plugin/android/device"
        },
        File: { // exists natively on Android WebView, override
            path: "cordova/plugin/File"
        },
        FileReader: { // exists natively on Android WebView, override
            path: "cordova/plugin/FileReader"
        },
        FileError: { //exists natively on Android WebView on Android 4.x
            path: "cordova/plugin/FileError"
        },
        MediaError: { // exists natively on Android WebView on Android 4.x
            path: "cordova/plugin/MediaError"
        }
    },
    merges: {
        navigator: {
            children: {
                notification: {
                    path: 'cordova/plugin/android/notification'
                }
            }
        }
    }
};
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import { Button } from 'react-bootstrap';
import { ButtonToolbar } from 'react-bootstrap';
import { FormControl } from 'react-bootstrap';
import { FormGroup } from 'react-bootstrap';
import { ControlLabel } from 'react-bootstrap';
import { HelpBlock } from 'react-bootstrap';
import { Modal } from 'react-bootstrap';
import Layout from '../Layout/Layout';
import './App.css';

/**
 * Rotations App
 *
 * @TODO:
 * - Handle adding people with same name.
 * - Add undo capabilities.
 * - Remove people.
 * - Handle latecomers properly (number of rounds may no longer be n - 1).
 */

let offset = null, interval = null

class App extends Component {
  constructor(props) {
    super(props);
    this.state = this.getInitialState();
    this.handleUserChange = this.handleUserChange.bind(this);
    this.handleAddPerson = this.handleAddPerson.bind(this);
    this.handleKeyPress = this.handleKeyPress.bind(this);
    this.handleStart = this.handleStart.bind(this);
    this.handleResetAttempt = this.handleResetAttempt.bind(this);
    this.handleReset = this.handleReset.bind(this);
    this.handleHideResetModal = this.handleHideResetModal.bind(this);
    this.handleRotate = this.handleRotate.bind(this);
    this.handlePause = this.handlePause.bind(this);
    this.handleResume = this.handleResume.bind(this);
  }

  getInitialState() {
    return {
      newPerson: "",
      people:[],
      roundNumber: 0,
      statusMessage: "Add 4 or more participants. When you're ready, press start.",
      validationMessage: "",
      showResetModal: false,
      clock: 0,
      time: '',
      paused: false,
    };
  }

  handleUserChange(event){
    this.setState({ newPerson: event.target.value });
  }

  handleAddPerson(event) {
    if (this.state.newPerson === '') {
      this.setState({ validationMessage: "Enter a valid name." })
      return false;
    }

    let people = this.state.people;
    let newPerson = {
      key: people.length,
      name: this.state.newPerson
    };

    if (people.length % 2 == 0) {
      this.setState({
        people: [].concat(
          people.slice(0, (people.length + 1) / 2),
          newPerson,
          people.slice((people.length + 1) / 2, people.length)
        ),
        newPerson: '',
        validationMessage: '',
      });
    }
    else {
      this.setState({
        people: people.concat([newPerson]),
        newPerson: '',
        validationMessage: '',
      });

    }

    return true;
  }

  handleKeyPress(event) {
    if (event.key === 'Enter') {
      this.handleAddPerson(event);
    }
  }

  handleStart() {
    // Check if there's enough people to start the game
    if (!this.canContinue()) {
      this.setState({
        validationMessage: "There isn't enough people to start the game."
      })
      return false;
    }

    // Increment roundNumber 1
    this.setState({
      roundNumber: this.state.roundNumber + 1,
      statusMessage: "Round 1 of " + (this.state.people.length - 1),
    });

    this.play();

  }

  handleResetAttempt() {
    this.setState({ showResetModal: true });
  }

  handleReset() {
    this.setState(this.getInitialState());
  }

  handleHideResetModal() {
    this.setState({ showResetModal: false });
  }

  handleRotate() {
    // Check if there's enough people to perform rotations
    if (!this.canContinue()) {
      return false;
    }

    let people = this.state.people.slice(0);

    let head = people.shift();
    let second = people.shift();
    let third = people.shift();
    let tail = people.pop();
    people.unshift(third);
    people.unshift(head);

    this.setState({
      people: [].concat(
        people.slice(0, (people.length + 1) / 2),
        tail,
        second,
        people.slice((people.length + 1) / 2, people.length)
      ),
      roundNumber: this.state.roundNumber + 1,
      statusMessage: "Round " + (this.state.roundNumber + 1) + " of " + (this.state.people.length - 1),
    });

    this.reset();
    this.play();

    return true;
  }

  handlePause() {
    this.pause();
  }

  handleResume() {
    this.play();
  }

  canContinue() {

    let enoughPeople = true;

    // There needs to be 4 or more people.
    if (this.state.people.length < 4) {
      enoughPeople = false;
    }
    // There can only be n - 1 rounds.
    if (this.state.roundNumber >= (this.state.people.length - 1)) {
      enoughPeople = false;
    }

    return enoughPeople;
  }

  // Timer functions

  play() {
    if (!interval) {
      offset = Date.now();
      interval = setInterval(this.update.bind(this), 1000);
      this.setState({paused: false});
    }
  }

  pause() {
    if (interval) {
      clearInterval(interval);
      interval = null;
    }
    this.setState({paused: true});
  }

  reset() {
    let clockReset = 0;
    this.setState({clock: clockReset });
    let time = this.secondsToHms(clockReset / 1000);
    this.setState({time: time });
  }

  update() {
    let clock = this.state.clock;
    clock += this.calculateOffset();
    this.setState({clock: clock });
    let time = this.secondsToHms(clock / 1000);
    this.setState({time: time });
  }

  calculateOffset() {
    let now = Date.now();
    let newOffset = now - offset;
    offset = now;
    return newOffset
  }

  secondsToHms(totalSeconds) {
    let hours   = Math.floor(totalSeconds / 3600);
    let minutes = Math.floor((totalSeconds - (hours * 3600)) / 60);
    let seconds = totalSeconds - (hours * 3600) - (minutes * 60);

    // round seconds
    seconds = Math.round(seconds);

    let result = (hours < 10 ? "0" + hours : hours);
    result += ":" + (minutes < 10 ? "0" + minutes : minutes);
    result += ":" + (seconds  < 10 ? "0" + seconds : seconds);
    return result;
  }

  render() {
    let validationStatus = null;

    if (this.state.validationMessage !== "") {
      validationStatus = "error";
    }

    return (

            Rotations

          <FormGroup className="flex-center-block" validationState={validationStatus}>

              <ControlLabel>New Participant:</ControlLabel>
              <FormControl type="text" id="new-user" placeholder="Enter name" value={this.state.newPerson} onChange={this.handleUserChange} onKeyPress={this.handleKeyPress} />
              <HelpBlock>{this.state.validationMessage}</HelpBlock>

          </FormGroup>
          <FormGroup className="flex-center-block">
            <ButtonToolbar>
              <Button className="action__add-person" bsStyle="primary" onClick={this.handleAddPerson}>Add Participant</Button>
              { this.state.people.length > 0 ? <Button className="action__reset" bsStyle="danger" onClick={this.handleResetAttempt}>Reset</Button> : false }
              { this.state.people.length> 3 && this.state.roundNumber === 0 ? <Button className="action__start" bsStyle="info" onClick={this.handleStart}>Start</Button> : false }
              { this.state.roundNumber > 0 ? <Button className="action__rotate" bsStyle="success" onClick={this.handleRotate}>Rotate</Button> : false }
            </ButtonToolbar>
          </FormGroup>

{this.state.statusMessage}

{this.state.time === '' ? "00:00:00" : this.state.time}

                  <ButtonToolbar>
                    { this.state.paused ? <Button className="action__resume" bsStyle="info" onClick={this.handleResume}></Button> : false }
                    { !this.state.paused ? <Button className="action__pause" bsStyle="" onClick={this.handlePause}></Button> : false }
                  </ButtonToolbar>

        <Layout people={this.state.people}/>

        <Modal
          {...this.props}
          show={this.state.showResetModal}
          onHide={this.handleHideResetModal}
          dialogClassName="custom-modal"
        >
          <Modal.Header closeButton>
            <Modal.Title id="contained-modal-title-lg">Reset Game</Modal.Title>
          </Modal.Header>
          <Modal.Body>

Are you sure you want to reset the game?

Pressing Reset will delete every participant.

          </Modal.Body>
          <Modal.Footer>
            <Button onClick={this.handleHideResetModal} >Cancel</Button>
            <Button onClick={this.handleReset} bsStyle="danger" >Reset</Button>
          </Modal.Footer>
        </Modal>

    );
  }
}

export default App;
<commit_msg>Clear interval on handleReset method.<commit_after>import React, {Component} from 'react';
import { Button } from 'react-bootstrap';
import { ButtonToolbar } from 'react-bootstrap';
import { FormControl } from 'react-bootstrap';
import { FormGroup } from 'react-bootstrap';
import { ControlLabel } from 'react-bootstrap';
import { HelpBlock } from 'react-bootstrap';
import { Modal } from 'react-bootstrap';
import Layout from '../Layout/Layout';
import './App.css';

/**
 * Rotations App
 *
 * @TODO:
 * - Handle adding people with same name.
 * - Add undo capabilities.
 * - Remove people.
 * - Handle latecomers properly (number of rounds may no longer be n - 1).
 */

let offset = null, interval = null

class App extends Component {
  constructor(props) {
    super(props);
    this.state = this.getInitialState();
    this.handleUserChange = this.handleUserChange.bind(this);
    this.handleAddPerson = this.handleAddPerson.bind(this);
    this.handleKeyPress = this.handleKeyPress.bind(this);
    this.handleStart = this.handleStart.bind(this);
    this.handleResetAttempt = this.handleResetAttempt.bind(this);
    this.handleReset = this.handleReset.bind(this);
    this.handleHideResetModal = this.handleHideResetModal.bind(this);
    this.handleRotate = this.handleRotate.bind(this);
    this.handlePause = this.handlePause.bind(this);
    this.handleResume = this.handleResume.bind(this);
  }

  getInitialState() {
    return {
      newPerson: "",
      people:[],
      roundNumber: 0,
      statusMessage: "Add 4 or more participants. When you're ready, press start.",
      validationMessage: "",
      showResetModal: false,
      clock: 0,
      time: '',
      paused: false,
    };
  }

  handleUserChange(event){
    this.setState({ newPerson: event.target.value });
  }

  handleAddPerson(event) {
    if (this.state.newPerson === '') {
      this.setState({ validationMessage: "Enter a valid name." })
      return false;
    }

    let people = this.state.people;
    let newPerson = {
      key: people.length,
      name: this.state.newPerson
    };

    if (people.length % 2 == 0) {
      this.setState({
        people: [].concat(
          people.slice(0, (people.length + 1) / 2),
          newPerson,
          people.slice((people.length + 1) / 2, people.length)
        ),
        newPerson: '',
        validationMessage: '',
      });
    }
    else {
      this.setState({
        people: people.concat([newPerson]),
        newPerson: '',
        validationMessage: '',
      });

    }

    return true;
  }

  handleKeyPress(event) {
    if (event.key === 'Enter') {
      this.handleAddPerson(event);
    }
  }

  handleStart() {
    // Check if there's enough people to start the game
    if (!this.canContinue()) {
      this.setState({
        validationMessage: "There isn't enough people to start the game."
      })
      return false;
    }

    // Increment roundNumber 1
    this.setState({
      roundNumber: this.state.roundNumber + 1,
      statusMessage: "Round 1 of " + (this.state.people.length - 1),
    });

    this.play();

  }

  handleResetAttempt() {
    this.setState({ showResetModal: true });
  }

  handleReset() {
    this.pause();
    this.reset();
    this.setState(this.getInitialState());
  }

  handleHideResetModal() {
    this.setState({ showResetModal: false });
  }

  handleRotate() {
    // Check if there's enough people to perform rotations
    if (!this.canContinue()) {
      return false;
    }

    let people = this.state.people.slice(0);

    let head = people.shift();
    let second = people.shift();
    let third = people.shift();
    let tail = people.pop();
    people.unshift(third);
    people.unshift(head);

    this.setState({
      people: [].concat(
        people.slice(0, (people.length + 1) / 2),
        tail,
        second,
        people.slice((people.length + 1) / 2, people.length)
      ),
      roundNumber: this.state.roundNumber + 1,
      statusMessage: "Round " + (this.state.roundNumber + 1) + " of " + (this.state.people.length - 1),
    });

    this.pause();
    this.reset();
    this.play();

    return true;
  }

  handlePause() {
    this.pause();
  }

  handleResume() {
    this.play();
  }

  canContinue() {

    let enoughPeople = true;

    // There needs to be 4 or more people.
    if (this.state.people.length < 4) {
      enoughPeople = false;
    }
    // There can only be n - 1 rounds.
    if (this.state.roundNumber >= (this.state.people.length - 1)) {
      enoughPeople = false;
    }

    return enoughPeople;
  }

  // Timer functions

  play() {
    if (!interval) {
      offset = Date.now();
      interval = setInterval(this.update.bind(this), 1000);
      this.setState({paused: false});
    }
  }

  pause() {
    if (interval) {
      clearInterval(interval);
      interval = null;
    }
    this.setState({paused: true});
  }

  reset() {
    let clockReset = 0;
    this.setState({clock: clockReset });
    let time = this.secondsToHms(clockReset / 1000);
    this.setState({time: time });
  }

  update() {
    let clock = this.state.clock;
    clock += this.calculateOffset();
    this.setState({clock: clock });
    let time = this.secondsToHms(clock / 1000);
    this.setState({time: time });
  }

  calculateOffset() {
    let now = Date.now();
    let newOffset = now - offset;
    offset = now;
    return newOffset
  }

  secondsToHms(totalSeconds) {
    let hours   = Math.floor(totalSeconds / 3600);
    let minutes = Math.floor((totalSeconds - (hours * 3600)) / 60);
    let seconds = totalSeconds - (hours * 3600) - (minutes * 60);

    // round seconds
    seconds = Math.round(seconds);

    let result = (hours < 10 ? "0" + hours : hours);
    result += ":" + (minutes < 10 ? "0" + minutes : minutes);
    result += ":" + (seconds  < 10 ? "0" + seconds : seconds);
    return result;
  }

  render() {
    let validationStatus = null;

    if (this.state.validationMessage !== "") {
      validationStatus = "error";
    }

    return (

            Rotations

          <FormGroup className="flex-center-block" validationState={validationStatus}>

              <ControlLabel>New Participant:</ControlLabel>
              <FormControl type="text" id="new-user" placeholder="Enter name" value={this.state.newPerson} onChange={this.handleUserChange} onKeyPress={this.handleKeyPress} />
              <HelpBlock>{this.state.validationMessage}</HelpBlock>

          </FormGroup>
          <FormGroup className="flex-center-block">
            <ButtonToolbar>
              <Button className="action__add-person" bsStyle="primary" onClick={this.handleAddPerson}>Add Participant</Button>
              { this.state.people.length > 0 ? <Button className="action__reset" bsStyle="danger" onClick={this.handleResetAttempt}>Reset</Button> : false }
              { this.state.people.length> 3 && this.state.roundNumber === 0 ? <Button className="action__start" bsStyle="info" onClick={this.handleStart}>Start</Button> : false }
              { this.state.roundNumber > 0 ? <Button className="action__rotate" bsStyle="success" onClick={this.handleRotate}>Rotate</Button> : false }
            </ButtonToolbar>
          </FormGroup>

{this.state.statusMessage}

{this.state.time === '' ? "00:00:00" : this.state.time}

                  <ButtonToolbar>
                    { this.state.paused ? <Button className="action__resume" bsStyle="info" onClick={this.handleResume}></Button> : false }
                    { !this.state.paused ? <Button className="action__pause" bsStyle="" onClick={this.handlePause}></Button> : false }
                  </ButtonToolbar>

        <Layout people={this.state.people}/>

        <Modal
          {...this.props}
          show={this.state.showResetModal}
          onHide={this.handleHideResetModal}
          dialogClassName="custom-modal"
        >
          <Modal.Header closeButton>
            <Modal.Title id="contained-modal-title-lg">Reset Game</Modal.Title>
          </Modal.Header>
          <Modal.Body>

Are you sure you want to reset the game?

Pressing Reset will delete every participant.

          </Modal.Body>
          <Modal.Footer>
            <Button onClick={this.handleHideResetModal} >Cancel</Button>
            <Button onClick={this.handleReset} bsStyle="danger" >Reset</Button>
          </Modal.Footer>
        </Modal>

    );
  }
}

export default App;
<|endoftext|>


<commit_before>var ProceduralGeneration = ProceduralGeneration || {};

//Constructor BootState
ProceduralGeneration.BootState = function () {
    "use strict";
    Phaser.State.call(this); //llamada al constructor de la superclase
};

//Subclase extiende de superclase
ProceduralGeneration.BootState.prototype = Object.create(Phaser.State.prototype);
//Se asigna a BootState un constructor determinado
ProceduralGeneration.BootState.prototype.constructor = ProceduralGeneration.BootState;

//Override de init de la superclase
ProceduralGeneration.BootState.prototype.init = function (level_file, next_state, extra_parameters, score, life) {
    "use strict";
    this.level_file = level_file; //Ruta del JSON
    this.next_state = next_state; //Contexto de RoomState
    this.extra_parameters = extra_parameters; //Sala inicial
    this.score = score || 0;
    this.life = life || 0;

};

ProceduralGeneration.BootState.prototype.preload = function () {
    "use strict";
    //Identificador para el archivo JSON
    //Incluye también su rota de alojamiento
    this.load.text("level1", this.level_file);
};

/*
Se accede al texto del archivo JSON con el identificaddor level1
En level_text se almacena el texto JSON accediendo
a los datos caché de Phaser con el identificador level1 En level_data.
Finalmente se llama al estado LoadingState con el método game.state.start
y se le envia la key del siguiente estado, limpia el mundo, no limpiamos la caché y
le mandamos los parámetros que nos interesen
*/

//Override del metodo create de la superclase
ProceduralGeneration.BootState.prototype.create = function () {
    "use strict";
    var level_text, level_data;
    level_text = this.game.cache.getText("level1");
    level_data = JSON.parse(level_text); //traduce el archivo JSON
    //Invoca al siguiente estado LoadingState
    //Envia: level_data: JSON traducido, next_state: contexto para RoomState, extra_parameters: sala inicial
    this.game.state.start("LoadingState", true, false, level_data, this.next_state, this.extra_parameters, this.score, this.life);
};<commit_msg>Recuperación de cambios perdidos por la versión 2<commit_after>var ProceduralGeneration = ProceduralGeneration || {};

//Constructor BootState
ProceduralGeneration.BootState = function () {
    "use strict";
    Phaser.State.call(this); //llamada al constructor de la superclase
};

//Subclase extiende de superclase
ProceduralGeneration.BootState.prototype = Object.create(Phaser.State.prototype);
//Se asigna a BootState un constructor determinado
ProceduralGeneration.BootState.prototype.constructor = ProceduralGeneration.BootState;

//Override de init de la superclase
ProceduralGeneration.BootState.prototype.init = function (level_file, next_state, extra_parameters, score, life) {
    "use strict";
    this.level_file = level_file; //Ruta del JSON
    this.next_state = next_state; //Contexto de RoomState
    this.extra_parameters = extra_parameters; //Sala inicial
    this.score = score || 0;
    this.life = life || 0;
    last_door = direction;
};

ProceduralGeneration.BootState.prototype.preload = function () {
    "use strict";
    //Identificador para el archivo JSON
    //Incluye también su rota de alojamiento
    this.load.text("level1", this.level_file);
};

/*
Se accede al texto del archivo JSON con el identificaddor level1
En level_text se almacena el texto JSON accediendo
a los datos caché de Phaser con el identificador level1 En level_data.
Finalmente se llama al estado LoadingState con el método game.state.start
y se le envia la key del siguiente estado, limpia el mundo, no limpiamos la caché y
le mandamos los parámetros que nos interesen
*/

//Override del metodo create de la superclase
ProceduralGeneration.BootState.prototype.create = function () {
    "use strict";
    var level_text, level_data;
    level_text = this.game.cache.getText("level1");
    level_data = JSON.parse(level_text); //traduce el archivo JSON
    //Invoca al siguiente estado LoadingState
    //Envia: level_data: JSON traducido, next_state: contexto para RoomState, extra_parameters: sala inicial
    this.game.state.start("LoadingState", true, false, level_data, this.next_state, this.extra_parameters, this.score, this.life);
};<|endoftext|>


<commit_before>import React from 'react'
import styled from 'styled-components'
import hoverCss from './hoverCss'

const Wrapper = styled.nav`
  margin: 0 auto;
  padding: 0.5rem;
  text-align: center;
  border-bottom: 1px solid var(--border-color);
  margin-bottom: 1.0rem;
  transition: 0.4s; /* Adds a transition effect when the padding is decreased */
  position: fixed;
  width: 100%;
  background-color: var(--bg-color);
`

const Title = styled.div`
  display: inline-block;
  font-weight: bold;
  font-size: 1.3rem;
  margin: 0.2rem 0;
  padding: 0.25rem 0.5rem;
  color: var(--title-color);
  ${hoverCss};
`

const NavList = styled.ul`
  color: var(--subtitle-color);
  font-size: 0.8rem;
  line-height: 1.2rem;
  margin: 0;
  li {
    display: inline;
  }
`

const OutLink = styled.a`
  text-decoration: none;
  color: var(--subtitle-color);
  padding: 0.25rem;
  margin: 0.25rem;
  ${ hoverCss}
`
const Profile = () => (
  <Wrapper>
      <Title>
        <a
          href='/'
          style={{ textDecoration: `none`, color: `inherit` }}>Jaehyun Baek

      </Title>
      <NavList>

        <OutLink href="/" >home</OutLink>

      ·

      <OutLink href="/wiki" >wiki</OutLink>

      ·

      <OutLink href="/about" >about</OutLink>

      ·

      <OutLink href="/search" >search</OutLink>

      </NavList>
  </Wrapper>
)

export default Profile;
<commit_msg>프로필 왼쪽 정렬<commit_after>import React from 'react'
import styled from 'styled-components'
import hoverCss from './hoverCss'

const Wrapper = styled.nav`
  margin: 0 auto;
  padding: 0.5rem;
  text-align: left;
  border-bottom: 1px solid var(--border-color);
  margin-bottom: 1.0rem;
  transition: 0.4s; /* Adds a transition effect when the padding is decreased */
  position: fixed;
  width: 100%;
  background-color: var(--bg-color);
`

const Title = styled.div`
  display: inline-block;
  font-weight: bold;
  font-size: 1.3rem;
  margin: 0.2rem 0;
  padding: 0.25rem 0.5rem;
  color: var(--title-color);
  ${hoverCss};
`

const NavList = styled.ul`
  color: var(--subtitle-color);
  font-size: 0.8rem;
  line-height: 1.2rem;
  margin: 0;
  li {
    display: inline;
  }
`

const OutLink = styled.a`
  text-decoration: none;
  color: var(--subtitle-color);
  padding: 0.25rem;
  margin: 0.25rem;
  ${ hoverCss}
`
const Profile = () => (
  <Wrapper>
      <Title>
        <a
          href='/'
          style={{ textDecoration: `none`, color: `inherit` }}>Jaehyun Baek

      </Title>
      <NavList>

        <OutLink href="/" >home</OutLink>

      ·

      <OutLink href="/wiki" >wiki</OutLink>

      ·

      <OutLink href="/about" >about</OutLink>

      ·

      <OutLink href="/search" >search</OutLink>

      </NavList>
  </Wrapper>
)

export default Profile;
<|endoftext|>


<commit_before>"use latest";

const _ = require('underscore');
const hbs = require('handlebars');
const async = require('async');
const request = require('request');
const cheerio = require('cheerio');

module.exports = (ctx, req, res) => {
  if (ctx.data && ctx.data.okta) {
    // The Okta tutorials are just raw HTML files in GitHub, no point in redirecting to it since it's unreadable.
    // Instead, we'll use this webtask as a proxy to serve the HTML within the page (in a modal dialog).
    return request.get('https://raw.githubusercontent.com' + ctx.data.okta.replace('/blob', ''), function(err, r, html) {
      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end(html
        .replace(/\"resources/g, '"https://raw.githubusercontent.com/okta/UserDocs/master/SAML_Docs/resources')
        .replace(/\"images/g, '"https://raw.githubusercontent.com/okta/UserDocs/master/SAML_Docs/images'));
    });
  }

  const View = `

        <title>Third Party SAML Configuration</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">

            <input id="filter" type="text" class="form-control" placeholder="Filter in {{total}} tutorials from Auth0, Azure AD, Okta, OneLogin...">

          {{#if err}}

{{message}}

          {{else}}

                Source
                Application
                Actions

              </thread>

              {{#each links}}

                  {{type}}
                  {{text}}

              {{/each}}

          {{/if}}

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

Thid Party Application

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

    `;

  getLinks((err, links) => {
    res.writeHead(200, { 'Content-Type': 'text/html' });

    const template = hbs.compile(View);
    res.end(template({
      err: err,
      links: links,
      total: links.length
    }));
  });
};

//
const getLinks = (done) => {
  const links = [];
  async.waterfall([
    (callback) => {
      request(`https://auth0.com/docs/saml-apps`, (err, res, html) => {
        if (err) {
          return callback(err);
        }

        if (res.statusCode !== 200) {
          return callback(new Error('Unexpected status code: ' + res.statusCode));
        }

        var $ = cheerio.load(html);
        $('section.docs-content h2').each((i, element) => {
          var header = $(element);
          links.push({
            text: header.text(),
            type: 'Auth0',
            url: 'https://auth0.com/docs/saml-apps' + header.find('span').attr('href')
          });
        });

        callback();
      });
    },
    (callback) => {
      const thirdParty = [{"id":"salesforce","name":"Salesforce","img_class":"salesforce","data_logo":"Salesforce","configRoute":"/add-ons/salesforce","callback":"https://login.salesforce.com"},{"id":"dropbox","name":"Dropbox","img_class":"dropbox","data_logo":"Dropbox","configRoute":"/add-ons/dropbox","callback":"https://www.dropbox.com/saml_login"},{"id":"sharepoint","name":"SharePoint","img_class":"microsoft-sharepoint-logo","data_logo":"Sharepoint","configRoute":"/add-ons/sharepoint"},{"id":"rms","name":"AD RMS","img_class":"windows-logo","data_logo":"Windows Server Active Directory RMS","configRoute":"/add-ons/rms"},{"id":"zendesk","name":"Zendesk","img_class":"zendesk","data_logo":"Zendesk","configRoute":"/add-ons/zendesk"},{"id":"box","name":"Box","img_class":"box","data_logo":"Box","configRoute":"/add-ons/box","callback":"https://sso.services.box.net/sp/ACS.saml2"},{"id":"echosign","name":"EchoSign","img_class":"echosign","data_logo":"AdobeEchoSign","configRoute":"/add-ons/echosign"},{"id":"springcm","name":"SpringCM","img_class":"springcm","data_logo":"SpringCM","configRoute":"/add-ons/springcm"},{"id":"newrelic","name":"New Relic","img_class":"newrelic","data_logo":"NewRelic","configRoute":"/add-ons/newrelic"},{"id":"egnyte","name":"Egnyte","img_class":"egnyte","data_logo":"Egnyte","configRoute":"/add-ons/egnyte"},{"id":"cloudbees","name":"CloudBees","img_class":"cloudbees","data_logo":"CloudBees","configRoute":"/add-ons/cloudbees","callback":"https://grandcentral.cloudbees.com/authenticate/saml/consume"},{"id":"mscrm","name":"Dynamics CRM","img_class":"mscrm","data_logo":"MicrosoftDynamicsCRM","configRoute":"/add-ons/mscrm"},{"id":"office365","name":"Office 365 (beta)","img_class":"office365","data_logo":"Office365","configRoute":"/add-ons/office365"},{"id":"zoom","name":"Zoom","img_class":"zoom","data_logo":"Zoom","configRoute":"/add-ons/zoom"},{"id":"concur","name":"Concur (beta)","img_class":"concur","data_logo":"Concur","configRoute":"/add-ons/concur","callback":"https://www.concursolutions.com/SAMLRedirector/ClientSAMLLogin.aspx"},{"id":"slack","name":"Slack","img_class":"slack","data_logo":"Slack","configRoute":"/add-ons/slack"}];
      thirdParty.forEach(a => {
        links.push({
          text: a.name,
          type: 'Auth0 (Third Party App)',
          url: 'https://manage.auth0.com/#/externalapps'
        });
      });

      callback();
    },
    (callback) => {
      request(`https://azure.microsoft.com/en-us/documentation/articles/active-directory-saas-tutorial-list/`, (err, res, html) => {
        if (err) {
          return callback(err);
        }

        if (res.statusCode !== 200) {
          return callback(new Error('Unexpected status code: ' + res.statusCode));
        }

        var $ = cheerio.load(html);
        $('div.wa-spacer-docContent table tbody tr a').each((i, element) => {
          var link = $(element);
          links.push({
            text: link.text(),
            type: 'Azure AD',
            url: link.attr('href')
          });
        });

        callback();
      });
    },
    (callback) => {
      request(`https://github.com/okta/UserDocs/tree/master/SAML_Docs`, (err, res, html) => {
        if (err) {
          return callback(err);
        }

        if (res.statusCode !== 200) {
          return callback(new Error('Unexpected status code: ' + res.statusCode));
        }

        var $ = cheerio.load(html);
        $('div.repository-content tr.js-navigation-item a').each((i, element) => {
          var link = $(element);
          if (link.attr('href').indexOf('.html') >= 0
            && (link.attr('href').indexOf('How-to-') >= 0 || link.attr('href').indexOf('Configuring-SAML-') >= 0)) {
            links.push({
              text: link.text()
                .replace('How-to-Enable-SAML-2.0-in-', '')
                .replace('How-to-Configure-SAML-for-', '')
                .replace('How-To-Configure-SAML-1.1-for-', '')
                .replace('How-To-Configure-SAML-2.0-for-', '')
                .replace('How-to-Configure-SAML-1.1-for-', '')
                .replace('How-to-Configure-SAML-2.0-for-', '')
                .replace('How-to-configure-SAML-2.0-for-', '')
                .replace('Configure-SAML-1.1-in-', '')
                .replace('Configure-SAML-2.0-in-', '')
                .replace('Configuring-SAML-2.0-in-', '')
                .replace('Configuring SAML SSO for', '')
                .replace('Configure-CustomSSO-for-', '')
                .replace('Configuring SAML SSO for', '')
                .replace('How-to-', '')
                .replace('-', ' ')
                .replace('.html', ''),
              type: 'Okta',
              url: '?okta=' + link.attr('href')
            });
          }
        });

        callback();
      });
    },
    (callback) => {
      async.each([1, 2, 3, 4], (index, cb) => {
        request(`https://onelogin.zendesk.com/hc/en-us/sections/200245384-Application-Integration-SAML-?page=${index}#articles`, (err, res, html) => {
          if (err) {
            return cb(err);
          }

          if (res.statusCode !== 200) {
            return cb(new Error('Unexpected status code: ' + res.statusCode));
          }

          var $ = cheerio.load(html);
          $('ul.article-list li a').each((i, element) => {
            var link = $(element);
            links.push({
              text: link.text().replace('Configuring SAML for ', ''),
              type: 'OneLogin',
              url: 'https://onelogin.zendesk.com' + link.attr('href')
            });
          });

          cb();
        });
      }, (err) => {
        return callback(err);
      });
  }], (err, context) => {
    done(err, _.sortBy(links, 'text'));
  });
};
<commit_msg>Updated bootstrap theme<commit_after>"use latest";

const _ = require('underscore');
const hbs = require('handlebars');
const async = require('async');
const request = require('request');
const cheerio = require('cheerio');

module.exports = (ctx, req, res) => {
  if (ctx.data && ctx.data.okta) {
    // The Okta tutorials are just raw HTML files in GitHub, no point in redirecting to it since it's unreadable.
    // Instead, we'll use this webtask as a proxy to serve the HTML within the page (in a modal dialog).
    return request.get('https://raw.githubusercontent.com' + ctx.data.okta.replace('/blob', ''), function(err, r, html) {
      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end(html
        .replace(/\"resources/g, '"https://raw.githubusercontent.com/okta/UserDocs/master/SAML_Docs/resources')
        .replace(/\"images/g, '"https://raw.githubusercontent.com/okta/UserDocs/master/SAML_Docs/images'));
    });
  }

  const View = `

        <title>Third Party SAML Configuration</title>
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootswatch/3.3.5/cosmo/bootstrap.min.css">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">

            <input id="filter" type="text" class="form-control" placeholder="Filter in {{total}} tutorials from Auth0, Azure AD, Okta, OneLogin...">

          {{#if err}}

{{message}}

          {{else}}

                Source
                Application
                Actions

              </thread>

              {{#each links}}

                  {{type}}
                  {{text}}

              {{/each}}

          {{/if}}

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

Thid Party Application

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

    `;

  getLinks((err, links) => {
    res.writeHead(200, { 'Content-Type': 'text/html' });

    const template = hbs.compile(View);
    res.end(template({
      err: err,
      links: links,
      total: links.length
    }));
  });
};

//
const getLinks = (done) => {
  const links = [];
  async.waterfall([
    (callback) => {
      request(`https://auth0.com/docs/saml-apps`, (err, res, html) => {
        if (err) {
          return callback(err);
        }

        if (res.statusCode !== 200) {
          return callback(new Error('Unexpected status code: ' + res.statusCode));
        }

        var $ = cheerio.load(html);
        $('section.docs-content h2').each((i, element) => {
          var header = $(element);
          links.push({
            text: header.text(),
            type: 'Auth0',
            url: 'https://auth0.com/docs/saml-apps' + header.find('span').attr('href')
          });
        });

        callback();
      });
    },
    (callback) => {
      const thirdParty = [{"id":"salesforce","name":"Salesforce","img_class":"salesforce","data_logo":"Salesforce","configRoute":"/add-ons/salesforce","callback":"https://login.salesforce.com"},{"id":"dropbox","name":"Dropbox","img_class":"dropbox","data_logo":"Dropbox","configRoute":"/add-ons/dropbox","callback":"https://www.dropbox.com/saml_login"},{"id":"sharepoint","name":"SharePoint","img_class":"microsoft-sharepoint-logo","data_logo":"Sharepoint","configRoute":"/add-ons/sharepoint"},{"id":"rms","name":"AD RMS","img_class":"windows-logo","data_logo":"Windows Server Active Directory RMS","configRoute":"/add-ons/rms"},{"id":"zendesk","name":"Zendesk","img_class":"zendesk","data_logo":"Zendesk","configRoute":"/add-ons/zendesk"},{"id":"box","name":"Box","img_class":"box","data_logo":"Box","configRoute":"/add-ons/box","callback":"https://sso.services.box.net/sp/ACS.saml2"},{"id":"echosign","name":"EchoSign","img_class":"echosign","data_logo":"AdobeEchoSign","configRoute":"/add-ons/echosign"},{"id":"springcm","name":"SpringCM","img_class":"springcm","data_logo":"SpringCM","configRoute":"/add-ons/springcm"},{"id":"newrelic","name":"New Relic","img_class":"newrelic","data_logo":"NewRelic","configRoute":"/add-ons/newrelic"},{"id":"egnyte","name":"Egnyte","img_class":"egnyte","data_logo":"Egnyte","configRoute":"/add-ons/egnyte"},{"id":"cloudbees","name":"CloudBees","img_class":"cloudbees","data_logo":"CloudBees","configRoute":"/add-ons/cloudbees","callback":"https://grandcentral.cloudbees.com/authenticate/saml/consume"},{"id":"mscrm","name":"Dynamics CRM","img_class":"mscrm","data_logo":"MicrosoftDynamicsCRM","configRoute":"/add-ons/mscrm"},{"id":"office365","name":"Office 365 (beta)","img_class":"office365","data_logo":"Office365","configRoute":"/add-ons/office365"},{"id":"zoom","name":"Zoom","img_class":"zoom","data_logo":"Zoom","configRoute":"/add-ons/zoom"},{"id":"concur","name":"Concur (beta)","img_class":"concur","data_logo":"Concur","configRoute":"/add-ons/concur","callback":"https://www.concursolutions.com/SAMLRedirector/ClientSAMLLogin.aspx"},{"id":"slack","name":"Slack","img_class":"slack","data_logo":"Slack","configRoute":"/add-ons/slack"}];
      thirdParty.forEach(a => {
        links.push({
          text: a.name,
          type: 'Auth0 (Third Party App)',
          url: 'https://manage.auth0.com/#/externalapps'
        });
      });

      callback();
    },
    (callback) => {
      request(`https://azure.microsoft.com/en-us/documentation/articles/active-directory-saas-tutorial-list/`, (err, res, html) => {
        if (err) {
          return callback(err);
        }

        if (res.statusCode !== 200) {
          return callback(new Error('Unexpected status code: ' + res.statusCode));
        }

        var $ = cheerio.load(html);
        $('div.wa-spacer-docContent table tbody tr a').each((i, element) => {
          var link = $(element);
          links.push({
            text: link.text(),
            type: 'Azure AD',
            url: link.attr('href')
          });
        });

        callback();
      });
    },
    (callback) => {
      request(`https://github.com/okta/UserDocs/tree/master/SAML_Docs`, (err, res, html) => {
        if (err) {
          return callback(err);
        }

        if (res.statusCode !== 200) {
          return callback(new Error('Unexpected status code: ' + res.statusCode));
        }

        var $ = cheerio.load(html);
        $('div.repository-content tr.js-navigation-item a').each((i, element) => {
          var link = $(element);
          if (link.attr('href').indexOf('.html') >= 0
            && (link.attr('href').indexOf('How-to-') >= 0 || link.attr('href').indexOf('Configuring-SAML-') >= 0)) {
            links.push({
              text: link.text()
                .replace('How-to-Enable-SAML-2.0-in-', '')
                .replace('How-to-Configure-SAML-for-', '')
                .replace('How-To-Configure-SAML-1.1-for-', '')
                .replace('How-To-Configure-SAML-2.0-for-', '')
                .replace('How-to-Configure-SAML-1.1-for-', '')
                .replace('How-to-Configure-SAML-2.0-for-', '')
                .replace('How-to-configure-SAML-2.0-for-', '')
                .replace('Configure-SAML-1.1-in-', '')
                .replace('Configure-SAML-2.0-in-', '')
                .replace('Configuring-SAML-2.0-in-', '')
                .replace('Configuring SAML SSO for', '')
                .replace('Configure-CustomSSO-for-', '')
                .replace('Configuring SAML SSO for', '')
                .replace('How-to-', '')
                .replace('-', ' ')
                .replace('.html', ''),
              type: 'Okta',
              url: '?okta=' + link.attr('href')
            });
          }
        });

        callback();
      });
    },
    (callback) => {
      async.each([1, 2, 3, 4], (index, cb) => {
        request(`https://onelogin.zendesk.com/hc/en-us/sections/200245384-Application-Integration-SAML-?page=${index}#articles`, (err, res, html) => {
          if (err) {
            return cb(err);
          }

          if (res.statusCode !== 200) {
            return cb(new Error('Unexpected status code: ' + res.statusCode));
          }

          var $ = cheerio.load(html);
          $('ul.article-list li a').each((i, element) => {
            var link = $(element);
            links.push({
              text: link.text().replace('Configuring SAML for ', ''),
              type: 'OneLogin',
              url: 'https://onelogin.zendesk.com' + link.attr('href')
            });
          });

          cb();
        });
      }, (err) => {
        return callback(err);
      });
  }], (err, context) => {
    done(err, _.sortBy(links, 'text'));
  });
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { match, spy, stub } from 'sinon';
import { inspect } from 'util';

export default chai => {
  const { Assertion } = chai;

  /**
   * @example
   * expect(ComponentClass).to.have.been.rendered;
   */
  Assertion.addProperty('rendered', function expectComponentRendered() {
    const ComponentClass = this._obj;

    function constructMessage({ not }) {
      return `Expected component '${ComponentClass.displayName}' to ${not ? 'not ' : ''}have been rendered`;
    }

    this.assert(ComponentClass.rendered,
                constructMessage({ not: false }),
                constructMessage({ not: true }));
  });

  /**
   * @param {Object} expectedProps
   *
   * @example
   * expect(ComponentClass).to.have.been.renderedWith({foo: 'bar'});
   */
  Assertion.addMethod('renderedWith', function expectComponentRenderedWith(
    expectedProps
  ) {
    const ComponentClass = this._obj;

    function constructMessage({ not }) {
      let msg = `Expected component '${ComponentClass.displayName}' to ${not ? 'not ' : ''}have been rendered with ${inspect(expectedProps)}`;

      if (ComponentClass.rendered) {
        const renders = ComponentClass.renders.map(
          props => inspect(props)
        ).join('\n');

        msg += `\n\nThe component has so far been rendered with:\n${renders}`;
      }

      return msg;
    }

    this.assert(ComponentClass.renderedWith(expectedProps),
                constructMessage({ not: false }),
                constructMessage({ not: true }));
  });
};

/**
 * @typedef {Object extends Sinon.stub} ReactStub
 *
 * @property {(props: Object) => ReactStub} withProps Use to customize the
 *   expectations of the stub. The given props are partially matched using
 *   sinon.match.
 * @property {(jsx: React.JSX.Element|string|null) => void} renders Force the
 *   stub to render the given JSX. If previously chained with a `withProps` call
 *   then it will render only for that match.
 */

/**
 * @returns {ReactStub} By default the stub renders some bogus content. Use
 *   `withProps` and `renders` to set expectations on it.
 */
export function createReactStub() {
  const reactStub = stub();

  reactStub.returns('::react stub::');

  reactStub.withProps = props => {
    const expectation = reactStub.withArgs(match(props));
    expectation.renders = expectation.returns.bind(expectation);
    return expectation;
  };

  reactStub.renders = reactStub.returns.bind(reactStub);

  Object.defineProperties(reactStub, {
    rendered: {
      get() {
        return reactStub.called;
      }
    },
    renderedWith: {
      value: props => reactStub.calledWithMatch(props)
    },
    /**
     * Return the first set of received props.
     */
    firstProps: {
      get() {
        return reactStub.firstCall.args[0];
      }
    },
    /**
     * Return the last set of received props.
     */
    lastProps: {
      get() {
        return reactStub.lastCall.args[0];
      }
    },
    /**
     * Return a list of received props from every render.
     */
    renders: {
      get() {
        return reactStub.args.map(args => args[0]);
      }
    }
  });

  return reactStub;
}

/**
 * @param {Object} options
 * @param {String} options.name The display name of the component.
 * @param {ReactClass} [options.Mock] If given, the spy will try to look like
 *     it. Currently it only copies the prop types.
 *     TODO: copy public methods; maybe inherit?
 *
 * @returns {ReactClass}
 */
export function createSpy({ name = 'Spy', Mock = Component } = {}) {
  const _renderSpy = spy();

  return class Spy extends Component {
    static displayName = name;

    static propTypes = Mock.propTypes;

    /**
     * Get whether the component was rendered at least once.
     *
     * @return {Boolean}
     */
    static get rendered() {
      return _renderSpy.called;
    }

    /**
     * Get the props used in the last render.
     *
     * @return {Object}
     */
    static get lastProps() {
      if (!_renderSpy.called) {
        throw new Error('Component was never rendered');
      }

      return _renderSpy.args[_renderSpy.callCount - 1][0];
    }

    /**
     * Get the props used in every render ever.
     *
     * @returns {Object[]}
     */
    static get renders() {
      if (!_renderSpy.called) {
        throw new Error('Component was never rendered');
      }

      return _renderSpy.args.map(args => args[0]);
    }

    /**
     * Check if the component was rendered at least once with the given props.
     *
     * @param {Object} props Supports sinon matchers. See
     * http://sinonjs.org/docs/#sinon-match-api.
     *
     * @returns {Boolean}
     */
    static renderedWith(props) {
      return _renderSpy.calledWithMatch(props);
    }

    static reset() {
      _renderSpy.resetHistory();
    }

    render() {
      _renderSpy(this.props);

      return
I am a fake component, here to spy on you!
;
    }
  };
}
<commit_msg>Remove duplicate property from createReactStub<commit_after>import React, { Component } from 'react';
import { match, spy, stub } from 'sinon';
import { inspect } from 'util';

export default chai => {
  const { Assertion } = chai;

  /**
   * @example
   * expect(ComponentClass).to.have.been.rendered;
   */
  Assertion.addProperty('rendered', function expectComponentRendered() {
    const ComponentClass = this._obj;

    function constructMessage({ not }) {
      return `Expected component '${ComponentClass.displayName}' to ${not ? 'not ' : ''}have been rendered`;
    }

    this.assert(ComponentClass.rendered,
                constructMessage({ not: false }),
                constructMessage({ not: true }));
  });

  /**
   * @param {Object} expectedProps
   *
   * @example
   * expect(ComponentClass).to.have.been.renderedWith({foo: 'bar'});
   */
  Assertion.addMethod('renderedWith', function expectComponentRenderedWith(
    expectedProps
  ) {
    const ComponentClass = this._obj;

    function constructMessage({ not }) {
      let msg = `Expected component '${ComponentClass.displayName}' to ${not ? 'not ' : ''}have been rendered with ${inspect(expectedProps)}`;

      if (ComponentClass.rendered) {
        const renders = ComponentClass.renders.map(
          props => inspect(props)
        ).join('\n');

        msg += `\n\nThe component has so far been rendered with:\n${renders}`;
      }

      return msg;
    }

    this.assert(ComponentClass.renderedWith(expectedProps),
                constructMessage({ not: false }),
                constructMessage({ not: true }));
  });
};

/**
 * @typedef {Object extends Sinon.stub} ReactStub
 *
 * @property {(props: Object) => ReactStub} withProps Use to customize the
 *   expectations of the stub. The given props are partially matched using
 *   sinon.match.
 * @property {(jsx: React.JSX.Element|string|null) => void} renders Force the
 *   stub to render the given JSX. If previously chained with a `withProps` call
 *   then it will render only for that match.
 */

/**
 * @returns {ReactStub} By default the stub renders some bogus content. Use
 *   `withProps` and `renders` to set expectations on it.
 */
export function createReactStub() {
  const reactStub = stub();

  reactStub.returns('::react stub::');

  reactStub.withProps = props => {
    const expectation = reactStub.withArgs(match(props));
    expectation.renders = expectation.returns.bind(expectation);
    return expectation;
  };

  Object.defineProperties(reactStub, {
    rendered: {
      get() {
        return reactStub.called;
      }
    },
    renderedWith: {
      value: props => reactStub.calledWithMatch(props)
    },
    /**
     * Return the first set of received props.
     */
    firstProps: {
      get() {
        return reactStub.firstCall.args[0];
      }
    },
    /**
     * Return the last set of received props.
     */
    lastProps: {
      get() {
        return reactStub.lastCall.args[0];
      }
    },
    /**
     * Return a list of received props from every render.
     */
    renders: {
      get() {
        return reactStub.args.map(args => args[0]);
      }
    }
  });

  return reactStub;
}

/**
 * @param {Object} options
 * @param {String} options.name The display name of the component.
 * @param {ReactClass} [options.Mock] If given, the spy will try to look like
 *     it. Currently it only copies the prop types.
 *     TODO: copy public methods; maybe inherit?
 *
 * @returns {ReactClass}
 */
export function createSpy({ name = 'Spy', Mock = Component } = {}) {
  const _renderSpy = spy();

  return class Spy extends Component {
    static displayName = name;

    static propTypes = Mock.propTypes;

    /**
     * Get whether the component was rendered at least once.
     *
     * @return {Boolean}
     */
    static get rendered() {
      return _renderSpy.called;
    }

    /**
     * Get the props used in the last render.
     *
     * @return {Object}
     */
    static get lastProps() {
      if (!_renderSpy.called) {
        throw new Error('Component was never rendered');
      }

      return _renderSpy.args[_renderSpy.callCount - 1][0];
    }

    /**
     * Get the props used in every render ever.
     *
     * @returns {Object[]}
     */
    static get renders() {
      if (!_renderSpy.called) {
        throw new Error('Component was never rendered');
      }

      return _renderSpy.args.map(args => args[0]);
    }

    /**
     * Check if the component was rendered at least once with the given props.
     *
     * @param {Object} props Supports sinon matchers. See
     * http://sinonjs.org/docs/#sinon-match-api.
     *
     * @returns {Boolean}
     */
    static renderedWith(props) {
      return _renderSpy.calledWithMatch(props);
    }

    static reset() {
      _renderSpy.resetHistory();
    }

    render() {
      _renderSpy(this.props);

      return
I am a fake component, here to spy on you!
;
    }
  };
}
<|endoftext|>


<commit_before>'use strict';
/*
  Import modules/files you may need to correctly run the script.
  Make sure to save your DB's uri in the config file, then import it with a require statement!
 */
var fs = require('fs'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    User = require('./user-registration.server.model.js'),
    Team = require('./team-registration.server.model.js'),
    BlankRubric = require('./blankRubric-review.server.model.js'),
    CompletedRating = require('./completedRating-review.server.model.js'),
    config = require('./config');

/* Connect to your database. DONE*/
  mongoose.connect(config.db.uri);

  var db = mongoose.connection;
  db.on('error', console.error.bind(console, 'connection error:'));
  db.once('open', function() {
    console.log("Connected!");

      /*
        Instantiate a mongoose model for each user object in the JSON file,
        and then save it to your Mongo database. DONE
       */

  var usersToAdd = JSON.parse(fs.readFileSync('./users.json', 'utf8')).userEntries;
    var callback1 = function(err){
      if(err) throw err;
    }

    var teamsToAdd = JSON.parse(fs.readFileSync('./teams.json', 'utf8')).teamEntries;
    var callback2 = function(err){
      if(err) throw err;
    }

    var blankRubricToAdd = JSON.parse(fs.readFileSync('./blankRubric.json', 'utf8')).blankRubricEntries;
    var callback3 = function(err){
      if(err) throw err;
    }

    var completedRatingToAdd = JSON.parse(fs.readFileSync('./completedRating.json', 'utf8')).completedRatingEntries;
    var callback4 = function(err){
      if(err) throw err;
    }

    for(var i = 0; i < usersToAdd.length; i++){
        new User(usersToAdd[i]).save(callback1);
    }
    for(var j = 0; j < teamsToAdd.length; j++){
        new Team(teamsToAdd[j]).save(callback2);
    }
    for(var k = 0; k < blankRubricToAdd.length; k++){
        new BlankRubric(blankRubricToAdd[k]).save(callback3);
    }
    for(var l = 0; l < completedRatingToAdd.length; l++){
        new CompletedRating(completedRatingToAdd[l]).save(callback4);
    }

  });
<commit_msg>Revert "Cleaned up comments"<commit_after>'use strict';
/*
  Import modules/files you may need to correctly run the script.
  Make sure to save your DB's uri in the config file, then import it with a require statement!
 */
var fs = require('fs'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    User = require('./user-registration.server.model.js'),
    Team = require('./team-registration.server.model.js'),
    BlankRubric = require('./blankRubric-review.server.model.js'),
    CompletedRating = require('./completedRating-review.server.model.js'),
    config = require('./config');

/* Connect to your database. DONE*/
  mongoose.connect(config.db.uri);

  var db = mongoose.connection;
  db.on('error', console.error.bind(console, 'connection error:'));
  db.once('open', function() {
    console.log("Connected!");

      /*
        Instantiate a mongoose model for each user object in the JSON file,
        and then save it to your Mongo database. DONE
       */

  /* var usersToAdd = JSON.parse(fs.readFileSync('./users.json', 'utf8')).userEntries;
    var callback1 = function(err){
      if(err) throw err;
    }

    var teamsToAdd = JSON.parse(fs.readFileSync('./teams.json', 'utf8')).teamEntries;
    var callback2 = function(err){
      if(err) throw err;
    }

    var blankRubricToAdd = JSON.parse(fs.readFileSync('./blankRubric.json', 'utf8')).blankRubricEntries;
    var callback3 = function(err){
      if(err) throw err;
    }*/

    var completedRatingToAdd = JSON.parse(fs.readFileSync('./completedRating.json', 'utf8')).completedRatingEntries;
    var callback4 = function(err){
      if(err) throw err;
    }

    /*for(var i = 0; i < usersToAdd.length; i++){
        new User(usersToAdd[i]).save(callback1);
    }
    for(var j = 0; j < teamsToAdd.length; j++){
        new Team(teamsToAdd[j]).save(callback2);
    }
    for(var k = 0; k < blankRubricToAdd.length; k++){
        new BlankRubric(blankRubricToAdd[k]).save(callback3);
    }*/
    for(var l = 0; l < completedRatingToAdd.length; l++){
        console.log(completedRatingToAdd[l]);
        new CompletedRating(completedRatingToAdd[l]).save(callback4);
    }

  });
<|endoftext|>


<commit_before>module.exports = {
  config: {
    // default font size in pixels for all tabs
    fontSize: 12,

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

    // terminal cursor background color (hex)
    cursorColor: '#2aa198',

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

    // terminal background color
    backgroundColor: '#fff',

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

    // custom css to embed in the main window
    css: `
      .tabs_title, .tab_active, .tab_active:hover, .tab_icon {
        color: #073642;
      }
    `,

    // custom padding (css format, i.e.: `top right bottom left`)
    termCSS: '',

    // custom padding
    padding: '12px 14px',

    // some color overrides. see http://bit.ly/29k1iU2 for
    // the full list
    colors: [
      '#073642',
      '#dc322f',
      '#859900',
      '#b58900',
      '#268bd2',
      '#d33682',
      '#2aa198',
      '#eee8d5',
      '#002b36',
      '#cb4b16',
      '#586e75',
      '#657b83',
      '#839496',
      '#6c71c4',
      '#93a1a1',
      '#fdf6e3'
    ]
  },

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

  // in development, you can create a directory under
  // `~/.hyperterm_plugins/local/` and include it here
  // to load it and avoid it being `npm install`ed
  localPlugins: []
};
<commit_msg>Hyperterm: Set cursor config<commit_after>module.exports = {
  config: {
    // default font size in pixels for all tabs
    fontSize: 12,

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

    // terminal cursor background color (hex)
    cursorColor: 'rgba(42, 161, 152, 0.6)',

    cursorShape: 'BLOCK',

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

    // terminal background color
    backgroundColor: '#fff',

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

    // custom css to embed in the main window
    css: `
      .tabs_title, .tab_active, .tab_active:hover, .tab_icon {
        color: #073642;
      }
    `,

    // custom padding (css format, i.e.: `top right bottom left`)
    termCSS: '',

    // custom padding
    padding: '12px 14px',

    // some color overrides. see http://bit.ly/29k1iU2 for
    // the full list
    colors: [
      '#073642',
      '#dc322f',
      '#859900',
      '#b58900',
      '#268bd2',
      '#d33682',
      '#2aa198',
      '#eee8d5',
      '#002b36',
      '#cb4b16',
      '#586e75',
      '#657b83',
      '#839496',
      '#6c71c4',
      '#93a1a1',
      '#fdf6e3'
    ]
  },

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

  // in development, you can create a directory under
  // `~/.hyperterm_plugins/local/` and include it here
  // to load it and avoid it being `npm install`ed
  localPlugins: []
};
<|endoftext|>


<commit_before>import React from 'react'
import styled from 'styled-components'
import ContentHeader from './ContentHeader'

const ContentBody = styled.div`
  line-height: 1.6;

  & > h2 {
    padding-top: 3rem;
    margin-top: 3rem;
    border-top: 1px solid #ececec;
  }

  & > h3 {
    padding-top: 3rem;
  }

  & > p {
    margin: 1em 0 0 0;
  }

  & a {
    border-bottom: 1px dotted rgba(162, 162, 162, 0.8);

    &:hover {
      border-bottom-style: solid;
    }

    &.anchor,
    &.gatsby-resp-image-link {
      border: none;
    }
  }

  & > blockquote {
    box-sizing: border-box;
    margin: 1.75em 0 1.75em -2.2em;
    padding: 0 0 0 1.75em;
    border-left: 0.4em solid rgba(32, 35, 42, 0.85);
  }

  & > blockquote p {
    margin: 0.8em 0;
    font-style: italic;
  }

  & .gatsby-highlight {
    border-radius: 5px;
    font-size: 15px;
    line-height: 1.7;
    background: #2d2d2d;
    color: #ffffff;
    border-radius: 10px;
    overflow: auto;
    tab-size: 1.5em;
    margin: 1.5em 0em 1.5em 0;
    /* padding: 1em; */
  }

  & .gatsby-highlight > pre {
    border: 0;
    margin: 0;
    padding: 1;
  }

  & .gatsby-highlight-code-line {
    background-color: #022a4b;
    display: block;
    margin-right: -1em;
    margin-left: -1em;
    padding-right: 1em;
    padding-left: .75em;
    border-left: .25em solid #ffa7c4;
  }

  & p > code.language-text,
  & li > code.language-text {
    background: rgba(255, 229, 100, 0.2);
    color: #222222cc;
    padding: 0 3px;
    font-size: 0.94em;
    border-radius: 0.3rem;
  }
`

class Content extends React.Component {
  render() {
    const { content, date, tags } = this.props

    return (

        {(tags || date) && <ContentHeader date={date} tags={tags} />}
        <ContentBody dangerouslySetInnerHTML={{ __html: content }} />

    )
  }
}

export default Content
<commit_msg>fix(Content): add missing CSS for
 (#33)<commit_after>import React from 'react'
import styled from 'styled-components'
import ContentHeader from './ContentHeader'

const ContentBody = styled.div`
  line-height: 1.6;

  & > h2 {
    padding-top: 3rem;
    margin-top: 3rem;
    border-top: 1px solid #ececec;
  }

  & > h3 {
    padding-top: 3rem;
  }

  & > p {
    margin: 1em 0 0 0;
  }

  & a {
    border-bottom: 1px dotted rgba(162, 162, 162, 0.8);

    &:hover {
      border-bottom-style: solid;
    }

    &.anchor,
    &.gatsby-resp-image-link {
      border: none;
    }
  }

  & > blockquote {
    box-sizing: border-box;
    margin: 1.75em 0 1.75em -2.2em;
    padding: 0 0 0 1.75em;
    border-left: 0.4em solid rgba(32, 35, 42, 0.85);
  }

  & > blockquote p {
    margin: 0.8em 0;
    font-style: italic;
  }

  & .gatsby-highlight {
    border-radius: 5px;
    font-size: 15px;
    line-height: 1.7;
    background: #2d2d2d;
    color: #ffffff;
    border-radius: 10px;
    overflow: auto;
    tab-size: 1.5em;
    margin: 1.5em 0em 1.5em 0;
    /* padding: 1em; */
  }

  & .gatsby-highlight > pre {
    border: 0;
    margin: 0;
    padding: 1;
  }

  & .gatsby-highlight-code-line {
    background-color: #022a4b;
    display: block;
    margin-right: -1em;
    margin-left: -1em;
    padding-right: 1em;
    padding-left: .75em;
    border-left: .25em solid #ffa7c4;
  }

  & p > code.language-text,
  & li > code.language-text {
    background: rgba(255, 229, 100, 0.2);
    color: #222222cc;
    padding: 0 3px;
    font-size: 0.94em;
    border-radius: 0.3rem;
  }

  & table {
    margin-top: 1em;
    border-collapse: collapse;
    border-radius: 1em;
    overflow: hidden;

    & th,
    & td {
      padding: 0.5em;
      background: #e8e8e8;
      border-bottom: 2px solid white;
    }
  }
`

class Content extends React.Component {
  render() {
    const { content, date, tags } = this.props

    return (

        {(tags || date) && <ContentHeader date={date} tags={tags} />}
        <ContentBody dangerouslySetInnerHTML={{ __html: content }} />

    )
  }
}

export default Content
<|endoftext|>


<commit_before>var SettingsFile = require('nachos-settings-file');
var nachosPackages = require('nachos-packages');
var _ = require('lodash');
var hooker = require('hooker');

var config = new SettingsFile('nachos').getSync();
var BASE_URL = 'http://localhost:' + config.port;

var client = require('socket.io-client')(BASE_URL);

// TODO: merge with nachos-configuration.configs, override config's functions with out own

module.exports = {
  settings: function (app) {
    var settingsFile = new SettingsFile(app);

    hooker.hook(settingsFile, 'save', {
      pre: function () {
        var args = arguments;
        var cb = args[1];
        args[1] = function () {
          client.emit('config.global-changed', {app: app, config: args[0]});
          cb();
        };

        return hooker.filter(this, args)
      }
    });

    settingsFile.onChange = function (cb) {
      client.on('config.global-changed:' + app, cb);
    };

    hooker.hook(settingsFile, 'instance', {
      post: function (returnedInstance) {
        hooker.hook(returnedInstance, 'save', {
          pre: function () {
            var args = arguments;
            var cb = args[1];
            args[1] = function () {
              client.emit('config.instance-changed', {instance: returnedInstance._id, config: args[0]});
              cb();
            };

            return hooker.filter(this, args)
          }
        });

        returnedInstance.onChange = function (cb) {
          client.on('config.instance-changed:' + returnedInstance._id, cb);
        };
      }
    });

    return settingsFile;
  },
  packages: nachosPackages
};<commit_msg>Packages is no longer included<commit_after>var SettingsFile = require('nachos-settings-file');
var hooker = require('hooker');

var config = new SettingsFile('nachos').getSync();
var BASE_URL = 'http://localhost:' + config.port;

var client = require('socket.io-client')(BASE_URL);

// TODO: merge with nachos-configuration.configs, override config's functions with out own

module.exports = {
  settings: function (app) {
    var settingsFile = new SettingsFile(app);

    hooker.hook(settingsFile, 'save', {
      pre: function () {
        var args = arguments;
        var cb = args[1];
        args[1] = function () {
          client.emit('config.global-changed', {app: app, config: args[0]});
          cb();
        };

        return hooker.filter(this, args)
      }
    });

    settingsFile.onChange = function (cb) {
      client.on('config.global-changed:' + app, cb);
    };

    hooker.hook(settingsFile, 'instance', {
      post: function (returnedInstance) {
        hooker.hook(returnedInstance, 'save', {
          pre: function () {
            var args = arguments;
            var cb = args[1];
            args[1] = function () {
              client.emit('config.instance-changed', {instance: returnedInstance._id, config: args[0]});
              cb();
            };

            return hooker.filter(this, args)
          }
        });

        returnedInstance.onChange = function (cb) {
          client.on('config.instance-changed:' + returnedInstance._id, cb);
        };
      }
    });

    return settingsFile;
  }
};<|endoftext|>


<commit_before>'use strict'

import 'normalize.css'
import React, { Component } from 'react'
import ReactCSS  from 'reactcss'

import '../fonts/work-sans/WorkSans.css!'
import '../styles/felony.css!'
import colors  from '../styles/variables/colors'

import Header from './header/Header'
import FloatingButtonContainer from '../containers/FloatingButtonContainer'
import ComposeContainer from '../containers/ComposeContainer'
import Encrypt from './encrypt/Encrypt'

export class Felony extends Component {
  state = {
    selected: [], // replaced with redux
  }

  classes() {
    return {
      'default': {
        app: {

          // NOTE: Set here and not in felony.css in order to use color variable
          background: colors.bgLight,
          position: 'absolute',
          width: '100%',
          height: '100%',
          color: 'white',
        },
        header: {
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
        },
      },
    }
  }

  // this will be replaced with Redux
  handleAddToSelected = (selected) => {
    this.setState({
      selected: this.state.selected.concat([selected]),
    })
  }

  render() {
    return (

        <Encrypt />

        <FloatingButtonContainer />
        <ComposeContainer />

    )
  }
}

export default ReactCSS(Felony)
<commit_msg>Use updated containers in main<commit_after>'use strict'

import 'normalize.css'
import React, { Component } from 'react'
import ReactCSS  from 'reactcss'

import '../fonts/work-sans/WorkSans.css!'
import '../styles/felony.css!'
import colors  from '../styles/variables/colors'

import Header from './header/Header'
import FloatingButtonContainer from '../containers/FloatingButtonContainer'
import ComposerContainer from '../containers/ComposerContainer'
import BuddiesContainer from '../containers/BuddiesContainer'

export class Felony extends Component {
  state = {
    selected: [], // replaced with redux
  }

  classes() {
    return {
      'default': {
        app: {

          // NOTE: Set here and not in felony.css in order to use color variable
          background: colors.bgLight,
          position: 'absolute',
          width: '100%',
          height: '100%',
          color: 'white',
        },
        header: {
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
        },
      },
    }
  }

  // this will be replaced with Redux
  handleAddToSelected = (selected) => {
    this.setState({
      selected: this.state.selected.concat([selected]),
    })
  }

  render() {
    return (

        <BuddiesContainer />

        <FloatingButtonContainer />
        <ComposerContainer />

    )
  }
}

export default ReactCSS(Felony)
<|endoftext|>