<commit_before>(function () {

    var root = this;
    var ArrayProto = Array.prototype;
    var slice = ArrayProto.slice;

    function argsToArray(args) {
        return slice.call(args, 0);
    }

    var thumbs;
    if (typeof exports !== 'undefined') {
        thumbs = exports;
    } else {
        thumbs = root.thumbs = {};
    }

    // Require Underscore, if we're on the server, and it's not already present.
    var _ = root._;
    if (!_ && ('undefined' !== typeof require )) {
        _ = require('underscore');
    }
    // Require Backbone, if we're on the server, and it's not already present.
    var Backbone = root.Backbone;
    if (!Backbone && ('undefined' !== typeof require)) {
        Backbone = require('underscore');
    }

    _.extend(thumbs, Backbone);

    // Current version of the library. Keep in sync with `package.json`.
    thumbs.VERSION = '0.0.0';

    //copy over Backbones $ for dom
    var Model = thumbs.Model, View = thumbs.View, Collection = thumbs.Collection, Router = thumbs.Router, History = thumbs.History;

    var _super = {
        _super: (function _super() {

            function findSuper(methodName, childObject) {
                var object = childObject;
                while (object[methodName] === childObject[methodName]) {
                    var constructor = object.__getConstructor();
                    object = constructor['__super__'];
                }

                return object;
            }

            return function __super(methodName, args) {

                // keep track of how far up the prototype chain we have traversed
                if (!this._superCallObjects) {
                    this._superCallObjects = {};
                }

                var currentObject = this._superCallObjects[methodName] || this,
                    parentObject = findSuper(methodName, currentObject);
                this._superCallObjects[methodName] = parentObject;

                var result = parentObject[methodName].apply(this, args || {});
                delete this._superCallObjects[methodName];
                return result;
            };
        }())
    };

    // this allows access to prototype.constructor.__super__
    // when _.bindAll is used
    var _extend = thumbs.Model.extend;

    function extend(protoProps, staticProps) {
        var child = _extend.apply(this, arguments);
        child.prototype.__getConstructor = function () {
            return child;
        };
        return child;
    }

    function Class(options) {
        this.cid = _.uniqueId('class');
        this.initialize.apply(this, arguments);
    }

    _.extend(Class.prototype, thumbs.Events, _super, {
        initialize: function initialize() {
        }
    });

    thumbs.Class = Class;

    Class.extend = Model.extend = View.extend = Collection.extend = Router.extend = History.extend = extend;
    Model = thumbs.Model = Model.extend(_super);
    View = thumbs.View = View.extend(_super);
    Collection = thumbs.Collection = Collection.extend(_super);
    Router = thumbs.Router = Router.extend(_super);

    var EventDelegator = {
        render: function render() {
            this._super('render', arguments);
            this.checkForEvents();
            return this;
        },

        checkForEvents: function checkForEvents() {
            var self = this;
            this.events = this.events || {};
            this.$('[data-thumbs-event]').each(function () {
                var $this = $(this), data = $this.data('thumbs-event').split(':'),
                    event = data[0], func = data[1];

                var id = _.uniqueId('thumbs_');
                $this.addClass(id);
                self.events[event + ' .' + id] = func;
            });
            this.delegateEvents();
            return this;
        }
    };

    var Identifier = {
        render: function render() {
            this._super('render', arguments);
            this.checkForIdentifiers();
            return this;
        },

        checkForIdentifiers: function checkForIdentifiers() {
            var self = this;
            this.$('[data-thumbs-id]').each(function (el) {
                var $this = $(this);
                var id = $this.data('thumbs-id');
                self[id] = this;
                self['$' + id] = $this;
            });
            return this;
        }
    };

    var Binder = {

        __monitors: null,

        initialize: function initialize() {
            this._super("initialize", arguments);
            this.__monitors = {};
        },

        __updateValues: function setValues() {
            return this.__setValues(this.model.changedAttributes());
        },

        __setValues: function __setValues(values) {
            var monitors = this.__monitors;
            if (monitors) {
                _.each(values, function changedEach(val, key) {
                    var mon = monitors[key];
                    if (mon) {
                        _.each(mon, function (fn) {
                            fn(val);
                        });
                    }
                });
            }
            return this;
        },

        setElData: function setElData(el, data, attribute) {
            if (this.checkFormatting) {
                this.checkFormatting(el, data);
            } else {
                data = (data !== null && "undefined" !== typeof data) ? data : "";
                this.$(el).text(data);
            }
        },

        setupBinders: function setUpMonitors() {
            var monitors = this.__monitors, setElData = _.bind(this.setElData, this);
            this.$("[data-thumbs-bind]").each(function () {
                var el = this, $el = $(el);
                var m = $el.data("thumbs-bind");
                if (!(m in monitors)) {
                    monitors[m] = [];
                }
                monitors[m].push(function monitor(data) {
                    setElData(el, data, m);
                });
            });
            var model = this.model;
            model.on("change", this.__updateValues, this);
            this.__setValues(model.attributes);
            return this;
        },

        render: function render() {
            this._super("render", arguments);
            if (this.model) {
                this.setupBinders();
            }
            return this;
        },

        remove: function remove() {
            if (this.model) {
                this.model.off("change", this.setValues, this);
            }
            this.__monitors = null;
            return this._super("remove", arguments);
        }

    };

    var Formatter = {

        checkFormatting: function checkFormatting(el, data) {
            var $el = this.$(el), args = argsToArray(arguments);
            data = args.length === 2 ? data : $el.text();
            data = (data !== null && "undefined" !== typeof data) ? data : "";
            var formatter = $el.data("thumbs-format");
            if (formatter && "function" === typeof this[formatter]) {
                $el.text(this[formatter](data));
            } else {
                $el.text(data);
            }
        },

        renderFormatters: function renderFormatters() {
            var checkFormatting = _.bind(this.checkFormatting, this);
            this.$("[data-thumbs-format]").each(function () {
                checkFormatting(this);
            });
            return this;
        },

        render: function render() {
            this._super("render", arguments);
            return this.renderFormatters();
        }

    };

    thumbs.templater = (function _templater() {
        var templater = _.template;
        return function __templater(tmplr) {
            if (tmplr) {
                return (templater = tmplr);
            } else {
                return templater;
            }
        };
    }());

    View = thumbs.View = View.extend(Formatter).extend(Identifier).extend(Binder).extend(EventDelegator).extend({
        _subviews: null,

        initialize: function initialize(options) {
            this._super("initialize", arguments);
            this._subviews = {};
        },

        addSubView: function addSubView(selector, view) {
            this.removeSubView(selector);
            this._subviews[selector] = view;
            view.setElement(this.$(selector)).render();
            //this.assign(this._subviews);
            return this;
        },

        removeSubView: function removeSubView(selector) {
            var view = this._subviews[selector];
            if (view) {
                // undelegate events, but we won't remove the element
                view.setElement(null);
                view.remove();
                this.$(selector).empty();
                delete this._subviews[selector];
            }
            return this;
        },

        removeSubViews: function removeSubViews() {
            _.each(this._subviews, function (view, selector) {
                this.removeSubView(selector);
            }, this);
            return this;
        },

        // default render functionality is to set the el html to the
        // compiled template run with the model data
        // override if that's not what's needed
        render: function render() {
            this._super("render", arguments);
            this.assign(this._subviews);
            return this;
        },

        assign: function assign(selector, view) {
            var selectors;
            if (_.isObject(selector)) {
                selectors = selector;
            } else if (selector) {
                selectors = {};
                selectors[selector] = view;
            }
            if (selectors) {
                _.each(selectors, function (view, selector) {
                    view.setElement(this.$(selector)).render();
                }, this);
            }

            return this;
        },

        // when a view is removed, remove all event bindings
        remove: function remove() {
            this.undelegateEvents();
            this.removeSubViews();
            return this._super('remove', arguments);
        }
    });

    thumbs.TemplateView = View.extend({
        /**@lends thumbs.TemplateView.prototype*/

        /**
         * The the `templater` to use to compile this view template. If not specified them {@link thumbs.templater}
         * will be used.
         *
         * @example
         *
         * var MyView = thumbs.TemplateView.extend({
         *     templater : function(template){
         *          return Handlebars.compile(template);
         *     },
         *
         *     template : "
{{firstName}}
"
         * })
         *
         * @function
         */
        templater: thumbs.templater(),

        /**
         * The template string for this view.
         *
         * @example
         * var MyView = thumbs.TemplateView.extend({
         *     template : "
{{firstName}}
"
         * });
         *
         */
        template: null,

        initialize: function (options) {
            this._super("initialize", arguments);
            if (this.template) {
                this._template = this.templater(this.template);
            }
        },

        /**
         * Gathers data to be interpolated into the template. By default serializes the model to json.
         *
         * @example
         * var MyView = thumbs.TemplateView.extend({
         *     template : "

{{i18n.hello}}

{{firstName}}

",
         *     getTemplateData : function(){
         *         var data = this._super("getTemplateData", arguments);
         *         data.i18n = {hello : "Hello"};
         *         return data;
         *     }
         * });
         *
         * @return {Object} Object with key value pairs to be interpolated into the View.
         */
        getTemplateData: function () {
            return this.model ? this.model.toJSON() : {};
        },

        /**
         * Fills the template with the data gathered from {@link thumbs.TemplateView#getTemplateData}
         * @return {thumbs.TemplateView} this for chaining.
         */
        fillTemplate: function fillTemplate() {
            if (this._template) {
                return this._template(this.getTemplateData());
            } else {
                return null;
            }
        },

        /**
         * Renders the the template.
         *
         * @return this
         */
        renderTemplate: function renderTemplate() {
            if (this._template) {
                var template = this.fillTemplate();
                if (template) {
                    this.$el.html(template);
                }
            }
            return this;
        },

        render: function () {
            //call render template
            return this.renderTemplate()._super("render", arguments);
        }
    });

    return View;

}).call(this);
<commit_msg>Added support for AMD<commit_after>(function () {

    var root = this;
    var ArrayProto = Array.prototype;
    var slice = ArrayProto.slice;

    function argsToArray(args) {
        return slice.call(args, 0);
    }

    var thumbs;
    if (typeof exports !== 'undefined') {
        thumbs = exports;
    } else if (typeof define === "function" && define.amd) {
        define(function () {
            thumbs = {};
            return thumbs;
        });
    } else {
        thumbs = root.thumbs = {};
    }

    // Require Underscore, if we're on the server, and it's not already present.
    var _ = root._;
    if (!_ && ('undefined' !== typeof require )) {
        _ = require('underscore');
    }
    // Require Backbone, if we're on the server, and it's not already present.
    var Backbone = root.Backbone;
    if (!Backbone && ('undefined' !== typeof require)) {
        Backbone = require('underscore');
    }

    _.extend(thumbs, Backbone);

    // Current version of the library. Keep in sync with `package.json`.
    thumbs.VERSION = '0.0.0';

    //copy over Backbones $ for dom
    var Model = thumbs.Model, View = thumbs.View, Collection = thumbs.Collection, Router = thumbs.Router, History = thumbs.History;

    var _super = {
        _super: (function _super() {

            function findSuper(methodName, childObject) {
                var object = childObject;
                while (object[methodName] === childObject[methodName]) {
                    var constructor = object.__getConstructor();
                    object = constructor['__super__'];
                }

                return object;
            }

            return function __super(methodName, args) {

                // keep track of how far up the prototype chain we have traversed
                if (!this._superCallObjects) {
                    this._superCallObjects = {};
                }

                var currentObject = this._superCallObjects[methodName] || this,
                    parentObject = findSuper(methodName, currentObject);
                this._superCallObjects[methodName] = parentObject;

                var result = parentObject[methodName].apply(this, args || {});
                delete this._superCallObjects[methodName];
                return result;
            };
        }())
    };

    // this allows access to prototype.constructor.__super__
    // when _.bindAll is used
    var _extend = thumbs.Model.extend;

    function extend(protoProps, staticProps) {
        var child = _extend.apply(this, arguments);
        child.prototype.__getConstructor = function () {
            return child;
        };
        return child;
    }

    function Class(options) {
        this.cid = _.uniqueId('class');
        this.initialize.apply(this, arguments);
    }

    _.extend(Class.prototype, thumbs.Events, _super, {
        initialize: function initialize() {
        }
    });

    thumbs.Class = Class;

    Class.extend = Model.extend = View.extend = Collection.extend = Router.extend = History.extend = extend;
    Model = thumbs.Model = Model.extend(_super);
    View = thumbs.View = View.extend(_super);
    Collection = thumbs.Collection = Collection.extend(_super);
    Router = thumbs.Router = Router.extend(_super);

    var EventDelegator = {
        render: function render() {
            this._super('render', arguments);
            this.checkForEvents();
            return this;
        },

        checkForEvents: function checkForEvents() {
            var self = this;
            this.events = this.events || {};
            this.$('[data-thumbs-event]').each(function () {
                var $this = $(this), data = $this.data('thumbs-event').split(':'),
                    event = data[0], func = data[1];

                var id = _.uniqueId('thumbs_');
                $this.addClass(id);
                self.events[event + ' .' + id] = func;
            });
            this.delegateEvents();
            return this;
        }
    };

    var Identifier = {
        render: function render() {
            this._super('render', arguments);
            this.checkForIdentifiers();
            return this;
        },

        checkForIdentifiers: function checkForIdentifiers() {
            var self = this;
            this.$('[data-thumbs-id]').each(function (el) {
                var $this = $(this);
                var id = $this.data('thumbs-id');
                self[id] = this;
                self['$' + id] = $this;
            });
            return this;
        }
    };

    var Binder = {

        __monitors: null,

        initialize: function initialize() {
            this._super("initialize", arguments);
            this.__monitors = {};
        },

        __updateValues: function setValues() {
            return this.__setValues(this.model.changedAttributes());
        },

        __setValues: function __setValues(values) {
            var monitors = this.__monitors;
            if (monitors) {
                _.each(values, function changedEach(val, key) {
                    var mon = monitors[key];
                    if (mon) {
                        _.each(mon, function (fn) {
                            fn(val);
                        });
                    }
                });
            }
            return this;
        },

        setElData: function setElData(el, data, attribute) {
            if (this.checkFormatting) {
                this.checkFormatting(el, data);
            } else {
                data = (data !== null && "undefined" !== typeof data) ? data : "";
                this.$(el).text(data);
            }
        },

        setupBinders: function setUpMonitors() {
            var monitors = this.__monitors, setElData = _.bind(this.setElData, this);
            this.$("[data-thumbs-bind]").each(function () {
                var el = this, $el = $(el);
                var m = $el.data("thumbs-bind");
                if (!(m in monitors)) {
                    monitors[m] = [];
                }
                monitors[m].push(function monitor(data) {
                    setElData(el, data, m);
                });
            });
            var model = this.model;
            model.on("change", this.__updateValues, this);
            this.__setValues(model.attributes);
            return this;
        },

        render: function render() {
            this._super("render", arguments);
            if (this.model) {
                this.setupBinders();
            }
            return this;
        },

        remove: function remove() {
            if (this.model) {
                this.model.off("change", this.setValues, this);
            }
            this.__monitors = null;
            return this._super("remove", arguments);
        }

    };

    var Formatter = {

        checkFormatting: function checkFormatting(el, data) {
            var $el = this.$(el), args = argsToArray(arguments);
            data = args.length === 2 ? data : $el.text();
            data = (data !== null && "undefined" !== typeof data) ? data : "";
            var formatter = $el.data("thumbs-format");
            if (formatter && "function" === typeof this[formatter]) {
                $el.text(this[formatter](data));
            } else {
                $el.text(data);
            }
        },

        renderFormatters: function renderFormatters() {
            var checkFormatting = _.bind(this.checkFormatting, this);
            this.$("[data-thumbs-format]").each(function () {
                checkFormatting(this);
            });
            return this;
        },

        render: function render() {
            this._super("render", arguments);
            return this.renderFormatters();
        }

    };

    thumbs.templater = (function _templater() {
        var templater = _.template;
        return function __templater(tmplr) {
            if (tmplr) {
                return (templater = tmplr);
            } else {
                return templater;
            }
        };
    }());

    View = thumbs.View = View.extend(Formatter).extend(Identifier).extend(Binder).extend(EventDelegator).extend({
        _subviews: null,

        initialize: function initialize(options) {
            this._super("initialize", arguments);
            this._subviews = {};
        },

        addSubView: function addSubView(selector, view) {
            this.removeSubView(selector);
            this._subviews[selector] = view;
            view.setElement(this.$(selector)).render();
            //this.assign(this._subviews);
            return this;
        },

        removeSubView: function removeSubView(selector) {
            var view = this._subviews[selector];
            if (view) {
                // undelegate events, but we won't remove the element
                view.setElement(null);
                view.remove();
                this.$(selector).empty();
                delete this._subviews[selector];
            }
            return this;
        },

        removeSubViews: function removeSubViews() {
            _.each(this._subviews, function (view, selector) {
                this.removeSubView(selector);
            }, this);
            return this;
        },

        // default render functionality is to set the el html to the
        // compiled template run with the model data
        // override if that's not what's needed
        render: function render() {
            this._super("render", arguments);
            this.assign(this._subviews);
            return this;
        },

        assign: function assign(selector, view) {
            var selectors;
            if (_.isObject(selector)) {
                selectors = selector;
            } else if (selector) {
                selectors = {};
                selectors[selector] = view;
            }
            if (selectors) {
                _.each(selectors, function (view, selector) {
                    view.setElement(this.$(selector)).render();
                }, this);
            }

            return this;
        },

        // when a view is removed, remove all event bindings
        remove: function remove() {
            this.undelegateEvents();
            this.removeSubViews();
            return this._super('remove', arguments);
        }
    });

    thumbs.TemplateView = View.extend({
        /**@lends thumbs.TemplateView.prototype*/

        /**
         * The the `templater` to use to compile this view template. If not specified them {@link thumbs.templater}
         * will be used.
         *
         * @example
         *
         * var MyView = thumbs.TemplateView.extend({
         *     templater : function(template){
         *          return Handlebars.compile(template);
         *     },
         *
         *     template : "
{{firstName}}
"
         * })
         *
         * @function
         */
        templater: thumbs.templater(),

        /**
         * The template string for this view.
         *
         * @example
         * var MyView = thumbs.TemplateView.extend({
         *     template : "
{{firstName}}
"
         * });
         *
         */
        template: null,

        initialize: function (options) {
            this._super("initialize", arguments);
            if (this.template) {
                this._template = this.templater(this.template);
            }
        },

        /**
         * Gathers data to be interpolated into the template. By default serializes the model to json.
         *
         * @example
         * var MyView = thumbs.TemplateView.extend({
         *     template : "

{{i18n.hello}}

{{firstName}}

",
         *     getTemplateData : function(){
         *         var data = this._super("getTemplateData", arguments);
         *         data.i18n = {hello : "Hello"};
         *         return data;
         *     }
         * });
         *
         * @return {Object} Object with key value pairs to be interpolated into the View.
         */
        getTemplateData: function () {
            return this.model ? this.model.toJSON() : {};
        },

        /**
         * Fills the template with the data gathered from {@link thumbs.TemplateView#getTemplateData}
         * @return {thumbs.TemplateView} this for chaining.
         */
        fillTemplate: function fillTemplate() {
            if (this._template) {
                return this._template(this.getTemplateData());
            } else {
                return null;
            }
        },

        /**
         * Renders the the template.
         *
         * @return this
         */
        renderTemplate: function renderTemplate() {
            if (this._template) {
                var template = this.fillTemplate();
                if (template) {
                    this.$el.html(template);
                }
            }
            return this;
        },

        render: function () {
            //call render template
            return this.renderTemplate()._super("render", arguments);
        }
    });

}).call(this);
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import DetailsPage from './DetailsPage';
import Loader from '../../components/Loader';

