<commit_before>/* globals controlplane: true */

/* AppsController
 * Displays top level apps
 */
(function() {
    'use strict';

    controlplane.controller("AppsController", [
        "$scope", "$routeParams", "$location",
        "$notification", "resourcesFactory", "authService",
        "$modalService", "$translate", "$timeout",
        "$cookies", "servicesFactory", "miscUtils",
        "ngTableParams", "$filter", "poolsFactory",
    function($scope, $routeParams, $location,
    $notification, resourcesFactory, authService,
    $modalService, $translate, $timeout,
    $cookies, servicesFactory, utils,
    NgTableParams, $filter, poolsFactory){

        // Ensure logged in
        authService.checkLogin($scope);

        // alias hostname instead of using localhost or IP
        $scope.defaultHostAlias = $location.host();

        // redirect to specific service details
        $scope.routeToService = function(id) {
            resourcesFactory.routeToService(id);
        };

        // redirect to specific pool
        $scope.routeToPool = function(id) {
            resourcesFactory.routeToPool(id);
        };

        $scope.modal_deployWizard = function() {
            // the modal occasionally won't show on page load, so we use a timeout to get around that.
            $timeout(function(){
                $('#addApp').modal('show');

                // don't auto-show this wizard again
                // NOTE: $cookies can only deal with string values
                $cookies.put("autoRunWizardHasRun","true");
            });
        };

        $scope.modal_addTemplate = function() {
            $modalService.create({
                templateUrl: "add-template.html",
                model: $scope,
                title: "template_add",
                actions: [
                    {
                        role: "cancel",
                        action: function(){
                            $scope.newHost = {};
                            this.close();
                        }
                    },{
                        role: "ok",
                        label: "template_add",
                        action: function(){
                            if(this.validate()){
                                var data = new FormData();

                                $.each($("#new_template_filename")[0].files, function(key, value){
                                    data.append("tpl", value);
                                });

                                // disable ok button, and store the re-enable function
                                var enableSubmit = this.disableSubmitButton();

                                resourcesFactory.addAppTemplate(data)
                                    .success(function(data){
                                        $notification.create("Added template", data.Detail).success();
                                        refreshTemplates();
                                        this.close();
                                    }.bind(this))
                                    .error(function(data){
                                        this.createNotification("Adding template failed", data.Detail).error();
                                        enableSubmit();
                                    }.bind(this));
                            }
                        }
                    }
                ]
            });
        };

        // aggregate vhosts for a specified service, but
        // only if the service has changed since last request
        $scope.aggregateVHosts = utils.memoize(function(service) {
            var endPoints = [];

            service.model.Endpoints.forEach(endpoint => {
                if(endpoint.VHostList){
                    endpoint.VHostList.forEach(vHost => endPoints.push(vHost));
                }
                if(endpoint.PortList){
                    endpoint.PortList.forEach(port => endPoints.push(port));
                }
            });

            return endPoints;
        }, function(service){
            return service.id + service.model.DatabaseVersion;
        });

        $scope.modal_removeService = function(service) {
            $modalService.create({
                template: $translate.instant("warning_remove_service"),
                model: $scope,
                title: "remove_service",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "remove_service",
                        classes: "btn-danger submit",
                        action: function(){
                            if(this.validate()){
                                this.disableSubmitButton();

                                removeService(service)
                                    .success(() => {
                                        $notification.create("Removed App", service.name).success();
                                        this.close();
                                    })
                                    .error((data, status) => {
                                        $notification.create("Remove App failed", data.Detail).error();
                                        this.close();
                                    });
                            }
                        }
                    }
                ]
            });
        };

        $scope.startService = function(service){
            $scope.modal_startStopService(service, "start");
        };
        $scope.stopService = function(service){
            $scope.modal_startStopService(service, "stop");
        };
        $scope.modal_startStopService = function(service, status) {
            var displayStatus = utils.capitalizeFirst(status);

            $modalService.create({
                template: $translate.instant("confirm_"+ status +"_app"),
                model: $scope,
                title: displayStatus +" Services",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: displayStatus +" Services",
                        action: function(){
                            service[status]();
                            this.close();
                        }
                    }
                ]
            });
        };

        // sets a service to start, stop or restart state
        $scope.setServiceState = function(service, state, skipChildren){
            service[state](skipChildren).error(function(data, status){
                $notification.create("Unable to " + state + " service", data.Detail).error();
            });
        };

        // filters to be used when counting how many descendent
        // services will be affected by a state change
        var serviceStateChangeFilters = {
            // only stopped services will be started
            "start": service => service.desiredState === 0,
            // only started services will be stopped
            "stop": service => service.desiredState === 1,
            // only started services will be restarted
            "restart": service => service.desiredState === 1
        };

        // clicks to a service's start, stop, or restart
        // button should first determine if the service has
        // children and ask the user to choose to start all
        // children or only the top service
        $scope.clickRunning = function(service, state){
            var filterFn = serviceStateChangeFilters[state];
            var childCount = utils.countTheKids(service, filterFn);

            // if the service has affected children, check if the user
            // wants to start just the service, or the service and children
            if(childCount > 0){
                $scope.modal_confirmSetServiceState(service, state, childCount);

            // if no children, just start the service
            } else {
                $scope.setServiceState(service, state);
            }
            servicesFactory.updateHealth();
        };

        // verifies if use wants to start parent service, or parent
        // and all children
        $scope.modal_confirmSetServiceState = function(service, state, childCount){
            $modalService.create({
                template: ["
"+ $translate.instant("choose_services_"+ state) +"

",
                    "
"+ $translate.instant(state +"_service_name", {name: ""+service.name+""}) +"
",
                    "
"+ $translate.instant(state +"_service_name_and_children", {name: ""+service.name+"", count: ""+childCount+""}) +"

"
                ].join(""),
                model: $scope,
                title: $translate.instant(state +"_service"),
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        classes: " ",
                        label: $translate.instant(state +"_service"),
                        action: function(){
                            // the arg here explicitly prevents child services
                            // from being started
                            $scope.setServiceState(service, state, true);
                            this.close();
                        }
                    },{
                        role: "ok",
                        label: $translate.instant(state +"_service_and_children", {count: childCount}),
                        action: function(){
                            $scope.setServiceState(service, state);
                            this.close();
                        }
                    }
                ]
            });
        };

        $scope.modal_deleteTemplate = function(templateID){
            $modalService.create({
                template: $translate.instant("template_remove_confirm") + ""+ templateID +"",
                model: $scope,
                title: "template_remove",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "template_remove",
                        classes: "btn-danger",
                        action: function(){
                            deleteTemplate(templateID)
                                .success(() => {
                                    $notification.create("Removed Template", templateID).success();
                                    this.close();
                                })
                                .error((data, status) => {
                                    $notification.create("Remove Template failed", data.Detail).error();
                                });
                        }
                    }
                ]
            });
        };

        /*
         * PRIVATE FUNCTIONS
         */
        function refreshTemplates(){
            resourcesFactory.getAppTemplates().success(function(templates) {
                $scope.templates.data = utils.mapToArr(templates);
            });
        }

        // poll for apps that are being deployed
        $scope.deployingServices = [];
        var lastPollResults = 0;
        function getDeploying(){
            resourcesFactory.getDeployingTemplates().success(function(data) {
                if(data){
                    $scope.deployingServices = data;
                }

                //if we have fewer results than last poll, we need to refresh our table
                //TODO - better checking for deploying apps
                if(lastPollResults > $scope.deployingServices.length){
                    servicesFactory.update();
                }
                lastPollResults = $scope.deployingServices.length;
            });
        }

        function removeService(service) {
            return resourcesFactory.removeService(service.id)
                .success(function(){
                    // NOTE: this is here because services are
                    // incrementally updated, which makes it impossible
                    // to determine if a service has been removed
                    // TODO - once the backend notifies on deleted
                    // services, this should be removed
                    // FIXME - should not modify servicesFactory's
                    // objects!
                    for(var i = 0; i < $scope.apps.length; i++){
                        // find the removed service and remove it
                        if($scope.apps[i].id === service.id){
                            $scope.apps.splice(i, 1);
                            return;
                        }
                    }
                });
        }

        function deleteTemplate(templateID){
            return resourcesFactory.removeAppTemplate(templateID)
                .success(refreshTemplates);
        }

        // init stuff for this controller
        function init(){
            if(utils.needsHostAlias($location.host())){
                resourcesFactory.getHostAlias().success(function(data) {
                    $scope.defaultHostAlias = data.hostalias;
                });
            }

            // configure tables
            // TODO - move table config to view/directive
            $scope.breadcrumbs = [
                { label: 'breadcrumb_deployed', itemClass: 'active' }
            ];

            $scope.servicesTable = {
                sorting: {
                    name: "asc"
                },
                getData: function(data, params) {
                    // use built-in angular filter
                    var orderedData = params.sorting() ?
                        $filter('orderBy')(data, params.orderBy()) :
                        data;

                    if(!orderedData){
                        return;
                    }

                    // mark any deploying services so they can be treated differently
                    orderedData.forEach(function(service){
                        service.deploying = false;
                        $scope.deployingServices.forEach(function(deploying){
                            if(service.model.DeploymentID === deploying.DeploymentID){
                                service.deploying = true;
                            }
                        });
                    });

                    return orderedData;
                },
                watchExpression: function(){
                    // TODO - check $scope.deployingServices as well
                    return servicesFactory.lastUpdate;
                }
            };

            $scope.templates = { data: [] };
            // table config
            $scope.templatesTable = {
                sorting: {
                    Name: "asc"
                }
            };

            // Get a list of templates
            refreshTemplates();

            // check for deploying apps
            getDeploying();

            // start polling for apps
            servicesFactory.activate();
            servicesFactory.update().then(function(){
                // locally bind top level service list
                $scope.apps = servicesFactory.serviceTree;

                // if only isvcs are deployed, and this is the first time
                // running deploy wizard, show the deploy apps modal
                if(!$cookies.get("autoRunWizardHasRun") && $scope.apps.length === 1){
                    $scope.modal_deployWizard();
                }
            });

            // deploy wizard needs updated pools
            poolsFactory.activate();

            //register polls
            resourcesFactory.registerPoll("deployingApps", getDeploying, 3000);
            resourcesFactory.registerPoll("templates", refreshTemplates, 5000);

            //unregister polls on destroy
            $scope.$on("$destroy", function(){
                resourcesFactory.unregisterAllPolls();
            });
        }

        // kick this controller off
        init();

        $scope.$on("$destroy", function(){
            resourcesFactory.unregisterAllPolls();
            servicesFactory.deactivate();
            poolsFactory.deactivate();
        });
    }]);
})();
<commit_msg>Build appropriate objects when aggregating public endpoints<commit_after>/* globals controlplane: true */

