<commit_before>/*
*     (C) Copyright 2008 Telefonica Investigacion y Desarrollo
*     S.A.Unipersonal (Telefonica I+D)
*
*     This file is part of Morfeo EzWeb Platform.
*
*     Morfeo EzWeb Platform is free software: you can redistribute it and/or modify
*     it under the terms of the GNU Affero General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     Morfeo EzWeb Platform is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU Affero General Public License for more details.
*
*     You should have received a copy of the GNU Affero General Public License
*     along with Morfeo EzWeb Platform.  If not, see <http://www.gnu.org/licenses/>.
*
*     Info about members and contributors of the MORFEO project
*     is available at
*
*     http://morfeo-project.org
 */

var OpManagerFactory = function () {

    // *********************************
    // SINGLETON INSTANCE
    // *********************************
    var instance = null;

    function OpManager () {

        // ****************
        // CALLBACK METHODS
        // ****************

        var loadEnvironment = function (transport) {
            // JSON-coded user tabspaces
            var response = transport.responseText;
            var workspaces = JSON.parse(response);

            for (var i = 0; i < workspaces.length; i++) {
                var workspace = workspaces[i];

                var workspace_instance = new Workspace(workspace);
                this.workspaceInstances.set(workspace.id, workspace_instance);
                if (!(workspace.creator in this.workspacesByUserAndName)) {
                    this.workspacesByUserAndName[workspace.creator] = {};
                }
                this.workspacesByUserAndName[workspace.creator][workspace.name] = workspace_instance;
            }

            HistoryManager.init();
            var state = HistoryManager.getCurrentState();
            this.activeWorkspace = this.workspacesByUserAndName[state.workspace_creator][state.workspace_name];

            this.activeWorkspace.downloadWorkspaceInfo(HistoryManager.getCurrentState().tab);
        }

        var onError = function (transport, e) {
            var msg;
            try {
                var logManager = LogManagerFactory.getInstance();
                msg = logManager.formatError(gettext("Error loading Wirecloud Platform: %(errorMsg)s."), transport, e);
                LayoutManagerFactory.getInstance().showMessageMenu(msg, Constants.Logging.ERROR_MSG);
                logManager.log(msg);
            } catch (e) {
                if (msg != null)
                    alert(msg);
                else
                    alert (gettext("Error loading Wirecloud Platform"));
            }
        }

        /*****WORKSPACE CALLBACK***/
        var createWSSuccess = function(onSuccess, response) {
            var workspace_data = JSON.parse(response.responseText);
            var workspace = new Workspace(workspace_data);
            this.workspaceInstances.set(workspace.getId(), workspace);
            this.changeActiveWorkspace(workspace);

            if (typeof onSuccess === 'function') {
                try {
                    onSuccess(workspace);
                } catch (e) {}
            }
        };

        var createWSError = function(onFailure, response) {
            var logManager = LogManagerFactory.getInstance();
            var msg = logManager.formatError(gettext("Error creating a workspace: %(errorMsg)s."), response);
            logManager.log(msg);

            if (typeof onFailure === 'function') {
                try {
                    onFailure(msg);
                } catch (e) {}
            }
        };

        // *********************************
        // PRIVATE VARIABLES AND FUNCTIONS
        // *********************************

        // Singleton modules
        this.showcaseModule = null;
        this.catalogue = null;
        this.logs = null;
        this.platformPreferences = null;

        this.loadCompleted = false;

        // Variables for controlling the collection of wiring and dragboard instances of a user
        this.workspaceInstances = new Hash();
        this.workspacesByUserAndName = {};

        this.activeWorkspace = null;

        // ****************
        // PUBLIC METHODS
        // ****************

        OpManager.prototype.showLogs = function (logManager) {
            logManager = arguments.length > 0 ? logManager : LogManagerFactory.getInstance();

            if (this.activeWorkspace && this.activeWorkspace.getVisibleTab()) {
                this.activeWorkspace.getVisibleTab().unmark();
                        }

            LogManagerFactory.getInstance().show(logManager);
        }

        OpManager.prototype.mergeMashupResource = function(resource) {

            var mergeOk = function(transport) {
                LayoutManagerFactory.getInstance().logStep('');
                this.changeActiveWorkspace(this.activeWorkspace);
            }
            var mergeError = function(transport, e) {
                var logManager, layoutManager, msg;

                logManager = LogManagerFactory.getInstance();
                msg = logManager.formatError(gettext("Error merging workspace: %(errorMsg)s."), transport, e);
                logManager.log(msg);

                layoutManager = LayoutManagerFactory.getInstance();
                layoutManager.logStep('');
                layoutManager._notifyPlatformReady();

                layoutManager.showMessageMenu(msg, Constants.Logging.ERROR_MSG);
            }

            LayoutManagerFactory.getInstance()._startComplexTask(gettext("Adding the mashup"), 1);
            LayoutManagerFactory.getInstance().logSubTask(gettext("Merging with current workspace"));

            var active_ws_id = OpManagerFactory.getInstance().getActiveWorkspaceId();
            var mergeURL = Wirecloud.URLs.WORKSPACE_MERGE.evaluate({to_ws_id: active_ws_id});

            Wirecloud.io.makeRequest(mergeURL, {
                method: 'POST',
                contentType: 'application/json',
                postBody: JSON.stringify({'mashup': resource.getURI()}),
                onSuccess: mergeOk.bind(this),
                onFailure: mergeError.bind(this),
                onException: mergeError.bind(this)
            });
        };

        OpManager.prototype.addWorkspaceFromMashup = function addWorkspaceFromMashup(resource, options) {

            options = EzWebExt.merge({
                dry_run: false
            }, options);

            var cloneOk = function(transport) {
                var response, wsInfo, opManager, workspace = null;

                if (transport.status === 201) {
                    response = transport.responseText;
                    wsInfo = JSON.parse(response);
                    opManager = OpManagerFactory.getInstance();
                    workspace = new Workspace(wsInfo);
                    opManager.workspaceInstances.set(wsInfo.id, workspace);
                }

                if (typeof options.onSuccess === 'function') {
                    try {
                        options.onSuccess(workspace);
                    } catch (e) {}
                }
            };

            var cloneError = function(transport, e) {
                var logManager, msg, details;

                logManager = LogManagerFactory.getInstance();

                msg = logManager.formatError(gettext("Error adding the workspace: %(errorMsg)s."), transport, e);
                logManager.log(msg);

                if (typeof options.onFailure === 'function') {
                    try {
                        if (transport.status === 422) {
                            details = JSON.parse(transport.responseText).details;
                        }
                    } catch (e) {}

                    try {
                        options.onFailure(msg, details);
                    } catch (e) {}
                }
            };

            Wirecloud.io.makeRequest(Wirecloud.URLs.WORKSPACE_COLLECTION, {
                method: 'POST',
                contentType: 'application/json',
                postBody: Object.toJSON({
                    'mashup': resource.getURI(),
                    'dry_run': options.dry_run
                }),
                onSuccess: cloneOk.bind(this),
                onFailure: cloneError.bind(this)
            });
        };

        OpManager.prototype.showPlatformPreferences = function () {
            PreferencesManagerFactory.getInstance().show();
        }

        OpManager.prototype.changeActiveWorkspace = function (workspace, initial_tab) {
            var state, steps = this.activeWorkspace != null ? 2 : 1;

            state = {
                workspace_creator: workspace.workspaceState.creator,
                workspace_name: workspace.getName(),
                view: "workspace"
            };
            if (initial_tab) {
                state.tab = initial_tab;
            }
            HistoryManager.pushState(state);
            LayoutManagerFactory.getInstance()._startComplexTask(gettext("Changing current workspace"), steps);

            if (this.activeWorkspace != null) {
                this.activeWorkspace.unload();
            }

            this.activeWorkspace = workspace;
            this.activeWorkspace.downloadWorkspaceInfo(initial_tab);
        }

        OpManager.prototype.logout = function logout() {
            window.location = Wirecloud.URLs.LOGOUT_VIEW;
        }

        OpManager.prototype.addInstance = function (widget, options) {
            if (!this.loadCompleted) {
                return;
            }

            this.activeWorkspace.getVisibleTab().getDragboard().addInstance(widget, options);
        };

        OpManager.prototype.removeInstance = function (iWidgetId, orderFromServer) {
            if (!this.loadCompleted)
                return;

            this.activeWorkspace.removeIWidget(iWidgetId, orderFromServer);
        }

        OpManager.prototype.getActiveWorkspaceId = function () {
            return this.activeWorkspace.getId();
        }

        /**
         * Loads the Wirecloud Platform.
         */
        OpManager.prototype.loadEnviroment = function () {
            // Init Layout Manager
            var layoutManager = LayoutManagerFactory.getInstance();
            layoutManager.resizeWrapper();
            layoutManager._startComplexTask(gettext('Loading Wirecloud Platform'), 3);
            layoutManager.logSubTask(gettext('Retrieving Wirecloud code'));
            layoutManager.logStep('');

            // Init log manager
            this.logs = LogManagerFactory.getInstance();

            Event.observe(window,
                          "beforeunload",
                          this.unloadEnvironment.bind(this),
                          true);

            Wirecloud.io.makeRequest(Wirecloud.URLs.PLATFORM_CONTEXT_COLLECTION, {
                method: 'GET',
                onSuccess: function (transport) {
                    OpManagerFactory.getInstance().contextManager = new Wirecloud.ContextManager(this, JSON.parse(transport.responseText));
                    LayoutManagerFactory.getInstance().header._initUserMenu();
                    OpManagerFactory.getInstance().continueLoadingGlobalModules(Modules.prototype.CONTEXT);
                }
            });
        }

        /**
         * Unloads the Wirecloud Platform. This method is called, by default, when
         * the unload event is captured.
         */
        OpManager.prototype.unloadEnvironment = function() {
            var layoutManager = LayoutManagerFactory.getInstance();
            layoutManager.hideCover();
            layoutManager._startComplexTask(gettext('Unloading Wirecloud Platform'));

            if (this.activeWorkspace) {
                this.activeWorkspace.unload();
            }

            //TODO: unloadCatalogue
        }

        OpManager.prototype.iwidgetLoaded = function (iwidgetId) {
            this.activeWorkspace.iwidgetLoaded(iwidgetId);
        }

        OpManager.prototype.iwidgetUnloaded = function (iwidgetId) {
            this.activeWorkspace.iwidgetUnloaded(iwidgetId);
        }

        OpManager.prototype.checkForWidgetUpdates = function () {
            this.activeWorkspace.checkForWidgetUpdates();
        }

        OpManager.prototype.showActiveWorkspace = function (refreshMenu) {
            // TODO
        }

        OpManager.prototype.preferencesChanged = function (modifiedValues) {
            if ('language' in modifiedValues) {
                window.location.reload();
            }
        };

        OpManager.prototype.continueLoadingGlobalModules = function (module) {
            // Asynchronous load of modules
            // Each singleton module notifies OpManager it has finished loading!
            var preferencesManager;

            switch (module) {
            case Modules.prototype.CONTEXT:

                Wirecloud.io.makeRequest(Wirecloud.URLs.THEME_ENTRY.evaluate({name: this.contextManager.get('theme')}), {
                    method: 'GET',
                    onSuccess: function (transport) {
                        Wirecloud.currentTheme = new Wirecloud.ui.Theme(JSON.parse(transport.responseText));
                        this.continueLoadingGlobalModules(Modules.prototype.THEME_MANAGER);
                    }.bind(this)
                });
                break;

            case Modules.prototype.THEME_MANAGER:
                this.platformPreferences = PreferencesManagerFactory.getInstance();
                break;

            case Modules.prototype.PLATFORM_PREFERENCES:
                preferencesManager = PreferencesManagerFactory.getInstance();
                preferencesManager.getPlatformPreferences().addCommitHandler(this.preferencesChanged.bind(this), 'post-commit');
                Wirecloud.LocalCatalogue.reload({
                    onSuccess: function () {
                        this.continueLoadingGlobalModules(Modules.prototype.SHOWCASE);
                    }.bind(this),
                    onFailure: function () {
                        var msg, logManager = LogManagerFactory.getInstance();
                        msg = logManager.formatError(gettext("Error retrieving available resources: %(errorMsg)s."), transport, e);
                        logManager.log(msg);
                        LayoutManagerFactory.getInstance().showMessageMenu(msg, Constants.Logging.ERROR_MSG);
                    }
                });
                break;

            case Modules.prototype.SHOWCASE:
            case Modules.prototype.CATALOGUE:
                // All singleton modules has been loaded!
                // It's time for loading tabspace information!
                this.loadActiveWorkspace();
                break;

            case Modules.prototype.ACTIVE_WORKSPACE:
                var layoutManager = LayoutManagerFactory.getInstance();
                layoutManager.logSubTask(gettext("Activating current Workspace"));

                this.showActiveWorkspace();

                layoutManager.logStep('');
                layoutManager._notifyPlatformReady();
                this.loadCompleted = true;
            }
        }

        OpManager.prototype.loadActiveWorkspace = function () {
            // Asynchronous load of modules
            // Each singleton module notifies OpManager it has finished loading!

            Wirecloud.io.makeRequest(Wirecloud.URLs.WORKSPACE_COLLECTION, {
                method: 'GET',
                onSuccess: loadEnvironment.bind(this),
                onFailure: onError.bind(this)
            });
        }

        OpManager.prototype.logIWidgetError = function(iWidgetId, msg, level) {
            var iWidget = this.activeWorkspace.getIWidget(iWidgetId);
            if (iWidget == null) {
                var msg2 = gettext("Some pice of code tried to notify an error in the iWidget %(iWidgetId)s when it did not exist or it was not loaded yet. This is an error in Wirecloud Platform, please notify it.\nError Message: %(errorMsg)s");
                msg2 = interpolate(msg2, {iWidgetId: iWidgetId, errorMsg: msg}, true);
                this.logs.log(msg2);
                return;
            }

            iWidget.log(msg, level);
        }

        OpManager.prototype.drawAttention = function(iWidgetId) {
            this.activeWorkspace.drawAttention(iWidgetId);
        };

        //Operations on workspaces

        OpManager.prototype.workspaceExists = function (newName) {
            var workspace_keys, workspace, i;
            workspace_keys = this.workspaceInstances.keys();
            for (i = 0; i < workspace_keys.length; i += 1) {
                workspace = this.workspaceInstances.get(workspace_keys[i]);
                if (workspace.workspaceState.name === newName) {
                    return true;
                }
            }
            return false;
        }

        OpManager.prototype.addWorkspace = function addWorkspace(newName, options) {
            if (options == null) {
                options = {};
            }

            Wirecloud.io.makeRequest(Wirecloud.URLs.WORKSPACE_COLLECTION, {
                method: 'POST',
                contentType: 'application/json',
                postBody: JSON.stringify({
                    allow_renaming: !!options.allow_renaming,
                    name: newName
                }),
                onSuccess: createWSSuccess.bind(this, options.onSuccess),
                onFailure: createWSError.bind(this, options.onFailure)
            });
        };

        OpManager.prototype.unloadWorkspace = function(workspaceId) {
            //Unloading the Workspace
            this.workspaceInstances.get(workspaceId).unload();
        }

        OpManager.prototype.removeWorkspace = function(workspaceId) {
            // Removing reference
            this.workspaceInstances.unset(workspaceId);

            // Set the first workspace as current
            this.changeActiveWorkspace(this.workspaceInstances.values()[0]);
        };

        OpManager.prototype.getWorkspaceCount = function(){
            return this.workspaceInstances.keys().length;
        }
    }

    // *********************************
    // SINGLETON GET INSTANCE
    // *********************************
    return new function() {
        this.getInstance = function() {
            if (instance == null) {
                instance = new OpManager();
            }
            return instance;
        }
    }
}();