class GameDetail extends Component {
    constructor(props) {
        super(props);
        this.state = {
            name: "",
            description: "",
            mainbar: [],
            img: "",
            sidebar: [],
            relatedGames: [],
            loading: true
        };
    }

    componentDidMount() {
        this._fetchData();
    }

    componentDidUpdate(prevProps) {
        if (this.props.location !== prevProps.location) {
            this.onRouteChanged();
        }
    }

    onRouteChanged() {
        this.setState({
            loading: true,
            relatedGames: []
        }, () => {
            this._fetchData();
        });
    }

    render() {
        return(

                {this.state.loading && <Loader/>}
                {!this.state.loading &&
                    <DetailsPage name={this.state.name} description={this.state.description}
                            mainbar={this.state.mainbar} img={this.state.img} sidebar={this.state.sidebar}
                            linkbar={this.state.linkbar} games={this.state.relatedGames}
                            gamesTitle={"Related Games:"}/>
                }

        );
    }

    _fetchData() {
        fetch("http://gamingdb.info/api/game/" + this.props.match.params.id,{
            method: 'GET'
        }).then(response => response.json())
        .then(response => {
            console.log(response);
            Promise.all(
                this._fetchRelatedGames(response.related_game_ids)
            ).then(results => {
                let relatedGamesArray = [];
                for (let i = 0; i < results.length; i++) {
                    let response = results[i];
                    let item = {
                        name: response.name,
                        img: response.thumb_url,
                        url: "/games/" + response.game_id,
                        details: this._buildDetails(response)
                    };
                    relatedGamesArray.push(item);
                }
                this.setState({
                    relatedGames: relatedGamesArray
                });
            });
            let genres = this._stringFromArray(response.genres);
            let devs = this._linkbarFromArray(response.developers, "/developers/","developer_id");
            let platforms = this._linkbarFromArray(response.platforms,"/platforms/", "platform_id");
            let characters = this._linkbarFromArray(response.characters, "/characters/", "character_id");

            this.setState({
                name: response.name ? response.name : "",
                description: response.description ? response.description : "",
                mainbar: [
                    { title: "Rating", content: response.rating ? response.rating + "/100" : "" },
                    { title: "Genres", content: genres }

                ],
                img: response.image_url,
                linkbar: [
                    { title: "Platforms", links: platforms },
                    { title: "Developers", links: devs },
                    { title: "Characters", links: characters }
                ]
            });
            this.setState({
                loading: false
            })
        });
    };