/* AppsController
 * Displays top level apps
 */
(function() {
    'use strict';

    controlplane.controller("AppsController", [
        "$scope", "$routeParams", "$location",
        "$notification", "resourcesFactory", "authService",
        "$modalService", "$translate", "$timeout",
        "$cookies", "servicesFactory", "miscUtils",
        "ngTableParams", "$filter", "poolsFactory",
    function($scope, $routeParams, $location,
    $notification, resourcesFactory, authService,
    $modalService, $translate, $timeout,
    $cookies, servicesFactory, utils,
    NgTableParams, $filter, poolsFactory){

        // Ensure logged in
        authService.checkLogin($scope);

        // alias hostname instead of using localhost or IP
        $scope.defaultHostAlias = $location.host();

        // redirect to specific service details
        $scope.routeToService = function(id) {
            resourcesFactory.routeToService(id);
        };

        // redirect to specific pool
        $scope.routeToPool = function(id) {
            resourcesFactory.routeToPool(id);
        };

        $scope.modal_deployWizard = function() {
            // the modal occasionally won't show on page load, so we use a timeout to get around that.
            $timeout(function(){
                $('#addApp').modal('show');

                // don't auto-show this wizard again
                // NOTE: $cookies can only deal with string values
                $cookies.put("autoRunWizardHasRun","true");
            });
        };

        $scope.modal_addTemplate = function() {
            $modalService.create({
                templateUrl: "add-template.html",
                model: $scope,
                title: "template_add",
                actions: [
                    {
                        role: "cancel",
                        action: function(){
                            $scope.newHost = {};
                            this.close();
                        }
                    },{
                        role: "ok",
                        label: "template_add",
                        action: function(){
                            if(this.validate()){
                                var data = new FormData();

                                $.each($("#new_template_filename")[0].files, function(key, value){
                                    data.append("tpl", value);
                                });

                                // disable ok button, and store the re-enable function
                                var enableSubmit = this.disableSubmitButton();

                                resourcesFactory.addAppTemplate(data)
                                    .success(function(data){
                                        $notification.create("Added template", data.Detail).success();
                                        refreshTemplates();
                                        this.close();
                                    }.bind(this))
                                    .error(function(data){
                                        this.createNotification("Adding template failed", data.Detail).error();
                                        enableSubmit();
                                    }.bind(this));
                            }
                        }
                    }
                ]
            });
        };

        // aggregate vhosts for a specified service, but
        // only if the service has changed since last request
        $scope.aggregateVHosts = utils.memoize(function(service) {
            var endPoints = [];

            service.model.Endpoints.forEach(endpoint => {
                if(endpoint.VHostList){
                    endpoint.VHostList.forEach(vHost => endPoints.push({
                        VHostName:     vHost.Name,
                        Enabled:       vHost.Enabled,
                        desiredState:  service.desiredState
                    }));
                }
                if(endpoint.PortList){
                    endpoint.PortList.forEach(port => endPoints.push({
                        PortAddress:  port.PortAddr,
                        Enabled:      port.Enabled,
                        desiredState: service.desiredState,
                        Protocol:     port.Protocol
                    }));
                }
            });

            return endPoints;
        }, function(service){
            return service.id + service.model.DatabaseVersion;
        });

        $scope.modal_removeService = function(service) {
            $modalService.create({
                template: $translate.instant("warning_remove_service"),
                model: $scope,
                title: "remove_service",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "remove_service",
                        classes: "btn-danger submit",
                        action: function(){
                            if(this.validate()){
                                this.disableSubmitButton();

                                removeService(service)
                                    .success(() => {
                                        $notification.create("Removed App", service.name).success();
                                        this.close();
                                    })
                                    .error((data, status) => {
                                        $notification.create("Remove App failed", data.Detail).error();
                                        this.close();
                                    });
                            }
                        }
                    }
                ]
            });
        };

        $scope.startService = function(service){
            $scope.modal_startStopService(service, "start");
        };
        $scope.stopService = function(service){
            $scope.modal_startStopService(service, "stop");
        };
        $scope.modal_startStopService = function(service, status) {
            var displayStatus = utils.capitalizeFirst(status);

            $modalService.create({
                template: $translate.instant("confirm_"+ status +"_app"),
                model: $scope,
                title: displayStatus +" Services",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: displayStatus +" Services",
                        action: function(){
                            service[status]();
                            this.close();
                        }
                    }
                ]
            });
        };

        // sets a service to start, stop or restart state
        $scope.setServiceState = function(service, state, skipChildren){
            service[state](skipChildren).error(function(data, status){
                $notification.create("Unable to " + state + " service", data.Detail).error();
            });
        };

        // filters to be used when counting how many descendent
        // services will be affected by a state change
        var serviceStateChangeFilters = {
            // only stopped services will be started
            "start": service => service.desiredState === 0,
            // only started services will be stopped
            "stop": service => service.desiredState === 1,
            // only started services will be restarted
            "restart": service => service.desiredState === 1
        };

        // clicks to a service's start, stop, or restart
        // button should first determine if the service has
        // children and ask the user to choose to start all
        // children or only the top service
        $scope.clickRunning = function(service, state){
            var filterFn = serviceStateChangeFilters[state];
            var childCount = utils.countTheKids(service, filterFn);

            // if the service has affected children, check if the user
            // wants to start just the service, or the service and children
            if(childCount > 0){
                $scope.modal_confirmSetServiceState(service, state, childCount);

            // if no children, just start the service
            } else {
                $scope.setServiceState(service, state);
            }
            servicesFactory.updateHealth();
        };

        // verifies if use wants to start parent service, or parent
        // and all children
        $scope.modal_confirmSetServiceState = function(service, state, childCount){
            $modalService.create({
                template: ["
"+ $translate.instant("choose_services_"+ state) +"

",
                    "
"+ $translate.instant(state +"_service_name", {name: ""+service.name+""}) +"
",
                    "
"+ $translate.instant(state +"_service_name_and_children", {name: ""+service.name+"", count: ""+childCount+""}) +"

"
                ].join(""),
                model: $scope,
                title: $translate.instant(state +"_service"),
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        classes: " ",
                        label: $translate.instant(state +"_service"),
                        action: function(){
                            // the arg here explicitly prevents child services
                            // from being started
                            $scope.setServiceState(service, state, true);
                            this.close();
                        }
                    },{
                        role: "ok",
                        label: $translate.instant(state +"_service_and_children", {count: childCount}),
                        action: function(){
                            $scope.setServiceState(service, state);
                            this.close();
                        }
                    }
                ]
            });
        };

        $scope.modal_deleteTemplate = function(templateID){
            $modalService.create({
                template: $translate.instant("template_remove_confirm") + ""+ templateID +"",
                model: $scope,
                title: "template_remove",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "template_remove",
                        classes: "btn-danger",
                        action: function(){
                            deleteTemplate(templateID)
                                .success(() => {
                                    $notification.create("Removed Template", templateID).success();
                                    this.close();
                                })
                                .error((data, status) => {
                                    $notification.create("Remove Template failed", data.Detail).error();
                                });
                        }
                    }
                ]
            });
        };

        /*
         * PRIVATE FUNCTIONS
         */
        function refreshTemplates(){
            resourcesFactory.getAppTemplates().success(function(templates) {
                $scope.templates.data = utils.mapToArr(templates);
            });
        }

        // poll for apps that are being deployed
        $scope.deployingServices = [];
        var lastPollResults = 0;
        function getDeploying(){
            resourcesFactory.getDeployingTemplates().success(function(data) {
                if(data){
                    $scope.deployingServices = data;
                }

                //if we have fewer results than last poll, we need to refresh our table
                //TODO - better checking for deploying apps
                if(lastPollResults > $scope.deployingServices.length){
                    servicesFactory.update();
                }
                lastPollResults = $scope.deployingServices.length;
            });
        }

        function removeService(service) {
            return resourcesFactory.removeService(service.id)
                .success(function(){
                    // NOTE: this is here because services are
                    // incrementally updated, which makes it impossible
                    // to determine if a service has been removed
                    // TODO - once the backend notifies on deleted
                    // services, this should be removed
                    // FIXME - should not modify servicesFactory's
                    // objects!
                    for(var i = 0; i < $scope.apps.length; i++){
                        // find the removed service and remove it
                        if($scope.apps[i].id === service.id){
                            $scope.apps.splice(i, 1);
                            return;
                        }
                    }
                });
        }

        function deleteTemplate(templateID){
            return resourcesFactory.removeAppTemplate(templateID)
                .success(refreshTemplates);
        }

        // init stuff for this controller
        function init(){
            if(utils.needsHostAlias($location.host())){
                resourcesFactory.getHostAlias().success(function(data) {
                    $scope.defaultHostAlias = data.hostalias;
                });
            }

            // configure tables
            // TODO - move table config to view/directive
            $scope.breadcrumbs = [
                { label: 'breadcrumb_deployed', itemClass: 'active' }
            ];

            $scope.servicesTable = {
                sorting: {
                    name: "asc"
                },
                getData: function(data, params) {
                    // use built-in angular filter
                    var orderedData = params.sorting() ?
                        $filter('orderBy')(data, params.orderBy()) :
                        data;

                    if(!orderedData){
                        return;
                    }

                    // mark any deploying services so they can be treated differently
                    orderedData.forEach(function(service){
                        service.deploying = false;
                        $scope.deployingServices.forEach(function(deploying){
                            if(service.model.DeploymentID === deploying.DeploymentID){
                                service.deploying = true;
                            }
                        });
                    });

                    return orderedData;
                },
                watchExpression: function(){
                    // TODO - check $scope.deployingServices as well
                    return servicesFactory.lastUpdate;
                }
            };

            $scope.templates = { data: [] };
            // table config
            $scope.templatesTable = {
                sorting: {
                    Name: "asc"
                }
            };

            // Get a list of templates
            refreshTemplates();

            // check for deploying apps
            getDeploying();

            // start polling for apps
            servicesFactory.activate();
            servicesFactory.update().then(function(){
                // locally bind top level service list
                $scope.apps = servicesFactory.serviceTree;

                // if only isvcs are deployed, and this is the first time
                // running deploy wizard, show the deploy apps modal
                if(!$cookies.get("autoRunWizardHasRun") && $scope.apps.length === 1){
                    $scope.modal_deployWizard();
                }
            });

            // deploy wizard needs updated pools
            poolsFactory.activate();

            //register polls
            resourcesFactory.registerPoll("deployingApps", getDeploying, 3000);
            resourcesFactory.registerPoll("templates", refreshTemplates, 5000);

            //unregister polls on destroy
            $scope.$on("$destroy", function(){
                resourcesFactory.unregisterAllPolls();
            });
        }

        // kick this controller off
        init();

        $scope.$on("$destroy", function(){
            resourcesFactory.unregisterAllPolls();
            servicesFactory.deactivate();
            poolsFactory.deactivate();
        });
    }]);
})();
<|endoftext|>