<commit_msg>Allow renaming when creating workspaces from mashups<commit_after>/*
*     (C) Copyright 2008 Telefonica Investigacion y Desarrollo
*     S.A.Unipersonal (Telefonica I+D)
*
*     This file is part of Morfeo EzWeb Platform.
*
*     Morfeo EzWeb Platform is free software: you can redistribute it and/or modify
*     it under the terms of the GNU Affero General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     Morfeo EzWeb Platform is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU Affero General Public License for more details.
*
*     You should have received a copy of the GNU Affero General Public License
*     along with Morfeo EzWeb Platform.  If not, see <http://www.gnu.org/licenses/>.
*
*     Info about members and contributors of the MORFEO project
*     is available at
*
*     http://morfeo-project.org
 */

var OpManagerFactory = function () {

    // *********************************
    // SINGLETON INSTANCE
    // *********************************
    var instance = null;

    function OpManager () {

        // ****************
        // CALLBACK METHODS
        // ****************

        var loadEnvironment = function (transport) {
            // JSON-coded user tabspaces
            var response = transport.responseText;
            var workspaces = JSON.parse(response);

            for (var i = 0; i < workspaces.length; i++) {
                var workspace = workspaces[i];

                var workspace_instance = new Workspace(workspace);
                this.workspaceInstances.set(workspace.id, workspace_instance);
                if (!(workspace.creator in this.workspacesByUserAndName)) {
                    this.workspacesByUserAndName[workspace.creator] = {};
                }
                this.workspacesByUserAndName[workspace.creator][workspace.name] = workspace_instance;
            }

            HistoryManager.init();
            var state = HistoryManager.getCurrentState();
            this.activeWorkspace = this.workspacesByUserAndName[state.workspace_creator][state.workspace_name];

            this.activeWorkspace.downloadWorkspaceInfo(HistoryManager.getCurrentState().tab);
        }

        var onError = function (transport, e) {
            var msg;
            try {
                var logManager = LogManagerFactory.getInstance();
                msg = logManager.formatError(gettext("Error loading Wirecloud Platform: %(errorMsg)s."), transport, e);
                LayoutManagerFactory.getInstance().showMessageMenu(msg, Constants.Logging.ERROR_MSG);
                logManager.log(msg);
            } catch (e) {
                if (msg != null)
                    alert(msg);
                else
                    alert (gettext("Error loading Wirecloud Platform"));
            }
        }

        /*****WORKSPACE CALLBACK***/
        var createWSSuccess = function(onSuccess, response) {
            var workspace_data = JSON.parse(response.responseText);
            var workspace = new Workspace(workspace_data);
            this.workspaceInstances.set(workspace.getId(), workspace);
            this.changeActiveWorkspace(workspace);

            if (typeof onSuccess === 'function') {
                try {
                    onSuccess(workspace);
                } catch (e) {}
            }
        };

        var createWSError = function(onFailure, response) {
            var logManager = LogManagerFactory.getInstance();
            var msg = logManager.formatError(gettext("Error creating a workspace: %(errorMsg)s."), response);
            logManager.log(msg);

            if (typeof onFailure === 'function') {
                try {
                    onFailure(msg);
                } catch (e) {}
            }
        };

        // *********************************
        // PRIVATE VARIABLES AND FUNCTIONS
        // *********************************

        // Singleton modules
        this.showcaseModule = null;
        this.catalogue = null;
        this.logs = null;
        this.platformPreferences = null;

        this.loadCompleted = false;

        // Variables for controlling the collection of wiring and dragboard instances of a user
        this.workspaceInstances = new Hash();
        this.workspacesByUserAndName = {};

        this.activeWorkspace = null;

        // ****************
        // PUBLIC METHODS
        // ****************

        OpManager.prototype.showLogs = function (logManager) {
            logManager = arguments.length > 0 ? logManager : LogManagerFactory.getInstance();

            if (this.activeWorkspace && this.activeWorkspace.getVisibleTab()) {
                this.activeWorkspace.getVisibleTab().unmark();
                        }

            LogManagerFactory.getInstance().show(logManager);
        }

        OpManager.prototype.mergeMashupResource = function(resource) {

            var mergeOk = function(transport) {
                LayoutManagerFactory.getInstance().logStep('');
                this.changeActiveWorkspace(this.activeWorkspace);
            }
            var mergeError = function(transport, e) {
                var logManager, layoutManager, msg;

                logManager = LogManagerFactory.getInstance();
                msg = logManager.formatError(gettext("Error merging workspace: %(errorMsg)s."), transport, e);
                logManager.log(msg);

                layoutManager = LayoutManagerFactory.getInstance();
                layoutManager.logStep('');
                layoutManager._notifyPlatformReady();

                layoutManager.showMessageMenu(msg, Constants.Logging.ERROR_MSG);
            }

            LayoutManagerFactory.getInstance()._startComplexTask(gettext("Adding the mashup"), 1);
            LayoutManagerFactory.getInstance().logSubTask(gettext("Merging with current workspace"));

            var active_ws_id = OpManagerFactory.getInstance().getActiveWorkspaceId();
            var mergeURL = Wirecloud.URLs.WORKSPACE_MERGE.evaluate({to_ws_id: active_ws_id});

            Wirecloud.io.makeRequest(mergeURL, {
                method: 'POST',
                contentType: 'application/json',
                postBody: JSON.stringify({'mashup': resource.getURI()}),
                onSuccess: mergeOk.bind(this),
                onFailure: mergeError.bind(this),
                onException: mergeError.bind(this)
            });
        };

        OpManager.prototype.addWorkspaceFromMashup = function addWorkspaceFromMashup(resource, options) {

            options = EzWebExt.merge({
                allow_renaming: true,
                dry_run: false
            }, options);

            var cloneOk = function(transport) {
                var response, wsInfo, opManager, workspace = null;

                if (transport.status === 201) {
                    response = transport.responseText;
                    wsInfo = JSON.parse(response);
                    opManager = OpManagerFactory.getInstance();
                    workspace = new Workspace(wsInfo);
                    opManager.workspaceInstances.set(wsInfo.id, workspace);
                }

                if (typeof options.onSuccess === 'function') {
                    try {
                        options.onSuccess(workspace);
                    } catch (e) {}
                }
            };

            var cloneError = function(transport, e) {
                var logManager, msg, details;

                logManager = LogManagerFactory.getInstance();

                msg = logManager.formatError(gettext("Error adding the workspace: %(errorMsg)s."), transport, e);
                logManager.log(msg);

                if (typeof options.onFailure === 'function') {
                    try {
                        if (transport.status === 422) {
                            details = JSON.parse(transport.responseText).details;
                        }
                    } catch (e) {}

                    try {
                        options.onFailure(msg, details);
                    } catch (e) {}
                }
            };

            Wirecloud.io.makeRequest(Wirecloud.URLs.WORKSPACE_COLLECTION, {
                method: 'POST',
                contentType: 'application/json',
                postBody: Object.toJSON({
                    'mashup': resource.getURI(),
                    'dry_run': options.dry_run
                }),
                onSuccess: cloneOk.bind(this),
                onFailure: cloneError.bind(this)
            });
        };

        OpManager.prototype.showPlatformPreferences = function () {
            PreferencesManagerFactory.getInstance().show();
        }

        OpManager.prototype.changeActiveWorkspace = function (workspace, initial_tab) {
            var state, steps = this.activeWorkspace != null ? 2 : 1;

            state = {
                workspace_creator: workspace.workspaceState.creator,
                workspace_name: workspace.getName(),
                view: "workspace"
            };
            if (initial_tab) {
                state.tab = initial_tab;
            }
            HistoryManager.pushState(state);
            LayoutManagerFactory.getInstance()._startComplexTask(gettext("Changing current workspace"), steps);

            if (this.activeWorkspace != null) {
                this.activeWorkspace.unload();
            }

            this.activeWorkspace = workspace;
            this.activeWorkspace.downloadWorkspaceInfo(initial_tab);
        }

        OpManager.prototype.logout = function logout() {
            window.location = Wirecloud.URLs.LOGOUT_VIEW;
        }

        OpManager.prototype.addInstance = function (widget, options) {
            if (!this.loadCompleted) {
                return;
            }

            this.activeWorkspace.getVisibleTab().getDragboard().addInstance(widget, options);
        };

        OpManager.prototype.removeInstance = function (iWidgetId, orderFromServer) {
            if (!this.loadCompleted)
                return;

            this.activeWorkspace.removeIWidget(iWidgetId, orderFromServer);
        }

        OpManager.prototype.getActiveWorkspaceId = function () {
            return this.activeWorkspace.getId();
        }

        /**
         * Loads the Wirecloud Platform.
         */
        OpManager.prototype.loadEnviroment = function () {
            // Init Layout Manager
            var layoutManager = LayoutManagerFactory.getInstance();
            layoutManager.resizeWrapper();
            layoutManager._startComplexTask(gettext('Loading Wirecloud Platform'), 3);
            layoutManager.logSubTask(gettext('Retrieving Wirecloud code'));
            layoutManager.logStep('');

            // Init log manager
            this.logs = LogManagerFactory.getInstance();

            Event.observe(window,
                          "beforeunload",
                          this.unloadEnvironment.bind(this),
                          true);

            Wirecloud.io.makeRequest(Wirecloud.URLs.PLATFORM_CONTEXT_COLLECTION, {
                method: 'GET',
                onSuccess: function (transport) {
                    OpManagerFactory.getInstance().contextManager = new Wirecloud.ContextManager(this, JSON.parse(transport.responseText));
                    LayoutManagerFactory.getInstance().header._initUserMenu();
                    OpManagerFactory.getInstance().continueLoadingGlobalModules(Modules.prototype.CONTEXT);
                }
            });
        }

        /**
         * Unloads the Wirecloud Platform. This method is called, by default, when
         * the unload event is captured.
         */
        OpManager.prototype.unloadEnvironment = function() {
            var layoutManager = LayoutManagerFactory.getInstance();
            layoutManager.hideCover();
            layoutManager._startComplexTask(gettext('Unloading Wirecloud Platform'));

            if (this.activeWorkspace) {
                this.activeWorkspace.unload();
            }

            //TODO: unloadCatalogue
        }

        OpManager.prototype.iwidgetLoaded = function (iwidgetId) {
            this.activeWorkspace.iwidgetLoaded(iwidgetId);
        }

        OpManager.prototype.iwidgetUnloaded = function (iwidgetId) {
            this.activeWorkspace.iwidgetUnloaded(iwidgetId);
        }

        OpManager.prototype.checkForWidgetUpdates = function () {
            this.activeWorkspace.checkForWidgetUpdates();
        }

        OpManager.prototype.showActiveWorkspace = function (refreshMenu) {
            // TODO
        }

        OpManager.prototype.preferencesChanged = function (modifiedValues) {
            if ('language' in modifiedValues) {
                window.location.reload();
            }
        };

        OpManager.prototype.continueLoadingGlobalModules = function (module) {
            // Asynchronous load of modules
            // Each singleton module notifies OpManager it has finished loading!
            var preferencesManager;

            switch (module) {
            case Modules.prototype.CONTEXT:

                Wirecloud.io.makeRequest(Wirecloud.URLs.THEME_ENTRY.evaluate({name: this.contextManager.get('theme')}), {
                    method: 'GET',
                    onSuccess: function (transport) {
                        Wirecloud.currentTheme = new Wirecloud.ui.Theme(JSON.parse(transport.responseText));
                        this.continueLoadingGlobalModules(Modules.prototype.THEME_MANAGER);
                    }.bind(this)
                });
                break;

            case Modules.prototype.THEME_MANAGER:
                this.platformPreferences = PreferencesManagerFactory.getInstance();
                break;

            case Modules.prototype.PLATFORM_PREFERENCES:
                preferencesManager = PreferencesManagerFactory.getInstance();
                preferencesManager.getPlatformPreferences().addCommitHandler(this.preferencesChanged.bind(this), 'post-commit');
                Wirecloud.LocalCatalogue.reload({
                    onSuccess: function () {
                        this.continueLoadingGlobalModules(Modules.prototype.SHOWCASE);
                    }.bind(this),
                    onFailure: function () {
                        var msg, logManager = LogManagerFactory.getInstance();
                        msg = logManager.formatError(gettext("Error retrieving available resources: %(errorMsg)s."), transport, e);
                        logManager.log(msg);
                        LayoutManagerFactory.getInstance().showMessageMenu(msg, Constants.Logging.ERROR_MSG);
                    }
                });
                break;

            case Modules.prototype.SHOWCASE:
            case Modules.prototype.CATALOGUE:
                // All singleton modules has been loaded!
                // It's time for loading tabspace information!
                this.loadActiveWorkspace();
                break;

            case Modules.prototype.ACTIVE_WORKSPACE:
                var layoutManager = LayoutManagerFactory.getInstance();
                layoutManager.logSubTask(gettext("Activating current Workspace"));

                this.showActiveWorkspace();

                layoutManager.logStep('');
                layoutManager._notifyPlatformReady();
                this.loadCompleted = true;
            }
        }

        OpManager.prototype.loadActiveWorkspace = function () {
            // Asynchronous load of modules
            // Each singleton module notifies OpManager it has finished loading!

            Wirecloud.io.makeRequest(Wirecloud.URLs.WORKSPACE_COLLECTION, {
                method: 'GET',
                onSuccess: loadEnvironment.bind(this),
                onFailure: onError.bind(this)
            });
        }

        OpManager.prototype.logIWidgetError = function(iWidgetId, msg, level) {
            var iWidget = this.activeWorkspace.getIWidget(iWidgetId);
            if (iWidget == null) {
                var msg2 = gettext("Some pice of code tried to notify an error in the iWidget %(iWidgetId)s when it did not exist or it was not loaded yet. This is an error in Wirecloud Platform, please notify it.\nError Message: %(errorMsg)s");
                msg2 = interpolate(msg2, {iWidgetId: iWidgetId, errorMsg: msg}, true);
                this.logs.log(msg2);
                return;
            }

            iWidget.log(msg, level);
        }

        OpManager.prototype.drawAttention = function(iWidgetId) {
            this.activeWorkspace.drawAttention(iWidgetId);
        };

        //Operations on workspaces

        OpManager.prototype.workspaceExists = function (newName) {
            var workspace_keys, workspace, i;
            workspace_keys = this.workspaceInstances.keys();
            for (i = 0; i < workspace_keys.length; i += 1) {
                workspace = this.workspaceInstances.get(workspace_keys[i]);
                if (workspace.workspaceState.name === newName) {
                    return true;
                }
            }
            return false;
        }

        OpManager.prototype.addWorkspace = function addWorkspace(newName, options) {
            if (options == null) {
                options = {};
            }

            Wirecloud.io.makeRequest(Wirecloud.URLs.WORKSPACE_COLLECTION, {
                method: 'POST',
                contentType: 'application/json',
                postBody: JSON.stringify({
                    allow_renaming: !!options.allow_renaming,
                    name: newName
                }),
                onSuccess: createWSSuccess.bind(this, options.onSuccess),
                onFailure: createWSError.bind(this, options.onFailure)
            });
        };

        OpManager.prototype.unloadWorkspace = function(workspaceId) {
            //Unloading the Workspace
            this.workspaceInstances.get(workspaceId).unload();
        }

        OpManager.prototype.removeWorkspace = function(workspaceId) {
            // Removing reference
            this.workspaceInstances.unset(workspaceId);

            // Set the first workspace as current
            this.changeActiveWorkspace(this.workspaceInstances.values()[0]);
        };

        OpManager.prototype.getWorkspaceCount = function(){
            return this.workspaceInstances.keys().length;
        }
    }

    // *********************************
    // SINGLETON GET INSTANCE
    // *********************************
    return new function() {
        this.getInstance = function() {
            if (instance == null) {
                instance = new OpManager();
            }
            return instance;
        }
    }
}();