    _fetchRelatedGames(idArray) {
        let promiseArray = [];
        console.log(idArray);
        if(idArray !== null) {
            for (var i = 0; i < idArray.length; i++) {
                promiseArray.push(
                    this._fetchGame(idArray[i])
                );
            }
        }
        return promiseArray;
    }

    _fetchGame(id) {
        return fetch("http://gamingdb.info/api/game/" + id,{
            method: 'GET'
        }).then(response => response.json());
    }

    _stringFromArray(a) {
        if(!a) {
            return "";
        }
        let s = "";
        for( let x of a ) {
            s += x.name;
            s += ", ";
        }
        return s.substring(0, s.length - 2);
    }

    _linkbarFromArray(array, path, idKey) {
        let result = [];
        for (var i = 0; i < array.length; i++) {
            result.push({
                link: path + array[i][idKey],
                text: array[i]["name"]
            });
        }
        return result;
    }

    _buildDetails(obj) {
        let details = []
        if(obj.release_date)
            details.push({ title: "Released:", content:obj.release_date});
        if(obj.rating)
            details.push({title: "Rating:", content: obj.rating + "/100"});
        if(obj.genres.length > 0)
            details.push({title: "Genre:", content:obj.genres[0].name});

        return details;
    }

}

export default GameDetail;<commit_msg>removing console.logs<commit_after>import React, {Component} from 'react';
import DetailsPage from './DetailsPage';
import Loader from '../../components/Loader';

class GameDetail extends Component {
    constructor(props) {
        super(props);
        this.state = {
            name: "",
            description: "",
            mainbar: [],
            img: "",
            sidebar: [],
            relatedGames: [],
            loading: true
        };
    }

    componentDidMount() {
        this._fetchData();
    }

    componentDidUpdate(prevProps) {
        if (this.props.location !== prevProps.location) {
            this.onRouteChanged();
        }
    }

    onRouteChanged() {
        this.setState({
            loading: true,
            relatedGames: []
        }, () => {
            this._fetchData();
        });
    }

    render() {
        return(

                {this.state.loading && <Loader/>}
                {!this.state.loading &&
                    <DetailsPage name={this.state.name} description={this.state.description}
                            mainbar={this.state.mainbar} img={this.state.img} sidebar={this.state.sidebar}
                            linkbar={this.state.linkbar} games={this.state.relatedGames}
                            gamesTitle={"Related Games:"}/>
                }

        );
    }

    _fetchData() {
        fetch("http://gamingdb.info/api/game/" + this.props.match.params.id,{
            method: 'GET'
        }).then(response => response.json())
        .then(response => {
            Promise.all(
                this._fetchRelatedGames(response.related_game_ids)
            ).then(results => {
                let relatedGamesArray = [];
                for (let i = 0; i < results.length; i++) {
                    let response = results[i];
                    let item = {
                        name: response.name,
                        img: response.thumb_url,
                        url: "/games/" + response.game_id,
                        details: this._buildDetails(response)
                    };
                    relatedGamesArray.push(item);
                }
                this.setState({
                    relatedGames: relatedGamesArray
                });
            });
            let genres = this._stringFromArray(response.genres);
            let devs = this._linkbarFromArray(response.developers, "/developers/","developer_id");
            let platforms = this._linkbarFromArray(response.platforms,"/platforms/", "platform_id");
            let characters = this._linkbarFromArray(response.characters, "/characters/", "character_id");

            this.setState({
                name: response.name ? response.name : "",
                description: response.description ? response.description : "",
                mainbar: [
                    { title: "Rating", content: response.rating ? response.rating + "/100" : "" },
                    { title: "Genres", content: genres }

                ],
                img: response.image_url,
                linkbar: [
                    { title: "Platforms", links: platforms },
                    { title: "Developers", links: devs },
                    { title: "Characters", links: characters }
                ]
            });
            this.setState({
                loading: false
            })
        });
    };

    _fetchRelatedGames(idArray) {
        let promiseArray = [];
        if(idArray !== null) {
            for (var i = 0; i < idArray.length; i++) {
                promiseArray.push(
                    this._fetchGame(idArray[i])
                );
            }
        }
        return promiseArray;
    }

    _fetchGame(id) {
        return fetch("http://gamingdb.info/api/game/" + id,{
            method: 'GET'
        }).then(response => response.json());
    }

    _stringFromArray(a) {
        if(!a) {
            return "";
        }
        let s = "";
        for( let x of a ) {
            s += x.name;
            s += ", ";
        }
        return s.substring(0, s.length - 2);
    }

    _linkbarFromArray(array, path, idKey) {
        let result = [];
        for (var i = 0; i < array.length; i++) {
            result.push({
                link: path + array[i][idKey],
                text: array[i]["name"]
            });
        }
        return result;
    }

