<commit_before>'use strict';

// Intrinsic modules.
var url = require('url');
var fs = require('fs');
var path = require('path');

// NPM modules
var Promise = require('bluebird');
var _ = require('lodash');

// "Constants"
var PLUGIN_NAME = 'kalabox-plugin-pantheon';

module.exports = function(kbox) {

  kbox.whenApp(function(app) {

    // Grab the terminus client
    var Client = require('./client.js');
    var terminus = new Client(kbox, app);
    // Grab the git client
    var Git = require('../../../node_modules/kalabox-plugin-git/lib/git.js');
    var git = new Git(kbox, app);
    // Grab the rsync client
    var Rsync =
      require('../../../node_modules/kalabox-plugin-rsync/lib/rsync.js');
    var rsync = new Rsync(kbox, app);

    // Grab some kalabox modules
    var events = kbox.core.events;
    var engine = kbox.engine;

    /*
     * Pull down our sites code
     */
    var pullCode = function(site, env) {

      // the pantheon site UUID
      var siteid = null;
      var repo = null;

      // Check to see what our connection mode is
      return terminus.getConnectionMode(site, env)
        // Set the connection mode to git if needed
        // and then try again
        .then(function(connectionMode) {
          var modeSplit = connectionMode.split(':');
          var mode = modeSplit[1].trim().toLowerCase();
          if (mode !== 'git') {
            // @todo: actually test this part
            return terminus.setConnectionMode(site, env)
              .then(function(data) {
                // this is going to balk because same CID
                pullCode(site, env);
              });
          }
        })
        // Grab the sites UUID from teh machinename
        .then(function() {
          return terminus.getUUID(site)
            .then(function(uuid) {
              siteid = uuid.trim();
            });
        })
        // Generate our code repo URL and CUT THAT MEAT!
        // errr PULL THAT CODE!
        .then(function() {
          // @todo: better way to generate this?
          // @todo: is 'dev' the only thing that
          var build = {
            protocol: 'ssh',
            slashes: true,
            auth: ['codeserver', 'dev', siteid].join('.'),
            hostname: ['codeserver', 'dev', siteid, 'drush', 'in'].join('.'),
            port: 2222,
            pathname: ['~', 'repository.git'].join('/')
          };
          repo = url.format(build);
          // @todo: check for code dir before we decide to pull or clone
          return git.cmd(['clone', repo, './'], []);
        });
    };

    /*
     * Pull down our sites database
     */
    var pullDB = function(site, env) {
      // Get the cid of this apps database
      // @todo: this looks gross
      var dbID = _.result(_.find(app.components, function(cmp) {
        console.log(cmp);
        return cmp.name === 'db';
      }), 'containerId');

      // Set this later to store the location to the DB file
      var dbFile = null;

      // @todo: put this in dot notation
      var defaults = {
        PublishAllPorts: true,
        Binds: [app.rootBind + ':/src:rw']
      };
      // Start up the DB
      return engine.start(dbID, defaults)
      // Grab the DB
        .then(function() {
          return terminus.getDB(site, env);
        })
        .then(function(data) {
          var downloadSplit = data.split('Downloaded');
          dbFile = downloadSplit[1].trim();
          // Perform a container run.
          var payload = [
            'import-mysql',
            dbFile
          ];
          return engine.queryData(dbID, payload);
        })
        .then(function(data) {
          // @todo: use real logger
          console.log(data);
          // @todo: would be great to get terminus to be able to
          // overwrite files so we dont have to do this
          //return terminus.removeDB(dbFile);
        })
        // Stop the DB
        .then(function() {
          return engine.stop(dbID);
        });
    };

    /*
     * Pull down our sites database
     */
    var pullFiles = function(site, env) {
      // the pantheon site UUID
      var siteid = null;
      // Get our UUID
      // @todo: cache this
      return terminus.getUUID(site)
        .then(function(uuid) {
          siteid = uuid.trim();
        })
        // Generate our code repo URL and CUT THAT MEAT!
        // errr PULL THAT CODE!
        .then(function() {
          // @todo: lots of cleanup here
          var envSite = [env, siteid].join('.');
          var fileBox = envSite + '@appserver.' + envSite + '.drush.in:files/';
          var fileMount = 'sites/default/files/';
          return rsync.cmd([
            '-rlvz',
            '--size-only',
            '--ipv4',
            '--progress',
            '-e \'ssh -p 2222\'',
            fileBox,
            fileMount
          ]);
        });
    };

    // Events
    // Install the terminus container for our things and also
    // pull down a site or create a new site
    events.on('post-install', function(app, done) {
      // Make sure we install the terminus container for this app
      var opts = {
        name: 'terminus',
        srcRoot: path.resolve(__dirname, '..', '..', '..'),
      };
      // Our pantheon config for later on
      var pantheonConf = app.config.pluginConf['kalabox-plugin-pantheon'];

      // Install the terminus container and then do install things
      return engine.build(opts)
        .then(function() {
          return terminus.getSiteAliases();
        })
        .then(function() {
          return pullCode(pantheonConf.site, pantheonConf.env);
        })
        .then(function() {
          return pullDB(pantheonConf.site, pantheonConf.env);
        })
        .then(function() {
          return pullFiles(pantheonConf.site, pantheonConf.env);
        })
        .nodeify(done);
    });

  });
};
<commit_msg>#257: complete rsync support<commit_after>'use strict';

// Intrinsic modules.
var url = require('url');
var fs = require('fs');
var path = require('path');

// NPM modules
var Promise = require('bluebird');
var _ = require('lodash');

// "Constants"
var PLUGIN_NAME = 'kalabox-plugin-pantheon';

module.exports = function(kbox) {

  kbox.whenApp(function(app) {

    // Grab the terminus client
    var Client = require('./client.js');
    var terminus = new Client(kbox, app);
    // Grab the git client
    var Git = require('../../../node_modules/kalabox-plugin-git/lib/git.js');
    var git = new Git(kbox, app);
    // Grab the rsync client
    var Rsync =
      require('../../../node_modules/kalabox-plugin-rsync/lib/rsync.js');
    var rsync = new Rsync(kbox, app);

    // Grab some kalabox modules
    var events = kbox.core.events;
    var engine = kbox.engine;

    /*
     * Pull down our sites code
     */
    var pullCode = function(site, env) {

      // the pantheon site UUID
      var siteid = null;
      var repo = null;

      // Check to see what our connection mode is
      return terminus.getConnectionMode(site, env)
        // Set the connection mode to git if needed
        // and then try again
        .then(function(connectionMode) {
          var modeSplit = connectionMode.split(':');
          var mode = modeSplit[1].trim().toLowerCase();
          if (mode !== 'git') {
            // @todo: actually test this part
            return terminus.setConnectionMode(site, env)
              .then(function(data) {
                // this is going to balk because same CID
                pullCode(site, env);
              });
          }
        })
        // Grab the sites UUID from teh machinename
        .then(function() {
          return terminus.getUUID(site)
            .then(function(uuid) {
              siteid = uuid.trim();
            });
        })
        // Generate our code repo URL and CUT THAT MEAT!
        // errr PULL THAT CODE!
        .then(function() {
          // @todo: better way to generate this?
          // @todo: is 'dev' the only thing that
          var build = {
            protocol: 'ssh',
            slashes: true,
            auth: ['codeserver', 'dev', siteid].join('.'),
            hostname: ['codeserver', 'dev', siteid, 'drush', 'in'].join('.'),
            port: 2222,
            pathname: ['~', 'repository.git'].join('/')
          };
          repo = url.format(build);
          // @todo: check for code dir before we decide to pull or clone
          return git.cmd(['clone', repo, './'], []);
        });
    };

    /*
     * Pull down our sites database
     */
    var pullDB = function(site, env) {
      // Get the cid of this apps database
      // @todo: this looks gross
      var dbID = _.result(_.find(app.components, function(cmp) {
        console.log(cmp);
        return cmp.name === 'db';
      }), 'containerId');

      // Set this later to store the location to the DB file
      var dbFile = null;

      // @todo: put this in dot notation
      var defaults = {
        PublishAllPorts: true,
        Binds: [app.rootBind + ':/src:rw']
      };
      // Start up the DB
      return engine.start(dbID, defaults)
      // Grab the DB
        .then(function() {
          return terminus.getDB(site, env);
        })
        .then(function(data) {
          var downloadSplit = data.split('Downloaded');
          dbFile = downloadSplit[1].trim();
          // Perform a container run.
          var payload = [
            'import-mysql',
            dbFile
          ];
          return engine.queryData(dbID, payload);
        })
        .then(function(data) {
          // @todo: use real logger
          console.log(data);
          // @todo: would be great to get terminus to be able to
          // overwrite files so we dont have to do this
          //return terminus.removeDB(dbFile);
        })
        // Stop the DB
        .then(function() {
          return engine.stop(dbID);
        });
    };

    /*
     * Pull down our sites database
     */
    var pullFiles = function(site, env) {
      // the pantheon site UUID
      var siteid = null;
      // Get our UUID
      // @todo: cache this
      return terminus.getUUID(site)
        .then(function(uuid) {
          siteid = uuid.trim();
        })
        // Generate our code repo URL and CUT THAT MEAT!
        // errr PULL THAT CODE!
        .then(function() {
          // @todo: lots of cleanup here
          // /kbox rsync -rlvz --size-only --ipv4 --progress -e 'ssh -p 2222'
          var envSite = [env, siteid].join('.');
          var fileBox = envSite + '@appserver.' + envSite + '.drush.in:files/';
          var fileMount = 'sites/default/files';
          var opts = '-rlvz --size-only --ipv4 --progress -e \'ssh -p 2222\'';

          return rsync.cmd([opts, fileBox, fileMount], true);
        });
    };

    // Events
    // Install the terminus container for our things and also
    // pull down a site or create a new site
    events.on('post-install', function(app, done) {
      // Make sure we install the terminus container for this app
      var opts = {
        name: 'terminus',
        srcRoot: path.resolve(__dirname, '..', '..', '..'),
      };
      // Our pantheon config for later on
      var pantheonConf = app.config.pluginConf['kalabox-plugin-pantheon'];

      // Install the terminus container and then do install things
      return engine.build(opts)
        .then(function() {
          return terminus.getSiteAliases();
        })
        .then(function() {
          return pullCode(pantheonConf.site, pantheonConf.env);
        })
        .then(function() {
          return pullDB(pantheonConf.site, pantheonConf.env);
        })
        .then(function() {
          return pullFiles(pantheonConf.site, pantheonConf.env);
        })
        .nodeify(done);
    });

  });
};
<|endoftext|>