<|endoftext|>


<commit_before><commit_msg>Small edit for code reverse.js<commit_after><|endoftext|>


<commit_before>import {vivliostylePrint} from "vivliostyle-print"

import {PAPER_SIZES} from "../../schema/const"
import {HTMLExporter} from "../html"
import {addAlert} from "../../common"
import {removeHidden} from "../tools/doc_contents"

export class PrintExporter extends HTMLExporter {

    constructor(schema, doc, bibDB, imageDB, citationStyles, citationLocales, documentStyles, staticUrl) {
        super(schema, doc, bibDB, imageDB, citationStyles, citationLocales, documentStyles, staticUrl)
        this.staticUrl = staticUrl
        this.removeUrlPrefix = false
        this.styleSheets.push({contents:
            `a.fn {
                -adapt-template: url(data:application/xml,${
                    encodeURI(
                        '<s:template id="footnote"><s:content/><s:include class="footnote-content"/></s:template>#footnote'
                    )
                });
                text-decoration: none;
                color: inherit;
                vertical-align: baseline;
                font-size: 70%;
                position: relative;
                top: -0.3em;

            }
            section[role=doc-footnote] > *:first-child:before {
                counter-increment: footnote-counter;
                content: counter(footnote-counter) ". ";
            }
            section.fnlist {
                display: none;
            }
            section:footnote-content {
                display: block;
                font-style:normal;
                font-weight:normal;
            }
            .table-of-contents a {
            	display: inline-flex;
            	width: 100%;
            	text-decoration: none;
            	color: currentColor;
            	break-inside: avoid;
            	align-items: baseline;
            }
            .table-of-contents a::before {
            	margin-left: 1px;
            	margin-right: 1px;
            	border-bottom: solid 1px lightgray;
            	content: "";
            	order: 1;
            	flex: auto;
            }
            .table-of-contents a::after {
            	text-align: right;
            	content: target-counter(attr(href, url), page);
            	align-self: flex-end;
            	flex: none;
            	order: 2;
            }
            @page {
                size: ${PAPER_SIZES.find(size => size[0] === this.doc.settings.papersize)[1]};
                @top-center {
                    content: env(doc-title);
                }
                @bottom-center {
                    content: counter(page);
                }
            }`
        })
    }