<commit_before>'use strict';

var resetUrl = 'http://localhost:8080/camunda/ensureCleanDb/default';
var request = require('request');
var CamSDK = require('camunda-bpm-sdk-js');
var camClient = new CamSDK.Client({
  mock: false,
  apiUri: 'http://localhost:8080/engine-rest'
});

var keys = Object.keys;

module.exports = function (operations, noReset, done) {
  var deferred = protractor.promise.defer();

  if (arguments.length === 1 && typeof operations === 'function') {
    // testHelper(function(){ console.log('setup complete'); });
    done = operations;
    noReset = false;
    operations = {};
  } else if (arguments.length === 1 && typeof operations === 'object') {
    // testHelper(setupObject);
    noReset = false;
    done = function(){};
  } else if (arguments.length === 2 && typeof noReset === 'function') {
    // testHelper(setupObject, function(err, result){ console.log('setup complete', result); });
    done = noReset;
    noReset = false;
  } else if (arguments.length === 2 && typeof noReset === 'boolean') {
    done = function(){};
  }

  var callbacks = [
    function (cb) {
      if (noReset) {
        return cb();
      }

      browser.manage().deleteAllCookies();

      request(resetUrl, function(err, res, body) {
        if (err) {
          return cb(err);
        }
        body = JSON.parse(body);
        cb(null, body);
      });
    }
  ];

  keys(operations).forEach(function (resourceName) {
    keys(operations[resourceName]).forEach(function (methodName) {
      operations[resourceName][methodName].forEach(function (data) {
        var resource = new camClient.resource(resourceName);
        callbacks.push(function (cb) {
          console.info('doing '+resourceName+'.'+methodName);//, data);
          resource[methodName](data, function(){
            cb();
          });
        });
      });
    });
  });

  CamSDK.utils.series(callbacks, function(err, result) {
    // now all process instances are started, we can start the jobs to create incidents
    if(err) {
      done(err, result);
      deferred.reject();
    }

    var resource = new camClient.resource('job');

    resource.list({}, function(err, result) {
      var jobTasks = [];
      for(var i = 0; i < result.length; i++) {
        jobTasks.push((function(i) {
          return function(cb) {
            resource.setRetries({
              id: result[i].id,
              retries: 0
            }, cb);
          };
        })(i));
      }
      CamSDK.utils.series(jobTasks, function(err, result) {
        done(err, result);
        deferred.fulfill();
      });
    });
  });

  return deferred.promise;
};
<commit_msg>chore(test-helper): new data structure for test setup<commit_after>'use strict';

var resetUrl = 'http://localhost:8080/camunda/ensureCleanDb/default';
var request = require('request');
var CamSDK = require('camunda-bpm-sdk-js');
var camClient = new CamSDK.Client({
  mock: false,
  apiUri: 'http://localhost:8080/engine-rest'
});

var keys = Object.keys;

module.exports = function (operations, noReset, done) {
  var deferred = protractor.promise.defer();

  if (arguments.length === 1 && typeof operations === 'function') {
    // testHelper(function(){ console.log('setup complete'); });
    done = operations;
    noReset = false;
    operations = {};
  } else if (arguments.length === 1 && typeof operations === 'object') {
    // testHelper(setupObject);
    noReset = false;
    done = function(){};
  } else if (arguments.length === 2 && typeof noReset === 'function') {
    // testHelper(setupObject, function(err, result){ console.log('setup complete', result); });
    done = noReset;
    noReset = false;
  } else if (arguments.length === 2 && typeof noReset === 'boolean') {
    done = function(){};
  }

  var callbacks = [
    function (cb) {
      if (noReset) {
        return cb();
      }

      browser.manage().deleteAllCookies();

      request(resetUrl, function(err, res, body) {
        if (err) {
          return cb(err);
        }
        body = JSON.parse(body);
        cb(null, body);
      });
    }
  ];

  operations.forEach(function(operation) {
    var resource = new camClient.resource(operation.module);
    callbacks.push(function (cb) {
      console.info('doing '+operation.module+'.'+operation.operation);//, operation.params);
      resource[operation.operation](operation.params, function(){
        cb();
      });
    });
  });

  CamSDK.utils.series(callbacks, function(err, result) {
    // now all process instances are started, we can start the jobs to create incidents
    // This method sets retries to 0 for all jobs that were created in the test setup
    if(err) {
      done(err, result);
      deferred.reject();
    }

    var resource = new camClient.resource('job');

    resource.list({}, function(err, result) {
      var jobTasks = [];
      for(var i = 0; i < result.length; i++) {
        jobTasks.push((function(i) {
          return function(cb) {
            resource.setRetries({
              id: result[i].id,
              retries: 0
            }, cb);
          };
        })(i));
      }
      CamSDK.utils.series(jobTasks, function(err, result) {
        done(err, result);
        deferred.fulfill();
      });
    });
  });

  return deferred.promise;
};
<|endoftext|>