<commit_before>// @ngInject
export default function authCallbackRoutes($stateProvider) {
  $stateProvider
    .state('home.login_completed', {
      url: '/login_completed/:token/:method/',
      template: '<auth-login-completed></auth-login-completed>',
      data: {
        anonymous: true,
        bodyClass: 'old',
      }
    })

    .state('home.login_failed', {
      url: '/login_failed/',
      template: '<auth-login-failed></auth-login-failed>',
      data: {
        anonymous: true,
        bodyClass: 'old',
      }
    })

    .state('home.logout_completed', {
      url: '/logout_completed/',
      template: '<auth-logout-completed></auth-logout-completed>',
      data: {
        anonymous: true,
        bodyClass: 'old',
      }
    })

    .state('home.logout_failed', {
      url: '/logout_failed/',
      template: '<auth-logout-failed></auth-logout-failed>',
      data: {
        anonymous: true,
        bodyClass: 'old',
      }
    });
}
<commit_msg>Prevent redirect to profile page on logout and failed login.<commit_after>// @ngInject
export default function authCallbackRoutes($stateProvider) {
  $stateProvider
    .state('home.login_completed', {
      url: '/login_completed/:token/:method/',
      template: '<auth-login-completed></auth-login-completed>',
      data: {
        anonymous: true,
        bodyClass: 'old',
      }
    })

    .state('home.login_failed', {
      url: '/login_failed/',
      template: '<auth-login-failed></auth-login-failed>',
      data: {
        bodyClass: 'old',
      }
    })

    .state('home.logout_completed', {
      url: '/logout_completed/',
      template: '<auth-logout-completed></auth-logout-completed>',
      data: {
        bodyClass: 'old',
      }
    })

    .state('home.logout_failed', {
      url: '/logout_failed/',
      template: '<auth-logout-failed></auth-logout-failed>',
      data: {
        bodyClass: 'old',
      }
    });
}
<|endoftext|>


<commit_before>'use strict';

(function() {
    angular.module('ncsaas')
    .controller('CustomerListController', [
      'customersService',
      'baseControllerListClass',
      'usersService',
      'ENTITYLISTFIELDTYPES',
      '$rootScope',
      '$state',
      'ENV',
      'ncUtils',
      'currentStateService',
      CustomerListController
    ]);

  function CustomerListController(
    customersService,
    baseControllerListClass,
    usersService,
    ENTITYLISTFIELDTYPES,
    $rootScope,
    $state,
    ENV,
    ncUtils,
    currentStateService) {
    var controllerScope = this;
    var CustomerController = baseControllerListClass.extend({
      init:function() {
        this.service = customersService;
        this.controllerScope = controllerScope;
        this._super();
        this.searchFieldName = 'name';
        this.currentUser = usersService.currentUser;
        var vm = this;
        this.actionButtonsListItems = [
          {
            title: 'Remove',
            icon: 'fa-trash',
            clickFunction: this.remove.bind(controllerScope),

            isDisabled: function(customer) {
              return !this.isOwnerOrStaff(customer) || customer.projects.length != 0;
            }.bind(controllerScope),

            tooltip: function(customer) {
              if (!this.isOwnerOrStaff(customer)) {
                return 'Only owner or staff can remove organization';
              }
              if (customer.projects.length != 0) {
               return 'Organization has projects. Please remove them first';
              }
            }.bind(controllerScope),
          }
        ];
        this.entityOptions = {
          entityData: {
            noDataText: 'You have no organizations yet.',
            noMatchesText: 'No organizations found matching filter.',
            title: 'Organizations',
            createLink: 'organizations.create',
            createLinkText: 'Add organization',
            rowTemplateUrl: 'views/customer/row.html'
          },
          list: [
            {
              type: ENTITYLISTFIELDTYPES.awesomeIcon,
              iconClass: 'fa-star-o',
              show: vm.isOwnerOrStaff.bind(controllerScope),
              name: 'Owner',
              className: 'customer-owner-icon',
              notSortable: true
            },
            {
              name: 'Name',
              propertyName: 'name',
              type: ENTITYLISTFIELDTYPES.name,
              link: 'organizations.details({uuid: entity.uuid})',
              showForMobile: ENTITYLISTFIELDTYPES.showForMobile
            }
          ]
        };
        if (ENV.featuresVisible || ENV.toBeFeatures.indexOf('plans') == -1) {
          this.entityOptions.list.push({
            name: 'Plan',
            propertyName: 'plan_name',
            type: ENTITYLISTFIELDTYPES.noType,
            emptyText: 'No plan',
            notSortable: true
          });
        }
      },
      isOwnerOrStaff: function(customer) {
        if (this.currentUserIsStaff()) return true;
        for (var i = 0; i < customer.owners.length; i++) {
          if (this.currentUser.uuid === customer.owners[i].uuid) {
            return true;
          }
        }
      },
      currentUserIsStaff: function() {
        return this.currentUser.is_staff;
      },
      removeInstance: function(model) {
        currentStateService.setCustomer(null);
        return model.$delete().catch(function() {
          currentStateService.setCustomer(model);
        });
      },
      afterInstanceRemove: function(intance) {
        $rootScope.$broadcast('refreshCustomerList', {model: intance, remove: true});
        this._super(intance);
      },
      afterGetList: function() {
        if (ENV.featuresVisible || ENV.toBeFeatures.indexOf('plans') == -1) {
          for (var i = 0; i < this.list.length; i++) {
            var item = this.list[i];
            if (item.plan) {
              item.plan_name = item.plan.name;
            }
          }
        }
        this.getQuotas();
        this._super();
      },
      getQuotas: function() {
        for (var i = 0; i < this.list.length; i++) {
          var item = this.list[i];
          item.quotas_usage = ncUtils.getQuotaUsage(item.quotas);
        }
      }
    });

    controllerScope.__proto__ = new CustomerController();

  }

  angular.module('ncsaas')
    .controller('CustomerDetailUpdateController', [
      'baseControllerDetailUpdateClass',
      'customersService',
      'customerImageService',
      'usersService',
      'ENV',
      '$stateParams',
      '$rootScope',
      '$scope',
      '$interval',
      '$timeout',
      '$q',
      'joinService',
      'ncUtilsFlash',
      'eventsService',
      'resourcesCountService',
      'currentStateService',
      '$state',
      CustomerDetailUpdateController
    ]);

  function CustomerDetailUpdateController(
    baseControllerDetailUpdateClass,
    customersService,
    customerImageService,
    usersService,
    ENV,
    $stateParams,
    $rootScope,
    $scope,
    $interval,
    $timeout,
    $q,
    joinService,
    ncUtilsFlash,
    eventsService,
    resourcesCountService,
    currentStateService,
    $state
    ) {
    var controllerScope = this,
      timer,
      CustomerController = baseControllerDetailUpdateClass.extend({
      files: [],
      canEdit: false,
      showChart: false,

      init: function() {
        this.service = customersService;
        this.controllerScope = controllerScope;
        this.setSignalHandler('refreshCounts', this.setCounters.bind(controllerScope));
        this._super();
        this.detailsState = 'organizations.details';
        this.currentUser = usersService.currentUser;
        this.detailsViewOptions = {
          title_plural: 'organizations',
          hasLogo: false,
          listState: 'organizations.list',
          aboutFields: [
            {
              fieldKey: 'name',
              isEditable: true,
              className: 'name',
              emptyText: 'Add name'
            },
            {
              fieldKey: 'contact_details',
              isEditable: true,
              className: 'details',
              emptyText: 'Add contact details'
            },
            {
              fieldKey: 'registration_code',
              isEditable: true,
              className: 'details',
              emptyText: 'Add registration code'
            }
          ],
          tabs: [
            {
              title: 'Sizing',
              key: 'sizing',
              viewName: 'tabSizing',
              icon: 'calculator',
              count: -1
            },
            {
              title: 'Events',
              key: 'eventlog',
              viewName: 'tabEventlog',
              icon: 'event',
              count: -1
            },
            {
              title: 'Alerts',
              key: 'alerts',
              viewName: 'tabAlerts',
              countFieldKey: 'alerts',
              icon: 'alerts'
            },
            {
              title: 'VMs',
              key: ENV.resourcesTypes.vms,
              viewName: 'tabResources',
              countFieldKey: 'vms',
              icon: 'resource'
            },
            {
              title: 'Private clouds',
              key: ENV.resourcesTypes.privateClouds,
              viewName: 'tabPrivateClouds',
              countFieldKey: 'private_clouds',
              icon: 'cloud'
            },
            {
              title: 'Applications',
              key: ENV.resourcesTypes.applications,
              viewName: 'tabApplications',
              countFieldKey: 'apps',
              icon: 'application'
            },
            {
              title: 'Projects',
              key: 'projects',
              viewName: 'tabProjects',
              countFieldKey: 'projects',
              icon: 'project'
            },
            {
              title: 'Providers',
              key: 'providers',
              viewName: 'tabServices',
              countFieldKey: 'services',
              icon: 'service'
            },
            {
              title: 'Billing',
              key: 'billing',
              viewName: 'tabBilling',
              hideSearch: true,
              icon: 'invoice',
              count: -1
            },
            {
              title: 'Team',
              key: 'team',
              viewName: 'tabTeam',
              hideSearch: false,
              countFieldKey: 'users',
              icon: 'customer'
            },
            {
              title: 'Manage',
              key: 'delete',
              viewName: 'tabDelete',
              hideSearch: true,
              icon: 'wrench'
            }
          ]
        };
        this.detailsViewOptions.activeTab = this.getActiveTab();
      },
      isOwnerOrStaff: function(customer) {
        if (this.currentUser.is_staff) return true;
        for (var i = 0; i < customer.owners.length; i++) {
          if (this.currentUser.uuid === customer.owners[i].uuid) {
            return true;
          }
        }
      },

      loadAll: function() {
        var deferred = $q.defer();
        this.getModel().then(function(customer) {
          $rootScope.$broadcast('adjustCurrentCustomer', customer);
          $timeout(function() {
            deferred.resolve();
          });
        });
        return deferred.promise;
      },

      afterActivate: function() {
        controllerScope.canEdit = controllerScope.isOwnerOrStaff(controllerScope.model);
        controllerScope.updateImageUrl();
        var vm = this;
        vm.setCounters();
        timer = $interval(vm.setCounters.bind(vm), ENV.countersTimerInterval * 1000);
        $scope.$on('$destroy', function() {
          $interval.cancel(timer);
        });
      },

      getCounters: function() {
        return currentStateService.getCustomer().then(function(customer) {
          if (!customer) {
            return $q.reject();
          }
          var query = angular.extend(
              {UUID: customer.uuid},
              joinService.defaultFilter,
              eventsService.defaultFilter
          );
          return customersService.getCounters(query);
        });
      },

      getCountersError: function() {
        $interval.cancel(timer);
        customersService.getPersonalOrFirstCustomer().then(function(customer) {
          $state.go('organizations.details', {uuid: customer.uuid});
        });
      },

      // XXX: Avatar is temporarily disabled via detailsViewOptions.hasLogo = false
      // That's why following functions are not used: updateImageUrl, uploadImage, deleteImage
      updateImageUrl: function() {
        controllerScope.imageUrl = controllerScope.model.image || ENV.defaultCustomerIcon;
      },

      uploadImage: function() {
        customerImageService.create({
          uuid: controllerScope.model.uuid,
          file: controllerScope.files[0]
        }).then(function(response) {
          controllerScope.files = [];
          controllerScope.model.image = response.data.image;
          controllerScope.updateImageUrl();
          ncUtilsFlash.success('Organization image is uploaded');
        }, function(response) {
          ncUtilsFlash.warning('Unable to upload image');
        });
      },

      deleteImage: function() {
        controllerScope.model.image = null;
        customerImageService.delete({
          uuid: controllerScope.model.uuid
        }).then(function(response) {
          ncUtilsFlash.success('Organization image is deleted');
          controllerScope.model.image = null;
          controllerScope.updateImageUrl();
        }, function(response) {
          ncUtilsFlash.warning('Unable to delete image');
        });
      },
      editInPlace: function(data, fieldName) {
        var d = $q.defer();
        if (data || fieldName != 'name') {
          return this._super(data, fieldName);
        }
        d.resolve('This field is required.');
        return d.promise;
      },
      afterUpdate: function() {
        ncUtilsFlash.success('Organization {} is updated'.replace('{}', controllerScope.model.name));
        $rootScope.$broadcast('refreshCustomerList', {model: this.model, update: true});
      }
    });

    controllerScope.__proto__ = new CustomerController();
  }

})();