    init() {
        addAlert('info', `${this.doc.title}: ${gettext('Printing has been initiated.')}`)
        this.docContents = removeHidden(this.doc.contents, false)
        return this.addStyle().then(
            () => this.joinDocumentParts()
        ).then(
            () => this.fillToc()
        ).then(
            () => this.postProcess()
        ).then(
            ({html, title}) => vivliostylePrint(
                html,
                {
                    title,
                    resourcesUrl: `${this.staticUrl}vivliostyle-resources/`
                }
            )
        )
    }

    getFootnoteAnchor(counter) {
        const footnoteAnchor = super.getFootnoteAnchor(counter)
        // Add the counter directly into the footnote.
        footnoteAnchor.innerHTML = counter
        return footnoteAnchor
    }
}
<commit_msg>Added fix for inheriting underline styles<commit_after>import {vivliostylePrint} from "vivliostyle-print"

import {PAPER_SIZES} from "../../schema/const"
import {HTMLExporter} from "../html"
import {addAlert} from "../../common"
import {removeHidden} from "../tools/doc_contents"

export class PrintExporter extends HTMLExporter {

    constructor(schema, doc, bibDB, imageDB, citationStyles, citationLocales, documentStyles, staticUrl) {
        super(schema, doc, bibDB, imageDB, citationStyles, citationLocales, documentStyles, staticUrl)
        this.staticUrl = staticUrl
        this.removeUrlPrefix = false
        this.styleSheets.push({contents:
            `a.fn {
                -adapt-template: url(data:application/xml,${
                    encodeURI(
                        '<s:template id="footnote"><s:content/><s:include class="footnote-content"/></s:template>#footnote'
                    )
                });
                text-decoration: none;
                color: inherit;
                vertical-align: baseline;
                font-size: 70%;
                position: relative;
                top: -0.3em;

            }
            section[role=doc-footnote] > *:first-child:before {
                counter-increment: footnote-counter;
                content: counter(footnote-counter) ". ";
            }
            section.fnlist {
                display: none;
            }
            section:footnote-content {
                display: block;
                font-style:normal;
                font-weight:normal;
                text-decoration:none;
            }
            .table-of-contents a {
            	display: inline-flex;
            	width: 100%;
            	text-decoration: none;
            	color: currentColor;
            	break-inside: avoid;
            	align-items: baseline;
            }
            .table-of-contents a::before {
            	margin-left: 1px;
            	margin-right: 1px;
            	border-bottom: solid 1px lightgray;
            	content: "";
            	order: 1;
            	flex: auto;
            }
            .table-of-contents a::after {
            	text-align: right;
            	content: target-counter(attr(href, url), page);
            	align-self: flex-end;
            	flex: none;
            	order: 2;
            }
            @page {
                size: ${PAPER_SIZES.find(size => size[0] === this.doc.settings.papersize)[1]};
                @top-center {
                    content: env(doc-title);
                }
                @bottom-center {
                    content: counter(page);
                }
            }`
        })
    }

    init() {
        addAlert('info', `${this.doc.title}: ${gettext('Printing has been initiated.')}`)
        this.docContents = removeHidden(this.doc.contents, false)
        return this.addStyle().then(
            () => this.joinDocumentParts()
        ).then(
            () => this.fillToc()
        ).then(
            () => this.postProcess()
        ).then(
            ({html, title}) => vivliostylePrint(
                html,
                {
                    title,
                    resourcesUrl: `${this.staticUrl}vivliostyle-resources/`
                }
            )
        )
    }