<commit_before>import path from 'path'
import webpack from 'webpack'
import config from '../config'
import isomorphicWebpackConfig from '../webpack.isomorphic'
import ManifestPlugin from 'webpack-manifest-plugin'
import _ from 'lodash'
//
const {
	GA_ID,
	SENTRY_PUBLIC_DSN,
	NODE_ENV,
	APP_LANGUAGE,
	srcPath,
	distPath,
	publicPath
} = config

const definePluginArgs = {
	'process.env.GA_ID': JSON.stringify(GA_ID),
	'process.env.SENTRY_PUBLIC_DSN': JSON.stringify(SENTRY_PUBLIC_DSN),
	'process.env.BROWSER': JSON.stringify(true)
}

const baseBuild = {
	entry: {
		client: path.join(srcPath, './client')
	},
	output: {
		path: path.join(distPath, './client', APP_LANGUAGE),
		filename: '[name].js',
		chunkFilename: '[name].[chunkhash:6].js',
		publicPath
	},
	performance: {
		hints: NODE_ENV === 'production' ? 'warning' : false
	},
	resolve: {
		alias: isomorphicWebpackConfig.resolve.alias,
		modules: isomorphicWebpackConfig.resolve.modules,
		extensions: isomorphicWebpackConfig.resolve.extensions.concat(['.css', '.scss'])
	},
	module: {
		rules: isomorphicWebpackConfig.module.rules.concat([
			{
				test: /\.(ico|eot|otf|webp|ttf|woff|woff2)$/i,
				use: `file-loader?limit=100000&name=assets/[name].[hash:8].[ext]`
			},
			{
				test: /\.(jpe?g|png|gif|svg)$/,
				use: [
					{
						loader: 'url-loader',
						options: {
							limit: 8192,
							// path: '/images',
							name: 'images/[name].[hash:8].[ext]'
						}
					},
					'img-loader'
				]
			}
			// NOTE: LQIP loader doesn't work with file-loader and url-loader :(
			// `npm i --save-dev lqip-loader`
			// {
			//   test: /\.(jpe?g|png)$/i,
			//   enforce: 'pre',
			//   loaders: [
			//     {
			//       loader: 'lqip-loader',
			//       options: {
			//         path: '/images-lqip', // your image going to be in media folder in the output dir
			//         name: '[name]-lqip.[hash:8].[ext]' // you can use [hash].[ext] too if you wish
			//       }
			//     }
			//   ]
			// }
		])
	},
	plugins: isomorphicWebpackConfig.plugins.concat([
		new webpack.DefinePlugin(definePluginArgs),
		new ManifestPlugin({fileName: 'manifest.json', cache: config.manifest})
	]),
	target: 'web'
}

export default baseBuild
<commit_msg>feat(webpack_config/client/webpack.base.js): add more style extension to resolve<commit_after>import path from 'path'
import webpack from 'webpack'
import config from '../config'
import isomorphicWebpackConfig from '../webpack.isomorphic'
import ManifestPlugin from 'webpack-manifest-plugin'
import _ from 'lodash'
//
const {
	GA_ID,
	SENTRY_PUBLIC_DSN,
	NODE_ENV,
	APP_LANGUAGE,
	srcPath,
	distPath,
	publicPath
} = config

const definePluginArgs = {
	'process.env.GA_ID': JSON.stringify(GA_ID),
	'process.env.SENTRY_PUBLIC_DSN': JSON.stringify(SENTRY_PUBLIC_DSN),
	'process.env.BROWSER': JSON.stringify(true)
}

const baseBuild = {
	entry: {
		client: path.join(srcPath, './client')
	},
	output: {
		path: path.join(distPath, './client', APP_LANGUAGE),
		filename: '[name].js',
		chunkFilename: '[name].[chunkhash:6].js',
		publicPath
	},
	performance: {
		hints: NODE_ENV === 'production' ? 'warning' : false
	},
	resolve: {
		alias: isomorphicWebpackConfig.resolve.alias,
		modules: isomorphicWebpackConfig.resolve.modules,
		extensions: isomorphicWebpackConfig.resolve.extensions.concat(['.css', '.scss', '.sass'])
	},
	module: {
		rules: isomorphicWebpackConfig.module.rules.concat([
			{
				test: /\.(ico|eot|otf|webp|ttf|woff|woff2)$/i,
				use: `file-loader?limit=100000&name=assets/[name].[hash:8].[ext]`
			},
			{
				test: /\.(jpe?g|png|gif|svg)$/,
				use: [
					{
						loader: 'url-loader',
						options: {
							limit: 8192,
							// path: '/images',
							name: 'images/[name].[hash:8].[ext]'
						}
					},
					'img-loader'
				]
			}
			// NOTE: LQIP loader doesn't work with file-loader and url-loader :(
			// `npm i --save-dev lqip-loader`
			// {
			//   test: /\.(jpe?g|png)$/i,
			//   enforce: 'pre',
			//   loaders: [
			//     {
			//       loader: 'lqip-loader',
			//       options: {
			//         path: '/images-lqip', // your image going to be in media folder in the output dir
			//         name: '[name]-lqip.[hash:8].[ext]' // you can use [hash].[ext] too if you wish
			//       }
			//     }
			//   ]
			// }
		])
	},
	plugins: isomorphicWebpackConfig.plugins.concat([
		new webpack.DefinePlugin(definePluginArgs),
		new ManifestPlugin({fileName: 'manifest.json', cache: config.manifest})
	]),
	target: 'web'
}

export default baseBuild
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const versionCache = {};

const TRY_LIB_CONTENTS = `
declare type $JSXIntrinsics = {
  [string]: {
    instance: any,
    props: {
      children?: React$Node,
      [key: string]: any,
    },
  },
};
`.slice(1);

function get(url) {
  return new Promise(function(resolve, reject) {
    var req = new XMLHttpRequest();
    req.open('GET', url);
    req.onload = function() {
      if (req.status == 200) {
        resolve([url, req.response]);
      }
      else {
        reject(Error(req.statusText));
      }
    };
    req.onerror = function() {
      reject(Error("Network Error"));
    };
    req.send();
  });
}

export function load(version) {
  if (version in versionCache) {
    return Promise.resolve(versionCache[version]);
  }
  const majorVersion =
    version === 'master'
    ? Infinity
    : parseInt(version.split('.')[1], 10);
  const libs = majorVersion <= 54 ? [
    `/static/${version}/flowlib/core.js`,
    `/static/${version}/flowlib/bom.js`,
    `/static/${version}/flowlib/cssom.js`,
    `/static/${version}/flowlib/dom.js`,
    `/static/${version}/flowlib/node.js`,
    `/static/${version}/flowlib/react.js`,
    `/static/${version}/flowlib/streams.js`,
  ] : majorVersion <= 71 ? [
    `/static/${version}/flowlib/core.js`,
    `/static/${version}/flowlib/react.js`,
  ] : [
    `/static/${version}/flowlib/core.js`,
    `/static/${version}/flowlib/react.js`,
    `/static/${version}/flowlib/intl.js`,
  ];
  const flowLoader = new Promise(function(resolve) {
    requirejs([`/static/${version}/flow.js`], resolve);
  });
  return Promise.all([flowLoader, ...libs.map(get)])
    .then(function([_flow, ...contents]) {
      contents.forEach(function(nameAndContent) {
        self.flow.registerFile(nameAndContent[0], nameAndContent[1]);
      });
      self.flow.registerFile('try-lib.js', TRY_LIB_CONTENTS);
      if (majorVersion <= 125) {
        self.flow.setLibs([...libs, 'try-lib.js']);
      } else {
        self.flow.initBuiltins([...libs, 'try-lib.js']);
      }
      versionCache[version] = self.flow;
      return flow;
    })
    .catch(function(err) {
      throw err;
    });
}
<commit_msg>fix try-flow<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const versionCache = {};

const TRY_LIB_CONTENTS = `
declare type $JSXIntrinsics = {
  [string]: {
    instance: any,
    props: {
      children?: React$Node,
      [key: string]: any,
    },
  },
};
`.slice(1);

function get(url) {
  return new Promise(function(resolve, reject) {
    var req = new XMLHttpRequest();
    req.open('GET', url);
    req.onload = function() {
      if (req.status == 200) {
        resolve([url, req.response]);
      }
      else {
        reject(Error(req.statusText));
      }
    };
    req.onerror = function() {
      reject(Error("Network Error"));
    };
    req.send();
  });
}