(function() {
  angular.module('ncsaas')
    .controller('CustomerAddController',
    ['customersService', 'baseControllerAddClass', '$rootScope', CustomerAddController]);

  function CustomerAddController(customersService, baseControllerAddClass, $rootScope) {
    var controllerScope = this;
    var Controller = baseControllerAddClass.extend({
      init: function() {
        this.service = customersService;
        this.controllerScope = controllerScope;
        this._super();
        this.listState = 'organizations.list';
        this.detailsState = 'organizations.details';
        this.redirectToDetailsPage = true;

        var vm = this;
        customersService.loadCountries().then(function(countryChoices) {
          vm.countryChoices = countryChoices;
        });
      },
      beforeSave: function() {
        if (this.instance.vat_code) {
          this.instance.is_company = true;
        } else {
          this.instance.is_company = false;
        }
      },
      afterSave: function() {
        this._super();
        $rootScope.$broadcast('refreshCustomerList', {model: this.instance, new: true, current: true});
      }
    });

    controllerScope.__proto__ = new Controller();
  }
})();
<commit_msg>Use ternary operator (SAAS-1340)<commit_after>'use strict';

(function() {
    angular.module('ncsaas')
    .controller('CustomerListController', [
      'customersService',
      'baseControllerListClass',
      'usersService',
      'ENTITYLISTFIELDTYPES',
      '$rootScope',
      '$state',
      'ENV',
      'ncUtils',
      'currentStateService',
      CustomerListController
    ]);

  function CustomerListController(
    customersService,
    baseControllerListClass,
    usersService,
    ENTITYLISTFIELDTYPES,
    $rootScope,
    $state,
    ENV,
    ncUtils,
    currentStateService) {
    var controllerScope = this;
    var CustomerController = baseControllerListClass.extend({
      init:function() {
        this.service = customersService;
        this.controllerScope = controllerScope;
        this._super();
        this.searchFieldName = 'name';
        this.currentUser = usersService.currentUser;
        var vm = this;
        this.actionButtonsListItems = [
          {
            title: 'Remove',
            icon: 'fa-trash',
            clickFunction: this.remove.bind(controllerScope),

            isDisabled: function(customer) {
              return !this.isOwnerOrStaff(customer) || customer.projects.length != 0;
            }.bind(controllerScope),

            tooltip: function(customer) {
              if (!this.isOwnerOrStaff(customer)) {
                return 'Only owner or staff can remove organization';
              }
              if (customer.projects.length != 0) {
               return 'Organization has projects. Please remove them first';
              }
            }.bind(controllerScope),
          }
        ];
        this.entityOptions = {
          entityData: {
            noDataText: 'You have no organizations yet.',
            noMatchesText: 'No organizations found matching filter.',
            title: 'Organizations',
            createLink: 'organizations.create',
            createLinkText: 'Add organization',
            rowTemplateUrl: 'views/customer/row.html'
          },
          list: [
            {
              type: ENTITYLISTFIELDTYPES.awesomeIcon,
              iconClass: 'fa-star-o',
              show: vm.isOwnerOrStaff.bind(controllerScope),
              name: 'Owner',
              className: 'customer-owner-icon',
              notSortable: true
            },
            {
              name: 'Name',
              propertyName: 'name',
              type: ENTITYLISTFIELDTYPES.name,
              link: 'organizations.details({uuid: entity.uuid})',
              showForMobile: ENTITYLISTFIELDTYPES.showForMobile
            }
          ]
        };
        if (ENV.featuresVisible || ENV.toBeFeatures.indexOf('plans') == -1) {
          this.entityOptions.list.push({
            name: 'Plan',
            propertyName: 'plan_name',
            type: ENTITYLISTFIELDTYPES.noType,
            emptyText: 'No plan',
            notSortable: true
          });
        }
      },
      isOwnerOrStaff: function(customer) {
        if (this.currentUserIsStaff()) return true;
        for (var i = 0; i < customer.owners.length; i++) {
          if (this.currentUser.uuid === customer.owners[i].uuid) {
            return true;
          }
        }
      },
      currentUserIsStaff: function() {
        return this.currentUser.is_staff;
      },
      removeInstance: function(model) {
        currentStateService.setCustomer(null);
        return model.$delete().catch(function() {
          currentStateService.setCustomer(model);
        });
      },
      afterInstanceRemove: function(intance) {
        $rootScope.$broadcast('refreshCustomerList', {model: intance, remove: true});
        this._super(intance);
      },
      afterGetList: function() {
        if (ENV.featuresVisible || ENV.toBeFeatures.indexOf('plans') == -1) {
          for (var i = 0; i < this.list.length; i++) {
            var item = this.list[i];
            if (item.plan) {
              item.plan_name = item.plan.name;
            }
          }
        }
        this.getQuotas();
        this._super();
      },
      getQuotas: function() {
        for (var i = 0; i < this.list.length; i++) {
          var item = this.list[i];
          item.quotas_usage = ncUtils.getQuotaUsage(item.quotas);
        }
      }
    });

    controllerScope.__proto__ = new CustomerController();

  }

  angular.module('ncsaas')
    .controller('CustomerDetailUpdateController', [
      'baseControllerDetailUpdateClass',
      'customersService',
      'customerImageService',
      'usersService',
      'ENV',
      '$stateParams',
      '$rootScope',
      '$scope',
      '$interval',
      '$timeout',
      '$q',
      'joinService',
      'ncUtilsFlash',
      'eventsService',
      'resourcesCountService',
      'currentStateService',
      '$state',
      CustomerDetailUpdateController
    ]);

  function CustomerDetailUpdateController(
    baseControllerDetailUpdateClass,
    customersService,
    customerImageService,
    usersService,
    ENV,
    $stateParams,
    $rootScope,
    $scope,
    $interval,
    $timeout,
    $q,
    joinService,
    ncUtilsFlash,
    eventsService,
    resourcesCountService,
    currentStateService,
    $state
    ) {
    var controllerScope = this,
      timer,
      CustomerController = baseControllerDetailUpdateClass.extend({
      files: [],
      canEdit: false,
      showChart: false,

      init: function() {
        this.service = customersService;
        this.controllerScope = controllerScope;
        this.setSignalHandler('refreshCounts', this.setCounters.bind(controllerScope));
        this._super();
        this.detailsState = 'organizations.details';
        this.currentUser = usersService.currentUser;
        this.detailsViewOptions = {
          title_plural: 'organizations',
          hasLogo: false,
          listState: 'organizations.list',
          aboutFields: [
            {
              fieldKey: 'name',
              isEditable: true,
              className: 'name',
              emptyText: 'Add name'
            },
            {
              fieldKey: 'contact_details',
              isEditable: true,
              className: 'details',
              emptyText: 'Add contact details'
            },
            {
              fieldKey: 'registration_code',
              isEditable: true,
              className: 'details',
              emptyText: 'Add registration code'
            }
          ],
          tabs: [
            {
              title: 'Sizing',
              key: 'sizing',
              viewName: 'tabSizing',
              icon: 'calculator',
              count: -1
            },
            {
              title: 'Events',
              key: 'eventlog',
              viewName: 'tabEventlog',
              icon: 'event',
              count: -1
            },
            {
              title: 'Alerts',
              key: 'alerts',
              viewName: 'tabAlerts',
              countFieldKey: 'alerts',
              icon: 'alerts'
            },
            {
              title: 'VMs',
              key: ENV.resourcesTypes.vms,
              viewName: 'tabResources',
              countFieldKey: 'vms',
              icon: 'resource'
            },
            {
              title: 'Private clouds',
              key: ENV.resourcesTypes.privateClouds,
              viewName: 'tabPrivateClouds',
              countFieldKey: 'private_clouds',
              icon: 'cloud'
            },
            {
              title: 'Applications',
              key: ENV.resourcesTypes.applications,
              viewName: 'tabApplications',
              countFieldKey: 'apps',
              icon: 'application'
            },
            {
              title: 'Projects',
              key: 'projects',
              viewName: 'tabProjects',
              countFieldKey: 'projects',
              icon: 'project'
            },
            {
              title: 'Providers',
              key: 'providers',
              viewName: 'tabServices',
              countFieldKey: 'services',
              icon: 'service'
            },
            {
              title: 'Billing',
              key: 'billing',
              viewName: 'tabBilling',
              hideSearch: true,
              icon: 'invoice',
              count: -1
            },
            {
              title: 'Team',
              key: 'team',
              viewName: 'tabTeam',
              hideSearch: false,
              countFieldKey: 'users',
              icon: 'customer'
            },
            {
              title: 'Manage',
              key: 'delete',
              viewName: 'tabDelete',
              hideSearch: true,
              icon: 'wrench'
            }
          ]
        };
        this.detailsViewOptions.activeTab = this.getActiveTab();
      },
      isOwnerOrStaff: function(customer) {
        if (this.currentUser.is_staff) return true;
        for (var i = 0; i < customer.owners.length; i++) {
          if (this.currentUser.uuid === customer.owners[i].uuid) {
            return true;
          }
        }
      },

      loadAll: function() {
        var deferred = $q.defer();
        this.getModel().then(function(customer) {
          $rootScope.$broadcast('adjustCurrentCustomer', customer);
          $timeout(function() {
            deferred.resolve();
          });
        });
        return deferred.promise;
      },

      afterActivate: function() {
        controllerScope.canEdit = controllerScope.isOwnerOrStaff(controllerScope.model);
        controllerScope.updateImageUrl();
        var vm = this;
        vm.setCounters();
        timer = $interval(vm.setCounters.bind(vm), ENV.countersTimerInterval * 1000);
        $scope.$on('$destroy', function() {
          $interval.cancel(timer);
        });
      },

      getCounters: function() {
        return currentStateService.getCustomer().then(function(customer) {
          if (!customer) {
            return $q.reject();
          }
          var query = angular.extend(
              {UUID: customer.uuid},
              joinService.defaultFilter,
              eventsService.defaultFilter
          );
          return customersService.getCounters(query);
        });
      },

      getCountersError: function() {
        $interval.cancel(timer);
        customersService.getPersonalOrFirstCustomer().then(function(customer) {
          $state.go('organizations.details', {uuid: customer.uuid});
        });
      },

      // XXX: Avatar is temporarily disabled via detailsViewOptions.hasLogo = false
      // That's why following functions are not used: updateImageUrl, uploadImage, deleteImage
      updateImageUrl: function() {
        controllerScope.imageUrl = controllerScope.model.image || ENV.defaultCustomerIcon;
      },

      uploadImage: function() {
        customerImageService.create({
          uuid: controllerScope.model.uuid,
          file: controllerScope.files[0]
        }).then(function(response) {
          controllerScope.files = [];
          controllerScope.model.image = response.data.image;
          controllerScope.updateImageUrl();
          ncUtilsFlash.success('Organization image is uploaded');
        }, function(response) {
          ncUtilsFlash.warning('Unable to upload image');
        });
      },

      deleteImage: function() {
        controllerScope.model.image = null;
        customerImageService.delete({
          uuid: controllerScope.model.uuid
        }).then(function(response) {
          ncUtilsFlash.success('Organization image is deleted');
          controllerScope.model.image = null;
          controllerScope.updateImageUrl();
        }, function(response) {
          ncUtilsFlash.warning('Unable to delete image');
        });
      },
      editInPlace: function(data, fieldName) {
        var d = $q.defer();
        if (data || fieldName != 'name') {
          return this._super(data, fieldName);
        }
        d.resolve('This field is required.');
        return d.promise;
      },
      afterUpdate: function() {
        ncUtilsFlash.success('Organization {} is updated'.replace('{}', controllerScope.model.name));
        $rootScope.$broadcast('refreshCustomerList', {model: this.model, update: true});
      }
    });

    controllerScope.__proto__ = new CustomerController();
  }

})();