    _buildDetails(obj) {
        let details = []
        if(obj.release_date)
            details.push({ title: "Released:", content:obj.release_date});
        if(obj.rating)
            details.push({title: "Rating:", content: obj.rating + "/100"});
        if(obj.genres.length > 0)
            details.push({title: "Genre:", content:obj.genres[0].name});

        return details;
    }

}

export default GameDetail;<|endoftext|>


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

/**

If you don't know which DAO implementation to choose, EasyDAO is
    ready to help. Simply require foam.dao.EasyDAO and create() with the flags
    to indicate what behavior you're looking for. Under the hood, EasyDAO
    will create one or more DAO instances to service your requirements.

Since EasyDAO is a proxy, just use it like you would any other
    DAO, without worrying about the internal DAO doing the work.

*/
foam.CLASS({
  package: 'foam.dao',
  name: 'EasyDAO',
  extends: 'foam.dao.ProxyDAO',

  requires: [
    'foam.dao.MDAO',
    'foam.dao.JournalDAO',
    'foam.dao.GUIDDAO',
    'foam.dao.IDBDAO',
    'foam.dao.SequenceNumberDAO',
    'foam.dao.CachingDAO',
    'foam.dao.SyncDAO',
    'foam.dao.ContextualizingDAO',
    'foam.dao.DeDupDAO',
    'foam.dao.ClientDAO',
    'foam.box.Context',
    'foam.box.HTTPBox',
    'foam.box.SocketBox',
    //'foam.core.dao.MergeDAO',
    //'foam.core.dao.MigrationDAO',
    //'foam.core.dao.VersionNoDAO',
    //'foam.dao.EasyClientDAO',
    'foam.dao.LoggingDAO',
    'foam.dao.TimingDAO',
  ],

  imports: [ 'document' ],

  properties: [
    {
      /** The developer-friendly name for this EasyDAO. */
      name: 'name',
      factory: function() { return this.of.id; },
    },
    {
      /** This is set automatically when you create an EasyDAO.
        @private */
      name: 'delegate'
    },
    {
      /** Have EasyDAO use a sequence number to index items. Note that
        .seqNo and .guid features are mutually
        exclusive. */
      class: 'Boolean',
      name: 'seqNo',
      value: false,
    },
    {
      /** Have EasyDAO generate guids to index items. Note that .seqNo and .guid features are mutually exclusive. */
      class: 'Boolean',
      name: 'guid',
      label: 'GUID',
      value: false,
    },
    {
      /** The property on your items to use to store the sequence number or guid. This is required for .seqNo or .guid mode. */
      name: 'seqProperty',
      class: 'Property',
    },
    {
      /** Enable local in-memory caching of the DAO. */
      class: 'Boolean',
      name: 'cache',
      value: false,
    },
    {
      /** Enable value de-duplication to save memory when caching. */
      class: 'Boolean',
      name: 'dedup',
      value: false,
    },
    {
      /** Keep a history of all state changes to the DAO. */
      name: 'journal',
      value: false
    },
    {
      /** Enable logging on the DAO. */
      class: 'Boolean',
      name: 'logging',
      value: false,
    },
    {
      /** Enable time tracking for concurrent DAO operations. */
      class: 'Boolean',
      name: 'timing',
      value: false,
    },
    {
      /** Contextualize objects on .find, re-creating them with this EasyDAO's
        exports, as if they were children of this EasyDAO. */
      class: 'Boolean',
      name: 'contextualize',
      value: false,
    },
//     {
//       class: 'Boolean',
//       name: 'cloning',
//       value: false,
//       //documentation: "True to clone results on select"
//     },
    {
      /**

Selects the basic functionality this EasyDAO should provide.
        You can specify an instance of a DAO model definition such as
        MDAO, or a constant indicating your requirements.

Choices are:

IDB: Use IndexDB for storage.

LOCAL: Use local storage.

MDAO: Use non-persistent in-memory storage.

      */
      name: 'daoType',
      value: 'foam.dao.IDBDAO',
    },
    {
      /** Automatically generate indexes as necessary, if using an MDAO or cache. */
      class: 'Boolean',
      name: 'autoIndex',
      value: false,
    },
//     {
//       /** Creates an internal MigrationDAO and applies the given array of MigrationRule. */
//       class: 'FObjectArray',
//       name: 'migrationRules',
//       of: 'foam.core.dao.MigrationRule',
//     },
    {
      /** Turn on to activate synchronization with a server. Specify serverUri
        and syncProperty as well. */
      class: 'Boolean',
      name: 'syncWithServer',
      value: false
    },
    {
      /** Setting to true activates polling, periodically checking in with
        the server. If sockets are used, polling is optional as the server
        can push changes to this client. */
      class: 'Boolean',
      name: 'syncPolling',
      value: true
    },
    {
      /** The URI of the server to use. If sockets is true, this will use
        a web socket, otherwise HTTP to contact the server-side DAO. On your
        server, use an EasyDAO with isServer:true to provide the other end
        of the connection. */
      class: 'String',
      name: 'serverUri',
      factory: function() {
        return this.document && this.document.location ?
            this.document.location.origin + '/api' :
            '';
      }
    },
    {
      /** Set to true if you are running this on a server, and clients will
        synchronize with this DAO. */
      class: 'Boolean',
      name: 'isServer',
      value: false
    },
    {
      /** The property to synchronize on. This is typically an integer value
        indicating the version last seen on the remote. */
      name: 'syncProperty'
    },
    {
      /** If true, uses sockets instead of HTTP for server communication. */
      name: 'sockets',
      value: false
    },

  ],

  constants: {
    // Aliases for daoType
    ALIASES: {
      MDAO:  'foam.dao.MDAO',
      IDB:   'foam.dao.IDBDAO',
      LOCAL: 'foam.dao.LocalStorageDAO',
    }
  },

  methods: [
    function init() {
      /**

On initialization, the EasyDAO creates an appropriate chain of
        internal EasyDAO instances based on the EasyDAO
        property settings.

This process is transparent to the developer, and you can use your
        EasyDAO like any other DAO.

      */
      this.SUPER(args);

      var daoType = typeof this.daoType === 'string' ?
        this.ALIASES[this.daoType] || this.daoType :
        this.daoType;

      var daoModel = typeof daoType === 'string' ?
        this.lookup(daoType) || global[daoType] :
        daoType;

      var params = { of: this.of };

      if ( ! daoModel ) {
        this.warn(
          "EasyDAO: Unknown DAO Type.  Add '" + daoType + "' to requires: list."
        );
      }

      if ( this.name && daoModel.getAxiomByName('name')  ) params.name = this.name;
      if ( daoModel.getAxiomByName('autoIndex') ) params.autoIndex = this.autoIndex;
      //if ( this.seqNo || this.guid ) params.property = this.seqProperty;

      var dao = daoModel.create(params, this.__subContext__);

      if ( this.MDAO.isInstance(dao) ) {
        this.mdao = dao;
        if ( this.dedup ) dao = this.DeDupDAO.create({delegate: dao});
      } else {
//         if ( this.migrationRules && this.migrationRules.length ) {
//           dao = this.MigrationDAO.create({
//             delegate: dao,
//             rules: this.migrationRules,
//             name: this.model.id + "_" + daoModel.id + "_" + this.name
//           });
//         }
        if ( this.cache ) {
          this.mdao = this.MDAO.create(params);
          dao = this.CachingDAO.create({
            cache: this.dedup ?
              this.mdao :
              this.DeDupDAO.create({delegate: this.mdao}),
            src: dao,
            of: this.model});
        }
      }

      if ( this.seqNo && this.guid ) throw "EasyDAO 'seqNo' and 'guid' features are mutually exclusive.";

      if ( this.seqNo ) {
        var args = {__proto__: params, delegate: dao, of: this.of};
        if ( this.seqProperty ) args.property = this.seqProperty;
        dao = this.SequenceNumberDAO.create(args);
      }

      if ( this.guid ) {
        var args = {__proto__: params, delegate: dao, of: this.of};
        if ( this.seqProperty ) args.property = this.seqProperty;
        dao = this.GUIDDAO.create(args);
      }

      var cls = this.of$cls;

      if ( this.syncWithServer && this.isServer ) throw "isServer and syncWithServer are mutually exclusive.";

      if ( this.syncWithServer || this.isServer ) {
        if ( ! this.syncProperty ) {
          this.syncProperty = cls.SYNC_PROPERTY;
          if ( ! this.syncProperty ) {
            throw "EasyDAO sync with class " + cls.id + " invalid. Sync requires a sync property be set, or be of a class including a property 'sync_property'.";
          }
        }
      }

      if ( this.syncWithServer ) {
        var boxContext = this.Context.create();
        var boxSender = ( this.sockets ) ?
          this.SocketBox.create({
            address: this.serverUri
          }, boxContext) :
          this.HTTPBox.create({
             url: this.serverUri,
             method: 'POST'
          }, boxContext); // TODO: retry?
          //TODO: EasyClientDAO

        dao = this.SyncDAO.create({
          remoteDAO: this.ClientDAO.create({
              name: this.name,
              delegate: boxSender
          }, boxContext),
          syncProperty: this.syncProperty,
          delegate: dao,
          pollingFrequency: 1000
        });
        dao.syncRecordDAO = foam.dao.EasyDAO.create({
          of: dao.SyncRecord,
          cache: true,
          daoType: this.daoType,
          name: this.name + '_SyncRecords'
        });
      }

//       if ( this.isServer ) {
//         dao = this.VersionNoDAO.create({
//           delegate: dao,
//           property: this.syncProperty,
//           version: 2
//         });
//       }

      if ( this.contextualize ) {
        dao = this.ContextualizingDAO.create({delegate: dao});
      }

      if ( this.journal ) {
        dao = this.JournalDAO.create({
          delegate: dao,
          journal: foam.dao.EasyDAO.create({
            of: foam.dao.JournalEntry,
            daoType: this.daoType,
            seqNo: true,
            name: this.name + '_Journal'
          })
        });
      }

      if ( this.timing  ) dao = this.TimingDAO.create({ name: this.name + 'DAO', delegate: dao });
      if ( this.logging ) dao = this.LoggingDAO.create({ delegate: dao });

      this.delegate = dao;
    },

    /** Only relevant if cache is true or if daoType
       was set to MDAO, but harmless otherwise. Generates an index
       for a query over all specified properties together.
       @arg var_args specify any number of Properties to be indexed.
    */
    function addIndex(/* foam.core.Property* */ var_args) {
      this.mdao && this.mdao.addIndex.apply(this.mdao, arguments);
      return this;
    },

    /** Only relevant if cache is true or if daoType
      was set to MDAO, but harmless otherwise. Adds an existing index
      to the MDAO.
      @arg index The index to add.
    */
    function addRawIndex(/* foam.dao.index.Index */ index) {
      this.mdao && this.mdao.addRawIndex.apply(this.mdao, arguments);
      return this;
    }
  ]
});
<commit_msg>Added ARRAY alias in EasyDAO.<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**