export function load(version) {
  if (version in versionCache) {
    return Promise.resolve(versionCache[version]);
  }
  const majorVersion =
    version === 'master'
    ? Infinity
    : parseInt(version.split('.')[1], 10);
  const libs = majorVersion <= 54 ? [
    `/static/${version}/flowlib/core.js`,
    `/static/${version}/flowlib/bom.js`,
    `/static/${version}/flowlib/cssom.js`,
    `/static/${version}/flowlib/dom.js`,
    `/static/${version}/flowlib/node.js`,
    `/static/${version}/flowlib/react.js`,
    `/static/${version}/flowlib/streams.js`,
  ] : majorVersion <= 71 ? [
    `/static/${version}/flowlib/core.js`,
    `/static/${version}/flowlib/react.js`,
  ] : [
    `/static/${version}/flowlib/core.js`,
    `/static/${version}/flowlib/react.js`,
    `/static/${version}/flowlib/intl.js`,
  ];
  const flowLoader = new Promise(function(resolve) {
    requirejs([`/static/${version}/flow.js`], resolve);
  });
  return Promise.all([flowLoader, ...libs.map(get)])
    .then(function([_flow, ...contents]) {
      contents.forEach(function(nameAndContent) {
        self.flow.registerFile(nameAndContent[0], nameAndContent[1]);
      });
      self.flow.registerFile('try-lib.js', TRY_LIB_CONTENTS);
      if (majorVersion <= 126) {
        self.flow.setLibs([...libs, 'try-lib.js']);
      } else {
        self.flow.initBuiltins([...libs, 'try-lib.js']);
      }
      versionCache[version] = self.flow;
      return flow;
    })
    .catch(function(err) {
      throw err;
    });
}
<|endoftext|>


<commit_before>require('es6-promise/auto')
require('whatwg-fetch')
const Uppy = require('@uppy/core')
const DragDrop = require('@uppy/drag-drop')
const ProgressBar = require('@uppy/progress-bar')
const Tus = require('@uppy/tus')

// Function for displaying uploaded files
const onUploadSuccess = (elForUploadedFiles) =>
  (file, response) => {
    const url = response.uploadURL
    const fileName = file.name

    document.querySelector(elForUploadedFiles).innerHTML +=
      `<li><a href="${url}" target="_blank">${fileName}</a></li>`
  }

const uppyOne = new Uppy({ debug: true, autoProceed: true })
uppyOne
  .use(DragDrop, { target: '.example-one .for-DragDrop' })
  .use(Tus, { endpoint: 'https://master.tus.io/files/' })
  .use(ProgressBar, { target: '.example-one .for-ProgressBar', hideAfterFinish: false })
  .on('upload-success', onUploadSuccess('.example-one .uploaded-files ol'))

const uppyTwo = new Uppy({ debug: true, autoProceed: false })
uppyTwo
  .use(DragDrop, { target: '.example-two .for-DragDrop' })
  .use(Tus, { endpoint: 'https://master.tus.io/files/' })
  .use(ProgressBar, { target: '.example-two .for-ProgressBar', hideAfterFinish: false })
  .on('upload-success', onUploadSuccess('.example-two .uploaded-files ol'))

const uploadBtn = document.querySelector('.example-two button.upload-button')
uploadBtn.addEventListener('click', function () {
  uppyTwo.upload()
})
<commit_msg>website: also escape output in dragdrop example<commit_after>require('es6-promise/auto')
require('whatwg-fetch')
const Uppy = require('@uppy/core')
const DragDrop = require('@uppy/drag-drop')
const ProgressBar = require('@uppy/progress-bar')
const Tus = require('@uppy/tus')

// Function for displaying uploaded files
const onUploadSuccess = (elForUploadedFiles) =>
  (file, response) => {
    const url = response.uploadURL
    const fileName = file.name

    const li = document.createElement('li')
    const a = document.createElement('a')
    a.href = url
    a.target = '_blank'
    a.appendChild(document.createTextNode(fileName))
    li.appendChild(a)

    document.querySelector(elForUploadedFiles).appendChild(li)
  }

const uppyOne = new Uppy({ debug: true, autoProceed: true })
uppyOne
  .use(DragDrop, { target: '.example-one .for-DragDrop' })
  .use(Tus, { endpoint: 'https://master.tus.io/files/' })
  .use(ProgressBar, { target: '.example-one .for-ProgressBar', hideAfterFinish: false })
  .on('upload-success', onUploadSuccess('.example-one .uploaded-files ol'))

const uppyTwo = new Uppy({ debug: true, autoProceed: false })
uppyTwo
  .use(DragDrop, { target: '.example-two .for-DragDrop' })
  .use(Tus, { endpoint: 'https://master.tus.io/files/' })
  .use(ProgressBar, { target: '.example-two .for-ProgressBar', hideAfterFinish: false })
  .on('upload-success', onUploadSuccess('.example-two .uploaded-files ol'))

const uploadBtn = document.querySelector('.example-two button.upload-button')
uploadBtn.addEventListener('click', function () {
  uppyTwo.upload()
})
<|endoftext|>


<commit_before>/**
 * UI and function to add project
 */
'use strict';

require('css/add-project-plugin.css');
var $ = require('jquery');
var m = require('mithril');
var $osf = require('js/osfHelpers');

// XHR configuration to get apiserver connection to work
var xhrconfig = function (xhr) {
    xhr.withCredentials = true;
};