(function() {
  angular.module('ncsaas')
    .controller('CustomerAddController',
    ['customersService', 'baseControllerAddClass', '$rootScope', CustomerAddController]);

  function CustomerAddController(customersService, baseControllerAddClass, $rootScope) {
    var controllerScope = this;
    var Controller = baseControllerAddClass.extend({
      init: function() {
        this.service = customersService;
        this.controllerScope = controllerScope;
        this._super();
        this.listState = 'organizations.list';
        this.detailsState = 'organizations.details';
        this.redirectToDetailsPage = true;

        var vm = this;
        customersService.loadCountries().then(function(countryChoices) {
          vm.countryChoices = countryChoices;
        });
      },
      beforeSave: function() {
        this.instance.is_company = this.instance.vat_code ? true : false;
      },
      afterSave: function() {
        this._super();
        $rootScope.$broadcast('refreshCustomerList', {model: this.instance, new: true, current: true});
      }
    });

    controllerScope.__proto__ = new Controller();
  }
})();
<|endoftext|>


<commit_before>import React from 'react';

import gql from 'graphql-tag';
import { Mutation, Query } from 'react-apollo';

import Entry, { EntryForm, EntryBody } from './component';
import { CALENDAR_GQL_QUERY } from '../Calendar';

const ENTRY_GQL_QUERY = gql`
  query Entries($year: Int!, $month: Int!, $date: Int!) {
    myCouple {
      id
      me {
        id
        name
      }
      partner {
        id
        name
      }
    }
    me {
      id
      name
    }
    entries(year: $year, month: $month, date: $date) {
      id
      content
      author {
        id
        name
      }
    }
  }
`;

function EntryContainer({ year, month, date, author: requestedAuthor }) {
  return (
    <Query
      query={ENTRY_GQL_QUERY}
      variables={{ year, month, date }}
      fetchPolicy="cache-and-network"
    >
      {renderEntry(year, month, date, requestedAuthor)}
    </Query>
  );
}

function renderEntry(year, month, date, requestedAuthor) {
  return ({ data: dataFromQuery, loading: loadingQuery }) => (
    <Entry
      body={
        loadingQuery ? (
          renderEmptyEntryBody()
        ) : isLoggedInUserAuthor(
          getLoggedInUserNameFromQuery(dataFromQuery),
          requestedAuthor
        ) ? (
          <EditableEntryBody
            year={year}
            month={month}
            date={date}
            nameOfUser={getLoggedInUserNameFromQuery(dataFromQuery)}
            entry={getEntryForAuthor(
              requestedAuthor,
              getEntriesFromQuery(dataFromQuery)
            )}
          />
        ) : (
          <EntryBody
            nameOfUser={getPartnerNameFromQuery(dataFromQuery)}
            entry={getEntryForAuthor(
              requestedAuthor,
              getEntriesFromQuery(dataFromQuery)
            )}
            loading={loadingQuery}
          />
        )
      }
      year={year}
      month={month}
      date={date}
      nameOfPartner={getNameOfPartnerForAuthor(dataFromQuery, requestedAuthor)}
    />
  );
}

function renderEmptyEntryBody() {
  return <EntryBody nameOfUser={''} entry={''} loading={true} />;
}

function isLoggedInUserAuthor(loggedInUser, author) {
  return loggedInUser.toLowerCase() === author.toLowerCase();
}

function getLoggedInUserNameFromQuery(query) {
  return (query && query.me && query.me.name) || '';
}

function getEntriesFromQuery(query) {
  return (query && query.entries) || [];
}

function getNameOfPartnerForAuthor(query, requestedAuthor) {
  return isLoggedInUserAuthor(
    getLoggedInUserNameFromQuery(query),
    requestedAuthor
  )
    ? getPartnerNameFromQuery(query)
    : getLoggedInUserNameFromQuery(query);
}

function getPartnerNameFromQuery(query) {
  return (query && query.myCouple && query.myCouple.partner.name) || '';
}

function EditableEntryBody({ year, month, date, nameOfUser, entry }) {
  return (
    <Mutation
      mutation={gql`
        mutation SetEntry(
          $year: Int!
          $month: Int!
          $date: Int!
          $content: String!
        ) {
          setEntry(year: $year, month: $month, date: $date, content: $content) {
            content
          }
        }
      `}
      refetchQueries={[
        { query: CALENDAR_GQL_QUERY, variables: { year, month } },
        { query: ENTRY_GQL_QUERY, variables: { year, month, date } },
      ]}
    >
      {(
        setEntry,
        {
          data: dataFromMutation,
          called: didCallMutation,
          error: errorFromMutation,
          loading,
        }
      ) => {
        if (didCallMutation && errorFromMutation == null) {
          removeLocallySavedEntry(
            locallySavedEntryKey(nameOfUser, year, month, date)
          );
        }

        return (
          <EntryForm
            saveEntry={content =>
              setEntry({ variables: { year, month, date, content } })
            }
            nameOfUser={nameOfUser}
            entry={
              (dataFromMutation &&
                dataFromMutation.setEntry &&
                dataFromMutation.setEntry.content) ||
              entry
            }
            getLocallySavedEntry={() =>
              getLocallySavedEntry(
                locallySavedEntryKey(nameOfUser, year, month, date)
              )
            }
            locallySaveEntry={entry =>
              setLocallySavedEntry(
                locallySavedEntryKey(nameOfUser, year, month, date),
                entry
              )
            }
            errorOnSave={didCallMutation && errorFromMutation != null}
            loading={loading}
          />
        );
      }}
    </Mutation>
  );
}

function getEntryForAuthor(author, entries) {
  const entry = entries.filter(({ author: { name } }) => name === author)[0];

  if (entry !== undefined) {
    return entry.content;
  }

  return '';
}

function getLocallySavedEntry(key) {
  return localStorage.getItem(key);
}

function setLocallySavedEntry(key, entry) {
  return localStorage.setItem(key, entry);
}

function removeLocallySavedEntry(key) {
  return localStorage.removeItem(key);
}

function locallySavedEntryKey(user, year, month, date) {
  return `${user}${year}${month}${date}`;
}
export default EntryContainer;
<commit_msg>Finished cleaning on entry rendering logic<commit_after>import React from 'react';

import gql from 'graphql-tag';
import { Mutation, Query } from 'react-apollo';

import Entry, { EntryForm, EntryBody } from './component';
import { CALENDAR_GQL_QUERY } from '../Calendar';