If you don't know which DAO implementation to choose, EasyDAO is
    ready to help. Simply require foam.dao.EasyDAO and create() with the flags
    to indicate what behavior you're looking for. Under the hood, EasyDAO
    will create one or more DAO instances to service your requirements.

Since EasyDAO is a proxy, just use it like you would any other
    DAO, without worrying about the internal DAO doing the work.

*/
foam.CLASS({
  package: 'foam.dao',
  name: 'EasyDAO',
  extends: 'foam.dao.ProxyDAO',

  requires: [
    'foam.dao.MDAO',
    'foam.dao.JournalDAO',
    'foam.dao.GUIDDAO',
    'foam.dao.IDBDAO',
    'foam.dao.SequenceNumberDAO',
    'foam.dao.CachingDAO',
    'foam.dao.SyncDAO',
    'foam.dao.ContextualizingDAO',
    'foam.dao.DeDupDAO',
    'foam.dao.ClientDAO',
    'foam.box.Context',
    'foam.box.HTTPBox',
    'foam.box.SocketBox',
    //'foam.core.dao.MergeDAO',
    //'foam.core.dao.MigrationDAO',
    //'foam.core.dao.VersionNoDAO',
    //'foam.dao.EasyClientDAO',
    'foam.dao.LoggingDAO',
    'foam.dao.TimingDAO',
  ],

  imports: [ 'document' ],

  properties: [
    {
      /** The developer-friendly name for this EasyDAO. */
      name: 'name',
      factory: function() { return this.of.id; },
    },
    {
      /** This is set automatically when you create an EasyDAO.
        @private */
      name: 'delegate'
    },
    {
      /** Have EasyDAO use a sequence number to index items. Note that
        .seqNo and .guid features are mutually
        exclusive. */
      class: 'Boolean',
      name: 'seqNo',
      value: false,
    },
    {
      /** Have EasyDAO generate guids to index items. Note that .seqNo and .guid features are mutually exclusive. */
      class: 'Boolean',
      name: 'guid',
      label: 'GUID',
      value: false,
    },
    {
      /** The property on your items to use to store the sequence number or guid. This is required for .seqNo or .guid mode. */
      name: 'seqProperty',
      class: 'Property',
    },
    {
      /** Enable local in-memory caching of the DAO. */
      class: 'Boolean',
      name: 'cache',
      value: false,
    },
    {
      /** Enable value de-duplication to save memory when caching. */
      class: 'Boolean',
      name: 'dedup',
      value: false,
    },
    {
      /** Keep a history of all state changes to the DAO. */
      name: 'journal',
      value: false
    },
    {
      /** Enable logging on the DAO. */
      class: 'Boolean',
      name: 'logging',
      value: false,
    },
    {
      /** Enable time tracking for concurrent DAO operations. */
      class: 'Boolean',
      name: 'timing',
      value: false,
    },
    {
      /** Contextualize objects on .find, re-creating them with this EasyDAO's
        exports, as if they were children of this EasyDAO. */
      class: 'Boolean',
      name: 'contextualize',
      value: false,
    },
//     {
//       class: 'Boolean',
//       name: 'cloning',
//       value: false,
//       //documentation: "True to clone results on select"
//     },
    {
      /**

Selects the basic functionality this EasyDAO should provide.
        You can specify an instance of a DAO model definition such as
        MDAO, or a constant indicating your requirements.

Choices are:

IDB: Use IndexDB for storage.

LOCAL: Use local storage.

MDAO: Use non-persistent in-memory storage.

      */
      name: 'daoType',
      value: 'foam.dao.IDBDAO',
    },
    {
      /** Automatically generate indexes as necessary, if using an MDAO or cache. */
      class: 'Boolean',
      name: 'autoIndex',
      value: false,
    },
//     {
//       /** Creates an internal MigrationDAO and applies the given array of MigrationRule. */
//       class: 'FObjectArray',
//       name: 'migrationRules',
//       of: 'foam.core.dao.MigrationRule',
//     },
    {
      /** Turn on to activate synchronization with a server. Specify serverUri
        and syncProperty as well. */
      class: 'Boolean',
      name: 'syncWithServer',
      value: false
    },
    {
      /** Setting to true activates polling, periodically checking in with
        the server. If sockets are used, polling is optional as the server
        can push changes to this client. */
      class: 'Boolean',
      name: 'syncPolling',
      value: true
    },
    {
      /** The URI of the server to use. If sockets is true, this will use
        a web socket, otherwise HTTP to contact the server-side DAO. On your
        server, use an EasyDAO with isServer:true to provide the other end
        of the connection. */
      class: 'String',
      name: 'serverUri',
      factory: function() {
        return this.document && this.document.location ?
            this.document.location.origin + '/api' :
            '';
      }
    },
    {
      /** Set to true if you are running this on a server, and clients will
        synchronize with this DAO. */
      class: 'Boolean',
      name: 'isServer',
      value: false
    },
    {
      /** The property to synchronize on. This is typically an integer value
        indicating the version last seen on the remote. */
      name: 'syncProperty'
    },
    {
      /** If true, uses sockets instead of HTTP for server communication. */
      name: 'sockets',
      value: false
    },

  ],

  constants: {
    // Aliases for daoType
    ALIASES: {
      ARRAY: 'foam.dao.ArrayDAO',
      MDAO:  'foam.dao.MDAO',
      IDB:   'foam.dao.IDBDAO',
      LOCAL: 'foam.dao.LocalStorageDAO',
    }
  },

  methods: [
    function init() {
      /**

On initialization, the EasyDAO creates an appropriate chain of
        internal EasyDAO instances based on the EasyDAO
        property settings.

This process is transparent to the developer, and you can use your
        EasyDAO like any other DAO.

      */
      this.SUPER(args);

      var daoType = typeof this.daoType === 'string' ?
        this.ALIASES[this.daoType] || this.daoType :
        this.daoType;

      var daoModel = typeof daoType === 'string' ?
        this.lookup(daoType) || global[daoType] :
        daoType;

      var params = { of: this.of };

      if ( ! daoModel ) {
        this.warn(
          "EasyDAO: Unknown DAO Type.  Add '" + daoType + "' to requires: list."
        );
      }

      if ( this.name && daoModel.getAxiomByName('name')  ) params.name = this.name;
      if ( daoModel.getAxiomByName('autoIndex') ) params.autoIndex = this.autoIndex;
      //if ( this.seqNo || this.guid ) params.property = this.seqProperty;

      var dao = daoModel.create(params, this.__subContext__);

      if ( this.MDAO.isInstance(dao) ) {
        this.mdao = dao;
        if ( this.dedup ) dao = this.DeDupDAO.create({delegate: dao});
      } else {
//         if ( this.migrationRules && this.migrationRules.length ) {
//           dao = this.MigrationDAO.create({
//             delegate: dao,
//             rules: this.migrationRules,
//             name: this.model.id + "_" + daoModel.id + "_" + this.name
//           });
//         }
        if ( this.cache ) {
          this.mdao = this.MDAO.create(params);
          dao = this.CachingDAO.create({
            cache: this.dedup ?
              this.mdao :
              this.DeDupDAO.create({delegate: this.mdao}),
            src: dao,
            of: this.model});
        }
      }

      if ( this.seqNo && this.guid ) throw "EasyDAO 'seqNo' and 'guid' features are mutually exclusive.";

      if ( this.seqNo ) {
        var args = {__proto__: params, delegate: dao, of: this.of};
        if ( this.seqProperty ) args.property = this.seqProperty;
        dao = this.SequenceNumberDAO.create(args);
      }

      if ( this.guid ) {
        var args = {__proto__: params, delegate: dao, of: this.of};
        if ( this.seqProperty ) args.property = this.seqProperty;
        dao = this.GUIDDAO.create(args);
      }

      var cls = this.of$cls;

      if ( this.syncWithServer && this.isServer ) throw "isServer and syncWithServer are mutually exclusive.";

      if ( this.syncWithServer || this.isServer ) {
        if ( ! this.syncProperty ) {
          this.syncProperty = cls.SYNC_PROPERTY;
          if ( ! this.syncProperty ) {
            throw "EasyDAO sync with class " + cls.id + " invalid. Sync requires a sync property be set, or be of a class including a property 'sync_property'.";
          }
        }
      }

      if ( this.syncWithServer ) {
        var boxContext = this.Context.create();
        var boxSender = ( this.sockets ) ?
          this.SocketBox.create({
            address: this.serverUri
          }, boxContext) :
          this.HTTPBox.create({
             url: this.serverUri,
             method: 'POST'
          }, boxContext); // TODO: retry?
          //TODO: EasyClientDAO

        dao = this.SyncDAO.create({
          remoteDAO: this.ClientDAO.create({
              name: this.name,
              delegate: boxSender
          }, boxContext),
          syncProperty: this.syncProperty,
          delegate: dao,
          pollingFrequency: 1000
        });
        dao.syncRecordDAO = foam.dao.EasyDAO.create({
          of: dao.SyncRecord,
          cache: true,
          daoType: this.daoType,
          name: this.name + '_SyncRecords'
        });
      }

//       if ( this.isServer ) {
//         dao = this.VersionNoDAO.create({
//           delegate: dao,
//           property: this.syncProperty,
//           version: 2
//         });
//       }

      if ( this.contextualize ) {
        dao = this.ContextualizingDAO.create({delegate: dao});
      }

      if ( this.journal ) {
        dao = this.JournalDAO.create({
          delegate: dao,
          journal: foam.dao.EasyDAO.create({
            of: foam.dao.JournalEntry,
            daoType: this.daoType,
            seqNo: true,
            name: this.name + '_Journal'
          })
        });
      }

      if ( this.timing  ) dao = this.TimingDAO.create({ name: this.name + 'DAO', delegate: dao });
      if ( this.logging ) dao = this.LoggingDAO.create({ delegate: dao });

      this.delegate = dao;
    },

    /** Only relevant if cache is true or if daoType
       was set to MDAO, but harmless otherwise. Generates an index
       for a query over all specified properties together.
       @arg var_args specify any number of Properties to be indexed.
    */
    function addIndex(/* foam.core.Property* */ var_args) {
      this.mdao && this.mdao.addIndex.apply(this.mdao, arguments);
      return this;
    },

    /** Only relevant if cache is true or if daoType
      was set to MDAO, but harmless otherwise. Adds an existing index
      to the MDAO.
      @arg index The index to add.
    */
    function addRawIndex(/* foam.dao.index.Index */ index) {
      this.mdao && this.mdao.addRawIndex.apply(this.mdao, arguments);
      return this;
    }
  ]
});
<|endoftext|>