var AddProject = {
    controller : function (options) {
        var self = this;
        self.defaults = {
            buttonTemplate : m('.btn.btn-primary[data-toggle="modal"][data-target="#addProjectModal"]', 'Create new project'),
            parentID : null,
            title: 'Create new project',
            modalID : 'addProjectModal',
            stayCallback :null, // Function to call when user decides to stay after project creation
            categoryList : []
        };

        self.viewState = m.prop('form'); // 'processing', 'success', 'error';
        self.options = $.extend({}, self.defaults, options);
        self.nodeType = self.options.parentID === null ? 'project' : 'component';
        self.defaultCat = self.options.parentID === null ? 'project' : '';
        self.showMore = m.prop(false);
        self.newProjectName = m.prop('');
        self.newProjectDesc = m.prop('');
        self.newProjectCategory = m.prop(self.defaultCat);
        self.newProjectTemplate = m.prop('');
        self.goToProjectLink = m.prop('');
        self.saveResult = m.prop({});
        self.errorMessageType = m.prop('unknown');
        self.errorMessage = {
            'unknown' : 'There was an unknown error. Please try again later.'
        };
        self.userProjects =  m.prop([]); // User nodes

        // Validation
        self.isValid = m.prop(false);
        self.checkValid = function _checkValid() {
            self.isValid(self.newProjectName().trim().length > 0);
        };

        self.mapTemplates = function() {
            self.userProjects([]);
            options.templatesFetcher._flat.map(function(node){
                self.userProjects().push({title: node.attributes.title, id: node.id});
            });
            return self.userProjects();
        };

        options.templatesFetcher.on(['page', 'done'], self.mapTemplates);

        self.add = function _add () {
            var url;
            var data;
            self.viewState('processing');
            if(self.options.parentID) {
                url = $osf.apiV2Url('nodes/' + self.options.parentID + '/children/', { query : {}});
            } else {
                url = $osf.apiV2Url('nodes/', { query : {}});
            }
            data = {
                    'data' : {
                        'type': 'nodes',
                        'attributes': {
                            'title': self.newProjectName(),
                            'category': self.newProjectCategory(),
                            'description' : self.newProjectDesc()
                        }
                    }
                };

            if (self.newProjectTemplate()) {
                data.data.attributes.template_from = self.newProjectTemplate();
            }

            var success = function _success (result) {
                self.viewState('success');
                self.goToProjectLink(result.data.links.html);
                self.saveResult(result);
            };
            var error = function _error (result) {
                self.viewState('error');
            };
            m.request({method : 'POST', url : url, data : data, config : xhrconfig})
                .then(success, error);
            self.newProjectName('');
            self.isValid(false);
        };
        self.reset = function _reset(){
            self.newProjectName('');
            self.viewState('form');
            self.newProjectDesc('');
            self.newProjectCategory(self.defaultCat);
            $('.modal').modal('hide');
            self.isValid(false);
        };
    },
    view : function (ctrl, options) {
        var templates = {
            form : m('.modal-content', [
                m('.modal-header', [
                    m('button.close[data-dismiss="modal"][aria-label="Close"]',{ onclick : function() {
                        ctrl.reset();
                        $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-close-add-project-modal');
                    }}, [
                        m('span[aria-hidden="true"]','×')
                    ]),
                    m('h3.modal-title', ctrl.options.title)
                ]),
                m('.modal-body', [
                    m('.text-left', [
                        m('.form-group.m-v-sm', [
                            m('label[for="projectName].f-w-lg.text-bigger', 'Title'),
                            m('input[type="text"].form-control', {
                                onkeyup: function(ev){
                                    if (ev.which === 13) {
                                         ctrl.add();
                                    }
                                    ctrl.newProjectName($(this).val());
                                    ctrl.checkValid();
                                },
                                onchange: function() {
                                    $osf.trackClick(options.trackingCategory, options.trackingAction, 'type-project-name');
                                },
                                value : ctrl.newProjectName(),
                                placeholder : 'Enter ' + ctrl.nodeType + ' title'
                            })
                        ]),
                        m('.text-muted.pointer', { onclick : function(){
                            ctrl.showMore(!ctrl.showMore());
                            $osf.trackClick(options.trackingCategory, options.trackingAction, 'show-more-or-less');
                        }},[
                            ctrl.showMore() ? m('i.fa.fa-caret-down', { style: 'width: 10px;'}) : m('i.fa.fa-caret-right', { style: 'width: 10px;'}),
                            ' More'
                        ]),
                        ctrl.showMore() ? [
                            m('.form-group.m-v-sm', [
                                m('label[for="projectDesc].f-w-lg.text-bigger', 'Description'),
                                m('input[type="text"].form-control.noresize', {
                                    onkeyup: function (ev){
                                        ctrl.newProjectDesc($(this).val());
                                    },
                                    onchange: function() {
                                        $osf.trackClick(options.trackingCategory, options.trackingAction, 'type-project-description');
                                    },
                                    value : ctrl.newProjectDesc(),
                                    placeholder : 'Enter ' + ctrl.nodeType + ' description'
                                })
                            ]),
                            ctrl.options.parentID !== null ? [
                                m('.f-w-lg.text-bigger','Category'),
                                m('.category-radio.p-h-md', [
                                    ctrl.options.categoryList.map(function(cat){
                                        return m('.radio', m('label', [  m('input', {
                                            type: 'radio',
                                            name: 'projectCategory',
                                            value: cat.value,
                                            checked: ctrl.newProjectCategory() === cat.value,
                                            onchange : function(event) {
                                                ctrl.newProjectCategory(cat.value);
                                                $osf.trackClick(options.trackingCategory, options.trackingAction, 'select-project-category');
                                            }
                                        }), cat.display_name|| m('i.text-muted', '(Empty category)') ]));

                                    })
                                ])
                            ] : '',
                             ctrl.options.parentID === null ? m('.form-group.m-v-md', [
                                m('label[for="projectTemplate].f-w-lg.text-bigger', 'Template (optional)'),
                                m('p.f-w-xs.help-text', 'Start typing to search your projects. Selecting project as template will duplicate its ' +
                                    'structure in the new project without importing the content of that project.'),
                                m.component(Select2Template, {
                                    value: ctrl.newProjectTemplate,
                                    trackingCategory: options.trackingCategory,
                                    trackingAction: options.trackingAction,
                                    mapTemplates: ctrl.userProjects
                                })
                            ]) : ''
                        ] : ''
                    ])
                ]),
                m('.modal-footer', [
                    m('button[type="button"].btn.btn-default[data-dismiss="modal"]', { onclick : function(){
                        ctrl.reset();
                        $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-cancel-button');
                    }},  'Cancel'),
                    ctrl.isValid() ? m('button[type="button"].btn.btn-success', { onclick : function(){
                        ctrl.add();
                        $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-create-button');
                    }},'Create') : m('button[type="button"].btn.btn-success[disabled]','Create')
                ])
            ]),
            processing : m('.modal-content',
                m('.modal-content',
                    m('.modal-header', [
                        m('button.close[data-dismiss="modal"][aria-label="Close"]',{ onclick : ctrl.reset}, [
                            m('span[aria-hidden="true"]','×')
                        ])
                    ]),
                    m('.modal-body.text-left', [
                            m('.add-project-processing', 'Saving your ' + ctrl.nodeType + '...')
                        ]
                    )
                )
            ),
            success : m('.modal-content', [
                m('.modal-content',
                    m('.modal-body.text-left', [
                            m('button.close[data-dismiss="modal"][aria-label="Close"]',{ onclick : function() {
                                ctrl.reset();
                                $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-close-success-modal');
                            }}, [
                                m('span[aria-hidden="true"]','×')
                            ]),
                            m('h4.add-project-success.text-success', 'New ' + ctrl.nodeType + ' created successfully!')
                        ]
                    ),
                    m('.modal-footer', [
                        m('button[type="button"].btn.btn-default[data-dismiss="modal"]', {
                            onclick : function() {
                                ctrl.reset();
                                ctrl.options.stayCallback.call(ctrl); // results are at ctrl.saveResult
                                $osf.trackClick(options.trackingCategory, options.trackingAction, 'keep-working-here');
                            }
                        },  'Keep working here'),
                        m('a.btn.btn-success', {
                            href : ctrl.goToProjectLink(),
                            onclick: function(){
                            $osf.trackClick(options.trackingCategory, options.trackingAction, 'go-to-new-project');
                            }
                        },'Go to new ' + ctrl.nodeType + '')
                    ])
                )
            ]),
            error : m('.modal-content', [
                m('.modal-content',
                    m('.modal-body.text-left', [
                            m('button.close[data-dismiss="modal"][aria-label="Close"]',{ onclick : function() {
                                ctrl.reset();
                                $osf.trackClick(options.trackingCategory, options.trackingAction, 'close-couldn\'t-create-your-project');
                                }}, [
                                m('span[aria-hidden="true"]','×')
                            ]),
                            m('h4.add-project-error.text-danger', 'Couldn\'t create your ' + ctrl.nodeType + ''),
                            m('p', ctrl.errorMessage[ctrl.errorMessageType()])
                        ]
                    ),
                    m('.modal-footer', [
                        m('button[type="button"].btn.btn-default[data-dismiss="modal"]', {onclick: function() {
                            $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-OK-couldn\'t-create-your-project');
                        }},  'OK')
                    ])
                )
            ])
        };

        return  m('span', [
            ctrl.options.buttonTemplate,
            m('#' + ctrl.options.modalID + '.modal.fade[tabindex=-1][role="dialog"][aria-labelledby="addProject"][aria-hidden="true"]',
                m('.modal-dialog.text-left',
                    templates[ctrl.viewState()]
                )
            )
        ]);
    }
};

var Select2Template = {
    view: function(ctrl, options) {
        return m('select', {config: Select2Template.config(options), onchange: function(){
            $osf.trackClick(options.trackingCategory, options.trackingAction, 'select-project-template');
        }}, [
            m('option', {value: ''}, ''),
            options.mapTemplates().map(function(node) {
                var args = {value: node.id};
                return m('option', args, node.title);
            })
        ]);
    },
    /**Select2 config factory - adapted from https://lhorie.github.io/mithril/integration.html **/
    config: function(ctrl) {
        return function(element, isInitialized) {
            var $el = $(element);
            if (!isInitialized) {
                $el.select2({placeholder: 'Select a project to use as a template', allowClear: true, width: '100%'}).on('change', function(e) {
                    var id = $el.select2('val');
                    m.startComputation();
                    //Set the value to the selected option
                    ctrl.mapTemplates().map(function(node){
                        if(node.id === id) {
                            ctrl.value(node.id);
                        }
                    });
                    m.endComputation();
                });
            }
        };
    }
};

module.exports = AddProject;
<commit_msg>Add check for whether templatesFetcher exists in addproject options<commit_after>/**
 * UI and function to add project
 */
'use strict';

require('css/add-project-plugin.css');
var $ = require('jquery');
var m = require('mithril');
var $osf = require('js/osfHelpers');

// XHR configuration to get apiserver connection to work
var xhrconfig = function (xhr) {
    xhr.withCredentials = true;
};