const ENTRY_GQL_QUERY = gql`
  query Entries($year: Int!, $month: Int!, $date: Int!) {
    myCouple {
      id
      me {
        id
        name
      }
      partner {
        id
        name
      }
    }
    me {
      id
      name
    }
    entries(year: $year, month: $month, date: $date) {
      id
      content
      author {
        id
        name
      }
    }
  }
`;

function EntryContainer({ year, month, date, author: requestedAuthor }) {
  return (
    <Query
      query={ENTRY_GQL_QUERY}
      variables={{ year, month, date }}
      fetchPolicy="cache-and-network"
    >
      {renderEntry(year, month, date, requestedAuthor)}
    </Query>
  );
}

function renderEntry(year, month, date, requestedAuthor) {
  return ({ data: dataFromQuery, loading: loadingQuery }) => (
    <Entry
      body={
        loadingQuery
          ? renderEmptyEntryBody()
          : renderEntryBodyWithContent(
              dataFromQuery,
              loadingQuery,
              requestedAuthor,
              year,
              month,
              date
            )
      }
      year={year}
      month={month}
      date={date}
      nameOfPartner={getNameOfPartnerForAuthor(dataFromQuery, requestedAuthor)}
    />
  );
}

function renderEmptyEntryBody() {
  return <EntryBody nameOfUser={''} entry={''} loading={true} />;
}

function renderEntryBodyWithContent(
  dataFromQuery,
  loadingQuery,
  requestedAuthor,
  year,
  month,
  date
) {
  return isLoggedInUserAuthor(
    getLoggedInUserNameFromQuery(dataFromQuery),
    requestedAuthor
  )
    ? renderEditableEntryBody(dataFromQuery, requestedAuthor, year, month, date)
    : renderEntryBody(dataFromQuery, loadingQuery, requestedAuthor);
}

function renderEditableEntryBody(
  dataFromQuery,
  requestedAuthor,
  year,
  month,
  date
) {
  return (
    <EditableEntryBody
      year={year}
      month={month}
      date={date}
      nameOfUser={getLoggedInUserNameFromQuery(dataFromQuery)}
      entry={getEntryForAuthor(
        requestedAuthor,
        getEntriesFromQuery(dataFromQuery)
      )}
    />
  );
}

function renderEntryBody(dataFromQuery, loadingQuery, requestedAuthor) {
  return (
    <EntryBody
      nameOfUser={getPartnerNameFromQuery(dataFromQuery)}
      entry={getEntryForAuthor(
        requestedAuthor,
        getEntriesFromQuery(dataFromQuery)
      )}
      loading={loadingQuery}
    />
  );
}

function isLoggedInUserAuthor(loggedInUser, author) {
  return loggedInUser.toLowerCase() === author.toLowerCase();
}

function getLoggedInUserNameFromQuery(query) {
  return (query && query.me && query.me.name) || '';
}

function getEntriesFromQuery(query) {
  return (query && query.entries) || [];
}

function getNameOfPartnerForAuthor(query, requestedAuthor) {
  return isLoggedInUserAuthor(
    getLoggedInUserNameFromQuery(query),
    requestedAuthor
  )
    ? getPartnerNameFromQuery(query)
    : getLoggedInUserNameFromQuery(query);
}

function getPartnerNameFromQuery(query) {
  return (query && query.myCouple && query.myCouple.partner.name) || '';
}

function EditableEntryBody({ year, month, date, nameOfUser, entry }) {
  return (
    <Mutation
      mutation={gql`
        mutation SetEntry(
          $year: Int!
          $month: Int!
          $date: Int!
          $content: String!
        ) {
          setEntry(year: $year, month: $month, date: $date, content: $content) {
            content
          }
        }
      `}
      refetchQueries={[
        { query: CALENDAR_GQL_QUERY, variables: { year, month } },
        { query: ENTRY_GQL_QUERY, variables: { year, month, date } },
      ]}
    >
      {(
        setEntry,
        {
          data: dataFromMutation,
          called: didCallMutation,
          error: errorFromMutation,
          loading,
        }
      ) => {
        if (didCallMutation && errorFromMutation == null) {
          removeLocallySavedEntry(
            locallySavedEntryKey(nameOfUser, year, month, date)
          );
        }

        return (
          <EntryForm
            saveEntry={content =>
              setEntry({ variables: { year, month, date, content } })
            }
            nameOfUser={nameOfUser}
            entry={
              (dataFromMutation &&
                dataFromMutation.setEntry &&
                dataFromMutation.setEntry.content) ||
              entry
            }
            getLocallySavedEntry={() =>
              getLocallySavedEntry(
                locallySavedEntryKey(nameOfUser, year, month, date)
              )
            }
            locallySaveEntry={entry =>
              setLocallySavedEntry(
                locallySavedEntryKey(nameOfUser, year, month, date),
                entry
              )
            }
            errorOnSave={didCallMutation && errorFromMutation != null}
            loading={loading}
          />
        );
      }}
    </Mutation>
  );
}

function getEntryForAuthor(author, entries) {
  const entry = entries.filter(({ author: { name } }) => name === author)[0];

  if (entry !== undefined) {
    return entry.content;
  }

  return '';
}

function getLocallySavedEntry(key) {
  return localStorage.getItem(key);
}

function setLocallySavedEntry(key, entry) {
  return localStorage.setItem(key, entry);
}

function removeLocallySavedEntry(key) {
  return localStorage.removeItem(key);
}

function locallySavedEntryKey(user, year, month, date) {
  return `${user}${year}${month}${date}`;
}
export default EntryContainer;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */
/*global define, $, XMLHttpRequest, window */

/**
 * RemoteAgent defines and provides an interface for custom remote functions
 * loaded from RemoteFunctions. Remote commands are executed via
 * `call(name, varargs)`.
 *
 * Remote events are dispatched as events on this object.
 */
define(function RemoteAgent(require, exports, module) {
    "use strict";

    var $exports = $(exports);

    var LiveDevelopment = require("LiveDevelopment/LiveDevelopment"),
        Inspector       = require("LiveDevelopment/Inspector/Inspector"),
        RemoteFunctions = require("text!LiveDevelopment/Agents/RemoteFunctions.js");

    var _load; // deferred load
    var _objectId; // the object id of the remote object
    var _intervalId; // interval used to send keepAlive events

    // WebInspector Event: DOM.attributeModified
    function _onAttributeModified(event, res) {
        // res = {nodeId, name, value}
        var matches = /^data-ld-(.*)/.exec(res.name);
        if (matches) {
            $exports.triggerHandler(matches[1], res);
        }
    }

    function _call(objectId, method, varargs) {
        console.assert(objectId, "Attempted to call remote method without objectId set.");
        var args = Array.prototype.slice.call(arguments, 2),
            callback,
            deferred = new $.Deferred();

        // if the last argument is a function it is the callback function
        if (typeof args[args.length - 1] === "function") {
            callback = args.pop();
        }

        // Resolve node parameters
        args = args.map(function (arg) {
            if (arg && arg.nodeId) {
                return arg.resolve();
            }

            return arg;
        });

        $.when.apply(undefined, args).done(function onResolvedAllNodes() {
            var params = [];

            args.forEach(function (arg) {
                if (arg.objectId) {
                    params.push({objectId: arg.objectId});
                } else {
                    params.push({value: arg});
                }
            });

            Inspector.Runtime.callFunctionOn(objectId, method, params, undefined, callback)
                .then(deferred.resolve, deferred.reject);
        });

        return deferred.promise();
    }

    /** Call a remote function
     * The parameters are passed on to the remote functions. Nodes are resolved
     * and sent as objectIds.
     * @param {string} function name
     */
    function call(method, varargs) {
        var argsArray = [_objectId, "_LD." + method];

        if (arguments.length > 1) {
            argsArray = argsArray.concat(Array.prototype.slice.call(arguments, 1));
        }

        return _call.apply(null, argsArray);
    }

    function _stopKeepAliveInterval() {
        if (_intervalId) {
            window.clearInterval(_intervalId);
            _intervalId = null;
        }
    }

    function _startKeepAliveInterval() {
        _stopKeepAliveInterval();

        _intervalId = window.setInterval(function () {
            call("keepAlive");
        }, 1000);
    }

    /**
     * @private
     * Cancel the keepAlive interval if the page reloads
     */
    function _onFrameStartedLoading(event, res) {
        _stopKeepAliveInterval();
    }

    // WebInspector Event: Page.loadEventFired
    function _onLoadEventFired(event, res) {
        // res = {timestamp}

        // inject RemoteFunctions
        var command = "window._LD=" + RemoteFunctions + "(" + LiveDevelopment.config.experimental + ");";

        Inspector.Runtime.evaluate(command, function onEvaluate(response) {
            if (response.error || response.wasThrown) {
                _load.reject(null, response.error);
            } else {
                _objectId = response.result.objectId;
                _load.resolve();

                _startKeepAliveInterval();
            }
        });
    }

    /** Initialize the agent */
    function load() {
        _load = new $.Deferred();
        $(Inspector.Page).on("loadEventFired.RemoteAgent", _onLoadEventFired);
        $(Inspector.Page).on("frameStartedLoading.RemoteAgent", _onFrameStartedLoading);
        $(Inspector.DOM).on("attributeModified.RemoteAgent", _onAttributeModified);

        return _load.promise();
    }

    /** Clean up */
    function unload() {
        $(Inspector.Page).off(".RemoteAgent");
        $(Inspector.DOM).off(".RemoteAgent");
        _stopKeepAliveInterval();
    }

    // Export public functions
    exports.call = call;
    exports.load = load;
    exports.unload = unload;
});
<commit_msg>Inject remote functions earlier after frameNavigated instead of loadEventFired<commit_after>/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */
/*global define, $, XMLHttpRequest, window */

/**
 * RemoteAgent defines and provides an interface for custom remote functions
 * loaded from RemoteFunctions. Remote commands are executed via
 * `call(name, varargs)`.
 *
 * Remote events are dispatched as events on this object.
 */