<commit_before>const {app, dialog, shell, Menu} = require('electron')

const fs = require('fs')
const Module = require('module')
const path = require('path')
const url = require('url')

// Parse command line options.
const argv = process.argv.slice(1)

const option = {
  file: null,
  help: null,
  default: null,
  version: null,
  webdriver: null,
  modules: []
}

for (let i = 0; i < argv.length; i++) {
  if (argv[i] === '--version' || argv[i] === '-v') {
    option.version = true
    break
  } else if (argv[i].match(/^--app=/)) {
    option.file = argv[i].split('=')[1]
    break
  } else if (argv[i] === '--default' || argv[i] === '-d') {
    option.default = true
    break
  } else if (argv[i] === '--interactive' || argv[i] === '-i' || argv[i] === '-repl') {
    option.interactive = true
  } else if (argv[i] === '--test-type=webdriver') {
    option.webdriver = true
  } else if (argv[i] === '--require' || argv[i] === '-r') {
    option.modules.push(argv[++i])
    continue
  } else if (argv[i][0] === '-') {
    continue
  } else {
    option.file = argv[i]
    break
  }
}

// Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', () => {
  if (app.listeners('window-all-closed').length === 1 && !option.interactive) {
    app.quit()
  }
})

// Create default menu.
app.once('ready', () => {
  if (Menu.getApplicationMenu()) return

  const template = [
    {
      label: 'Edit',
      submenu: [
        {
          role: 'undo'
        },
        {
          role: 'redo'
        },
        {
          type: 'separator'
        },
        {
          role: 'cut'
        },
        {
          role: 'copy'
        },
        {
          role: 'paste'
        },
        {
          role: 'pasteandmatchstyle'
        },
        {
          role: 'delete'
        },
        {
          role: 'selectall'
        }
      ]
    },
    {
      label: 'View',
      submenu: [
        {
          role: 'reload'
        },
        {
          role: 'forcereload'
        },
        {
          role: 'toggledevtools'
        },
        {
          type: 'separator'
        },
        {
          role: 'resetzoom'
        },
        {
          role: 'zoomin'
        },
        {
          role: 'zoomout'
        },
        {
          type: 'separator'
        },
        {
          role: 'togglefullscreen'
        }
      ]
    },
    {
      role: 'window',
      submenu: [
        {
          role: 'minimize'
        },
        {
          role: 'close'
        }
      ]
    },
    {
      role: 'help',
      submenu: [
        {
          label: 'Learn More',
          click () {
            shell.openExternal('https://electron.atom.io')
          }
        },
        {
          label: 'Documentation',
          click () {
            shell.openExternal(
              `https://github.com/electron/electron/tree/v${process.versions.electron}/docs#readme`
            )
          }
        },
        {
          label: 'Community Discussions',
          click () {
            shell.openExternal('https://discuss.atom.io/c/electron')
          }
        },
        {
          label: 'Search Issues',
          click () {
            shell.openExternal('https://github.com/electron/electron/issues')
          }
        }
      ]
    }
  ]

  if (process.platform === 'darwin') {
    template.unshift({
      label: 'Electron',
      submenu: [
        {
          role: 'about'
        },
        {
          type: 'separator'
        },
        {
          role: 'services',
          submenu: []
        },
        {
          type: 'separator'
        },
        {
          role: 'hide'
        },
        {
          role: 'hideothers'
        },
        {
          role: 'unhide'
        },
        {
          type: 'separator'
        },
        {
          role: 'quit'
        }
      ]
    })
    template[1].submenu.push({
      type: 'separator'
    }, {
      label: 'Speech',
      submenu: [
        {
          role: 'startspeaking'
        },
        {
          role: 'stopspeaking'
        }
      ]
    })
    template[3].submenu = [
      {
        role: 'close'
      },
      {
        role: 'minimize'
      },
      {
        role: 'zoom'
      },
      {
        type: 'separator'
      },
      {
        role: 'front'
      }
    ]
  } else {
    template.unshift({
      label: 'File',
      submenu: [{
        role: 'quit'
      }]
    })
  }

  const menu = Menu.buildFromTemplate(template)
  Menu.setApplicationMenu(menu)
})

if (option.modules.length > 0) {
  Module._preloadModules(option.modules)
}

function loadApplicationPackage (packagePath) {
  // Add a flag indicating app is started from default app.
  process.defaultApp = true

  try {
    // Override app name and version.
    packagePath = path.resolve(packagePath)
    const packageJsonPath = path.join(packagePath, 'package.json')
    if (fs.existsSync(packageJsonPath)) {
      let packageJson
      try {
        packageJson = require(packageJsonPath)
      } catch (e) {
        showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${e.message}`)
        return
      }

      if (packageJson.version) {
        app.setVersion(packageJson.version)
      }
      if (packageJson.productName) {
        app.setName(packageJson.productName)
      } else if (packageJson.name) {
        app.setName(packageJson.name)
      }
      app.setPath('userData', path.join(app.getPath('appData'), app.getName()))
      app.setPath('userCache', path.join(app.getPath('cache'), app.getName()))
      app.setAppPath(packagePath)
    }

    try {
      Module._resolveFilename(packagePath, module, true)
    } catch (e) {
      showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`)
      return
    }

    // Run the app.
    Module._load(packagePath, module, true)
  } catch (e) {
    console.error('App threw an error during load')
    console.error(e.stack || e)
    throw e
  }
}