var AddProject = {
    controller : function (options) {
        var self = this;
        self.defaults = {
            buttonTemplate : m('.btn.btn-primary[data-toggle="modal"][data-target="#addProjectModal"]', 'Create new project'),
            parentID : null,
            title: 'Create new project',
            modalID : 'addProjectModal',
            stayCallback :null, // Function to call when user decides to stay after project creation
            categoryList : []
        };

        self.viewState = m.prop('form'); // 'processing', 'success', 'error';
        self.options = $.extend({}, self.defaults, options);
        self.nodeType = self.options.parentID === null ? 'project' : 'component';
        self.defaultCat = self.options.parentID === null ? 'project' : '';
        self.showMore = m.prop(false);
        self.newProjectName = m.prop('');
        self.newProjectDesc = m.prop('');
        self.newProjectCategory = m.prop(self.defaultCat);
        self.newProjectTemplate = m.prop('');
        self.goToProjectLink = m.prop('');
        self.saveResult = m.prop({});
        self.errorMessageType = m.prop('unknown');
        self.errorMessage = {
            'unknown' : 'There was an unknown error. Please try again later.'
        };
        self.userProjects =  m.prop([]); // User nodes

        // Validation
        self.isValid = m.prop(false);
        self.checkValid = function _checkValid() {
            self.isValid(self.newProjectName().trim().length > 0);
        };

        self.mapTemplates = function() {
            self.userProjects([]);
            options.templatesFetcher._flat.map(function(node){
                self.userProjects().push({title: node.attributes.title, id: node.id});
            });
            return self.userProjects();
        };

        if(options.templatesFetcher){
            options.templatesFetcher.on(['page', 'done'], self.mapTemplates);
        }

        self.add = function _add () {
            var url;
            var data;
            self.viewState('processing');
            if(self.options.parentID) {
                url = $osf.apiV2Url('nodes/' + self.options.parentID + '/children/', { query : {}});
            } else {
                url = $osf.apiV2Url('nodes/', { query : {}});
            }
            data = {
                    'data' : {
                        'type': 'nodes',
                        'attributes': {
                            'title': self.newProjectName(),
                            'category': self.newProjectCategory(),
                            'description' : self.newProjectDesc()
                        }
                    }
                };

            if (self.newProjectTemplate()) {
                data.data.attributes.template_from = self.newProjectTemplate();
            }

            var success = function _success (result) {
                self.viewState('success');
                self.goToProjectLink(result.data.links.html);
                self.saveResult(result);
            };
            var error = function _error (result) {
                self.viewState('error');
            };
            m.request({method : 'POST', url : url, data : data, config : xhrconfig})
                .then(success, error);
            self.newProjectName('');
            self.isValid(false);
        };
        self.reset = function _reset(){
            self.newProjectName('');
            self.viewState('form');
            self.newProjectDesc('');
            self.newProjectCategory(self.defaultCat);
            $('.modal').modal('hide');
            self.isValid(false);
        };
    },
    view : function (ctrl, options) {
        var templates = {
            form : m('.modal-content', [
                m('.modal-header', [
                    m('button.close[data-dismiss="modal"][aria-label="Close"]',{ onclick : function() {
                        ctrl.reset();
                        $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-close-add-project-modal');
                    }}, [
                        m('span[aria-hidden="true"]','×')
                    ]),
                    m('h3.modal-title', ctrl.options.title)
                ]),
                m('.modal-body', [
                    m('.text-left', [
                        m('.form-group.m-v-sm', [
                            m('label[for="projectName].f-w-lg.text-bigger', 'Title'),
                            m('input[type="text"].form-control', {
                                onkeyup: function(ev){
                                    if (ev.which === 13) {
                                         ctrl.add();
                                    }
                                    ctrl.newProjectName($(this).val());
                                    ctrl.checkValid();
                                },
                                onchange: function() {
                                    $osf.trackClick(options.trackingCategory, options.trackingAction, 'type-project-name');
                                },
                                value : ctrl.newProjectName(),
                                placeholder : 'Enter ' + ctrl.nodeType + ' title'
                            })
                        ]),
                        m('.text-muted.pointer', { onclick : function(){
                            ctrl.showMore(!ctrl.showMore());
                            $osf.trackClick(options.trackingCategory, options.trackingAction, 'show-more-or-less');
                        }},[
                            ctrl.showMore() ? m('i.fa.fa-caret-down', { style: 'width: 10px;'}) : m('i.fa.fa-caret-right', { style: 'width: 10px;'}),
                            ' More'
                        ]),
                        ctrl.showMore() ? [
                            m('.form-group.m-v-sm', [
                                m('label[for="projectDesc].f-w-lg.text-bigger', 'Description'),
                                m('input[type="text"].form-control.noresize', {
                                    onkeyup: function (ev){
                                        ctrl.newProjectDesc($(this).val());
                                    },
                                    onchange: function() {
                                        $osf.trackClick(options.trackingCategory, options.trackingAction, 'type-project-description');
                                    },
                                    value : ctrl.newProjectDesc(),
                                    placeholder : 'Enter ' + ctrl.nodeType + ' description'
                                })
                            ]),
                            ctrl.options.parentID !== null ? [
                                m('.f-w-lg.text-bigger','Category'),
                                m('.category-radio.p-h-md', [
                                    ctrl.options.categoryList.map(function(cat){
                                        return m('.radio', m('label', [  m('input', {
                                            type: 'radio',
                                            name: 'projectCategory',
                                            value: cat.value,
                                            checked: ctrl.newProjectCategory() === cat.value,
                                            onchange : function(event) {
                                                ctrl.newProjectCategory(cat.value);
                                                $osf.trackClick(options.trackingCategory, options.trackingAction, 'select-project-category');
                                            }
                                        }), cat.display_name|| m('i.text-muted', '(Empty category)') ]));

                                    })
                                ])
                            ] : '',
                             ctrl.options.parentID === null ? m('.form-group.m-v-md', [
                                m('label[for="projectTemplate].f-w-lg.text-bigger', 'Template (optional)'),
                                m('p.f-w-xs.help-text', 'Start typing to search your projects. Selecting project as template will duplicate its ' +
                                    'structure in the new project without importing the content of that project.'),
                                m.component(Select2Template, {
                                    value: ctrl.newProjectTemplate,
                                    trackingCategory: options.trackingCategory,
                                    trackingAction: options.trackingAction,
                                    mapTemplates: ctrl.userProjects
                                })
                            ]) : ''
                        ] : ''
                    ])
                ]),
                m('.modal-footer', [
                    m('button[type="button"].btn.btn-default[data-dismiss="modal"]', { onclick : function(){
                        ctrl.reset();
                        $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-cancel-button');
                    }},  'Cancel'),
                    ctrl.isValid() ? m('button[type="button"].btn.btn-success', { onclick : function(){
                        ctrl.add();
                        $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-create-button');
                    }},'Create') : m('button[type="button"].btn.btn-success[disabled]','Create')
                ])
            ]),
            processing : m('.modal-content',
                m('.modal-content',
                    m('.modal-header', [
                        m('button.close[data-dismiss="modal"][aria-label="Close"]',{ onclick : ctrl.reset}, [
                            m('span[aria-hidden="true"]','×')
                        ])
                    ]),
                    m('.modal-body.text-left', [
                            m('.add-project-processing', 'Saving your ' + ctrl.nodeType + '...')
                        ]
                    )
                )
            ),
            success : m('.modal-content', [
                m('.modal-content',
                    m('.modal-body.text-left', [
                            m('button.close[data-dismiss="modal"][aria-label="Close"]',{ onclick : function() {
                                ctrl.reset();
                                $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-close-success-modal');
                            }}, [
                                m('span[aria-hidden="true"]','×')
                            ]),
                            m('h4.add-project-success.text-success', 'New ' + ctrl.nodeType + ' created successfully!')
                        ]
                    ),
                    m('.modal-footer', [
                        m('button[type="button"].btn.btn-default[data-dismiss="modal"]', {
                            onclick : function() {
                                ctrl.reset();
                                ctrl.options.stayCallback.call(ctrl); // results are at ctrl.saveResult
                                $osf.trackClick(options.trackingCategory, options.trackingAction, 'keep-working-here');
                            }
                        },  'Keep working here'),
                        m('a.btn.btn-success', {
                            href : ctrl.goToProjectLink(),
                            onclick: function(){
                            $osf.trackClick(options.trackingCategory, options.trackingAction, 'go-to-new-project');
                            }
                        },'Go to new ' + ctrl.nodeType + '')
                    ])
                )
            ]),
            error : m('.modal-content', [
                m('.modal-content',
                    m('.modal-body.text-left', [
                            m('button.close[data-dismiss="modal"][aria-label="Close"]',{ onclick : function() {
                                ctrl.reset();
                                $osf.trackClick(options.trackingCategory, options.trackingAction, 'close-couldn\'t-create-your-project');
                                }}, [
                                m('span[aria-hidden="true"]','×')
                            ]),
                            m('h4.add-project-error.text-danger', 'Couldn\'t create your ' + ctrl.nodeType + ''),
                            m('p', ctrl.errorMessage[ctrl.errorMessageType()])
                        ]
                    ),
                    m('.modal-footer', [
                        m('button[type="button"].btn.btn-default[data-dismiss="modal"]', {onclick: function() {
                            $osf.trackClick(options.trackingCategory, options.trackingAction, 'click-OK-couldn\'t-create-your-project');
                        }},  'OK')
                    ])
                )
            ])
        };

        return  m('span', [
            ctrl.options.buttonTemplate,
            m('#' + ctrl.options.modalID + '.modal.fade[tabindex=-1][role="dialog"][aria-labelledby="addProject"][aria-hidden="true"]',
                m('.modal-dialog.text-left',
                    templates[ctrl.viewState()]
                )
            )
        ]);
    }
};