define(function RemoteAgent(require, exports, module) {
    "use strict";

    var $exports = $(exports);

    var LiveDevelopment = require("LiveDevelopment/LiveDevelopment"),
        Inspector       = require("LiveDevelopment/Inspector/Inspector"),
        RemoteFunctions = require("text!LiveDevelopment/Agents/RemoteFunctions.js");

    var _load; // deferred load
    var _objectId; // the object id of the remote object
    var _intervalId; // interval used to send keepAlive events

    // WebInspector Event: DOM.attributeModified
    function _onAttributeModified(event, res) {
        // res = {nodeId, name, value}
        var matches = /^data-ld-(.*)/.exec(res.name);
        if (matches) {
            $exports.triggerHandler(matches[1], res);
        }
    }

    function _call(objectId, method, varargs) {
        console.assert(objectId, "Attempted to call remote method without objectId set.");
        var args = Array.prototype.slice.call(arguments, 2),
            callback,
            deferred = new $.Deferred();

        // if the last argument is a function it is the callback function
        if (typeof args[args.length - 1] === "function") {
            callback = args.pop();
        }

        // Resolve node parameters
        args = args.map(function (arg) {
            if (arg && arg.nodeId) {
                return arg.resolve();
            }

            return arg;
        });

        $.when.apply(undefined, args).done(function onResolvedAllNodes() {
            var params = [];

            args.forEach(function (arg) {
                if (arg.objectId) {
                    params.push({objectId: arg.objectId});
                } else {
                    params.push({value: arg});
                }
            });

            Inspector.Runtime.callFunctionOn(objectId, method, params, undefined, callback)
                .then(deferred.resolve, deferred.reject);
        });

        return deferred.promise();
    }

    /** Call a remote function
     * The parameters are passed on to the remote functions. Nodes are resolved
     * and sent as objectIds.
     * @param {string} function name
     */
    function call(method, varargs) {
        var argsArray = [_objectId, "_LD." + method];

        if (arguments.length > 1) {
            argsArray = argsArray.concat(Array.prototype.slice.call(arguments, 1));
        }

        return _call.apply(null, argsArray);
    }

    function _stopKeepAliveInterval() {
        if (_intervalId) {
            window.clearInterval(_intervalId);
            _intervalId = null;
        }
    }

    function _startKeepAliveInterval() {
        _stopKeepAliveInterval();

        _intervalId = window.setInterval(function () {
            call("keepAlive");
        }, 1000);
    }

    /**
     * @private
     * Cancel the keepAlive interval if the page reloads
     */
    function _onFrameStartedLoading(event, res) {
        _stopKeepAliveInterval();
    }

    // WebInspector Event: Page.loadEventFired
    function _onFrameNavigated(event, res) {
        // res = {timestamp}

        // inject RemoteFunctions
        var command = "window._LD=" + RemoteFunctions + "(" + LiveDevelopment.config.experimental + ");";

        Inspector.Runtime.evaluate(command, function onEvaluate(response) {
            if (response.error || response.wasThrown) {
                _load.reject(response.error);
            } else {
                _objectId = response.result.objectId;
                _load.resolve();

                _startKeepAliveInterval();
            }
        });
    }

    /** Initialize the agent */
    function load() {
        _load = new $.Deferred();
        $(Inspector.Page).one("frameNavigated.RemoteAgent", _onFrameNavigated);
        $(Inspector.Page).on("frameStartedLoading.RemoteAgent", _onFrameStartedLoading);
        $(Inspector.DOM).on("attributeModified.RemoteAgent", _onAttributeModified);

        return _load.promise();
    }

    /** Clean up */
    function unload() {
        $(Inspector.Page).off(".RemoteAgent");
        $(Inspector.DOM).off(".RemoteAgent");
        _stopKeepAliveInterval();
    }

    // Export public functions
    exports.call = call;
    exports.load = load;
    exports.unload = unload;
});
<|endoftext|>