    getFootnoteAnchor(counter) {
        const footnoteAnchor = super.getFootnoteAnchor(counter)
        // Add the counter directly into the footnote.
        footnoteAnchor.innerHTML = counter
        return footnoteAnchor
    }
}
<|endoftext|>


<commit_before>$(document).ready({

});<commit_msg>Update index.js<commit_after>$(document).ready(function() {

  var chosen_reply;
  var n;

  // Talking phase
  $("#chat-talk").keypress(function(event) {
    if (event.which == 13) {
      var user_input = $(this).val()
      $(this).val("");

      $(".chatbox").append("
You: " + user_input + "
");
      botReply(user_input);

    }
  });

  // Bot reply phase
  function botReply(input) {

    var common = [];

    var uncommon = [
      "K",
      "Okay",
      "I don't really care",
      "Sure",
      "ok",
      "You're a real pain to talk to you know that?",
      "I don't really care about your opinion"
      "?",
      "Why do you lie so much?"
    ]

    common[0] = {
      word: "anime",
      reply: [
        "Anime is Shit.",
        "Anime is the worst.",
        "Your favourite Anime is Shit!",
        "Are you a weeb? I don't like weebs."
      ]
    }

    common[1] = {
      word: "manga",
      reply: [
        "Manga is Shit.",
        "Manga is Chinese comics isn't it?",
        "You must be living a sad life for reading that."
      ]
    }

    common[2] = {
      word: "waifu",
      reply: [
        "No, your waifu isn't real.",
        "Maybe you should get a life?",
        "Your waifu is dead and fake."
      ]
    }

    common[3] = {
      word: "real",
      reply: [
        "No, you're not real.",
        "Even if you were real, I don't think you belong in this world"
        "Yeap, you don't have any real friends."
      ]
    }

    common[4] = {
      word: "fake",
      reply: [
        "Yeap, you are a big fake.";
        "Yea I know, you're the biggest fake in the world.",
        "Your parents are fake.",
        "Your memories are fake.",
        "Your whole life is fake.",
        "Your friends are fake."
      ]
    }

    common[5] = {
      word: "lie",
      reply: [
        "You're the liar."
      ]
    }

    // Extra time for the bot to reply
    var ran1 = Math.random() * (2000 - 500 + 1) + 500;

    // Change the input to lower case
    input = input.toLowerCase();

    for (var i = 0; i < common.length; i += 1) {
      if (input.indexOf(common[i].word) >= 0) {
        n = Math.floor(Math.random() * (common[i].reply.length));
        chosen_reply = common[i].reply[n];
        break;
      }
      else if (i == common.length - 1) {
        n = Math.floor(Math.random() * (uncommon.length));
        chosen_reply = uncommon[n];
        break;
      }
      else {
        chosen_reply = "error";
      }
    }

    // Reply
    setTimeout(function() {

      $(".chatbox").append("
Mei: " + chosen_reply + "
");

    }, ran1);

    // Scroll to the bottom
    $("#chat-box").scrollTo('100%');

  };

});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var path = require("path");
var url = require("url");

// Local version replaces global one
try {
	var localWebpackDevServer = require.resolve(path.join(process.cwd(), "node_modules", "webpack-dev-server", "bin", "webpack-dev-server.js"));
	if(__filename !== localWebpackDevServer) {
		return require(localWebpackDevServer);
	}
} catch(e) {}

var Server = require("../lib/Server");
var webpack = require("webpack");

var optimist = require("optimist")

	.usage("webpack-dev-server " + require("../package.json").version + "\n" +
			"Usage: https://github.com/webpack/docs/wiki/webpack-detailed-usage")

	.boolean("colors").alias("colors", "c").describe("colors")

	.boolean("lazy").describe("lazy")

	.boolean("info").describe("info").default("info", true)

	.boolean("quiet").describe("quiet")

	.boolean("inline").describe("inline", "Inlines the webpack-dev-server logic into the bundle.")

	.string("content-base").describe("content-base", "A directory or URL to serve HTML content from.")

	.string("content-base-target").describe("content-base-target", "Proxy requests to this target.")

	.boolean("history-api-fallback").describe("history-api-fallback", "Fallback to /index.html for Single Page Applications.")

	.describe("port", "The port").default("port", 8080);

require("webpack/bin/config-optimist")(optimist);

var argv = optimist.argv;

var wpOpt = require("webpack/bin/convert-argv")(optimist, argv, { outputFilename: "/bundle.js" });

var options = wpOpt.devServer || {};

if(!options.publicPath) {
	options.publicPath = wpOpt.output && wpOpt.output.publicPath || "";
	if(!/^(https?:)?\/\//.test(options.publicPath) && options.publicPath[0] !== "/")
		options.publicPath = "/" + options.publicPath;
}

if(!options.outputPath)
	options.outputPath = "/";
if(!options.filename)
	options.filename = wpOpt.output && wpOpt.output.filename;
[].concat(wpOpt).forEach(function(wpOpt) {
	wpOpt.output.path = "/";
});
if(!options.hot)
	options.hot = argv["hot"];

if(argv["content-base"]) {
	options.contentBase = argv["content-base"];
	if(/^[0-9]$/.test(options.contentBase))
		options.contentBase = +options.contentBase;
	else if(!/^(https?:)?\/\//.test(options.contentBase))
		options.contentBase = path.resolve(options.contentBase);
} else if(argv["content-base-target"]) {
	options.contentBase = { target: argv["content-base-target"] };
} else if(!options.contentBase) {
	options.contentBase = process.cwd();
}
if(!options.stats) {
	options.stats = {
		cached: false,
		cachedAssets: false
	};
}

if(argv["colors"])
	options.stats.colors = true;

if(argv["lazy"])
	options.lazy = true;

if(!argv["info"])
	options.noInfo = true;

if(argv["quiet"])
	options.quiet = true;

if(argv["inline"]) {
	var devClient = [require.resolve("../client/") + "?http://localhost:" + argv.port];
	if(options.hot)
		devClient.push("webpack/hot/dev-server");
	[].concat(wpOpt).forEach(function(wpOpt) {
		if(typeof wpOpt.entry === "object") {
			Object.keys(wpOpt.entry).forEach(function(key) {
				wpOpt.entry[key] = devClient.concat(wpOpt.entry[key]);
			});
		} else {
			wpOpt.entry = devClient.concat(wpOpt.entry);
		}
	});
}

if(argv["history-api-fallback"])
	options.historyApiFallback = true;

new Server(webpack(wpOpt), options).listen(argv.port, function(err) {
	if(err) throw err;
	if(argv["inline"])
		console.log("http://localhost:" + argv.port + "/");
	else
		console.log("http://localhost:" + argv.port + "/webpack-dev-server/");
	console.log("webpack result is served from " + options.publicPath);
	if(typeof options.contentBase === "object")
		console.log("requests are proxied to " + options.contentBase.target);
	else
		console.log("content is served from " + options.contentBase);
	if(options.historyApiFallback)
		console.log("404s will fallback to /index.html");
});
<commit_msg>webpack/webpack-dev-server#80: Adds hostname option<commit_after>#!/usr/bin/env node

var path = require("path");
var url = require("url");

// Local version replaces global one
try {
	var localWebpackDevServer = require.resolve(path.join(process.cwd(), "node_modules", "webpack-dev-server", "bin", "webpack-dev-server.js"));
	if(__filename !== localWebpackDevServer) {
		return require(localWebpackDevServer);
	}
} catch(e) {}

var Server = require("../lib/Server");
var webpack = require("webpack");

var optimist = require("optimist")

	.usage("webpack-dev-server " + require("../package.json").version + "\n" +
			"Usage: https://github.com/webpack/docs/wiki/webpack-detailed-usage")

	.boolean("colors").alias("colors", "c").describe("colors")

	.boolean("lazy").describe("lazy")

	.boolean("info").describe("info").default("info", true)

	.boolean("quiet").describe("quiet")

	.boolean("inline").describe("inline", "Inlines the webpack-dev-server logic into the bundle.")

	.string("content-base").describe("content-base", "A directory or URL to serve HTML content from.")

	.string("content-base-target").describe("content-base-target", "Proxy requests to this target.")

	.boolean("history-api-fallback").describe("history-api-fallback", "Fallback to /index.html for Single Page Applications.")

	.describe("port", "The port").default("port", 8080)

	.describe("host", "The hostname/ip addresse the server will bind to").default("host", "localhost");

require("webpack/bin/config-optimist")(optimist);

var argv = optimist.argv;

var wpOpt = require("webpack/bin/convert-argv")(optimist, argv, { outputFilename: "/bundle.js" });

var options = wpOpt.devServer || {};

if(!options.publicPath) {
	options.publicPath = wpOpt.output && wpOpt.output.publicPath || "";
	if(!/^(https?:)?\/\//.test(options.publicPath) && options.publicPath[0] !== "/")
		options.publicPath = "/" + options.publicPath;
}

if(!options.outputPath)
	options.outputPath = "/";
if(!options.filename)
	options.filename = wpOpt.output && wpOpt.output.filename;
[].concat(wpOpt).forEach(function(wpOpt) {
	wpOpt.output.path = "/";
});
if(!options.hot)
	options.hot = argv["hot"];

if(argv["content-base"]) {
	options.contentBase = argv["content-base"];
	if(/^[0-9]$/.test(options.contentBase))
		options.contentBase = +options.contentBase;
	else if(!/^(https?:)?\/\//.test(options.contentBase))
		options.contentBase = path.resolve(options.contentBase);
} else if(argv["content-base-target"]) {
	options.contentBase = { target: argv["content-base-target"] };
} else if(!options.contentBase) {
	options.contentBase = process.cwd();
}
if(!options.stats) {
	options.stats = {
		cached: false,
		cachedAssets: false
	};
}

if(argv["colors"])
	options.stats.colors = true;

if(argv["lazy"])
	options.lazy = true;

if(!argv["info"])
	options.noInfo = true;

if(argv["quiet"])
	options.quiet = true;

if(argv["inline"]) {
	var devClient = [require.resolve("../client/") + "?http://" + argv.host + ":" + argv.port];
	if(options.hot)
		devClient.push("webpack/hot/dev-server");
	[].concat(wpOpt).forEach(function(wpOpt) {
		if(typeof wpOpt.entry === "object") {
			Object.keys(wpOpt.entry).forEach(function(key) {
				wpOpt.entry[key] = devClient.concat(wpOpt.entry[key]);
			});
		} else {
			wpOpt.entry = devClient.concat(wpOpt.entry);
		}
	});
}

if(argv["history-api-fallback"])
	options.historyApiFallback = true;

new Server(webpack(wpOpt), options).listen(argv.port, function(err) {
	if(err) throw err;
	if(argv["inline"])
		console.log("http://" + argv.host + ":" + argv.port + "/");
	else
		console.log("http://" + argv.host + ":" + argv.port + "/webpack-dev-server/");
	console.log("webpack result is served from " + options.publicPath);
	if(typeof options.contentBase === "object")
		console.log("requests are proxied to " + options.contentBase.target);
	else
		console.log("content is served from " + options.contentBase);
	if(options.historyApiFallback)
		console.log("404s will fallback to /index.html");
});
<|endoftext|>


<commit_before>function createEcho(selectedString, userText, url){
  var echo = new Echo(selectedString, userText, url);
  console.log(echo);
  debugger;
}<commit_msg>edited eventpage.js<commit_after>function createEcho(selectedString, userText, url){
  var echo = new Echo(selectedString, userText, url);
}<|endoftext|>


<commit_before>var config = require('../config');

var express = require('express');
var _ = require('lodash');
var request = require('request');
var fs = require('fs');
var xml2js = require('xml2js');

var async = require('async')

var router = express.Router();

var MongoClient = require('mongodb').MongoClient
var mongo_url = config.mongo + config.db;

var db = {};

require('../models/reactions.js');
require('../models/definition.js');
require('../models/votes.js');

// GET list of reactions
router.get('/', function(req, res, next) {

  var response = {};

  if (!req.query.limit) {req.query.limit = 25;} else {req.query.limit = parseInt(req.query.limit);}
  if (req.query.limit > 200) {
    req.query.limit = 200;
  }
  if (!req.query.offset) {req.query.offset = 0;} else {req.query.offset = parseInt(req.query.offset);}

  var findAll = function(db, callback) {

    var collection = db.collection('reactions');

    var cursor = collection.find({ });

    async.series([

        // Get count from cursor
        function(callback){
          cursor.count(function(err, count) {
            response.count = count;
            response.limit = req.query.limit;
            response.offset = req.query.offset;
          });
          callback(null);
        },

        // Get results from curor
        function(callback){
          cursor.limit(req.query.limit);
          cursor.skip(req.query.offset);

          cursor.toArray(function(err, result) {
            response.response = result;
            callback(null);
          });
        }

      ], function(err){

       // ... then remove the _id keys from the results and send response back
        _.forEach(response.response, function(v, k) {
          delete response.response[k]['_id'];
        })

        db.close();
        res.json(response);
    });

  }

  MongoClient.connect(mongo_url, function(err, db) {
    findAll(db, function() {

    });
  });

});

// TO DO: Post new or update reaction definition
router.post('/', function(req, res, next) {
  // Validate that incoming request is ok... and not a duplicate
  //res.json({todo: 'post reaction definition'});
  var reaction = new Reaction();

  if(Object.keys(req.body).length != 1 ||
     req.body.reaction == null ||
     req.headers['content-type'] != 'application/json' ||
     typeof req.body.reaction != "string") {
    var err = new Error();
    err.status = 400;
    err.error = "Invalid Request Body";
    err.message = "Either the incorrect number of attributes were provided or" +
                  " the 'reaction' attribute could not be found, or the" +
                  " 'reaction' attribute wasn't properly formatted.";
    next(err);
  }

  // Tries to find reaction in collection (returns the record if found)
  var findReaction = function(db, callback) {
    var collection = db.collection('reactions');
    collection.findOne({'reaction': req.body.reaction.toLowerCase()}, function(err, reaction) {
      callback(reaction);
    });
  }

  // Inserts reaction into Mongo
  var insertReaction = function(db, callback) {
    var collection = db.collection('reactions');

      collection.insert([
        reaction
      ], function(err, result) {

        db.close();
        callback(result);

      });
  }

  // Retrieves definition available from Merriam Webster Medical Dictionary API
  var getTermDefinitionFromMerriamWebsterMedical = function (callback) {

    var url = "http://www.dictionaryapi.com/api/v1/references/medical/xml/" + encodeURIComponent(reaction.reaction.toLowerCase()) + "?key=" + config.dictionaryapi_key;

    request(url, function (error, response, body) {

      if (!error && response.statusCode == 200) {

        var parser = new xml2js.Parser({ignoreAttrs: false});

        parser.parseString(body, function (err, result) {

          if (result) {

          _.forEach(result.entry_list.entry, function(v,k) {

            if (v['$'].id == reaction.reaction.toLowerCase()) {

                if (v.def) {

                  if (Array.isArray(v.def[0].sensb[0].sens)) {

                      _.forEach(v.def[0].sensb, function (v,k) {

                        if (v.sens[0].dt[0]['_']) {

                          if (typeof v.sens[0].dt[0]['_'] == "string") {

                            var definition = new Definition;
                            var dt = new Date();

                            definition.definition = v.sens[0].dt[0]['_'];
                            definition.source = 'dictionaryapi.com';
                            definition.created_at = dt.getTime();
                            definition.created_by = "";
                            definition.votes = new Votes();

                            reaction.addDefinition(definition);

                          }

                        } else {
                          var def = {};
                          if (typeof v.sens[0].dt[0] == "string") {

                            var definition = new Definition;
                            var dt = new Date();

                            definition.definition = v.sens[0].dt[0];
                            definition.source = 'dictionaryapi.com';
                            definition.created_at = dt.getTime();
                            definition.created_by = "";
                            definition.votes = new Votes();
                            reaction.addDefinition(definition);

                          }

                        }

                      });

                    } else {

                      if (typeof v.def[0].sensb[0].sens[0].dt == "string") {

                        var definition = new Definition;
                        var dt = new Date();

                        definition.definition = v.def[0].sensb[0].sens[0].dt;
                        definition.source = 'dictionaryapi.com';
                        definition.created_at = dt.getTime();
                        definition.created_by = "";
                        definition.votes = new Votes();
                        reaction.addDefinition(definition);

                      }

                      }

                    }

                }
            });
            }

          });

          callback(null);

      } else {
        callback(null);
      }
    })
  }

  // Retrieves definition available from Wordnik API
  var getDefinitionFromWordnik = function (callback) {
    var url = "http://api.wordnik.com:80/v4/word.json/" + encodeURIComponent(reaction.reaction.toLowerCase()) + "/definitions?limit=200&includeRelated=true&useCanonical=false&includeTags=false&api_key=" + config.wordnikapi_key ;

    request(url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        var deflist = JSON.parse(body);
        if (deflist[0]) {
          _.forEach(deflist, function(v,k) {

            var definition = new Definition;

            if (v.partOfSpeech == "noun") {
              var dt = new Date();

              definition.definition = v.text;
              definition.source = 'wordnik.com';
              definition.created_at = dt.getTime();
              definition.created_by = "";
              definition.votes = new Votes();

              reaction.addDefinition(definition);
            }

          });

        }
       callback();

      } else {
        callback();
      }
    })

  }

  // - Establish connection to mongo
  // - Check to see if reaction exists
  // - If it does not exist, find definitions and insert
if(!err) {
  MongoClient.connect(mongo_url, function(err, db) {
    if (err) {
      var err = new Error();
      err.status = 500;
      err.error = "Internal Error";
      next(err);
    }
    else {

      findReaction(db, function(result) {

        if(result) {

          var err = new Error();
          err.status = 422;
          err.error = "Duplicate Reaction";
          err.message = "The reaction that you are trying to create already exists" +
                        " and cannot be created again.";
          db.close();
          next(err);
        } else {

          var dt = new Date();

          reaction.reaction = req.body.reaction.toLowerCase();
          reaction.definitions = [];
          reaction.created_at = dt.getTime();
          reaction.created_by = "";

          async.series([
              function(callback){
                getTermDefinitionFromMerriamWebsterMedical(function (result) {
                  callback(null);
                });
              },
              function(callback){
                getDefinitionFromWordnik(function (result) {
                  callback(null);
                });
              }
          ],

          // insert into mongo
          function(err, results){
            insertReaction(db, function(result) {
                delete reaction['_id'];
                res.json(reaction);

            });

          });

        }
     });

    }

   });
 }

});

// TO DO: Get reaction defintion
router.get('/:id', function(req, res, next) {
  MongoClient.connect(mongo_url, function(err, db) {

    // Tries to find reaction in collection (returns the record if found)
    var findReaction = function(term, db, callback) {
      var collection = db.collection('reactions');
      collection.findOne({'reaction': term.toLowerCase()}, function(err, reaction) {

        callback(reaction);
      });
    };

    if(req.params.id == null || typeof req.params.id == "object") {
      var err = new Error();
      err.status = 500;
      err.error = "Unknown Server Error";
      err.message = "Please retry your request again or contact us if the"
                    + " problem persists";
      next(err);
    }

    findReaction(decodeURIComponent(req.params.id.toLowerCase()), db, function(result) {
      if(result === null) {
        var err = new Error();
        err.status = 404;
        err.error = "Reaction Not Found";
        err.message = "The reaction that you were looking for could not be found.";
        db.close();
        next(err);
      } else {
        delete result['_id'];
        res.json(result);
        db.close();
      }
    });
  });
});

// Reaction Definition Vote Up / Down
router.put('/:id/definitions/:index', function(req, res, next) {

  var id = req.params.id;
  var definitionIndex = req.params.index;

  // ensure proper content type
  if (req.headers['content-type'] != 'application/json') {
    var err = new Error();
    err.status = 400;
    err.error = "Invalid content type";
    err.message = "Valid content type is 'application/json'";
    next(err);
  } else {

    // ensure body has vote key value
    if (!req.body.vote) {
      var err = new Error();
      err.status = 400;
      err.error = "Vote attribute not found in body";
      err.message = "A vote attribute must be passed in body (ex. {'vote':'up'}) - valid values are 'up' or 'down'";
      next(err);
    } else {

      var vote = req.body.vote.toLowerCase();

      // ensure valid value for vote (up | down)
      if (!(vote == 'up' || vote == 'down')) {
        var err = new Error();
        err.status = 400;
        err.error = "Vote attribute '" + vote  + "' not valid";
        err.message = "A vote attribute must be passed in body (ex. {'vote':'up'}) - valid values are 'up' or 'down'";
        next(err);
      } else {

        // Tries to find reaction in collection (returns the record if found)
        var findReaction = function(term,db, callback) {
          var collection = db.collection('reactions');
          collection.findOne({'reaction': term.toLowerCase()}, function(err, reaction) {
            callback(reaction);
          });
        };

        // Update reaction with updated votes
        var updateReaction = function(reaction, reaction_document, db, callback) {
          var collection = db.collection('reactions');
          collection.update({reaction:reaction}, {$set: reaction_document}, {}, function(err, result) {
            if (err) {
                var err = new Error();
                err.status = 500;
                err.error = "Internal error";
                next(err);
            } else {
              callback(result);
            }

          });

        };

        MongoClient.connect(mongo_url, function(err, db) {
          if (err) {
            var err = new Error();
            err.status = 500;
            err.error = "Internal error";
            next(err);
          } else {

            // find reaction in requst
            findReaction(id, db, function (reaction) {
              if(reaction === null) {
                var err = new Error();
                err.status = 404;
                err.error = "Reaction Not Found";
                err.message = "The reaction that you were looking for could not be found.";
                db.close();
                next(err);
              } else {

                // check if definition exists - error if not
                if(!reaction.definitions[definitionIndex]) {
                  var err = new Error();
                  err.status = 404;
                  err.error = "Definition [" + definitionIndex + "] not found";
                  err.message = "The definition index provided was not found.";
                  db.close();
                  next(err);

                } else {

                  // update update count of ups / downs based upon request
                  if(vote == 'up') {
                    reaction.definitions[definitionIndex].votes.ups++;
                  }

                  if(vote == 'down') {
                    reaction.definitions[definitionIndex].votes.downs++;
                  }

                  // update the reaction document and respond
                  updateReaction(reaction.reaction, reaction, db, function (result) {
                    delete reaction['_id'];
                    db.close();
                    res.json(reaction);
                  });

                }

              }
            })
          }
        });

      }

    }

  }

});

// TO DO: Put reaction defintion
router.put('/:id', function(req, res, next) {
  var id = req.params.id;
  var example = JSON.parse('{"reaction":"' + id + '","terms":[{"term":"urosepsis","text":"sepsis caused by bacteria from the urinary tract invading the bloodstream","attributionText":"from Wiktionary, Creative Commons Attribution/Share-Alike License","source":"wordnik"},{"term":"urosepsis","text":"sepsis caused by bacteria from the urinary tract invading the bloodstream","attributionText":"from Wiktionary, Creative Commons Attribution/Share-Alike License","source":"wordnik"}]}');
  res.json(example);
});

// TO DO: Delete reaction definition
router.delete('/:id', function(req, res, next) {
  MongoClient.connect(mongo_url, function(err, db) {

    // Tries to find reaction in collection (returns the record if found)
    var findReaction = function(term, db, callback) {
      var collection = db.collection('reactions');
      collection.findOneAndDelete({'reaction': term.toLowerCase()}, function(err, reaction) {
        callback(reaction);
      });
    };

    if(req.params.id == null || typeof req.params.id == "object") {
      var err = new Error();
      err.status = 500;
      err.error = "Unknown Server Error";
      err.message = "Please retry your request again or contact us if the"
                    + " problem persists";
      next(err);
    }

    findReaction(decodeURIComponent(req.params.id.toLowerCase()), db, function(result) {
      res.json();
    });

    db.close();
  });
});

module.exports = router;
<commit_msg>fixed offset iss140 and aligned repsonse to match spec<commit_after>var config = require('../config');

var express = require('express');
var _ = require('lodash');
var request = require('request');
var fs = require('fs');
var xml2js = require('xml2js');

var async = require('async')

var router = express.Router();

var MongoClient = require('mongodb').MongoClient
var mongo_url = config.mongo + config.db;

var db = {};

require('../models/reactions.js');
require('../models/definition.js');
require('../models/votes.js');

// GET list of reactions
router.get('/', function(req, res, next) {

  var startTime = new Date().getTime();

  var response = {};
  response.meta = {};
  response.data = [];

  if (!req.query.limit) {req.query.limit = 25;} else {req.query.limit = parseInt(req.query.limit);}

  if (req.query.limit < 1) {
    req.query.limit = 1;
  }

  if (req.query.limit > 200) {
    req.query.limit = 200;
  }

  if (!req.query.offset) {req.query.offset = 0;} else {req.query.offset = parseInt(req.query.offset);}

  var findAll = function(db, callback) {

    var collection = db.collection('reactions');

    var cursor = collection.find({ });

    async.series([

        // Get count from cursor
        function(callback){
          cursor.count(function(err, count) {
            response.meta.limit = req.query.limit;
            response.meta.offset = req.query.offset;
            response.meta.total_count = count;

          });
          callback(null);
        },

        // Get results from curor
        function(callback){
          cursor.limit(req.query.limit);
          cursor.skip(req.query.offset);

          cursor.toArray(function(err, result) {
            response.data = result;
            callback(null);
          });
        }

      ], function(err){

        db.close();

        if (!response.data) {
          var endTime = new Date().getTime();
          response.meta.execution_time = String ((endTime - startTime) / 1000) + 's'  ;

          res.status(404);
          res.json(response);

        } else {

         // ... then remove the _id keys from the results and send response back
          _.forEach(response.data, function(v, k) {
            delete response.data[k]['_id'];
          })

          var endTime = new Date().getTime();
          response.meta.execution_time = String ((endTime - startTime) / 1000) + 's'  ;

          res.json(response);

        }

    });

  }

  MongoClient.connect(mongo_url, function(err, db) {
    findAll(db, function() {

    });
  });

});

// TO DO: Post new or update reaction definition
router.post('/', function(req, res, next) {
  // Validate that incoming request is ok... and not a duplicate
  //res.json({todo: 'post reaction definition'});
  var reaction = new Reaction();

  if(Object.keys(req.body).length != 1 ||
     req.body.reaction == null ||
     req.headers['content-type'] != 'application/json' ||
     typeof req.body.reaction != "string") {
    var err = new Error();
    err.status = 400;
    err.error = "Invalid Request Body";
    err.message = "Either the incorrect number of attributes were provided or" +
                  " the 'reaction' attribute could not be found, or the" +
                  " 'reaction' attribute wasn't properly formatted.";
    next(err);
  }

  // Tries to find reaction in collection (returns the record if found)
  var findReaction = function(db, callback) {
    var collection = db.collection('reactions');
    collection.findOne({'reaction': req.body.reaction.toLowerCase()}, function(err, reaction) {
      callback(reaction);
    });
  }

  // Inserts reaction into Mongo
  var insertReaction = function(db, callback) {
    var collection = db.collection('reactions');

      collection.insert([
        reaction
      ], function(err, result) {

        db.close();
        callback(result);

      });
  }

  // Retrieves definition available from Merriam Webster Medical Dictionary API
  var getTermDefinitionFromMerriamWebsterMedical = function (callback) {

    var url = "http://www.dictionaryapi.com/api/v1/references/medical/xml/" + encodeURIComponent(reaction.reaction.toLowerCase()) + "?key=" + config.dictionaryapi_key;

    request(url, function (error, response, body) {

      if (!error && response.statusCode == 200) {

        var parser = new xml2js.Parser({ignoreAttrs: false});

        parser.parseString(body, function (err, result) {

          if (result) {

          _.forEach(result.entry_list.entry, function(v,k) {

            if (v['$'].id == reaction.reaction.toLowerCase()) {

                if (v.def) {

                  if (Array.isArray(v.def[0].sensb[0].sens)) {

                      _.forEach(v.def[0].sensb, function (v,k) {

                        if (v.sens[0].dt[0]['_']) {

                          if (typeof v.sens[0].dt[0]['_'] == "string") {

                            var definition = new Definition;
                            var dt = new Date();

                            definition.definition = v.sens[0].dt[0]['_'];
                            definition.source = 'dictionaryapi.com';
                            definition.created_at = dt.getTime();
                            definition.created_by = "";
                            definition.votes = new Votes();

                            reaction.addDefinition(definition);

                          }

                        } else {
                          var def = {};
                          if (typeof v.sens[0].dt[0] == "string") {

                            var definition = new Definition;
                            var dt = new Date();

                            definition.definition = v.sens[0].dt[0];
                            definition.source = 'dictionaryapi.com';
                            definition.created_at = dt.getTime();
                            definition.created_by = "";
                            definition.votes = new Votes();
                            reaction.addDefinition(definition);

                          }

                        }

                      });

                    } else {

                      if (typeof v.def[0].sensb[0].sens[0].dt == "string") {

                        var definition = new Definition;
                        var dt = new Date();

                        definition.definition = v.def[0].sensb[0].sens[0].dt;
                        definition.source = 'dictionaryapi.com';
                        definition.created_at = dt.getTime();
                        definition.created_by = "";
                        definition.votes = new Votes();
                        reaction.addDefinition(definition);

                      }

                      }

                    }

                }
            });
            }

          });

          callback(null);

      } else {
        callback(null);
      }
    })
  }

  // Retrieves definition available from Wordnik API
  var getDefinitionFromWordnik = function (callback) {
    var url = "http://api.wordnik.com:80/v4/word.json/" + encodeURIComponent(reaction.reaction.toLowerCase()) + "/definitions?limit=200&includeRelated=true&useCanonical=false&includeTags=false&api_key=" + config.wordnikapi_key ;

    request(url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        var deflist = JSON.parse(body);
        if (deflist[0]) {
          _.forEach(deflist, function(v,k) {

            var definition = new Definition;

            if (v.partOfSpeech == "noun") {
              var dt = new Date();

              definition.definition = v.text;
              definition.source = 'wordnik.com';
              definition.created_at = dt.getTime();
              definition.created_by = "";
              definition.votes = new Votes();

              reaction.addDefinition(definition);
            }

          });

        }
       callback();

      } else {
        callback();
      }
    })

  }

  // - Establish connection to mongo
  // - Check to see if reaction exists
  // - If it does not exist, find definitions and insert
if(!err) {
  MongoClient.connect(mongo_url, function(err, db) {
    if (err) {
      var err = new Error();
      err.status = 500;
      err.error = "Internal Error";
      next(err);
    }
    else {

      findReaction(db, function(result) {

        if(result) {

          var err = new Error();
          err.status = 422;
          err.error = "Duplicate Reaction";
          err.message = "The reaction that you are trying to create already exists" +
                        " and cannot be created again.";
          db.close();
          next(err);
        } else {

          var dt = new Date();

          reaction.reaction = req.body.reaction.toLowerCase();
          reaction.definitions = [];
          reaction.created_at = dt.getTime();
          reaction.created_by = "";

          async.series([
              function(callback){
                getTermDefinitionFromMerriamWebsterMedical(function (result) {
                  callback(null);
                });
              },
              function(callback){
                getDefinitionFromWordnik(function (result) {
                  callback(null);
                });
              }
          ],

          // insert into mongo
          function(err, results){
            insertReaction(db, function(result) {
                delete reaction['_id'];
                res.json(reaction);

            });

          });

        }
     });

    }

   });
 }

});

// TO DO: Get reaction defintion
router.get('/:id', function(req, res, next) {
  MongoClient.connect(mongo_url, function(err, db) {

    // Tries to find reaction in collection (returns the record if found)
    var findReaction = function(term, db, callback) {
      var collection = db.collection('reactions');
      collection.findOne({'reaction': term.toLowerCase()}, function(err, reaction) {

        callback(reaction);
      });
    };

    if(req.params.id == null || typeof req.params.id == "object") {
      var err = new Error();
      err.status = 500;
      err.error = "Unknown Server Error";
      err.message = "Please retry your request again or contact us if the"
                    + " problem persists";
      next(err);
    }

    findReaction(decodeURIComponent(req.params.id.toLowerCase()), db, function(result) {
      if(result === null) {
        var err = new Error();
        err.status = 404;
        err.error = "Reaction Not Found";
        err.message = "The reaction that you were looking for could not be found.";
        db.close();
        next(err);
      } else {
        delete result['_id'];
        res.json(result);
        db.close();
      }
    });
  });
});

// Reaction Definition Vote Up / Down
router.put('/:id/definitions/:index', function(req, res, next) {

  var id = req.params.id;
  var definitionIndex = req.params.index;

  // ensure proper content type
  if (req.headers['content-type'] != 'application/json') {
    var err = new Error();
    err.status = 400;
    err.error = "Invalid content type";
    err.message = "Valid content type is 'application/json'";
    next(err);
  } else {

    // ensure body has vote key value
    if (!req.body.vote) {
      var err = new Error();
      err.status = 400;
      err.error = "Vote attribute not found in body";
      err.message = "A vote attribute must be passed in body (ex. {'vote':'up'}) - valid values are 'up' or 'down'";
      next(err);
    } else {

      var vote = req.body.vote.toLowerCase();

      // ensure valid value for vote (up | down)
      if (!(vote == 'up' || vote == 'down')) {
        var err = new Error();
        err.status = 400;
        err.error = "Vote attribute '" + vote  + "' not valid";
        err.message = "A vote attribute must be passed in body (ex. {'vote':'up'}) - valid values are 'up' or 'down'";
        next(err);
      } else {

        // Tries to find reaction in collection (returns the record if found)
        var findReaction = function(term,db, callback) {
          var collection = db.collection('reactions');
          collection.findOne({'reaction': term.toLowerCase()}, function(err, reaction) {
            callback(reaction);
          });
        };

        // Update reaction with updated votes
        var updateReaction = function(reaction, reaction_document, db, callback) {
          var collection = db.collection('reactions');
          collection.update({reaction:reaction}, {$set: reaction_document}, {}, function(err, result) {
            if (err) {
                var err = new Error();
                err.status = 500;
                err.error = "Internal error";
                next(err);
            } else {
              callback(result);
            }

          });

        };

        MongoClient.connect(mongo_url, function(err, db) {
          if (err) {
            var err = new Error();
            err.status = 500;
            err.error = "Internal error";
            next(err);
          } else {

            // find reaction in requst
            findReaction(id, db, function (reaction) {
              if(reaction === null) {
                var err = new Error();
                err.status = 404;
                err.error = "Reaction Not Found";
                err.message = "The reaction that you were looking for could not be found.";
                db.close();
                next(err);
              } else {

                // check if definition exists - error if not
                if(!reaction.definitions[definitionIndex]) {
                  var err = new Error();
                  err.status = 404;
                  err.error = "Definition [" + definitionIndex + "] not found";
                  err.message = "The definition index provided was not found.";
                  db.close();
                  next(err);

                } else {

                  // update update count of ups / downs based upon request
                  if(vote == 'up') {
                    reaction.definitions[definitionIndex].votes.ups++;
                  }

                  if(vote == 'down') {
                    reaction.definitions[definitionIndex].votes.downs++;
                  }

                  // update the reaction document and respond
                  updateReaction(reaction.reaction, reaction, db, function (result) {
                    delete reaction['_id'];
                    db.close();
                    res.json(reaction);
                  });

                }

              }
            })
          }
        });

      }

    }

  }

});

// TO DO: Put reaction defintion
router.put('/:id', function(req, res, next) {
  var id = req.params.id;
  var example = JSON.parse('{"reaction":"' + id + '","terms":[{"term":"urosepsis","text":"sepsis caused by bacteria from the urinary tract invading the bloodstream","attributionText":"from Wiktionary, Creative Commons Attribution/Share-Alike License","source":"wordnik"},{"term":"urosepsis","text":"sepsis caused by bacteria from the urinary tract invading the bloodstream","attributionText":"from Wiktionary, Creative Commons Attribution/Share-Alike License","source":"wordnik"}]}');
  res.json(example);
});

// TO DO: Delete reaction definition
router.delete('/:id', function(req, res, next) {
  MongoClient.connect(mongo_url, function(err, db) {

    // Tries to find reaction in collection (returns the record if found)
    var findReaction = function(term, db, callback) {
      var collection = db.collection('reactions');
      collection.findOneAndDelete({'reaction': term.toLowerCase()}, function(err, reaction) {
        callback(reaction);
      });
    };

    if(req.params.id == null || typeof req.params.id == "object") {
      var err = new Error();
      err.status = 500;
      err.error = "Unknown Server Error";
      err.message = "Please retry your request again or contact us if the"
                    + " problem persists";
      next(err);
    }

    findReaction(decodeURIComponent(req.params.id.toLowerCase()), db, function(result) {
      res.json();
    });

    db.close();
  });
});

module.exports = router;
<|endoftext|>