function showErrorMessage (message) {
  app.focus()
  dialog.showErrorBox('Error launching app', message)
  process.exit(1)
}

function loadApplicationByUrl (appUrl) {
  require('./default_app').load(appUrl)
}

function startRepl () {
  if (process.platform === 'win32') {
    console.error('Electron REPL not currently supported on Windows')
    process.exit(1)
    return
  }

  const repl = require('repl')
  repl.start('> ').on('exit', () => {
    process.exit(0)
  })
}

// Start the specified app if there is one specified in command line, otherwise
// start the default app.
if (option.file && !option.webdriver) {
  const file = option.file
  const protocol = url.parse(file).protocol
  const extension = path.extname(file)
  if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:') {
    loadApplicationByUrl(file)
  } else if (extension === '.html' || extension === '.htm') {
    loadApplicationByUrl('file://' + path.resolve(file))
  } else {
    loadApplicationPackage(file)
  }
} else if (option.version) {
  console.log('v' + process.versions.electron)
  process.exit(0)
} else if (option.default) {
  const indexPath = path.join(__dirname, '/index.html')
  loadApplicationByUrl(`file://${indexPath}`)
} else if (option.interactive) {
  startRepl()
} else {
  const welcomeMessage = `
  Electron ${process.versions.electron} - Build cross platform desktop apps with JavaScript, HTML, and CSS
  Usage: electron [options] [path]

  A path to an Electron app may be specified. It must be one of the following:
    - index.js file.
    - Folder containing a package.json file.
    - Folder containing an index.js file.
    - .html/.htm file.
    - http://, https://, or file:// URL.

  Options:
    -d, --default         Run the default bundled Electron app.
    -i, --interactive     Open a REPL to the main process.
    -r, --require         Module to preload (option can be repeated)
    -v, --version         Print the version.`

  console.log(welcomeMessage)
  const indexPath = path.join(__dirname, '/index.html')
  loadApplicationByUrl(`file://${indexPath}`)
}
<commit_msg>:wrench: Bring back —abi<commit_after>const {app, dialog, shell, Menu} = require('electron')

const fs = require('fs')
const Module = require('module')
const path = require('path')
const url = require('url')

// Parse command line options.
const argv = process.argv.slice(1)

const option = {
  file: null,
  help: null,
  default: null,
  version: null,
  webdriver: null,
  modules: []
}

for (let i = 0; i < argv.length; i++) {
  if (argv[i] === '--version' || argv[i] === '-v') {
    option.version = true
    break
  } else if (argv[i].match(/^--app=/)) {
    option.file = argv[i].split('=')[1]
    break
  } else if (argv[i] === '--default' || argv[i] === '-d') {
    option.default = true
    break
  } else if (argv[i] === '--interactive' || argv[i] === '-i' || argv[i] === '-repl') {
    option.interactive = true
  } else if (argv[i] === '--test-type=webdriver') {
    option.webdriver = true
  } else if (argv[i] === '--require' || argv[i] === '-r') {
    option.modules.push(argv[++i])
    continue
  } else if (argv[i] === '--abi' || argv[i] === '-a') {
    option.abi = true
    continue
  } else if (argv[i][0] === '-') {
    continue
  } else {
    option.file = argv[i]
    break
  }
}

// Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', () => {
  if (app.listeners('window-all-closed').length === 1 && !option.interactive) {
    app.quit()
  }
})

// Create default menu.
app.once('ready', () => {
  if (Menu.getApplicationMenu()) return

  const template = [
    {
      label: 'Edit',
      submenu: [
        {
          role: 'undo'
        },
        {
          role: 'redo'
        },
        {
          type: 'separator'
        },
        {
          role: 'cut'
        },
        {
          role: 'copy'
        },
        {
          role: 'paste'
        },
        {
          role: 'pasteandmatchstyle'
        },
        {
          role: 'delete'
        },
        {
          role: 'selectall'
        }
      ]
    },
    {
      label: 'View',
      submenu: [
        {
          role: 'reload'
        },
        {
          role: 'forcereload'
        },
        {
          role: 'toggledevtools'
        },
        {
          type: 'separator'
        },
        {
          role: 'resetzoom'
        },
        {
          role: 'zoomin'
        },
        {
          role: 'zoomout'
        },
        {
          type: 'separator'
        },
        {
          role: 'togglefullscreen'
        }
      ]
    },
    {
      role: 'window',
      submenu: [
        {
          role: 'minimize'
        },
        {
          role: 'close'
        }
      ]
    },
    {
      role: 'help',
      submenu: [
        {
          label: 'Learn More',
          click () {
            shell.openExternal('https://electron.atom.io')
          }
        },
        {
          label: 'Documentation',
          click () {
            shell.openExternal(
              `https://github.com/electron/electron/tree/v${process.versions.electron}/docs#readme`
            )
          }
        },
        {
          label: 'Community Discussions',
          click () {
            shell.openExternal('https://discuss.atom.io/c/electron')
          }
        },
        {
          label: 'Search Issues',
          click () {
            shell.openExternal('https://github.com/electron/electron/issues')
          }
        }
      ]
    }
  ]

  if (process.platform === 'darwin') {
    template.unshift({
      label: 'Electron',
      submenu: [
        {
          role: 'about'
        },
        {
          type: 'separator'
        },
        {
          role: 'services',
          submenu: []
        },
        {
          type: 'separator'
        },
        {
          role: 'hide'
        },
        {
          role: 'hideothers'
        },
        {
          role: 'unhide'
        },
        {
          type: 'separator'
        },
        {
          role: 'quit'
        }
      ]
    })
    template[1].submenu.push({
      type: 'separator'
    }, {
      label: 'Speech',
      submenu: [
        {
          role: 'startspeaking'
        },
        {
          role: 'stopspeaking'
        }
      ]
    })
    template[3].submenu = [
      {
        role: 'close'
      },
      {
        role: 'minimize'
      },
      {
        role: 'zoom'
      },
      {
        type: 'separator'
      },
      {
        role: 'front'
      }
    ]
  } else {
    template.unshift({
      label: 'File',
      submenu: [{
        role: 'quit'
      }]
    })
  }

  const menu = Menu.buildFromTemplate(template)
  Menu.setApplicationMenu(menu)
})

if (option.modules.length > 0) {
  Module._preloadModules(option.modules)
}

function loadApplicationPackage (packagePath) {
  // Add a flag indicating app is started from default app.
  process.defaultApp = true

  try {
    // Override app name and version.
    packagePath = path.resolve(packagePath)
    const packageJsonPath = path.join(packagePath, 'package.json')
    if (fs.existsSync(packageJsonPath)) {
      let packageJson
      try {
        packageJson = require(packageJsonPath)
      } catch (e) {
        showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${e.message}`)
        return
      }

      if (packageJson.version) {
        app.setVersion(packageJson.version)
      }
      if (packageJson.productName) {
        app.setName(packageJson.productName)
      } else if (packageJson.name) {
        app.setName(packageJson.name)
      }
      app.setPath('userData', path.join(app.getPath('appData'), app.getName()))
      app.setPath('userCache', path.join(app.getPath('cache'), app.getName()))
      app.setAppPath(packagePath)
    }

    try {
      Module._resolveFilename(packagePath, module, true)
    } catch (e) {
      showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`)
      return
    }

    // Run the app.
    Module._load(packagePath, module, true)
  } catch (e) {
    console.error('App threw an error during load')
    console.error(e.stack || e)
    throw e
  }
}

function showErrorMessage (message) {
  app.focus()
  dialog.showErrorBox('Error launching app', message)
  process.exit(1)
}

function loadApplicationByUrl (appUrl) {
  require('./default_app').load(appUrl)
}

function startRepl () {
  if (process.platform === 'win32') {
    console.error('Electron REPL not currently supported on Windows')
    process.exit(1)
    return
  }

  const repl = require('repl')
  repl.start('> ').on('exit', () => {
    process.exit(0)
  })
}

// Start the specified app if there is one specified in command line, otherwise
// start the default app.
if (option.file && !option.webdriver) {
  const file = option.file
  const protocol = url.parse(file).protocol
  const extension = path.extname(file)
  if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:') {
    loadApplicationByUrl(file)
  } else if (extension === '.html' || extension === '.htm') {
    loadApplicationByUrl('file://' + path.resolve(file))
  } else {
    loadApplicationPackage(file)
  }
} else if (option.version) {
  console.log('v' + process.versions.electron)
  process.exit(0)
} else if (option.abi) {
  console.log(process.versions.modules)
  process.exit(0)
} else if (option.default) {
  const indexPath = path.join(__dirname, '/index.html')
  loadApplicationByUrl(`file://${indexPath}`)
} else if (option.interactive) {
  startRepl()
} else {
  const welcomeMessage = `
  Electron ${process.versions.electron} - Build cross platform desktop apps with JavaScript, HTML, and CSS
  Usage: electron [options] [path]

  A path to an Electron app may be specified. It must be one of the following:
    - index.js file.
    - Folder containing a package.json file.
    - Folder containing an index.js file.
    - .html/.htm file.
    - http://, https://, or file:// URL.

  Options:
    -d, --default         Run the default bundled Electron app.
    -i, --interactive     Open a REPL to the main process.
    -r, --require         Module to preload (option can be repeated).
    -v, --version         Print the version.
    -a, --abi             Print the Node ABI version.`

  console.log(welcomeMessage)
  const indexPath = path.join(__dirname, '/index.html')
  loadApplicationByUrl(`file://${indexPath}`)
}
<|endoftext|>