<commit_before>(function($) {
  var Wheel = (function() {
    function Wheel(fact, params) {
      this.fact = fact;
      this.opinions = $(fact).find(".opinion");
      this.authority = $(fact).find(".authority").first();
      this.params = $.extend(params, {
        "dim": 24,
        "radius" : 18,
        "default_stroke": {
          "opacity": 0.2,
          "stroke": 9
        },
        "hover_stroke": {
          "opacity": 0.5,
          "stroke": 11
        }
      });
    }

    function arc(w, op, p) {
      var opacity = $(op).data("user-opinion") ? 1.0 : w.params.default_stroke.opacity;
      var the_arc = [op.display_value, p.offset, p.r];

      if (!op.raphael) {
        // set new path
        return (op.raphael = w.r.path().attr({
          arc: the_arc,
          stroke: $(op).data("color"),
          "stroke-width": w.params.default_stroke.stroke,
          opacity: opacity
        }));
      } else {
        return op.raphael.animate({
          arc: the_arc,
          opacity: opacity
        }, 200, '<>');
      }
    }

    function authority(w, authority_element) {
      var auth = authority_element.data("authority");
      var pos = w.params.dim + (w.params.dim * 0.25);
      if (!authority_element.raphael) {
        return (authority_element.raphael = w.r.text(pos, pos, auth).attr({"font-size" : "13px", "fill" : "#ccc"}));
      } else {
        return authority_element.raphael.attr({"text": auth});
      }
    }

    Wheel.prototype.calc_display = function(opinions) {
      var too_much = 0;
      var large_ones = 0;
      $(opinions).each(function() {
        var percentage = $(this).data("value");
        if (percentage < 15) {
          too_much += 15 - percentage;
        } else if (percentage > 40) {
          large_ones += percentage;
        }
      })
      .each(function() {
        var percentage = $(this).data("value");
        if (percentage < 15) {
          percentage = 15 ;
        } else if (percentage > 40) {
          percentage = percentage - percentage/large_ones*too_much;
        }
        this.display_value = percentage;
      });

    };

    Wheel.prototype.update = function() {
      var wheel = this;
      var a = authority(wheel, wheel.authority);
      wheel.calc_display(this.opinions);
      var offset = 0;
      $(this.opinions).each(function() {
        var z = arc(wheel, this, {
          offset: offset,
          val: this.display_value,
          r: wheel.params.radius
        });
        offset = offset + this.display_value;
      });
    };

    Wheel.prototype.bind_events = function() {
      var w = this;
      $(this.opinions).each(function() {
        // bind events
        var $t = $(this);
        this.raphael.mouseover(function() {
          if (!$t.data("user-opinion")) {
            this.animate({
              'stroke-width': w.params.hover_stroke.stroke,
              opacity: w.params.hover_stroke.opacity
            }, 200, '<>');
          } else {
            this.animate({
              'stroke-width': w.params.hover_stroke.stroke
            }, 200, '<>');
          }
        });
        this.raphael.mouseout(function() {
          if (!$t.data("user-opinion")) {
            this.stop().animate({
              'stroke-width': w.params.default_stroke.stroke,
              opacity: w.params.default_stroke.opacity
            }, 200, '<>');
          } else {
            this.animate({
              'stroke-width': w.params.default_stroke.stroke
            }, 200, '<>');
          }
        });
        $(this.raphael.node).bind("click", function() {
          $(w.fact).factlink("switch_opinion", $t);
        });
        $(this.raphael.node).hoverIntent({
          over: function(e) {
            optionBox = $(w.fact).find("." + $t.data("opinion") + "-box");
            $(optionBox).fadeIn("fast");
          },
          out: function() {
            $(w.fact).find("." + $t.data("opinion") + "-box").delay(500).fadeOut("fast");
          }
        });
      });
    };

    Wheel.prototype.init = function(canvas) {
      var w = this;
      w.r = Raphael(canvas, w.params.dim * 2 + 17, w.params.dim * 2 + 17);
      w.r.customAttributes.arc = function(percentage, percentage_offset, radius) {
      percentage = percentage - 2; // add padding after arc
       var  large_angle = percentage > 50,
            box_dim = w.params.dim + 6,
            start_angle = percentage_offset * 2 * Math.PI /100,
            end_angle   = (percentage_offset + percentage) * 2 * Math.PI / 100,
            start_x = box_dim +  radius * Math.cos(start_angle),
            start_y = box_dim - radius * Math.sin(start_angle),
            end_x   = box_dim + radius * Math.cos(end_angle),
            end_y   = box_dim - radius * Math.sin(end_angle);
        return {
          path: [
            ['M', start_x, start_y],
            ['A', radius, radius, 0, (large_angle ? 1 : 0), 0, end_x, end_y]
          ]};
      };
      this.update();
      this.bind_events();
    };
    return Wheel;
  })();

  var methods = {
    // Initialize factbubble
    init: function(options) {
      return this.each(function() {
        function stop_fade(t) {
          t.stop(true, true).css({
            "opacity": "1"
          });
        }
        function switchTabAction(active) {
          console.log('switchTabAction')
          $t.find(".tab_content[rel=" + active + "] .add-evidence").toggle();
          $t.find(".tab_content[rel=" + active + "] .evidence").toggle();
          var action = $t.find(".add-action[rel=" + active + "] > a");
          action.text($(action).text() === 'Add facts' ? 'Show facts' : 'Add facts');
        }
        function addEventHandlersDoAdd($t){
          $t.find("a.do-add").live("click", function() {
            $t.find('.evidence-list').hide();
            $t.find('.evidence-search-results').show();
            return false;
          });
        }
        function addEventHandlersReturnFromAdd($t) {
          $t.find("a.return-from-add").bind("click", function() {
            $t.find('.evidence-list').show();
            $t.find('.evidence-search-results').hide();
            return false;
          });
        }
        function addEventHandlersReturnFromEvidenceAdd($t) {
          $t.find("a.close-evidence-add").bind("click", function() {
            $t.find('.page').hide();
            $t.find('.evidence-search-results').show();
            return false;
          });

        }

        function addEventHandlersSubmitButton($t) {

          $t.find('button.supporting').bind('click', function() {
            submitEvidence($t, "supporting");
          });

          $t.find('button.weakening').bind('click', function() {
            submitEvidence($t, "weakening");
          });
        }

        function addEventHandlersTabs($t){
          $t.find("ul.evidence li").click(function() {
            $t.find(".tab_content, div.add-action").hide();
            var activeTab = $(this).find("a").attr("class");
            $t.find(".tab_content[rel='" + activeTab + "']").show();
            $t.find("div.add-action[rel='" + activeTab + "']").show();

            if($t.find(".dropdown-container").is(":hidden")) {
              $t.find(".dropdown-container").slideDown();

              if (!$t.data('loaded-evidence')) {
                getEvidence($t);
                $t.data('loaded-evidence', true);
              }

              $(this).addClass("active");
            } else {
              if($(this).hasClass("active")) {
                $t.find(".dropdown-container").slideUp(function() {
                  $t.find("ul.evidence li").removeClass("active");
                });
              } else {
                $t.find("ul.evidence li").removeClass("active");
                $(this).addClass("active");
              }
            }
            return false;
           });
         }
        function initialize($t) {
          /* based on http://www.sohtanaka.com/web-design/simple-tabs-w-css-jquery/ */
          //On Click Event
          addEventHandlersTabs($t);
          addEventHandlersDoAdd($t);
          addEventHandlersReturnFromAdd($t);
          addEventHandlersReturnFromEvidenceAdd($t);

          addEventHandlersSubmitButton($t);

          $t.data('loaded-evidence', false);

          $t.bind("factlink:switchTabAction", function(e, active)  {
            switchTabAction(active);
          });
          // Evidence buttons
          $t.find(".existing_evidence a").live("ajax:complete", function(et, e){
            $(this).closest('ul').children().find('a').removeClass("active");
            $(this).addClass('active');
           });
           $t.data("initialized", true);
        }
        /*start of method*/
        var $t = $(this);
        $t.data("facts",  {});
        if (!$t.data("initialized")) {
            initialize($t);
        }
        $t.find("article.fact").each(function() {
          var fact = init_fact(this, $t);
          $t.data("facts")[fact.attr("data-fact-id")] = fact;
        });

        // Prevents boxes from dissapearing on mouse over
        $t.find(".float-box").mouseover(function() { stop_fade($(this)); });
        $t.find(".float-box").mouseout(function() {
          if(!$(this).find("input#channel_title").is(":focus")) {
            $(this).delay(500).fadeOut("fast");
          }
        });
      });
    },
    // Update
    update: function(data) {
      var $t = $(this).data("container") || $(this);
      if($t.data("initialized")) {
       $(data).each(function() {
          var fact =  $t.data("facts")[this.id];
          if(fact && $(fact).data("initialized")) {
            $(fact).data("update")(this.score_dict_as_percentage); // Update the facts
          }
       });
      }
    },
    switch_opinion: function(opinion) {
      var fact = this,
          opinions = fact.data("wheel").opinions;
      opinions.each(function() {
        var current_op = this;
        if ($(current_op).data("opinion") === opinion.data("opinion")) {
          // The clicked op is the current op in the list
          if (!$(current_op).data("user-opinion")) {
            $.post("/fact_item/" + $(fact).data("fact-id") + "/opinion/" + opinion.data("opinion"), function(data) {
              data_attr(current_op, "user-opinion", true);
              fact.factlink("update", data);
            });
          }
          else {
            $.ajax({
              type: "DELETE",
              url: "/fact_item/" + $(fact).data("fact-id") + "/opinion/",
              success: function(data) {
                data_attr(current_op, "user-opinion", false);
                fact.factlink("update", data);
              }
            });
          }
        }
        else {
          data_attr(current_op, "user-opinion", false);
        }
      });
    },

    // Channels
    to_channel: function(user, channel, fact) {
      $.ajax({
        url: "/" + user + "/channels/toggle/fact",
        dataType: "script",
        type: "POST",
        data: {
          user: user,
          channel_id: channel,
          fact_id: fact
        }
      });
    }

  };

  $.fn.factlink = function(method) {
    // Method calling logic
    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    }
    else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    }
    else {
      $.error('Method ' + method + ' does not exist on jQuery.factlink');
    }
  };

  // Private functions
  function data_attr(el, attr, data) {
    $(el).attr("data-" + attr, data);
    $(el).data(attr, data);
  }

  function getEvidence($t) {
    var id = $t.attr("data-fact-id");

    $.ajax({
      url: '/facts/' + id + '/fact_relations',
      type: "GET",
      dataType: "script",
      success: function(data) {
      },
      error: function(data) {
      }
    });
  }

  function bindEvidencePrepare($c) {
    $c.find('.results ul li.evidence').live('click', function() {
      showEvidenceAdd($c);

      var elem = $(this);
      var evidenceId = elem.data('evidence-id');
      var evidenceDisplayString = elem.html();

      // Set the evidence ID used for posting
      console.log('setting: ' + evidenceId);
      $c.data('evidenceId', evidenceId);

      // Set the displaystring to the evidence bubble
      $c.find('.evidence-add .evidence').html(evidenceDisplayString);
    });
  }

  function submitEvidence($c, type) {
    var factId      = $c.attr("data-fact-id");
    var evidenceId  = $c.data("evidence-id");

    console.log('evId: ' + evidenceId);

    if (type === "supporting") {
      var url_part = "/add_supporting_evidence/";
    } else if (type === "weakening") {
      var url_part = "/add_weakening_evidence/";
    } else {
      alert('There is a problem adding the evidence to this Factlink. We are sorry for the inconvenience, please try again later.');
    }

    // TODO: This should changed to use the FactRelationController
    $.post("/factlink/" + factId + url_part + evidenceId, function(data) {
    });
  }

  function bindInstantSearch($c) {
    // Bind the instant search
    var is_timeout;
    $c.find('.search-area .evidence_search').keyup( function() {
      var elem = $(this);
      $('.user-search-input').html(elem.val());

      if (elem.val().length >= 2) {
          clearTimeout(is_timeout);
          is_timeout = setTimeout(function() {
            elem.closest('form').submit();
          }, 200); // <-- choose some sensible value here
      }
    });
  }

  function showEvidenceList($c) {
    hidePages($c);
    $c.find('.evidence-list').show();
  }
  function showEvidenceSearchResults($c) {
    hidePages($c);
    $c.find('.evidence-search-results').show();
  }
  function showEvidenceAdd($c) {
    hidePages($c);
    $c.find('.evidence-add').show();
  }
  function hidePages($c) {
    $c.find('.page').hide();
  }

  function init_fact(fact, container) {
    var $t = $(fact);
    var $c = $(container);
    if (!$t.data("initialized")) {
      $t.find('.edit').editable('/factlink/update_title', {
        indicator : 'Saving...',
        tooltip		: 'You can edit this title to place the fact in the correct context.'
      });

      $t.data("container", container);
      $t.data("wheel", new Wheel(fact));
      $t.data("wheel").init($t.find(".wheel").get(0));

      bindEvidencePrepare($c);
      bindInstantSearch($c);

      // Channels are in the container
      $t.find(".add-to-channel")
        .hoverIntent(function(e) {
          var channelList = $t.find(".channel-listing");

          $(channelList).fadeIn("fast");

          }, function() {
            $t.find(".channel-listing").delay(600).fadeOut("fast");
          })
        .bind('click', function(e) {
          e.preventDefault();
        });

      $t.find(".opinion-box").find("img").tipsy({
        gravity: 's'
      });
      // Now setting a function in the jquery data to keep track of it, would be prettier with custom events
      $t.data("update", function(data) {
        var fact = $t;
        fact.data("wheel").opinions.each(function() {
          data_attr(this, "value", data[$(this).data("opinions")].percentage);
        });
        fact.find(".authority span").text(data.authority);
        fact.data("wheel").update();
      });

      $t.data("initialized", true);
    }
    return $t;
  }
})(jQuery);
<commit_msg>Remove old code<commit_after>(function($) {
  var Wheel = (function() {
    function Wheel(fact, params) {
      this.fact = fact;
      this.opinions = $(fact).find(".opinion");
      this.authority = $(fact).find(".authority").first();
      this.params = $.extend(params, {
        "dim": 24,
        "radius" : 18,
        "default_stroke": {
          "opacity": 0.2,
          "stroke": 9
        },
        "hover_stroke": {
          "opacity": 0.5,
          "stroke": 11
        }
      });
    }

    function arc(w, op, p) {
      var opacity = $(op).data("user-opinion") ? 1.0 : w.params.default_stroke.opacity;
      var the_arc = [op.display_value, p.offset, p.r];

      if (!op.raphael) {
        // set new path
        return (op.raphael = w.r.path().attr({
          arc: the_arc,
          stroke: $(op).data("color"),
          "stroke-width": w.params.default_stroke.stroke,
          opacity: opacity
        }));
      } else {
        return op.raphael.animate({
          arc: the_arc,
          opacity: opacity
        }, 200, '<>');
      }
    }

    function authority(w, authority_element) {
      var auth = authority_element.data("authority");
      var pos = w.params.dim + (w.params.dim * 0.25);
      if (!authority_element.raphael) {
        return (authority_element.raphael = w.r.text(pos, pos, auth).attr({"font-size" : "13px", "fill" : "#ccc"}));
      } else {
        return authority_element.raphael.attr({"text": auth});
      }
    }

    Wheel.prototype.calc_display = function(opinions) {
      var too_much = 0;
      var large_ones = 0;
      $(opinions).each(function() {
        var percentage = $(this).data("value");
        if (percentage < 15) {
          too_much += 15 - percentage;
        } else if (percentage > 40) {
          large_ones += percentage;
        }
      })
      .each(function() {
        var percentage = $(this).data("value");
        if (percentage < 15) {
          percentage = 15 ;
        } else if (percentage > 40) {
          percentage = percentage - percentage/large_ones*too_much;
        }
        this.display_value = percentage;
      });

    };

    Wheel.prototype.update = function() {
      var wheel = this;
      var a = authority(wheel, wheel.authority);
      wheel.calc_display(this.opinions);
      var offset = 0;
      $(this.opinions).each(function() {
        var z = arc(wheel, this, {
          offset: offset,
          val: this.display_value,
          r: wheel.params.radius
        });
        offset = offset + this.display_value;
      });
    };

    Wheel.prototype.bind_events = function() {
      var w = this;
      $(this.opinions).each(function() {
        // bind events
        var $t = $(this);
        this.raphael.mouseover(function() {
          if (!$t.data("user-opinion")) {
            this.animate({
              'stroke-width': w.params.hover_stroke.stroke,
              opacity: w.params.hover_stroke.opacity
            }, 200, '<>');
          } else {
            this.animate({
              'stroke-width': w.params.hover_stroke.stroke
            }, 200, '<>');
          }
        });
        this.raphael.mouseout(function() {
          if (!$t.data("user-opinion")) {
            this.stop().animate({
              'stroke-width': w.params.default_stroke.stroke,
              opacity: w.params.default_stroke.opacity
            }, 200, '<>');
          } else {
            this.animate({
              'stroke-width': w.params.default_stroke.stroke
            }, 200, '<>');
          }
        });
        $(this.raphael.node).bind("click", function() {
          $(w.fact).factlink("switch_opinion", $t);
        });
        $(this.raphael.node).hoverIntent({
          over: function(e) {
            optionBox = $(w.fact).find("." + $t.data("opinion") + "-box");
            $(optionBox).fadeIn("fast");
          },
          out: function() {
            $(w.fact).find("." + $t.data("opinion") + "-box").delay(500).fadeOut("fast");
          }
        });
      });
    };

    Wheel.prototype.init = function(canvas) {
      var w = this;
      w.r = Raphael(canvas, w.params.dim * 2 + 17, w.params.dim * 2 + 17);
      w.r.customAttributes.arc = function(percentage, percentage_offset, radius) {
      percentage = percentage - 2; // add padding after arc
       var  large_angle = percentage > 50,
            box_dim = w.params.dim + 6,
            start_angle = percentage_offset * 2 * Math.PI /100,
            end_angle   = (percentage_offset + percentage) * 2 * Math.PI / 100,
            start_x = box_dim +  radius * Math.cos(start_angle),
            start_y = box_dim - radius * Math.sin(start_angle),
            end_x   = box_dim + radius * Math.cos(end_angle),
            end_y   = box_dim - radius * Math.sin(end_angle);
        return {
          path: [
            ['M', start_x, start_y],
            ['A', radius, radius, 0, (large_angle ? 1 : 0), 0, end_x, end_y]
          ]};
      };
      this.update();
      this.bind_events();
    };
    return Wheel;
  })();

  var methods = {
    // Initialize factbubble
    init: function(options) {
      return this.each(function() {
        function stop_fade(t) {
          t.stop(true, true).css({
            "opacity": "1"
          });
        }
        function switchTabAction(active) {
          console.log('switchTabAction')
          $t.find(".tab_content[rel=" + active + "] .add-evidence").toggle();
          $t.find(".tab_content[rel=" + active + "] .evidence").toggle();
          var action = $t.find(".add-action[rel=" + active + "] > a");
          action.text($(action).text() === 'Add facts' ? 'Show facts' : 'Add facts');
        }
        function addEventHandlersDoAdd($t){
          $t.find("a.do-add").live("click", function() {
            $t.find('.evidence-list').hide();
            $t.find('.evidence-search-results').show();
            return false;
          });
        }
        function addEventHandlersReturnFromAdd($t) {
          $t.find("a.return-from-add").bind("click", function() {
            $t.find('.evidence-list').show();
            $t.find('.evidence-search-results').hide();
            return false;
          });
        }
        function addEventHandlersReturnFromEvidenceAdd($t) {
          $t.find("a.close-evidence-add").bind("click", function() {
            $t.find('.page').hide();
            $t.find('.evidence-search-results').show();
            return false;
          });

        }

        function addEventHandlersSubmitButton($t) {

          $t.find('button.supporting').bind('click', function() {
            submitEvidence($t, "supporting");
          });

          $t.find('button.weakening').bind('click', function() {
            submitEvidence($t, "weakening");
          });
        }

        function addEventHandlersTabs($t){
          $t.find("ul.evidence li").click(function() {

            if($t.find(".dropdown-container").is(":hidden")) {
              $t.find(".dropdown-container").slideDown();

              // AJAX call to load the FactRelations
              if (!$t.data('loaded-evidence')) {
                getEvidence($t);
                $t.data('loaded-evidence', true);
              }

              $(this).addClass("active");

            } else {
              if($(this).hasClass("active")) {
                $t.find(".dropdown-container").slideUp(function() {
                  $t.find("ul.evidence li").removeClass("active");
                });
              } else {
                $t.find("ul.evidence li").removeClass("active");
                $(this).addClass("active");
              }
            }
            return false;
           });
         }
        function initialize($t) {
          /* based on http://www.sohtanaka.com/web-design/simple-tabs-w-css-jquery/ */
          //On Click Event
          addEventHandlersTabs($t);
          addEventHandlersDoAdd($t);
          addEventHandlersReturnFromAdd($t);
          addEventHandlersReturnFromEvidenceAdd($t);

          addEventHandlersSubmitButton($t);

          $t.data('loaded-evidence', false);

          $t.bind("factlink:switchTabAction", function(e, active)  {
            switchTabAction(active);
          });
          // Evidence buttons
          $t.find(".existing_evidence a").live("ajax:complete", function(et, e){
            $(this).closest('ul').children().find('a').removeClass("active");
            $(this).addClass('active');
           });
           $t.data("initialized", true);
        }
        /*start of method*/
        var $t = $(this);
        $t.data("facts",  {});
        if (!$t.data("initialized")) {
            initialize($t);
        }
        $t.find("article.fact").each(function() {
          var fact = init_fact(this, $t);
          $t.data("facts")[fact.attr("data-fact-id")] = fact;
        });

        // Prevents boxes from dissapearing on mouse over
        $t.find(".float-box").mouseover(function() { stop_fade($(this)); });
        $t.find(".float-box").mouseout(function() {
          if(!$(this).find("input#channel_title").is(":focus")) {
            $(this).delay(500).fadeOut("fast");
          }
        });
      });
    },
    // Update
    update: function(data) {
      var $t = $(this).data("container") || $(this);
      if($t.data("initialized")) {
       $(data).each(function() {
          var fact =  $t.data("facts")[this.id];
          if(fact && $(fact).data("initialized")) {
            $(fact).data("update")(this.score_dict_as_percentage); // Update the facts
          }
       });
      }
    },
    switch_opinion: function(opinion) {
      var fact = this,
          opinions = fact.data("wheel").opinions;
      opinions.each(function() {
        var current_op = this;
        if ($(current_op).data("opinion") === opinion.data("opinion")) {
          // The clicked op is the current op in the list
          if (!$(current_op).data("user-opinion")) {
            $.post("/fact_item/" + $(fact).data("fact-id") + "/opinion/" + opinion.data("opinion"), function(data) {
              data_attr(current_op, "user-opinion", true);
              fact.factlink("update", data);
            });
          }
          else {
            $.ajax({
              type: "DELETE",
              url: "/fact_item/" + $(fact).data("fact-id") + "/opinion/",
              success: function(data) {
                data_attr(current_op, "user-opinion", false);
                fact.factlink("update", data);
              }
            });
          }
        }
        else {
          data_attr(current_op, "user-opinion", false);
        }
      });
    },

    // Channels
    to_channel: function(user, channel, fact) {
      $.ajax({
        url: "/" + user + "/channels/toggle/fact",
        dataType: "script",
        type: "POST",
        data: {
          user: user,
          channel_id: channel,
          fact_id: fact
        }
      });
    }

  };

  $.fn.factlink = function(method) {
    // Method calling logic
    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    }
    else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    }
    else {
      $.error('Method ' + method + ' does not exist on jQuery.factlink');
    }
  };

  // Private functions
  function data_attr(el, attr, data) {
    $(el).attr("data-" + attr, data);
    $(el).data(attr, data);
  }

  function getEvidence($t) {
    var id = $t.attr("data-fact-id");

    $.ajax({
      url: '/facts/' + id + '/fact_relations',
      type: "GET",
      dataType: "script",
      success: function(data) {
      },
      error: function(data) {
      }
    });
  }

  function bindEvidencePrepare($c) {
    $c.find('.results ul li.evidence').live('click', function() {
      showEvidenceAdd($c);

      var elem = $(this);
      var evidenceId = elem.data('evidence-id');
      var evidenceDisplayString = elem.html();

      // Set the evidence ID used for posting
      console.log('setting: ' + evidenceId);
      $c.data('evidenceId', evidenceId);

      // Set the displaystring to the evidence bubble
      $c.find('.evidence-add .evidence').html(evidenceDisplayString);
    });
  }

  function submitEvidence($c, type) {
    var factId      = $c.attr("data-fact-id");
    var evidenceId  = $c.data("evidence-id");

    console.log('evId: ' + evidenceId);

    if (type === "supporting") {
      var url_part = "/add_supporting_evidence/";
    } else if (type === "weakening") {
      var url_part = "/add_weakening_evidence/";
    } else {
      alert('There is a problem adding the evidence to this Factlink. We are sorry for the inconvenience, please try again later.');
    }

    // TODO: This should changed to use the FactRelationController
    $.post("/factlink/" + factId + url_part + evidenceId, function(data) {
    });
  }

  function bindInstantSearch($c) {
    // Bind the instant search
    var is_timeout;
    $c.find('.search-area .evidence_search').keyup( function() {
      var elem = $(this);
      $('.user-search-input').html(elem.val());

      if (elem.val().length >= 2) {
          clearTimeout(is_timeout);
          is_timeout = setTimeout(function() {
            elem.closest('form').submit();
          }, 200); // <-- choose some sensible value here
      }
    });
  }

  function showEvidenceList($c) {
    hidePages($c);
    $c.find('.evidence-list').show();
  }
  function showEvidenceSearchResults($c) {
    hidePages($c);
    $c.find('.evidence-search-results').show();
  }
  function showEvidenceAdd($c) {
    hidePages($c);
    $c.find('.evidence-add').show();
  }
  function hidePages($c) {
    $c.find('.page').hide();
  }

  function init_fact(fact, container) {
    var $t = $(fact);
    var $c = $(container);
    if (!$t.data("initialized")) {
      $t.find('.edit').editable('/factlink/update_title', {
        indicator : 'Saving...',
        tooltip		: 'You can edit this title to place the fact in the correct context.'
      });

      $t.data("container", container);
      $t.data("wheel", new Wheel(fact));
      $t.data("wheel").init($t.find(".wheel").get(0));

      bindEvidencePrepare($c);
      bindInstantSearch($c);

      // Channels are in the container
      $t.find(".add-to-channel")
        .hoverIntent(function(e) {
          var channelList = $t.find(".channel-listing");

          $(channelList).fadeIn("fast");

          }, function() {
            $t.find(".channel-listing").delay(600).fadeOut("fast");
          })
        .bind('click', function(e) {
          e.preventDefault();
        });

      $t.find(".opinion-box").find("img").tipsy({
        gravity: 's'
      });
      // Now setting a function in the jquery data to keep track of it, would be prettier with custom events
      $t.data("update", function(data) {
        var fact = $t;
        fact.data("wheel").opinions.each(function() {
          data_attr(this, "value", data[$(this).data("opinions")].percentage);
        });
        fact.find(".authority span").text(data.authority);
        fact.data("wheel").update();
      });

      $t.data("initialized", true);
    }
    return $t;
  }
})(jQuery);
<|endoftext|>