var Select2Template = {
    view: function(ctrl, options) {
        return m('select', {config: Select2Template.config(options), onchange: function(){
            $osf.trackClick(options.trackingCategory, options.trackingAction, 'select-project-template');
        }}, [
            m('option', {value: ''}, ''),
            options.mapTemplates().map(function(node) {
                var args = {value: node.id};
                return m('option', args, node.title);
            })
        ]);
    },
    /**Select2 config factory - adapted from https://lhorie.github.io/mithril/integration.html **/
    config: function(ctrl) {
        return function(element, isInitialized) {
            var $el = $(element);
            if (!isInitialized) {
                $el.select2({placeholder: 'Select a project to use as a template', allowClear: true, width: '100%'}).on('change', function(e) {
                    var id = $el.select2('val');
                    m.startComputation();
                    //Set the value to the selected option
                    ctrl.mapTemplates().map(function(node){
                        if(node.id === id) {
                            ctrl.value(node.id);
                        }
                    });
                    m.endComputation();
                });
            }
        };
    }
};

module.exports = AddProject;
<|endoftext|>


<commit_before>'use strict';

var $ = require('jquery');
var ko = require('knockout');
var bootbox = require('bootbox');
var $osf = require('./osfHelpers');
var clipboard = require('./clipboard');
require('js/osfToggleHeight');

require('bootstrap-editable');

var ctx = window.contextVars;
//var LINK_CUTOFF = 2;

var setupEditable = function(elm, data) {
    var $elm = $(elm);
    var $editable = $elm.find('.link-name');
    $editable.editable({
        type: 'text',
        url: ctx.node.urls.api + 'private_link/edit/',
        placement: 'bottom',
        ajaxOptions: {
            type: 'PUT',
            dataType: 'json',
            contentType: 'application/json'
        },
        send: 'always',
        title: 'Edit Link Name',
        params: function(params){
            // Send JSON data
            params.pk = data.id;
            return JSON.stringify(params);
        },
        success: function(response, value) {
            data.name(value);
        },
        error: $osf.handleEditableError
    });
};

function LinkViewModel(data, $root) {

    var self = this;

    self.$root = $root;
    $.extend(self, data);

    self.name = ko.observable(data.name);
    self.readonly = 'readonly';
    self.selectText = 'this.setSelectionRange(0, this.value.length);';

    self.dateCreated = new $osf.FormattableDate(data.date_created);
    self.linkUrl = ko.computed(function() {
        return self.$root.nodeUrl() + '?view_only=' + data.key;
    });
    self.nodesList = ko.observableArray(data.nodes);
    self.removeLink = 'Remove this link';

    self.anonymousDisplay = ko.computed(function() {
        var openTag = '';
        var closeTag = '';
        var text;
        if (data.anonymous) {
            text = 'Yes';
            // Strikethrough if node is public
            if ($root.nodeIsPublic) {
                openTag = '';
                closeTag = '';
            }
        } else{
            text = 'No';
        }
        return [openTag, text, closeTag].join('');
    });

}

function ViewModel(url, nodeIsPublic) {
    var self = this;
    self.nodeIsPublic = nodeIsPublic || false;
    self.url = url;
    self.privateLinks = ko.observableArray();
    self.nodeUrl = ko.observable(null);

    function onFetchSuccess(response) {
        var node = response.node;
        self.privateLinks(ko.utils.arrayMap(node.private_links, function(link) {
            return new LinkViewModel(link, self);
        }));
        self.nodeUrl(node.absolute_url);
    }

    function onFetchError() {
        $osf.growl('Could not retrieve view-only links.', 'Please refresh the page or ' +
                'contact support@cos.io if the ' +
                'problem persists.');
    }

    function fetch() {
        $.ajax({
            url: url,
            type: 'GET',
            dataType: 'json'
        }).done(
            onFetchSuccess
        ).fail(
            onFetchError
        );
    }

    fetch();

    self.removeLink = function(data) {
        var dataToSend = {
            'private_link_id': data.id
        };
        bootbox.confirm({
            title: 'Remove view-only link?',
            message: 'Are you sure you want to remove this view-only link?',
            callback: function(result) {
                if(result) {
                    $.ajax({
                    type: 'delete',
                    url: ctx.node.urls.api + 'private_link/',
                    contentType: 'application/json',
                    dataType: 'json',
                    data: JSON.stringify(dataToSend)
                }).done(function() {
                    self.privateLinks.remove(data);
                }).fail(function() {
                    $osf.growl('Error:','Failed to delete the private link.');
                });
                }
            },
            buttons:{
                confirm:{
                    label:'Remove',
                    className:'btn-danger'
                }
            }
        });
    };

    self.afterRenderLink = function(elm, data) {
        var $tr = $(elm);
        var target = $tr.find('.copy-button');
        clipboard(target[0]);
        $tr.find('.remove-private-link').tooltip();
        setupEditable(elm, data);
        $('.private-link-list').osfToggleHeight({height: 50});
    };

}

function PrivateLinkTable (selector, url, nodeIsPublic) {
    var self = this;
    self.viewModel = new ViewModel(url, nodeIsPublic);
    $osf.applyBindings(self.viewModel, selector);

}
module.exports = PrivateLinkTable;
<commit_msg>remove commented declaration [skip ci]<commit_after>'use strict';

var $ = require('jquery');
var ko = require('knockout');
var bootbox = require('bootbox');
var $osf = require('./osfHelpers');
var clipboard = require('./clipboard');
require('js/osfToggleHeight');

require('bootstrap-editable');

var ctx = window.contextVars;

var setupEditable = function(elm, data) {
    var $elm = $(elm);
    var $editable = $elm.find('.link-name');
    $editable.editable({
        type: 'text',
        url: ctx.node.urls.api + 'private_link/edit/',
        placement: 'bottom',
        ajaxOptions: {
            type: 'PUT',
            dataType: 'json',
            contentType: 'application/json'
        },
        send: 'always',
        title: 'Edit Link Name',
        params: function(params){
            // Send JSON data
            params.pk = data.id;
            return JSON.stringify(params);
        },
        success: function(response, value) {
            data.name(value);
        },
        error: $osf.handleEditableError
    });
};

function LinkViewModel(data, $root) {

    var self = this;

    self.$root = $root;
    $.extend(self, data);

    self.name = ko.observable(data.name);
    self.readonly = 'readonly';
    self.selectText = 'this.setSelectionRange(0, this.value.length);';

    self.dateCreated = new $osf.FormattableDate(data.date_created);
    self.linkUrl = ko.computed(function() {
        return self.$root.nodeUrl() + '?view_only=' + data.key;
    });
    self.nodesList = ko.observableArray(data.nodes);
    self.removeLink = 'Remove this link';

    self.anonymousDisplay = ko.computed(function() {
        var openTag = '';
        var closeTag = '';
        var text;
        if (data.anonymous) {
            text = 'Yes';
            // Strikethrough if node is public
            if ($root.nodeIsPublic) {
                openTag = '';
                closeTag = '';
            }
        } else{
            text = 'No';
        }
        return [openTag, text, closeTag].join('');
    });

}

function ViewModel(url, nodeIsPublic) {
    var self = this;
    self.nodeIsPublic = nodeIsPublic || false;
    self.url = url;
    self.privateLinks = ko.observableArray();
    self.nodeUrl = ko.observable(null);

    function onFetchSuccess(response) {
        var node = response.node;
        self.privateLinks(ko.utils.arrayMap(node.private_links, function(link) {
            return new LinkViewModel(link, self);
        }));
        self.nodeUrl(node.absolute_url);
    }

    function onFetchError() {
        $osf.growl('Could not retrieve view-only links.', 'Please refresh the page or ' +
                'contact support@cos.io if the ' +
                'problem persists.');
    }

    function fetch() {
        $.ajax({
            url: url,
            type: 'GET',
            dataType: 'json'
        }).done(
            onFetchSuccess
        ).fail(
            onFetchError
        );
    }

    fetch();

    self.removeLink = function(data) {
        var dataToSend = {
            'private_link_id': data.id
        };
        bootbox.confirm({
            title: 'Remove view-only link?',
            message: 'Are you sure you want to remove this view-only link?',
            callback: function(result) {
                if(result) {
                    $.ajax({
                    type: 'delete',
                    url: ctx.node.urls.api + 'private_link/',
                    contentType: 'application/json',
                    dataType: 'json',
                    data: JSON.stringify(dataToSend)
                }).done(function() {
                    self.privateLinks.remove(data);
                }).fail(function() {
                    $osf.growl('Error:','Failed to delete the private link.');
                });
                }
            },
            buttons:{
                confirm:{
                    label:'Remove',
                    className:'btn-danger'
                }
            }
        });
    };

    self.afterRenderLink = function(elm, data) {
        var $tr = $(elm);
        var target = $tr.find('.copy-button');
        clipboard(target[0]);
        $tr.find('.remove-private-link').tooltip();
        setupEditable(elm, data);
        $('.private-link-list').osfToggleHeight({height: 50});
    };

}

function PrivateLinkTable (selector, url, nodeIsPublic) {
    var self = this;
    self.viewModel = new ViewModel(url, nodeIsPublic);
    $osf.applyBindings(self.viewModel, selector);

}
module.exports = PrivateLinkTable;
<|endoftext|>