<commit_before>// User: Chosen business process main display documents

'use strict';

var _ = require('mano').i18n.bind('View: Documents list')
, Institution = require('mano').db.Institution
, resolveIssuer = require('./utils/issuer-resolver');

module.exports = function (documents) {
	return div({ class: "table-responsive-container" },
		table({ class: 'submitted-user-data-table ' +
				'submitted-current-user-data-table user-request-table' },
			thead(
				tr(
					th({ class: 'submitted-user-data-table-status' }),
					th(_("Name")),
					th(_("Issuer")),
					th({ class: 'submitted-user-data-table-date' }, _("Issue date")),
					th({ class: 'submitted-user-data-table-link' })
				)
			),
			tbody({ onEmpty: tr({ class: 'empty' }, td({ colspan: 5 }, _("No documents"))) },
				documents, function (doc) {
					tr(
						td({ class: 'submitted-user-data-table-status' },
							doc._issuedBy.map(function (val) {
								if (!val) return;
								if (val.constructor === Institution) return span({ class: 'fa fa-certificate' });
							})),
						td(doc._label),
						td(doc._issuedBy.map(resolveIssuer)),
						td({ class: 'submitted-user-data-table-date' }, doc._issueDate),
						td({ class: 'submitted-user-data-table-link' },
							a({ href: '/business-process/' + doc.master.__id__ + doc.docUrl },
								span({ class: 'fa fa-search' }, _("Go to"))))
					);
				})));
};
<commit_msg>Issue #863. Base certificate icon display on isCertificate getter in business process documents list.<commit_after>// User: Chosen business process main display documents

'use strict';

var _ = require('mano').i18n.bind('View: Documents list')
, Institution = require('mano').db.Institution
, resolveIssuer = require('./utils/issuer-resolver');

module.exports = function (documents) {
	return div({ class: "table-responsive-container" },
		table({ class: 'submitted-user-data-table ' +
				'submitted-current-user-data-table user-request-table' },
			thead(
				tr(
					th({ class: 'submitted-user-data-table-status' }),
					th(_("Name")),
					th(_("Issuer")),
					th({ class: 'submitted-user-data-table-date' }, _("Issue date")),
					th({ class: 'submitted-user-data-table-link' })
				)
			),
			tbody({ onEmpty: tr({ class: 'empty' }, td({ colspan: 5 }, _("No documents"))) },
				documents, function (doc) {
					tr(
						td({ class: 'submitted-user-data-table-status' },
							_if(doc._isCertificate, span({ class: 'fa fa-certificate' }))),
						td(doc._label),
						td(doc._issuedBy.map(resolveIssuer)),
						td({ class: 'submitted-user-data-table-date' }, doc._issueDate),
						td({ class: 'submitted-user-data-table-link' },
							a({ href: '/business-process/' + doc.master.__id__ + doc.docUrl },
								span({ class: 'fa fa-search' }, _("Go to"))))
					);
				})));
};
<|endoftext|>


<commit_before>/*global angular*/
(function () {
  'use strict';

  var tipped = angular.module('decipher.tipped', []);

  var defaults = {
    showOn: 'mouseenter',
    showDelay: 1000,
    hideOn: 'mouseleave',
    hideDelay: 500,
    target: 'self'
  };

  /**
   * Grab this constant and put stuff in it to override the defaults above
   * or set any defaults you please.
   */
  tipped.constant('tippedOptions', {});

  /**
   * There are two ways to use this directive:
   *
   * An inline template, with interpolation available:
   *
   *

   *
   * Or a templateUrl, which will fetch the template via AJAX and be fancy.
   *
   *

   *
   * (the template URL is an AngularJS expression)
   *
   * To override any defaults, pass an options object to the tipped directive:
   *
   *

   *
   */
  tipped.directive('tipped',
    function ($window, $http, $interpolate, $compile, $templateCache, $timeout,
      tippedOptions) {
      return {
        restrict: 'A',
        link: function link(scope, element, attrs) {
          var tipped = attrs.tipped || '{}', skin,
            tippedDefaults = angular.copy(defaults),
            moduleDefaults = angular.copy(tippedOptions),
            ttDefaults = scope.$eval(tipped),
            options;

          options =
          angular.extend(tippedDefaults, angular.extend(moduleDefaults,
            ttDefaults));

          // explicitly get options from skin since we have to do stuff manually.
          if (options.skin && (skin = $window.Tipped.Skins[options.skin])) {
            options = angular.extend(options, skin);
          }

          if (attrs.title) {
            $window.Tipped.create(element[0], $interpolate(attrs.title)(scope),
              options);
          }
          else if (attrs.templateUrl) {
            $http.get(scope.$eval(attrs.templateUrl), {cache: $templateCache})
              .then(function receiveTemplate(res) {
                // we have to interpolate and compile the template first because Tipped
                // will size its tooltip based on the HTML.  if we left the
                // uninterpolated values in the HTML, the resulting tooltip
                // could be larger/smaller than what actually should be shown.
                // this means, unfortunately, we must compile once for this reason,
                // and again to actually wire up the resulting tooltip.
                // we wrap in a
 in order to get the html of the tooltip;
                // this allows us to use templates without wrappers.  we wrap in a
                // SECOND div because interpolation is wonky and becomes confused
                // if there is no wrapper.
                var template, tt, t;

                template = $compile('
' +
                  $interpolate('
' + res.data + '
')(scope) +
                  '
')(scope);

                options.afterUpdate = function afterUpdate(content, element) {
                  var c = angular.element(content),
                    el = angular.element(element);
                  scope.$apply(function () {
                    c.html($compile('
' + c.html() + '
')(scope));
                  });

                };
                tt = $window.Tipped.create(element[0], template.html(), options);
              });

          }
        }
      };
    }
  );
})();
<commit_msg>removed unused variable 't'<commit_after>/*global angular*/
(function () {
  'use strict';

  var tipped = angular.module('decipher.tipped', []);

  var defaults = {
    showOn: 'mouseenter',
    showDelay: 1000,
    hideOn: 'mouseleave',
    hideDelay: 500,
    target: 'self'
  };

  /**
   * Grab this constant and put stuff in it to override the defaults above
   * or set any defaults you please.
   */
  tipped.constant('tippedOptions', {});

  /**
   * There are two ways to use this directive:
   *
   * An inline template, with interpolation available:
   *
   *

   *
   * Or a templateUrl, which will fetch the template via AJAX and be fancy.
   *
   *

   *
   * (the template URL is an AngularJS expression)
   *
   * To override any defaults, pass an options object to the tipped directive:
   *
   *

   *
   */
  tipped.directive('tipped',
    function ($window, $http, $interpolate, $compile, $templateCache, $timeout,
      tippedOptions) {
      return {
        restrict: 'A',
        link: function link(scope, element, attrs) {
          var tipped = attrs.tipped || '{}', skin,
            tippedDefaults = angular.copy(defaults),
            moduleDefaults = angular.copy(tippedOptions),
            ttDefaults = scope.$eval(tipped),
            options;

          options =
          angular.extend(tippedDefaults, angular.extend(moduleDefaults,
            ttDefaults));

          // explicitly get options from skin since we have to do stuff manually.
          if (options.skin && (skin = $window.Tipped.Skins[options.skin])) {
            options = angular.extend(options, skin);
          }

          if (attrs.title) {
            $window.Tipped.create(element[0], $interpolate(attrs.title)(scope),
              options);
          }
          else if (attrs.templateUrl) {
            $http.get(scope.$eval(attrs.templateUrl), {cache: $templateCache})
              .then(function receiveTemplate(res) {
                // we have to interpolate and compile the template first because Tipped
                // will size its tooltip based on the HTML.  if we left the
                // uninterpolated values in the HTML, the resulting tooltip
                // could be larger/smaller than what actually should be shown.
                // this means, unfortunately, we must compile once for this reason,
                // and again to actually wire up the resulting tooltip.
                // we wrap in a
 in order to get the html of the tooltip;
                // this allows us to use templates without wrappers.  we wrap in a
                // SECOND div because interpolation is wonky and becomes confused
                // if there is no wrapper.
                var template, tt;

                template = $compile('
' +
                  $interpolate('
' + res.data + '
')(scope) +
                  '
')(scope);

                options.afterUpdate = function afterUpdate(content, element) {
                  var c = angular.element(content),
                    el = angular.element(element);
                  scope.$apply(function () {
                    c.html($compile('
' + c.html() + '
')(scope));
                  });

                };
                tt = $window.Tipped.create(element[0], template.html(), options);
              });

          }
        }
      };
    }
  );
})();
<|endoftext|>