<commit_before>'use strict';

const Joi = require('joi');
const moment = require('moment');

const Message = require('./Message');

class CustomerIoIdentifyMessage extends Message {

  constructor(...args) {
    super(...args);
    // Data validation rules.
    // TODO: move to helpers.
    const whenNullOrEmpty = Joi.valid(['', null]);
    const optionalStringDefaultsToUndefined = Joi
      .string()
      .empty(whenNullOrEmpty)
      .default(undefined);

    const optionalTimestampDefaultsToUndefined = Joi
      .date()
      .timestamp('unix')
      .raw()
      .empty(whenNullOrEmpty)
      .default(undefined);

    this.schema = Joi.object().keys({
      id: Joi.string().required().regex(/^[0-9a-f]{24}$/, 'valid object id'),
      data: Joi.object().keys({
        // Remove field when provided as empty string or null.
        email: Joi.string().empty(whenNullOrEmpty).default(undefined),

        // TODO: make sure has E.164 format
        // phone: Joi.string().empty(whenNullOrEmpty).default(undefined),

        // Required:
        updated_at: Joi.date().timestamp('unix').raw().required(),
        created_at: Joi.date().timestamp('unix').raw().required(),

        mobile_status: Joi.valid([
          'active',
          'undeliverable',
          'unknown',
          null,
        ]).default(undefined),

        // Optional, defaults to null when provided as empty string or null.
        last_authenticated_at: optionalTimestampDefaultsToUndefined,
        // Exception: kept as an isodate
        birthdate: Joi.string().isoDate().empty(whenNullOrEmpty).default(null),
        first_name: optionalStringDefaultsToUndefined,
        last_name: optionalStringDefaultsToUndefined,
        addr_city: optionalStringDefaultsToUndefined,
        addr_state: optionalStringDefaultsToUndefined,
        addr_zip: optionalStringDefaultsToUndefined,
        source: optionalStringDefaultsToUndefined,
        source_detail: optionalStringDefaultsToUndefined,
        language: optionalStringDefaultsToUndefined,
        country: optionalStringDefaultsToUndefined,
        unsubscribed: Joi.boolean(),

              // Allow anything as a role, but default to user.
        role: Joi.string().empty(whenNullOrEmpty).default('user'),

        // When interests not present, make them an empty array.
        interests: Joi.array().items(Joi.string()).empty(null).default(undefined),

        // TODO: add cio specific fields, like unsubscribe
      }),
      // TODO: Bring back when phone is formatted in Northstar
      // .or('email', 'phone'),
    });
  // Require presence at least one of: keyword, args, mms_image_url.
  }

  static fromUser(userMessage) {
    const user = userMessage.payload.data;
    // Copy user fields.
    const customerData = Object.assign({}, user);
    // Remove id from data, as it's available on top level.
    delete customerData.id;

    // Rename mobilecommon_status to mobile_status
    if (customerData.mobilecommon_status) {
      const mobileStatus = customerData.mobilecommon_status;
      delete customerData.mobilecommon_status;
      customerData.mobileStatus = mobileStatus;
    }

    // Rename mobile to phone
    // TODO: format phone

    if (customerData.mobile) {
      // const mobile = customerData.mobile;
      delete customerData.mobile;
      // TODO: Bring back when phone is formatted in Northstar
      // customerData.phone = mobile;
    }

    customerData.created_at = moment(customerData.created_at, moment.ISO_8601).unix();
    customerData.updated_at = moment(customerData.updated_at, moment.ISO_8601).unix();

    if (customerData.last_authenticated_at) {
      customerData.last_authenticated_at = moment(
        customerData.last_authenticated_at,
        moment.ISO_8601
      ).unix();
    }

    // TODO: Only explicitly set for new users.
    customerData.unsubscribed = false;

    // TODO: Transform timestamps

    const customerIoIdentifyMessage = new CustomerIoIdentifyMessage({
      data: {
        id: user.id,
        data: customerData,
      },
      meta: {
        request_id: userMessage.payload.meta.request_id,
      },
    });
    return customerIoIdentifyMessage;
  }

}

module.exports = CustomerIoIdentifyMessage;
<commit_msg>Comment fix<commit_after>'use strict';

const Joi = require('joi');
const moment = require('moment');

const Message = require('./Message');

class CustomerIoIdentifyMessage extends Message {

  constructor(...args) {
    super(...args);
    // Data validation rules.
    // TODO: move to helpers.
    const whenNullOrEmpty = Joi.valid(['', null]);
    const optionalStringDefaultsToUndefined = Joi
      .string()
      .empty(whenNullOrEmpty)
      .default(undefined);

    const optionalTimestampDefaultsToUndefined = Joi
      .date()
      .timestamp('unix')
      .raw()
      .empty(whenNullOrEmpty)
      .default(undefined);

    this.schema = Joi.object().keys({
      id: Joi.string().required().regex(/^[0-9a-f]{24}$/, 'valid object id'),
      data: Joi.object().keys({
        // Remove field when provided as empty string or null.
        email: Joi.string().empty(whenNullOrEmpty).default(undefined),

        // TODO: make sure has E.164 format
        // phone: Joi.string().empty(whenNullOrEmpty).default(undefined),

        // Required:
        updated_at: Joi.date().timestamp('unix').raw().required(),
        created_at: Joi.date().timestamp('unix').raw().required(),

        mobile_status: Joi.valid([
          'active',
          'undeliverable',
          'unknown',
          null,
        ]).default(undefined),

        // Optional, defaults to undefined when provided as empty string or null.
        last_authenticated_at: optionalTimestampDefaultsToUndefined,
        // Exception: kept as an isodate
        birthdate: Joi.string().isoDate().empty(whenNullOrEmpty).default(null),
        first_name: optionalStringDefaultsToUndefined,
        last_name: optionalStringDefaultsToUndefined,
        addr_city: optionalStringDefaultsToUndefined,
        addr_state: optionalStringDefaultsToUndefined,
        addr_zip: optionalStringDefaultsToUndefined,
        source: optionalStringDefaultsToUndefined,
        source_detail: optionalStringDefaultsToUndefined,
        language: optionalStringDefaultsToUndefined,
        country: optionalStringDefaultsToUndefined,
        unsubscribed: Joi.boolean(),

              // Allow anything as a role, but default to user.
        role: Joi.string().empty(whenNullOrEmpty).default('user'),

        // When interests not present, make them an empty array.
        interests: Joi.array().items(Joi.string()).empty(null).default(undefined),

        // TODO: add cio specific fields, like unsubscribe
      }),
      // TODO: Bring back when phone is formatted in Northstar
      // .or('email', 'phone'),
    });
  // Require presence at least one of: keyword, args, mms_image_url.
  }

  static fromUser(userMessage) {
    const user = userMessage.payload.data;
    // Copy user fields.
    const customerData = Object.assign({}, user);
    // Remove id from data, as it's available on top level.
    delete customerData.id;

    // Rename mobilecommon_status to mobile_status
    if (customerData.mobilecommon_status) {
      const mobileStatus = customerData.mobilecommon_status;
      delete customerData.mobilecommon_status;
      customerData.mobileStatus = mobileStatus;
    }

    // Rename mobile to phone
    // TODO: format phone

    if (customerData.mobile) {
      // const mobile = customerData.mobile;
      delete customerData.mobile;
      // TODO: Bring back when phone is formatted in Northstar
      // customerData.phone = mobile;
    }

    customerData.created_at = moment(customerData.created_at, moment.ISO_8601).unix();
    customerData.updated_at = moment(customerData.updated_at, moment.ISO_8601).unix();

    if (customerData.last_authenticated_at) {
      customerData.last_authenticated_at = moment(
        customerData.last_authenticated_at,
        moment.ISO_8601
      ).unix();
    }

    // TODO: Only explicitly set for new users.
    customerData.unsubscribed = false;

    // TODO: Transform timestamps

    const customerIoIdentifyMessage = new CustomerIoIdentifyMessage({
      data: {
        id: user.id,
        data: customerData,
      },
      meta: {
        request_id: userMessage.payload.meta.request_id,
      },
    });
    return customerIoIdentifyMessage;
  }

}

module.exports = CustomerIoIdentifyMessage;
<|endoftext|>


<commit_before>var optionsCache;

(function() {
	loadOptionsFromStorage();
})();

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
	if (message['message'] == 'optionsCacheUpdated')
		loadOptionsFromStorage(); // Reload options cache
});

// This is triggered when a document has finished loading
// see http://stackoverflow.com/questions/27239280 for pushstate (e.g. youtube pages that load via ajax)
chrome.webNavigation.onCompleted.addListener(function(o) {
	// Only act on the main page
	if (o.frameId > 0) return;

	// TODO: check if there is custom JS or CSS to execute for this URL
	var match = 'https://www.google.com/calendar/render';
	var customJs = getCustomJs(o.url);

	// Return if no custom JS or CSS for this URL
    //if (match !== o.url.substring(0, match.length)) return;

	chrome.tabs.executeScript(o.tabId, {
		code: customJs
	});
}, {
	url: []
});

function loadOptionsFromStorage() {
	chrome.storage.sync.get(null, function(items){
		optionsCache = items['options'] || {};
	});
}

function getCustomJs(url) {
	// TODO: maybe add the following placeholder when creating a custom JS: (function() { ... })();
	var isGlobalJsEnabled = optionsCache['IsGlobalJsEnabled'] || false;
	var customJs = optionsCache['sites'][url] !== undefined && optionsCache['sites'][url] !== undefined
		? optionsCache['sites'][url]['js'] || ''
		: '';

	if (isGlobalJsEnabled)
	{
		customJs += optionsCache['globalJs'];
	}

	return customJs;
}<commit_msg>Add support for wildcard URLs<commit_after>var optionsCache;

(function() {
	loadOptionsFromStorage();
})();

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
	if (message['message'] == 'optionsCacheUpdated')
		loadOptionsFromStorage(); // Reload options cache
});

// This is triggered when a document has finished loading
// see http://stackoverflow.com/questions/27239280 for pushstate (e.g. youtube pages that load via ajax)
chrome.webNavigation.onCompleted.addListener(function(o) {
	// Only act on the main page
	if (o.frameId > 0) return;

	// TODO: check if there is custom JS or CSS to execute for this URL
	var match = 'https://www.google.com/calendar/render';
	var customJs = getCustomJs(o.url);

	// Return if no custom JS or CSS for this URL
    //if (match !== o.url.substring(0, match.length)) return;

	chrome.tabs.executeScript(o.tabId, {
		code: customJs
	});
}, {
	url: []
});

function loadOptionsFromStorage() {
	chrome.storage.sync.get(null, function(items){
		optionsCache = items['options'] || {};
	});
}

function getCustomJs(url) {
	// TODO: maybe add the following placeholder when creating a custom JS: (function() { ... })();
	var isGlobalJsEnabled = optionsCache['IsGlobalJsEnabled'] || false;
	var customJs = optionsCache['sites'][url] !== undefined && optionsCache['sites'][url] !== undefined
		? optionsCache['sites'][url]['js'] || ''
		: '';

	if (customJs == '')
	{
		// Look for wildcards at the end of the string (TODO: make true wildcards that can be anywhere in the string)
		for (var siteUrl in optionsCache['sites']){
			if (siteUrl.indexOf('*') !== -1){
				let siteUrlWithoutWildcard = siteUrl.replace('*', '');
				if (url.includes(siteUrlWithoutWildcard)){
					customJs = optionsCache['sites'][siteUrl]['js'] || '';
					break;
				}
			}
		}
	}

	if (isGlobalJsEnabled)
	{
		customJs += optionsCache['globalJs'];
	}

	return customJs;
}<|endoftext|>


<commit_before>UseradminApp.controller('ApplicationCtrl', function($scope, $http,$window, $routeParams, Users, Applications) {

  $scope.session.activeTab = 'application';

  $scope.users = Users;
  $scope.applications = Applications;
  $scope.form = {};
  $scope.items = ['item1', 'item2', 'item3'];

  $scope.orderByColumn = 'name';
  $scope.orderReverse = false;

  $scope.changeOrder = function(orderByColumn) {
    $scope.orderByColumn = orderByColumn;
    $scope.orderReverse = !$scope.orderReverse;
  }

  $scope.searchApps = function() {
  	Applications.search($scope.searchQuery);
  }

  function init() {
    Applications.search();
  }

  if(Applications.list.length<1) {
    init();
  }

  $scope.activateApplicationDetail = function(id) {
    console.log('Activating application detail...', id);
    Applications.get(id, function(){
        //$scope.form.userDetail.$setPristine();
        $('#applicationdetail').modal('show');
    });
  }

  $scope.activateApplicationJson = function(id) {
    console.log('Activating application json...', id);
    Applications.get(id, function(){
      //$scope.form.userDetail.$setPristine();
      $('#applicationJson').modal('show');
      $scope.prettifyJson();
    });
  }

  $scope.newApplicationDetail = function() {
    Applications.application = {isNew: true};
    $scope.application = {isNew: true};
    //Users.userRoles = {};
    //$scope.form.applicationDetail.$setPristine();
    $('#applicationdetail').modal('show');
    /*
    var modalInstance = $uibModal.open({
      animation: $scope.animationsEnabled,
      templateUrl: 'template/applicationdetail.html',
      controller: 'ApplicationdetailCtrl',
      //size: size,
      resolve: {
        application: {isNew: true},
        items: function () {
          return $scope.items;
        }
      }
    });
    */
  }

  // -- Should be in ApplicationdetailCtrl ---
  $scope.applicationProperties = [
    {value: 'id', readOnly: 'true'},
    //{value: 'id',    minLength: 2, maxLength: 64, required: true, type: 'text', validationMsg:'Must be between 2-64 characters long.'},
    {value: 'name',    minLength: 2, maxLength: 64, required: true, type: 'text', validationMsg:'Must be between 2-64 characters long.'},
    {value: 'defaultOrganizationName',    minLength: 2, maxLength: 64, required: true, type: 'text', validationMsg:'Must be between 2-64 characters long.'},
    {value: 'defaultRoleName',    minLength: 2, maxLength: 64, required: true, type: 'text', validationMsg:'Must be between 2-64 characters long.'},
    {value: 'description',    required: false, type: 'text'},
    {value: 'applicationUrl',     required: false, type: 'url', validationMsg: 'Must be valid URL.'},
    {value: 'logoUrl', required: false, type: 'url', validationMsg: 'Must be valid URL.'},
    {value: 'fullTokenApplication',    required: false, type: 'text'},
    {value: 'secret', minLength: 12, maxLength: 254, required: false, type: 'text', validationMsg:'Must be between 12-254 characters long. No spaces allowed.'},
    {value: 'roleNames', required: false, type: 'text', validationMsg:'Comma separated list of available role names'},
    {value: 'orgNames', required: false, type: 'text', validationMsg:'Comma separated list of available organization names'}
  ];

  $scope.applicationJsonProperties = [
    {value: 'applicationJson', required: false, type: 'json', validationMsg:'The input must be valid json. Recomend http://jsonlint.com for manual validation.'},
  ];

  $scope.dict = {
    en: {
      name: 'Application Name (*)',
      id: 'Application Id',
      defaultOrganizationName: 'Default Organization Name (*)',
      defaultRoleName: 'Default Role Name (*)',
      applicationUrl: 'URL to Application',
      description: 'Description of Application',
      logoUrl: 'URL to Application Logo',
      fullTokenApplication: 'Whydah Admin application',
      secret: 'Application Secret',
      applicationJson: 'Json override',
      roleNames: 'Available role names',
      orgNames: 'Available organization names'
    }
  }

  $scope.save = function() {
    // Make sure these $scope-values are properly connected to the view
    if($scope.form.applicationDetail.$valid){
      if(Applications.application.isNew) {
        var newApplication = angular.copy(Applications.application);
        delete newApplication.isNew;
        Applications.add(newApplication, function(){
          delete Applications.application.isNew;
          $scope.form.applicationDetail.$setPristine();
        });
      } else {
       Applications.save(Applications.application, function(){
          $scope.form.applicationDetail.$setPristine();
        });
      }
    } else {
      console.log('Tried to save an invalid form.');
    }
  }

  $scope.saveFromJson = function() {
    // Make sure these $scope-values are properly connected to the view
    if($scope.form.applicationJson.$valid){
      if(Applications.application.isNew) {
        var newApplication = angular.copy(Applications.application);
        delete newApplication.isNew;
        Applications.addFromJson(newApplication, function(){
          delete Applications.application.isNew;
          $scope.form.applicationJson.$setPristine();
        });
      } else {
        Applications.saveFromJson(Applications.application, function(){
          $scope.form.applicationJson.$setPristine();
        });
      }
    } else {
      console.log('Tried to save an invalid form.');
    }
  }

  $scope.prettifyJson = function() {
    try {
      var jsonObject = JSON.parse($scope.applications.application.applicationJson);
      var prettifiedJson = JSON.stringify(jsonObject, undefined, 2);
      $scope.applications.application.applicationJson = prettifiedJson;
    }catch (e) {
      Messages.add('danger', 'Could not prettify applicationJson. Error while parsing');
    }
  }

  $scope.delete = function() {
    var deleteUser = $window.confirm('Are you absolutely sure you want to delete '+ Applications.application.name +'?');

    if (deleteUser) {
      Applications.delete(Applications.application, function(){
        $scope.form.applicationDetail.$setPristine();
      });
    }
  }

});<commit_msg>fortification<commit_after>UseradminApp.controller('ApplicationCtrl', function($scope, $http,$window, $routeParams, Users, Applications) {

  $scope.session.activeTab = 'application';

  $scope.users = Users;
  $scope.applications = Applications;
  $scope.form = {};
  $scope.items = ['item1', 'item2', 'item3'];

  $scope.orderByColumn = 'name';
  $scope.orderReverse = false;

  $scope.changeOrder = function(orderByColumn) {
    $scope.orderByColumn = orderByColumn;
    $scope.orderReverse = !$scope.orderReverse;
  }

  $scope.searchApps = function() {
  	Applications.search($scope.searchQuery);
  }

  function init() {
    Applications.search();
  }

  if(typeof(Applications) != 'undefined' && Applications.list.length<1) {
    init();
  }

  $scope.activateApplicationDetail = function(id) {
    console.log('Activating application detail...', id);
    Applications.get(id, function(){
        //$scope.form.userDetail.$setPristine();
        $('#applicationdetail').modal('show');
    });
  }

  $scope.activateApplicationJson = function(id) {
    console.log('Activating application json...', id);
    Applications.get(id, function(){
      //$scope.form.userDetail.$setPristine();
      $('#applicationJson').modal('show');
      $scope.prettifyJson();
    });
  }

  $scope.newApplicationDetail = function() {
    Applications.application = {isNew: true};
    $scope.application = {isNew: true};
    //Users.userRoles = {};
    //$scope.form.applicationDetail.$setPristine();
    $('#applicationdetail').modal('show');
    /*
    var modalInstance = $uibModal.open({
      animation: $scope.animationsEnabled,
      templateUrl: 'template/applicationdetail.html',
      controller: 'ApplicationdetailCtrl',
      //size: size,
      resolve: {
        application: {isNew: true},
        items: function () {
          return $scope.items;
        }
      }
    });
    */
  }

  // -- Should be in ApplicationdetailCtrl ---
  $scope.applicationProperties = [
    {value: 'id', readOnly: 'true'},
    //{value: 'id',    minLength: 2, maxLength: 64, required: true, type: 'text', validationMsg:'Must be between 2-64 characters long.'},
    {value: 'name',    minLength: 2, maxLength: 64, required: true, type: 'text', validationMsg:'Must be between 2-64 characters long.'},
    {value: 'defaultOrganizationName',    minLength: 2, maxLength: 64, required: true, type: 'text', validationMsg:'Must be between 2-64 characters long.'},
    {value: 'defaultRoleName',    minLength: 2, maxLength: 64, required: true, type: 'text', validationMsg:'Must be between 2-64 characters long.'},
    {value: 'description',    required: false, type: 'text'},
    {value: 'applicationUrl',     required: false, type: 'url', validationMsg: 'Must be valid URL.'},
    {value: 'logoUrl', required: false, type: 'url', validationMsg: 'Must be valid URL.'},
    {value: 'fullTokenApplication',    required: false, type: 'text'},
    {value: 'secret', minLength: 12, maxLength: 254, required: false, type: 'text', validationMsg:'Must be between 12-254 characters long. No spaces allowed.'},
    {value: 'roleNames', required: false, type: 'text', validationMsg:'Comma separated list of available role names'},
    {value: 'orgNames', required: false, type: 'text', validationMsg:'Comma separated list of available organization names'}
  ];

  $scope.applicationJsonProperties = [
    {value: 'applicationJson', required: false, type: 'json', validationMsg:'The input must be valid json. Recomend http://jsonlint.com for manual validation.'},
  ];

  $scope.dict = {
    en: {
      name: 'Application Name (*)',
      id: 'Application Id',
      defaultOrganizationName: 'Default Organization Name (*)',
      defaultRoleName: 'Default Role Name (*)',
      applicationUrl: 'URL to Application',
      description: 'Description of Application',
      logoUrl: 'URL to Application Logo',
      fullTokenApplication: 'Whydah Admin application',
      secret: 'Application Secret',
      applicationJson: 'Json override',
      roleNames: 'Available role names',
      orgNames: 'Available organization names'
    }
  }

  $scope.save = function() {
    // Make sure these $scope-values are properly connected to the view
    if($scope.form.applicationDetail.$valid){
      if(Applications.application.isNew) {
        var newApplication = angular.copy(Applications.application);
        delete newApplication.isNew;
        Applications.add(newApplication, function(){
          delete Applications.application.isNew;
          $scope.form.applicationDetail.$setPristine();
        });
      } else {
       Applications.save(Applications.application, function(){
          $scope.form.applicationDetail.$setPristine();
        });
      }
    } else {
      console.log('Tried to save an invalid form.');
    }
  }

  $scope.saveFromJson = function() {
    // Make sure these $scope-values are properly connected to the view
    if($scope.form.applicationJson.$valid){
      if(Applications.application.isNew) {
        var newApplication = angular.copy(Applications.application);
        delete newApplication.isNew;
        Applications.addFromJson(newApplication, function(){
          delete Applications.application.isNew;
          $scope.form.applicationJson.$setPristine();
        });
      } else {
        Applications.saveFromJson(Applications.application, function(){
          $scope.form.applicationJson.$setPristine();
        });
      }
    } else {
      console.log('Tried to save an invalid form.');
    }
  }

  $scope.prettifyJson = function() {
    try {
      var jsonObject = JSON.parse($scope.applications.application.applicationJson);
      var prettifiedJson = JSON.stringify(jsonObject, undefined, 2);
      $scope.applications.application.applicationJson = prettifiedJson;
    }catch (e) {
      Messages.add('danger', 'Could not prettify applicationJson. Error while parsing');
    }
  }

  $scope.delete = function() {
    var deleteUser = $window.confirm('Are you absolutely sure you want to delete '+ Applications.application.name +'?');

    if (deleteUser) {
      Applications.delete(Applications.application, function(){
        $scope.form.applicationDetail.$setPristine();
      });
    }
  }

});<|endoftext|>


<commit_before>/**
 * Functions for communication with API endpoints related to uploaded files.
 *
 * @module files/api
 */
import { Request } from "../app/request";

export const find = ({ fileType, page, perPage }) =>
    Request.get("/api/files").query({
        type: fileType,
        per_page: perPage,
        page
    });

/**
 * Get files of the given ``fileType``. Get a specific page of results using the ``page`` argument.
 *
 * @func
 * @param fileType {string} the file type to get
 * @param page {number} the page of results to get
 * @returns {promise}
 */
export const list = ({ fileType, page }) =>
    Request.get("/api/files").query({
        type: fileType,
        page
    });

/**
 * Remove the file with the given ``fileId``.
 *
 * @func
 * @param fileId {string} the fileId to handleRemove
 * @returns {promise}
 */
export const remove = ({ fileId }) => Request.delete(`/api/files/${fileId}`);

/**
 * Upload a ``file`` with the given ``fileType``. Pass progress events to ``onProgress``.
 *
 * @func
 * @param file {object} the file object to upload
 * @param fileType {string} the file type to assign to the uploaded file
 * @param onProgress {function} a callback to call with ``ProgressEvent``s when they are fired
 * @param onSuccess {function} a callback to call when the upload succeeds
 * @param onFailure {function} a callback to call when the upload fails
 * @returns {promise}
 */
export const upload = ({ file, fileType, onProgress, onSuccess, onFailure }) =>
    Request.post(`/upload/${fileType}`)
        .query({ name: file.name })
        .attach("file", file)
        .on("progress", onProgress)
        .then(onSuccess)
        .catch(onFailure);
<commit_msg>Update upload API code in client<commit_after>/**
 * Functions for communication with API endpoints related to uploaded files.
 *
 * @module files/api
 */
import { Request } from "../app/request";

export const find = ({ fileType }) =>
    Request.get("/api/uploads").query({
        type: fileType
    });

/**
 * Get files of the given ``fileType``. Get a specific page of results using the ``page`` argument.
 *
 * @func
 * @param fileType {string} the file type to get
 * @param page {number} the page of results to get
 * @returns {promise}
 */
export const list = ({ fileType }) =>
    Request.get("/api/uploads").query({
        type: fileType
    });

/**
 * Remove the file with the given ``fileId``.
 *
 * @func
 * @param fileId {string} the fileId to handleRemove
 * @returns {promise}
 */
export const remove = ({ fileId }) => Request.delete(`/api/uploads/${fileId}`);

/**
 * Upload a ``file`` with the given ``fileType``. Pass progress events to ``onProgress``.
 *
 * @func
 * @param file {object} the file object to upload
 * @param fileType {string} the file type to assign to the uploaded file
 * @param onProgress {function} a callback to call with ``ProgressEvent``s when they are fired
 * @param onSuccess {function} a callback to call when the upload succeeds
 * @param onFailure {function} a callback to call when the upload fails
 * @returns {promise}
 */
export const upload = ({ file, fileType, onProgress, onSuccess, onFailure }) =>
    Request.post(`/api/uploads`)
        .query({ name: file.name, type: fileType })
        .attach("file", file)
        .on("progress", onProgress)
        .then(onSuccess)
        .catch(onFailure);
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Box from 'grommet/components/Box'
import Button from 'grommet/components/Button'
import Heading from 'grommet/components/Heading'
import RefreshIcon from 'grommet/components/icons/base/Refresh'
import Close from 'grommet/components/icons/base/Close'
import TrashIcon from 'grommet/components/icons/base/Trash' //eslint-disable-line
import Value from 'grommet/components/Value'
import TestCard from './testcard'
import { TestWordsLens, TestPercentageLens } from './lenses'
import styled from 'styled-components'
import IdentityComponent from '../../futils/identitycomponent'
import LinkPrevious from 'grommet/components/icons/base/LinkPrevious'
import { FoldingCube } from 'better-react-spinkit'
import ComposeR from '../../futils/composer'
import EitherComponent from '../../futils/eithercomponent'
import {
  SidebarActions, WhiteHoverCard, LineLink, FlameSidebarAction, LightGreyTestArea, LimitedSplit
} from './localcomponents'
import { ProgressIndicator } from 'office-ui-fabric-react/lib/ProgressIndicator'

export const LowPadButton = styled(Button)`
  border-radius: 0px;
  span {
    padding: 10px !important;
  }
`

export const CreateGameStatSeries = (correctWords, incorrectWords, wordsToPlay) => {
  const a = ((correctWords / (correctWords + incorrectWords + wordsToPlay)) * 100)
  const b = ((wordsToPlay / (correctWords + incorrectWords + wordsToPlay)) * 100)
  return [{
    label: `Correct ${correctWords}`,
    value: a,
    colorIndex: 'ok',
    onClick: () => console.log(a)
  },
    {
      label: `Incorrect ${incorrectWords}`,
      value: incorrectWords,
      max: (correctWords + incorrectWords + wordsToPlay),
      colorIndex: 'critical',
      onClick: () => null
    },
    {
      label: `Remaining ${wordsToPlay}`,
      value: b,
      colorIndex: 'warning',
      onClick: () => console.log(((wordsToPlay / (correctWords + incorrectWords + wordsToPlay)) * 100))
    }
  ]
}

export const ColoredMeter = styled(ProgressIndicator)`
  .progressBar_ef24ad53{
    background-color: ${props => props.color};
  }
`

const AlmostHeadingLikeParagraph = styled.p`
  font-size: 20px;
  font-weight: bold;
  align-self: center;
  margin-bottom: 0px;
`
const NoMarginBottomBox = styled(Box)`
  padding-top: 0px;
  padding-left: 0px;
  padding-right: 0px;
`

export default class Test extends Component {

  componentDidMount () {
    ga('send', 'test') // eslint-disable-line
    this.props.initTestState()
  }

  render () {
    return (
      <LimitedSplit flex='right' priority='left' separator={false} showOnResponsive='both'>
        <IdentityComponent fn={styled(Box)`
          background-color: #E5E3DF;
          overflowY : auto;
          &::-webkit-scrollbar-track
          {
           background-color: #fff;
          }
          &::-webkit-scrollbar
          {
           width: 10px;
           background-color: #F5F5F5;
          }
          &::-webkit-scrollbar-thumb
          {
           background-color: #FF576D;
          }
        `}
          colorIndex='neutral-4'
          size='medium'
          justify='between'
          full
        >
          <EitherComponent conditionerFn={() => this.props.leftLoader}
            leftComponent={_ => <Box full align='center' alignContent='center' justify='center'>
              <FoldingCube size={100} color='#1B998B' />
            </Box>}
            rightComponent={_ => null}
          />
          <EitherComponent conditionerFn={() => !this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={_ => <IdentityComponent
              fn={SidebarActions()}
              colorIndex='grey-4'
              size='large'
              pad='medium'
              justify='center'
              align='center'
              onClick={() =>
                this.props.showModal({ header: 'SELECT A LIST FOR THE TEST', content: 'TEST_LIST_SELECT' })}>
              Create New Test
            </IdentityComponent>}
            rightComponent={_ => null} />
          <EitherComponent conditionerFn={() => !this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={_ => <Box pad='medium'>
              {
                this.props.savedTests.map((test, index) =>
                  <WhiteHoverCard
                    key={index}
                    colorIndex='light-1'
                    onClick={() => this.props.getTest({ index, listId: test.listId })}
                    stretch
                    contentPad='medium'
                    justify='around'
                  >
                    <NoMarginBottomBox
                      direction='row' full='horizontal' justify='between'
                      alignItems='baseline'
                    >
                      <AlmostHeadingLikeParagraph>{test.listName}</AlmostHeadingLikeParagraph>
                      <LowPadButton icon={<Close size='small' />}
                        alignSelf='center'
                        onClick={(e) => {
                          e.stopPropagation()
                          this.props.delete({ index, listId: test.listId })
                        }} />
                    </NoMarginBottomBox>
                    <Value size='small'
                      value={TestWordsLens(this.props, 'correctWords', index)} units='word(s)' label='Correct'
                    />
                    <ColoredMeter color='#8cc800'
                      percentComplete={TestPercentageLens(this.props, 'correctWords', index)}
                    />
                    <Value size='small'
                      value={TestWordsLens(this.props, 'incorrectWords', index)} units='word(s)' label='Incorrect'
                    />
                    <ColoredMeter color='#ff324d'
                      percentComplete={TestPercentageLens(this.props, 'incorrectWords', index)}
                    />
                    <Value size='small'
                      value={TestWordsLens(this.props, 'wordsToPlay', index)} units='word(s)' label='Remaining'
                    />
                    <ColoredMeter color='#0a64a0'
                      percentComplete={TestPercentageLens(this.props, 'wordsToPlay', index)}
                    />
                  </WhiteHoverCard>
                )
              }
            </Box>}
            rightComponent={_ => null}
          />
          <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={_ => <IdentityComponent
              fn={SidebarActions()}
              colorIndex='grey-4'
              size='large'
              pad='small'
              justify='center'
              align='center'
              onClick={() => this.props.goBack()}>
              <Button icon={<LinkPrevious size='medium' colorIndex='light-1' />} />
            </IdentityComponent>}
            rightComponent={_ => null} />
          <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={_ => <Heading align='center'>{this.props.listName}</Heading>}
            rightComponent={_ => null}
          />
          <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={
              _ => <Box justify='center' pad={{ horizontal: 'large', vertical: 'medium' }} alignContent='center' >
                <Value value={TestWordsLens(this.props, 'correctWords', this.props.testIndex)}
                  units='word(s)' label='Correct' />
                <ColoredMeter color='#8cc800'
                  percentComplete={TestPercentageLens(this.props, 'correctWords', this.props.testIndex)} />
                <Value value={TestWordsLens(this.props, 'incorrectWords', this.props.testIndex)}
                  units='word(s)' label='Incorrect' />
                <ColoredMeter color='#ff324d'
                  percentComplete={TestPercentageLens(this.props, 'incorrectWords', this.props.testIndex)} />
                <Value value={TestWordsLens(this.props, 'wordsToPlay', this.props.testIndex)}
                  units='word(s)' label='Remaining' />
                <ColoredMeter color='#0a64a0'
                  percentComplete={TestPercentageLens(this.props, 'wordsToPlay', this.props.testIndex)} />
              </Box>}
            rightComponent={_ => null}
          />
          <Box>
            <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.leftLoader}
              leftComponent={_ => <IdentityComponent
                fn={ComposeR(SidebarActions, FlameSidebarAction)()}
                colorIndex='grey-4'
                size='large'
                pad='small'
                justify='center'
                align='center'
                alignSelf='end'
                onClick={() => this.props.reset(this.props.listId)}>
                <Button icon={<RefreshIcon size='large' colorIndex='light-1' />} />
              </IdentityComponent>}
              rightComponent={_ => null}
            />
          </Box>
        </IdentityComponent>
        <LightGreyTestArea full colorIndex='light-2' justify='center' direction='row' align='center'>
          <EitherComponent conditionerFn={() => !this.props.ongoingTest}
            leftComponent={_ =>
              <Heading>
                <LineLink onClick={() =>
                  this.props.showModal({ header: 'SELECT A LIST FOR THE TEST', content: 'TEST_LIST_SELECT' })}>
                  Create New Test
                </LineLink> or select from previous ones</Heading>}
            rightComponent={_ => null}
          />
          <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.rightLoader}
            leftComponent={_ =>
              <TestCard word={this.props.testWordsArray[this.props.testWordsCounter] &&
              this.props.testWordsArray[this.props.testWordsCounter].word}
                lexicalCategory={this.props.testWordsArray[this.props.testWordsCounter] &&
                this.props.testWordsArray[this.props.testWordsCounter].lexicalCategory}
                meaning={this.props.testWordsArray[this.props.testWordsCounter] &&
                this.props.testWordsArray[this.props.testWordsCounter].meaning}
                example={this.props.testWordsArray[this.props.testWordsCounter] &&
                this.props.testWordsArray[this.props.testWordsCounter].example}
                hiddenCondition={!this.props.revealed && this.props.testWordsCounter <
                this.props.testWordsArray.length}
                revealedCondition={this.props.revealed &&
                this.props.testWordsCounter < this.props.testWordsArray.length}
                completedCondition={this.props.testWordsCounter === this.props.testWordsArray.length}
                revealFn={() => this.props.reveal()}
                onCorrect={() => this.props.setStatus({
                  status: 1, wordObj: this.props.testWordsArray[this.props.testWordsCounter]
                })}
                onIncorrect={() =>
                  this.props.setStatus({
                    status: -1, wordObj: this.props.testWordsArray[this.props.testWordsCounter]
                  })}
              />} rightComponent={_ => null} />
          { this.props.ongoingTest && this.props.rightLoader && <FoldingCube size={100} color='#865cd6' /> }
        </LightGreyTestArea>
      </LimitedSplit>
    )
  }
}

Test.propTypes = {
  initTestState: PropTypes.func,
  savedTests: PropTypes.array,
  ongoingTest: PropTypes.bool,
  goBack: PropTypes.func,
  listName: PropTypes.string,
  getTest: PropTypes.func,
  showModal: PropTypes.func,
  revealed: PropTypes.bool,
  reveal: PropTypes.func,
  testWordsArray: PropTypes.array,
  testWordsCounter: PropTypes.number,
  setStatus: PropTypes.func,
  listId: PropTypes.string,
  reset: PropTypes.func,
  testIndex: PropTypes.number,
  delete: PropTypes.func,
  leftLoader: PropTypes.bool,
  rightLoader: PropTypes.bool
}
<commit_msg>test main code cleanup<commit_after>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Box from 'grommet/components/Box'
import Button from 'grommet/components/Button'
import Heading from 'grommet/components/Heading'
import RefreshIcon from 'grommet/components/icons/base/Refresh'
import Close from 'grommet/components/icons/base/Close'
import TrashIcon from 'grommet/components/icons/base/Trash' //eslint-disable-line
import Value from 'grommet/components/Value'
import TestCard from './testcard'
import { TestWordsLens, TestPercentageLens } from './lenses'
import styled from 'styled-components'
import IdentityComponent from '../../futils/identitycomponent'
import LinkPrevious from 'grommet/components/icons/base/LinkPrevious'
import { FoldingCube } from 'better-react-spinkit'
import ComposeR from '../../futils/composer'
import EitherComponent from '../../futils/eithercomponent'
import {
  SidebarActions, WhiteHoverCard, LineLink, FlameSidebarAction, LightGreyTestArea, LimitedSplit
} from './localcomponents'
import { ProgressIndicator } from 'office-ui-fabric-react/lib/ProgressIndicator'

export const LowPadButton = styled(Button)`
  border-radius: 0px;
  span {
    padding: 10px !important;
  }
`

export const ColoredMeter = styled(ProgressIndicator)`
  .progressBar_ef24ad53{
    background-color: ${props => props.color};
  }
`

const AlmostHeadingLikeParagraph = styled.p`
  font-size: 20px;
  font-weight: bold;
  align-self: center;
  margin-bottom: 0px;
`
const NoMarginBottomBox = styled(Box)`
  padding-top: 0px;
  padding-left: 0px;
  padding-right: 0px;
`

export default class Test extends Component {

  componentDidMount () {
    ga('send', 'test') // eslint-disable-line
    this.props.initTestState()
  }

  render () {
    return (
      <LimitedSplit flex='right' priority='left' separator={false} showOnResponsive='both'>
        <IdentityComponent fn={styled(Box)`
          background-color: #E5E3DF;
          overflowY : auto;
          &::-webkit-scrollbar-track
          {
           background-color: #fff;
          }
          &::-webkit-scrollbar
          {
           width: 10px;
           background-color: #F5F5F5;
          }
          &::-webkit-scrollbar-thumb
          {
           background-color: #FF576D;
          }
        `}
          colorIndex='neutral-4'
          size='medium'
          justify='between'
          full
        >
          <EitherComponent conditionerFn={() => this.props.leftLoader}
            leftComponent={_ => <Box full align='center' alignContent='center' justify='center'>
              <FoldingCube size={100} color='#1B998B' />
            </Box>}
            rightComponent={_ => null}
          />
          <EitherComponent conditionerFn={() => !this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={_ => <IdentityComponent
              fn={SidebarActions()}
              colorIndex='grey-4'
              size='large'
              pad='medium'
              justify='center'
              align='center'
              onClick={() =>
                this.props.showModal({ header: 'SELECT A LIST FOR THE TEST', content: 'TEST_LIST_SELECT' })}>
              Create New Test
            </IdentityComponent>}
            rightComponent={_ => null} />
          <EitherComponent conditionerFn={() => !this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={_ => <Box pad='medium'>
              {
                this.props.savedTests.map((test, index) =>
                  <WhiteHoverCard
                    key={index}
                    colorIndex='light-1'
                    onClick={() => this.props.getTest({ index, listId: test.listId })}
                    stretch
                    contentPad='medium'
                    justify='around'
                  >
                    <NoMarginBottomBox
                      direction='row' full='horizontal' justify='between'
                      alignItems='baseline'
                    >
                      <AlmostHeadingLikeParagraph>{test.listName}</AlmostHeadingLikeParagraph>
                      <LowPadButton icon={<Close size='small' />}
                        alignSelf='center'
                        onClick={(e) => {
                          e.stopPropagation()
                          this.props.delete({ index, listId: test.listId })
                        }} />
                    </NoMarginBottomBox>
                    <Value size='small'
                      value={TestWordsLens(this.props, 'correctWords', index)} units='word(s)' label='Correct'
                    />
                    <ColoredMeter color='#8cc800'
                      percentComplete={TestPercentageLens(this.props, 'correctWords', index)}
                    />
                    <Value size='small'
                      value={TestWordsLens(this.props, 'incorrectWords', index)} units='word(s)' label='Incorrect'
                    />
                    <ColoredMeter color='#ff324d'
                      percentComplete={TestPercentageLens(this.props, 'incorrectWords', index)}
                    />
                    <Value size='small'
                      value={TestWordsLens(this.props, 'wordsToPlay', index)} units='word(s)' label='Remaining'
                    />
                    <ColoredMeter color='#0a64a0'
                      percentComplete={TestPercentageLens(this.props, 'wordsToPlay', index)}
                    />
                  </WhiteHoverCard>
                )
              }
            </Box>}
            rightComponent={_ => null}
          />
          <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={_ => <IdentityComponent
              fn={SidebarActions()}
              colorIndex='grey-4'
              size='large'
              pad='small'
              justify='center'
              align='center'
              onClick={() => this.props.goBack()}>
              <Button icon={<LinkPrevious size='medium' colorIndex='light-1' />} />
            </IdentityComponent>}
            rightComponent={_ => null} />
          <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={_ => <Heading align='center'>{this.props.listName}</Heading>}
            rightComponent={_ => null}
          />
          <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.leftLoader}
            leftComponent={
              _ => <Box justify='center' pad={{ horizontal: 'large', vertical: 'medium' }} alignContent='center' >
                <Value value={TestWordsLens(this.props, 'correctWords', this.props.testIndex)}
                  units='word(s)' label='Correct' />
                <ColoredMeter color='#8cc800'
                  percentComplete={TestPercentageLens(this.props, 'correctWords', this.props.testIndex)} />
                <Value value={TestWordsLens(this.props, 'incorrectWords', this.props.testIndex)}
                  units='word(s)' label='Incorrect' />
                <ColoredMeter color='#ff324d'
                  percentComplete={TestPercentageLens(this.props, 'incorrectWords', this.props.testIndex)} />
                <Value value={TestWordsLens(this.props, 'wordsToPlay', this.props.testIndex)}
                  units='word(s)' label='Remaining' />
                <ColoredMeter color='#0a64a0'
                  percentComplete={TestPercentageLens(this.props, 'wordsToPlay', this.props.testIndex)} />
              </Box>}
            rightComponent={_ => null}
          />
          <Box>
            <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.leftLoader}
              leftComponent={_ => <IdentityComponent
                fn={ComposeR(SidebarActions, FlameSidebarAction)()}
                colorIndex='grey-4'
                size='large'
                pad='small'
                justify='center'
                align='center'
                alignSelf='end'
                onClick={() => this.props.reset(this.props.listId)}>
                <Button icon={<RefreshIcon size='large' colorIndex='light-1' />} />
              </IdentityComponent>}
              rightComponent={_ => null}
            />
          </Box>
        </IdentityComponent>
        <LightGreyTestArea full colorIndex='light-2' justify='center' direction='row' align='center'>
          <EitherComponent conditionerFn={() => !this.props.ongoingTest}
            leftComponent={_ =>
              <Heading>
                <LineLink onClick={() =>
                  this.props.showModal({ header: 'SELECT A LIST FOR THE TEST', content: 'TEST_LIST_SELECT' })}>
                  Create New Test
                </LineLink> or select from previous ones</Heading>}
            rightComponent={_ => null}
          />
          <EitherComponent conditionerFn={() => this.props.ongoingTest && !this.props.rightLoader}
            leftComponent={_ =>
              <TestCard word={this.props.testWordsArray[this.props.testWordsCounter] &&
              this.props.testWordsArray[this.props.testWordsCounter].word}
                lexicalCategory={this.props.testWordsArray[this.props.testWordsCounter] &&
                this.props.testWordsArray[this.props.testWordsCounter].lexicalCategory}
                meaning={this.props.testWordsArray[this.props.testWordsCounter] &&
                this.props.testWordsArray[this.props.testWordsCounter].meaning}
                example={this.props.testWordsArray[this.props.testWordsCounter] &&
                this.props.testWordsArray[this.props.testWordsCounter].example}
                hiddenCondition={!this.props.revealed && this.props.testWordsCounter <
                this.props.testWordsArray.length}
                revealedCondition={this.props.revealed &&
                this.props.testWordsCounter < this.props.testWordsArray.length}
                completedCondition={this.props.testWordsCounter === this.props.testWordsArray.length}
                revealFn={() => this.props.reveal()}
                onCorrect={() => this.props.setStatus({
                  status: 1, wordObj: this.props.testWordsArray[this.props.testWordsCounter]
                })}
                onIncorrect={() =>
                  this.props.setStatus({
                    status: -1, wordObj: this.props.testWordsArray[this.props.testWordsCounter]
                  })}
              />} rightComponent={_ => null} />
          { this.props.ongoingTest && this.props.rightLoader && <FoldingCube size={100} color='#865cd6' /> }
        </LightGreyTestArea>
      </LimitedSplit>
    )
  }
}

Test.propTypes = {
  initTestState: PropTypes.func,
  savedTests: PropTypes.array,
  ongoingTest: PropTypes.bool,
  goBack: PropTypes.func,
  listName: PropTypes.string,
  getTest: PropTypes.func,
  showModal: PropTypes.func,
  revealed: PropTypes.bool,
  reveal: PropTypes.func,
  testWordsArray: PropTypes.array,
  testWordsCounter: PropTypes.number,
  setStatus: PropTypes.func,
  listId: PropTypes.string,
  reset: PropTypes.func,
  testIndex: PropTypes.number,
  delete: PropTypes.func,
  leftLoader: PropTypes.bool,
  rightLoader: PropTypes.bool
}
<|endoftext|>


<commit_before>/*jslint nomen: true, vars: true */
/*global interstate,able,uid,console,jQuery,window,Box2D */

(function (ist, $) {
	"use strict";

	if(!window.Box2D) { return; }

	var cjs = ist.cjs,
		_ = ist._;

	var PIXELS_PER_METER = 30;

	var B2Vec2 = Box2D.Common.Math.b2Vec2,
		B2AABB = Box2D.Collision.b2AABB,
		B2BodyDef = Box2D.Dynamics.b2BodyDef,
		b2Body = Box2D.Dynamics.b2Body,
		B2FixtureDef = Box2D.Dynamics.b2FixtureDef,
		B2Fixture = Box2D.Dynamics.b2Fixture,
		B2World = Box2D.Dynamics.b2World,
		B2MassData = Box2D.Collision.Shapes.b2MassData,
		B2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
		B2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
		B2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef,
		b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
		b2ContactListener = Box2D.Dynamics.b2ContactListener;

	var fixDef = new B2FixtureDef();
	fixDef.density = 1.0;
	fixDef.friction = 0.5;
	fixDef.restitution = 0.2;

	var bodyDef = new B2BodyDef();
	bodyDef.type = b2Body.b2_dynamicBody;

	ist.contact_listeners = new RedMap({
		equals: ist.check_contextual_object_equality,
		hash: function(obj) {
			if(obj.hash) {
				return obj.hash();
			} else {
				return obj.toString();
			}
		}
	});

	ist.WorldAttachment = ist.register_attachment("box2d_world", {
			ready: function() {
				this.world = new B2World(new B2Vec2(0, 0), true);
				this.world.SetContactListener({
					BeginContact: function() { },
					EndContact: function(contact) {
						var cobj_a = contact.m_fixtureA.cobj,
							cobj_b = contact.m_fixtureB.cobj;

						var contact_listeners = _.filter(ist.contact_listeners.get(cobj_a), function(x) {
							return ist.check_contextual_object_equality(x.target, cobj_b);
						}).concat(_.filter(ist.contact_listeners.get(cobj_b), function(x) {
							return ist.check_contextual_object_equality(x.target, cobj_a);
						}));
						window.setTimeout(function() {
							_.each(contact_listeners, function(x) {
								x.callback(contact);
							});
						}, 0);
					},
					PreSolve: function() { },
					PostSolve: function() { }
				});

				var update_world = _.bind(function() {
					this.world.Step(1 / 60, 10, 10);
					ist.requestAnimationFrame.call(window, update_world);
					/*
					if(this.world.m_gravity.y < 5) {
						this.world.DrawDebugData();
					}
					*/
				}, this);
				ist.requestAnimationFrame.call(window, update_world);

/*
				var world = this.world;
				if(world.m_gravity.y < 5) {
					var debugDraw = new b2DebugDraw();
					debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
					debugDraw.SetDrawScale(PIXELS_PER_METER);
					debugDraw.SetFillAlpha(0.3);
					debugDraw.SetLineThickness(1.0);
					debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
					world.SetDebugDraw(debugDraw);
				}
				*/
			},
			parameters: {
				gravity: function(contextual_object) {
					var gravity_x = contextual_object.prop_val("gx"),
						gravity_y = contextual_object.prop_val("gy");

					var gravity_vector = new B2Vec2(gravity_x, gravity_y);
					this.world.SetGravity(gravity_vector);
					var body_list = this.world.GetBodyList();
					var body_len = this.world.GetBodyCount();
					for(var i = 0; i<body_len; i++) {
						body_list.SetAwake(true);
						body_list = body_list.GetNext();
					}
				}
			},
			proto_props: {
				get_world: function() {
					return this.world;
				}
			}
		});
	ist.FixtureAttachment = ist.register_attachment("box2d_fixture", {
			ready: function() {
				var contextual_object = this.get_contextual_object();

				this.b2x = cjs.constraint(function() {
					var shape_type = contextual_object.prop_val("shape");
					if(shape_type === "circle") {
						return contextual_object.prop_val("cx");
					} else if(shape_type === "rectangle") {
						var x = contextual_object.prop_val("x"),
							width = contextual_object.prop_val("width");
						return x+width/2;
					} else {
						return -1;
					}
				});
				this.b2y = cjs.constraint(function() {
					var shape_type = contextual_object.prop_val("shape");
					if(shape_type === "circle") {
						return contextual_object.prop_val("cy");
					} else if(shape_type === "rectangle") {
						var y = contextual_object.prop_val("y"),
							height = contextual_object.prop_val("height");
						return y+height/2;
					} else {
						return -1;
					}
				});
				this.b2vx = cjs.constraint(0);
				this.b2vy= cjs.constraint(0);
				this.b2t = cjs.constraint(0);
				this.b2vt = cjs.constraint(0);
				this.body = cjs.constraint();
				this.shape = cjs.constraint();
				this.fixture = cjs.constraint();

				this._update_interval = window.setInterval(_.bind(function() {
					var body = this.get_body();
					if(body) {
						var position = body.GetPosition();
						var angle = body.GetAngle();
						var linearVelocity = body.GetLinearVelocity();
						var angularVelocity = body.GetAngularVelocity();

						cjs.wait();
						var shape = this.shape.get();
						if(shape instanceof B2CircleShape) {
							this.b2x.set(position.x * PIXELS_PER_METER);
							this.b2y.set(position.y * PIXELS_PER_METER);
						} else if(shape instanceof B2PolygonShape) {
							if(Math.random() < 0.001) {
								console.log(shape);
							}
							this.b2x.set((position.x) * PIXELS_PER_METER);
							this.b2y.set((position.y) * PIXELS_PER_METER);
						}

						this.b2vx.set(linearVelocity.x);
						this.b2vy.set(linearVelocity.y);

						this.b2t.set(angle);

						this.b2vt.set(angularVelocity);

						cjs.signal();
					}
					/**/
				}, this), 1000 / 60);
			},
			destroy: function(silent) {
				window.clearInterval(this._update_interval);

				var body = this.get_body();
				if(body) {
					var world = body.m_world;
					world.DestroyBody(body);
				}
			},
			parameters: {
				radius: function(contextual_object) {
					var shape = this.shape.get();
					if(shape instanceof B2CircleShape) {
						var radius = contextual_object.prop_val("r");
						shape.SetRadius(radius/PIXELS_PER_METER);
					}
				},
				fixture_attributes: function(contextual_object) {
					var fixture = this.get_fixture();
					if(fixture) {
						var density = contextual_object.prop_val("density"),
							friction = contextual_object.prop_val("friction"),
							restitution = contextual_object.prop_val("restitution");

						fixture.density = density;
						fixture.friction = friction;
						fixture.restition = restitution;
					}
				},
				path: function(contextual_object) {
					var shape = this.shape.get();
					if(shape instanceof B2PolygonShape) {
						var width = contextual_object.prop_val("width"),
							height = contextual_object.prop_val("height");
						shape.SetAsBox(width/(2*PIXELS_PER_METER),
										height/(2*PIXELS_PER_METER));
					}
				},
				fixed: function(contextual_object) {
					var fixed = contextual_object.prop_val("fixed");
					var body = this.body.get();

					if(body) {
						if(fixed) {
							var shape = this.shape.get(), x, y;
							if(shape instanceof B2CircleShape) {
								var radius = contextual_object.prop_val("r");
								x = (contextual_object.prop_val("cx")) / PIXELS_PER_METER;
								y = (contextual_object.prop_val("cy")) / PIXELS_PER_METER;
							} else if(shape instanceof B2PolygonShape) {
								var width = contextual_object.prop_val("width");
								var height = contextual_object.prop_val("height");
								x = (contextual_object.prop_val("x")+.5*width) / PIXELS_PER_METER;
								y = (contextual_object.prop_val("y")+.5*height) / PIXELS_PER_METER;
							}
							body.SetType(b2Body.b2_staticBody);
							body.SetPosition(new B2Vec2(x, y));
						} else {
							body.SetType(b2Body.b2_dynamicBody);
							body.SetAwake(true);
						}
					}
				}, world: function(contextual_object) {
					var world_val = contextual_object.prop_val("world");

					if(world_val) {
						var world_attachment = world_val.get_attachment_instance("box2d_world");
						var world = world_attachment.get_world();
						if(this.world !== world) {
							var shape_type = contextual_object.prop_val("shape");
							if(shape_type === "circle" || shape_type === "rectangle") {
								var density = contextual_object.prop_val("density"),
									friction = contextual_object.prop_val("friction"),
									restitution = contextual_object.prop_val("restitution"),
									fixed = contextual_object.prop_val("fixed"),
									fixture;

								fixDef.density = density;
								fixDef.friction = friction;
								fixDef.restitution = restitution;

								bodyDef.type = fixed ? b2Body.b2_staticBody : b2Body.b2_dynamicBody;

								if(shape_type === "circle") {
									var cx = contextual_object.prop_val("cx"),
										cy = contextual_object.prop_val("cy"),
										radius = contextual_object.prop_val("r");

									bodyDef.position.x = (cx) / PIXELS_PER_METER;
									bodyDef.position.y = (cy) / PIXELS_PER_METER;
									fixDef.shape = new B2CircleShape(radius/PIXELS_PER_METER);
								} else if(shape_type === "rectangle") {
									var x = contextual_object.prop_val("x"),
										y = contextual_object.prop_val("y"),
										width = contextual_object.prop_val("width"),
										height = contextual_object.prop_val("height");

									bodyDef.position.x = (x+.5*width) / PIXELS_PER_METER;
									bodyDef.position.y = (y+.5*height) / PIXELS_PER_METER;
									fixDef.shape = new B2PolygonShape();
									fixDef.shape.SetAsBox(width/(2*PIXELS_PER_METER),
															height/(2*PIXELS_PER_METER));

								}
								fixture = world.CreateBody(bodyDef).CreateFixture(fixDef);
								fixture.cobj = contextual_object;

								this.fixture.set(fixture);

								var body = fixture.GetBody();

								this.body.set(body);
								this.shape.set(fixture.GetShape());

								var position = body.GetPosition();
								var angle = body.GetAngle();
								var linearVelocity = body.GetLinearVelocity();
								var angularVelocity = body.GetAngularVelocity();

								this.b2x.set(position.x * PIXELS_PER_METER);
								this.b2y.set(position.y * PIXELS_PER_METER);

								this.b2vx.set(linearVelocity.x);
								this.b2vy.set(linearVelocity.y);

								this.b2t.set(angle);

								this.b2vt.set(angularVelocity);

								this.world = world;
							}
						}
					}
				}
			},
			proto_props: {
				get_fixture: function() {
					return this.fixture.get();
				},
				get_body: function() {
					return this.body.get();
				},
				get_shape: function() {
					return this.shape.get();
				},
				getComputedX: function() {
					return this.b2x.get();
				},
				getComputedY: function() {
					return this.b2y.get();
				},
				getComputedTheta: function() {
					return this.b2t.get();
				},
				applyForce: function(x, y) {
					var body = this.get_body();
					if(body) {
						body.ApplyForce(new B2Vec2(x, y), body.GetWorldCenter());
					}
				},
				applyImpulse: function(x, y) {
					var body = this.get_body();
					if(body) {
						body.ApplyImpulse(new B2Vec2(x, y), body.GetWorldCenter());
					}
				}
			}
		});
}(interstate, jQuery));
<commit_msg>updated attachment location<commit_after>/*jslint nomen: true, vars: true */
/*global interstate,able,uid,console,jQuery,window,Box2D */

(function (ist, $) {
	"use strict";

	if(!window.Box2D) { return; }

	var cjs = ist.cjs,
		_ = ist._;

	var PIXELS_PER_METER = 30;

	var B2Vec2 = Box2D.Common.Math.b2Vec2,
		B2AABB = Box2D.Collision.b2AABB,
		B2BodyDef = Box2D.Dynamics.b2BodyDef,
		b2Body = Box2D.Dynamics.b2Body,
		B2FixtureDef = Box2D.Dynamics.b2FixtureDef,
		B2Fixture = Box2D.Dynamics.b2Fixture,
		B2World = Box2D.Dynamics.b2World,
		B2MassData = Box2D.Collision.Shapes.b2MassData,
		B2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
		B2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
		B2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef,
		b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
		b2ContactListener = Box2D.Dynamics.b2ContactListener;

	var fixDef = new B2FixtureDef();
	fixDef.density = 1.0;
	fixDef.friction = 0.5;
	fixDef.restitution = 0.2;

	var bodyDef = new B2BodyDef();
	bodyDef.type = b2Body.b2_dynamicBody;

	ist.contact_listeners = new RedMap({
		equals: ist.check_contextual_object_equality,
		hash: function(obj) {
			if(obj.hash) {
				return obj.hash();
			} else {
				return obj.toString();
			}
		}
	});

	ist.WorldAttachment = ist.register_attachment("box2d_world", {
			ready: function() {
				this.world = new B2World(new B2Vec2(0, 0), true);
				this.world.SetContactListener({
					BeginContact: function() { },
					EndContact: function(contact) {
						var cobj_a = contact.m_fixtureA.cobj,
							cobj_b = contact.m_fixtureB.cobj;

						var contact_listeners = _.filter(ist.contact_listeners.get(cobj_a), function(x) {
							return ist.check_contextual_object_equality(x.target, cobj_b);
						}).concat(_.filter(ist.contact_listeners.get(cobj_b), function(x) {
							return ist.check_contextual_object_equality(x.target, cobj_a);
						}));
						window.setTimeout(function() {
							_.each(contact_listeners, function(x) {
								x.callback(contact);
							});
						}, 0);
					},
					PreSolve: function() { },
					PostSolve: function() { }
				});

				var update_world = _.bind(function() {
					this.world.Step(1 / 60, 10, 10);
					ist.requestAnimationFrame.call(window, update_world);
					/*
					if(this.world.m_gravity.y < 5) {
						this.world.DrawDebugData();
					}
					*/
				}, this);
				ist.requestAnimationFrame.call(window, update_world);

/*
				var world = this.world;
				if(world.m_gravity.y < 5) {
					var debugDraw = new b2DebugDraw();
					debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
					debugDraw.SetDrawScale(PIXELS_PER_METER);
					debugDraw.SetFillAlpha(0.3);
					debugDraw.SetLineThickness(1.0);
					debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
					world.SetDebugDraw(debugDraw);
				}
				*/
			},
			parameters: {
				gravity: function(contextual_object) {
					var gravity_x = contextual_object.prop_val("gx"),
						gravity_y = contextual_object.prop_val("gy");

					var gravity_vector = new B2Vec2(gravity_x, gravity_y);
					this.world.SetGravity(gravity_vector);
					var body_list = this.world.GetBodyList();
					var body_len = this.world.GetBodyCount();
					for(var i = 0; i<body_len; i++) {
						body_list.SetAwake(true);
						body_list = body_list.GetNext();
					}
				}
			},
			proto_props: {
				get_world: function() {
					return this.world;
				}
			}
		});
	ist.FixtureAttachment = ist.register_attachment("box2d_fixture", {
			ready: function() {
				var contextual_object = this.get_contextual_object();

				this.b2x = cjs.constraint(function() {
					var shape_type = contextual_object.prop_val("shape");
					if(shape_type === "circle") {
						return contextual_object.prop_val("cx");
					} else if(shape_type === "rectangle") {
						var x = contextual_object.prop_val("x"),
							width = contextual_object.prop_val("width");
						return x+width/2;
					} else {
						return -1;
					}
				});
				this.b2y = cjs.constraint(function() {
					var shape_type = contextual_object.prop_val("shape");
					if(shape_type === "circle") {
						return contextual_object.prop_val("cy");
					} else if(shape_type === "rectangle") {
						var y = contextual_object.prop_val("y"),
							height = contextual_object.prop_val("height");
						return y+height/2;
					} else {
						return -1;
					}
				});
				this.b2vx = cjs.constraint(0);
				this.b2vy= cjs.constraint(0);
				this.b2t = cjs.constraint(0);
				this.b2vt = cjs.constraint(0);
				this.body = cjs.constraint();
				this.shape = cjs.constraint();
				this.fixture = cjs.constraint();

				this._update_interval = window.setInterval(_.bind(function() {
					var body = this.get_body();
					if(body) {
						var position = body.GetPosition();
						var angle = body.GetAngle();
						var linearVelocity = body.GetLinearVelocity();
						var angularVelocity = body.GetAngularVelocity();

						cjs.wait();
						var shape = this.shape.get();
						if(shape instanceof B2CircleShape) {
							this.b2x.set(position.x * PIXELS_PER_METER);
							this.b2y.set(position.y * PIXELS_PER_METER);
						} else if(shape instanceof B2PolygonShape) {
							var v0 = shape.m_vertices[0],
								v1 = shape.m_vertices[2],
								width = Math.abs(v0.x-v1.x),
								height = Math.abs(v0.y-v1.y);
							this.b2x.set((position.x-width/2) * PIXELS_PER_METER);
							this.b2y.set((position.y-height/2) * PIXELS_PER_METER);
						}

						this.b2vx.set(linearVelocity.x);
						this.b2vy.set(linearVelocity.y);

						this.b2t.set(angle);

						this.b2vt.set(angularVelocity);

						cjs.signal();
					}
					/**/
				}, this), 1000 / 60);
			},
			destroy: function(silent) {
				window.clearInterval(this._update_interval);

				var body = this.get_body();
				if(body) {
					var world = body.m_world;
					world.DestroyBody(body);
				}
			},
			parameters: {
				radius: function(contextual_object) {
					var shape = this.shape.get();
					if(shape instanceof B2CircleShape) {
						var radius = contextual_object.prop_val("r");
						shape.SetRadius(radius/PIXELS_PER_METER);
					}
				},
				fixture_attributes: function(contextual_object) {
					var fixture = this.get_fixture();
					if(fixture) {
						var density = contextual_object.prop_val("density"),
							friction = contextual_object.prop_val("friction"),
							restitution = contextual_object.prop_val("restitution");

						fixture.density = density;
						fixture.friction = friction;
						fixture.restition = restitution;
					}
				},
				path: function(contextual_object) {
					var shape = this.shape.get();
					if(shape instanceof B2PolygonShape) {
						var width = contextual_object.prop_val("width"),
							height = contextual_object.prop_val("height");
						shape.SetAsBox(width/(2*PIXELS_PER_METER),
										height/(2*PIXELS_PER_METER));
					}
				},
				fixed: function(contextual_object) {
					var fixed = contextual_object.prop_val("fixed");
					var body = this.body.get();

					if(body) {
						if(fixed) {
							var shape = this.shape.get(), x, y;
							if(shape instanceof B2CircleShape) {
								var radius = contextual_object.prop_val("r");
								x = (contextual_object.prop_val("cx")) / PIXELS_PER_METER;
								y = (contextual_object.prop_val("cy")) / PIXELS_PER_METER;
							} else if(shape instanceof B2PolygonShape) {
								var width = contextual_object.prop_val("width");
								var height = contextual_object.prop_val("height");
								x = (contextual_object.prop_val("x")+.5*width) / PIXELS_PER_METER;
								y = (contextual_object.prop_val("y")+.5*height) / PIXELS_PER_METER;
							}
							body.SetType(b2Body.b2_staticBody);
							body.SetPosition(new B2Vec2(x, y));
						} else {
							body.SetType(b2Body.b2_dynamicBody);
							body.SetAwake(true);
						}
					}
				}, world: function(contextual_object) {
					var world_val = contextual_object.prop_val("world");

					if(world_val) {
						var world_attachment = world_val.get_attachment_instance("box2d_world");
						var world = world_attachment.get_world();
						if(this.world !== world) {
							var shape_type = contextual_object.prop_val("shape");
							if(shape_type === "circle" || shape_type === "rectangle") {
								var density = contextual_object.prop_val("density"),
									friction = contextual_object.prop_val("friction"),
									restitution = contextual_object.prop_val("restitution"),
									fixed = contextual_object.prop_val("fixed"),
									fixture;

								fixDef.density = density;
								fixDef.friction = friction;
								fixDef.restitution = restitution;

								bodyDef.type = fixed ? b2Body.b2_staticBody : b2Body.b2_dynamicBody;

								if(shape_type === "circle") {
									var cx = contextual_object.prop_val("cx"),
										cy = contextual_object.prop_val("cy"),
										radius = contextual_object.prop_val("r");

									bodyDef.position.x = (cx) / PIXELS_PER_METER;
									bodyDef.position.y = (cy) / PIXELS_PER_METER;
									fixDef.shape = new B2CircleShape(radius/PIXELS_PER_METER);
								} else if(shape_type === "rectangle") {
									var x = contextual_object.prop_val("x"),
										y = contextual_object.prop_val("y"),
										width = contextual_object.prop_val("width"),
										height = contextual_object.prop_val("height");

									bodyDef.position.x = (x+.5*width) / PIXELS_PER_METER;
									bodyDef.position.y = (y+.5*height) / PIXELS_PER_METER;
									fixDef.shape = new B2PolygonShape();
									fixDef.shape.SetAsBox(width/(2*PIXELS_PER_METER),
															height/(2*PIXELS_PER_METER));

								}
								fixture = world.CreateBody(bodyDef).CreateFixture(fixDef);
								fixture.cobj = contextual_object;

								this.fixture.set(fixture);

								var body = fixture.GetBody();

								this.body.set(body);
								this.shape.set(fixture.GetShape());

								var position = body.GetPosition();
								var angle = body.GetAngle();
								var linearVelocity = body.GetLinearVelocity();
								var angularVelocity = body.GetAngularVelocity();

								this.b2x.set(position.x * PIXELS_PER_METER);
								this.b2y.set(position.y * PIXELS_PER_METER);

								this.b2vx.set(linearVelocity.x);
								this.b2vy.set(linearVelocity.y);

								this.b2t.set(angle);

								this.b2vt.set(angularVelocity);

								this.world = world;
							}
						}
					}
				}
			},
			proto_props: {
				get_fixture: function() {
					return this.fixture.get();
				},
				get_body: function() {
					return this.body.get();
				},
				get_shape: function() {
					return this.shape.get();
				},
				getComputedX: function() {
					return this.b2x.get();
				},
				getComputedY: function() {
					return this.b2y.get();
				},
				getComputedTheta: function() {
					return this.b2t.get();
				},
				applyForce: function(x, y) {
					var body = this.get_body();
					if(body) {
						body.ApplyForce(new B2Vec2(x, y), body.GetWorldCenter());
					}
				},
				applyImpulse: function(x, y) {
					var body = this.get_body();
					if(body) {
						body.ApplyImpulse(new B2Vec2(x, y), body.GetWorldCenter());
					}
				}
			}
		});
}(interstate, jQuery));
<|endoftext|>


<commit_before>import { toBN, toHex, toChecksumAddress, isHexStrict } from 'web3-utils';
import { isAddress } from '@/core/helpers/addressUtils';
import SanitizeHex from '@/core/helpers/sanitizeHex';
import { Transaction } from '@ethereumjs/tx';
import { mapState, mapGetters } from 'vuex';
import vuexStore from '@/core/store';
import ErrorList from '../errors';
import Web3Contract from 'web3-eth-contract';
import { MAIN_TOKEN_ADDRESS } from '@/core/helpers/common';
import hasValidDecimals from '@/core/helpers/hasValidDecimals.js';
import { isNull } from 'lodash';
import BigNumber from 'bignumber.js';

class SendTransaction {
  constructor() {
    this.$store = vuexStore;
    Object.assign(this, mapState('wallet', ['balance', 'web3', 'address']));
    Object.assign(this, mapGetters('global', ['network']));
    this.currency = null;
    this.localGasPrice = '0';
    this.TX = {
      from: '0x',
      to: '0x',
      destination: '0x',
      nonce: '0x',
      gasPrice: '0x',
      gas: '0x5208', //21000
      value: '0x',
      destinationValue: '0x',
      data: '0x'
    };
  }
  setTo(_to, _type) {
    if (isAddress(_to)) {
      this.TX.destination = _to;
      this.TX.toDetails = _type;
    } else throw ErrorList.INVALID_TO_ADDRESS;
  }
  _setTo() {
    this.TX.to = this.isToken()
      ? toChecksumAddress(this.currency.contract)
      : toChecksumAddress(this.TX.destination);
  }
  setFrom(_from) {
    if (isAddress(_from)) this.TX.from = _from;
    else throw ErrorList.INVALID_FROM_ADDRESS;
  }
  _setGasPrice() {
    this.TX.gasPrice = toHex(toBN(this.localGasPrice));
  }
  setGasLimit(_gasLimit) {
    this.TX.gas = toHex(toBN(_gasLimit));
  }
  setLocalGasPrice(gasPrice) {
    this.localGasPrice = toHex(toBN(gasPrice));
  }
  setValue(_value) {
    if (isNaN(_value) || isNull(_value)) _value = 0;
    const _valueBN = new BigNumber(_value);
    if (!_valueBN.lt(0)) this.TX.destinationValue = toHex(_valueBN.toFixed());
    else throw ErrorList.NEGATIVE_VALUE;
  }
  _setValue() {
    if (this.isToken()) {
      this.TX.value = '0x00';
      this.setData(
        this.getTokenTransferABI(this.TX.destinationValue, this.TX.destination)
      );
    } else {
      this.TX.value = toHex(toBN(this.TX.destinationValue));
    }
  }
  setData(_data) {
    if (isHexStrict(_data)) this.TX.data = SanitizeHex(_data);
    else throw ErrorList.INVALID_DATA_HEX;
  }
  setNonce(_nonce) {
    this.TX.nonce = toHex(toBN(_nonce));
  }
  setCurrency(_currency) {
    this.currency = _currency;
    this.TX.data = '0x';
  }
  getEntireBal() {
    if (this.isToken()) {
      return this.currency.balance;
    }
    const gasPriceBN = toBN(this.localGasPrice);
    const fee = gasPriceBN.mul(toBN(this.TX.gas));
    return this.balance().gt(this.balance().sub(fee)) > 0
      ? this.balance().sub(fee)
      : 0;
  }
  txFee() {
    return toBN(this.localGasPrice).mul(toBN(this.TX.gas));
  }
  estimateGas() {
    this.setFrom(this.address());
    this._setTo();
    this._setValue();
    this._setGasPrice();
    return this.web3().eth.estimateGas({
      data: this.TX.data,
      from: this.TX.from,
      to: this.TX.to,
      value: this.TX.value
    });
  }
  isToken() {
    return this.currency?.contract !== MAIN_TOKEN_ADDRESS;
  }
  hasEnoughBalance() {
    const amount = toBN(this.TX.destinationValue);
    if (this.isToken() && this.currency.balance) {
      const hasAmountToken = amount.lte(toBN(this.currency.balance));
      const hasGas = this.txFee().lte(this.balance());
      return hasAmountToken && hasGas;
    }
    return amount.add(this.txFee()).lte(this.balance());
  }
  getTokenTransferABI(amount, _toAddress) {
    amount = toBN(amount);
    const jsonInterface = [
      {
        constant: false,
        inputs: [
          { name: '_to', type: 'address' },
          { name: '_amount', type: 'uint256' }
        ],
        name: 'transfer',
        outputs: [{ name: '', type: 'bool' }],
        payable: false,
        stateMutability: 'nonpayable',
        type: 'function'
      }
    ];
    const contract = new Web3Contract(jsonInterface);
    return contract.methods
      .transfer(_toAddress.toLowerCase(), amount)
      .encodeABI();
  }
  async submitTransaction() {
    try {
      this._setTo();
      this._setValue();
      this._setGasPrice();
      const nonce = await this.web3().eth.getTransactionCount(this.address());
      this.setNonce(nonce);
      this.TX.gasLimit = this.TX.gas;
      const _tx = Transaction.fromTxData(this.TX);
      const json = _tx.toJSON(true);
      json.from = this.address();
      json.toDetails = this.TX.toDetails;
      return this.web3().eth.sendTransaction(json);
    } catch (e) {
      return e;
    }
  }
}
SendTransaction.helpers = {
  hasValidDecimals
};
export default SendTransaction;
<commit_msg>devop: 🔧 added bn helper<commit_after>import { toBN, toHex, toChecksumAddress, isHexStrict } from 'web3-utils';
import { isAddress } from '@/core/helpers/addressUtils';
import SanitizeHex from '@/core/helpers/sanitizeHex';
import { Transaction } from '@ethereumjs/tx';
import { mapState, mapGetters } from 'vuex';
import vuexStore from '@/core/store';
import ErrorList from '../errors';
import Web3Contract from 'web3-eth-contract';
import { MAIN_TOKEN_ADDRESS } from '@/core/helpers/common';
import hasValidDecimals from '@/core/helpers/hasValidDecimals.js';
import { isNull } from 'lodash';
import BigNumber from 'bignumber.js';
import { toBNSafe } from '@/core/helpers/numberFormatHelper';

class SendTransaction {
  constructor() {
    this.$store = vuexStore;
    Object.assign(this, mapState('wallet', ['balance', 'web3', 'address']));
    Object.assign(this, mapGetters('global', ['network']));
    this.currency = null;
    this.localGasPrice = '0';
    this.TX = {
      from: '0x',
      to: '0x',
      destination: '0x',
      nonce: '0x',
      gasPrice: '0x',
      gas: '0x5208', //21000
      value: '0x',
      destinationValue: '0x',
      data: '0x'
    };
  }
  setTo(_to, _type) {
    if (isAddress(_to)) {
      this.TX.destination = _to;
      this.TX.toDetails = _type;
    } else throw ErrorList.INVALID_TO_ADDRESS;
  }
  _setTo() {
    this.TX.to = this.isToken()
      ? toChecksumAddress(this.currency.contract)
      : toChecksumAddress(this.TX.destination);
  }
  setFrom(_from) {
    if (isAddress(_from)) this.TX.from = _from;
    else throw ErrorList.INVALID_FROM_ADDRESS;
  }
  _setGasPrice() {
    this.TX.gasPrice = toHex(toBN(this.localGasPrice));
  }
  setGasLimit(_gasLimit) {
    this.TX.gas = toHex(toBN(_gasLimit));
  }
  setLocalGasPrice(gasPrice) {
    this.localGasPrice = toHex(toBN(gasPrice));
  }
  setValue(_value) {
    if (isNaN(_value) || isNull(_value)) _value = 0;
    const _valueBN = new BigNumber(_value);
    if (!_valueBN.lt(0)) this.TX.destinationValue = toHex(_valueBN.toFixed());
    else throw ErrorList.NEGATIVE_VALUE;
  }
  _setValue() {
    if (this.isToken()) {
      this.TX.value = '0x00';
      this.setData(
        this.getTokenTransferABI(this.TX.destinationValue, this.TX.destination)
      );
    } else {
      this.TX.value = toHex(toBN(this.TX.destinationValue));
    }
  }
  setData(_data) {
    if (isHexStrict(_data)) this.TX.data = SanitizeHex(_data);
    else throw ErrorList.INVALID_DATA_HEX;
  }
  setNonce(_nonce) {
    this.TX.nonce = toHex(toBN(_nonce));
  }
  setCurrency(_currency) {
    this.currency = _currency;
    this.TX.data = '0x';
  }
  getEntireBal() {
    if (this.isToken()) {
      return this.currency.balance;
    }
    const gasPriceBN = toBN(this.localGasPrice);
    const fee = gasPriceBN.mul(toBN(this.TX.gas));
    return this.balance().gt(this.balance().sub(fee)) > 0
      ? this.balance().sub(fee)
      : 0;
  }
  txFee() {
    return toBN(this.localGasPrice).mul(toBN(this.TX.gas));
  }
  estimateGas() {
    this.setFrom(this.address());
    this._setTo();
    this._setValue();
    this._setGasPrice();
    return this.web3().eth.estimateGas({
      data: this.TX.data,
      from: this.TX.from,
      to: this.TX.to,
      value: this.TX.value
    });
  }
  isToken() {
    return this.currency?.contract !== MAIN_TOKEN_ADDRESS;
  }
  hasEnoughBalance() {
    const amount = toBN(this.TX.destinationValue);
    if (this.isToken() && this.currency.balance) {
      const hasAmountToken = amount.lte(toBNSafe(this.currency.balance));
      const hasGas = this.txFee().lte(this.balance());
      return hasAmountToken && hasGas;
    }
    return amount.add(this.txFee()).lte(this.balance());
  }
  getTokenTransferABI(amount, _toAddress) {
    amount = toBN(amount);
    const jsonInterface = [
      {
        constant: false,
        inputs: [
          { name: '_to', type: 'address' },
          { name: '_amount', type: 'uint256' }
        ],
        name: 'transfer',
        outputs: [{ name: '', type: 'bool' }],
        payable: false,
        stateMutability: 'nonpayable',
        type: 'function'
      }
    ];
    const contract = new Web3Contract(jsonInterface);
    return contract.methods
      .transfer(_toAddress.toLowerCase(), amount)
      .encodeABI();
  }
  async submitTransaction() {
    try {
      this._setTo();
      this._setValue();
      this._setGasPrice();
      const nonce = await this.web3().eth.getTransactionCount(this.address());
      this.setNonce(nonce);
      this.TX.gasLimit = this.TX.gas;
      const _tx = Transaction.fromTxData(this.TX);
      const json = _tx.toJSON(true);
      json.from = this.address();
      json.toDetails = this.TX.toDetails;
      return this.web3().eth.sendTransaction(json);
    } catch (e) {
      return e;
    }
  }
}
SendTransaction.helpers = {
  hasValidDecimals
};
export default SendTransaction;
<|endoftext|>


<commit_before>//controller and any services relating to the main boaard
plugin.controller("BoardController", function ($scope, autoRefresh, $rootScope) {
	$rootScope.projectName = "cdpipeline";
	$scope.results = autoRefresh.data;
	$rootScope.dataLoaded = false;

	//scroll for new data
	$scope.totalDisplayed = 15;
	$scope.loadMore = function() {
		$scope.totalDisplayed += 5;
	};
});

//polls a REST endpoint every five seconds and automatically refreshes
plugin.factory('autoRefresh', function ($http, $timeout, $rootScope) {
	var data = { resp: {}};
	var poller = function() {
		$http.get('?data=all').then( function(r) {
			data.resp = r.data;
			$rootScope.dataLoaded = true;
			$timeout(poller, 5000);
		});
	};
	poller();

	return {
		data: data
	};
});

// filter that puts element with key == null to the end of the list
plugin.filter("emptyToEnd", function () {
	return function (array, key) {
		if(!angular.isArray(array)) return;
        var present = array.filter(function (item) {
            return item[key]["lastUpdateTime"];
        });
        var empty = array.filter(function (item) {
            return !item[key]["lastUpdateTime"];
        });
		return present.concat(empty);
	};
});

// filter that puts in progress and queued projects to the top
plugin.filter("progressToFront", function () {
	return function (array, key) {
		if(!angular.isArray(array)) return;
        var inProgress = array.filter(function (item) {
            return item[key]["currentBuild"]["cdpipelineState"] == "CD_IN_PROGRESS";
        });
        var queued = array.filter(function (item) {
        	return item[key]["currentBuild"]["cdpipelineState"] == "CD_QUEUED";
        });
        var finished = array.filter(function (item) {
            return item[key]["currentBuild"]["cdpipelineState"] != "CD_IN_PROGRESS" && item[key]["currentBuild"]["cdpipelineState"] != "CD_QUEUED";
        });
		return inProgress.concat(queued).concat(finished);
	};
});

// The search button on the menu bar
plugin.filter('searchFor', keywordSearch);

// Helper method for the search button on the menu bar
function keywordSearch(){

	// All filters must return a function. The first parameter
	// is the data that is to be filtered, and the second is an
	// argument that may be passed with a colon (searchFor:searchString)

	return function(arr, searchString){

		if(!searchString){
			return arr;
		}
		var result = [];
		searchString = searchString.toLowerCase();
		// Using the forEach helper method to loop through the array
		angular.forEach(arr, function(item){
            if(item.cdresult.projectName.toLowerCase().indexOf(searchString) !== -1 |
                item.cdresult.planName.toLowerCase().indexOf(searchString) !== -1) {
                    result.push(item);
            }
            for (i = 0; i < item.cdresult.contributors.length; i++) {
                if (item.cdresult.contributors[i].username.toLowerCase().indexOf(searchString) !== -1 |
                     item.cdresult.contributors[i].fullname.toLowerCase().indexOf(searchString) !== -1) {
                    result.push(item);
                }
            }
        });

		return result;
	};
}

// Filter that deals with edge case of the pipeline
// (when there's only one stage)
plugin.filter('pipelineWidth', function(){
  return function(input){
    if(input > 1) {
      return (1 / (input - 1));
    } else {
      return 0;
    }
  };
});

plugin.filter('percentageLimit', function(){
	return function(input){
		if(input <= 100) {
			return input;
		} else {
			return 100;
		}
	};
});

// Filter that strips the '+' or '-' of letter grades.
// E.g. from B+ to B.
plugin.filter('letterOnly', function() {
	return function(input){
		return input.substring(0, 1);
	};
});<commit_msg>Removing searching contributor names when searching for projects as we removed this to enhance performance<commit_after>//controller and any services relating to the main boaard
plugin.controller("BoardController", function ($scope, autoRefresh, $rootScope) {
	$rootScope.projectName = "cdpipeline";
	$scope.results = autoRefresh.data;
	$rootScope.dataLoaded = false;

	//scroll for new data
	$scope.totalDisplayed = 15;
	$scope.loadMore = function() {
		$scope.totalDisplayed += 5;
	};
});

//polls a REST endpoint every five seconds and automatically refreshes
plugin.factory('autoRefresh', function ($http, $timeout, $rootScope) {
	var data = { resp: {}};
	var poller = function() {
		$http.get('?data=all').then( function(r) {
			data.resp = r.data;
			$rootScope.dataLoaded = true;
			$timeout(poller, 5000);
		});
	};
	poller();

	return {
		data: data
	};
});

// filter that puts element with key == null to the end of the list
plugin.filter("emptyToEnd", function () {
	return function (array, key) {
		if(!angular.isArray(array)) return;
        var present = array.filter(function (item) {
            return item[key]["lastUpdateTime"];
        });
        var empty = array.filter(function (item) {
            return !item[key]["lastUpdateTime"];
        });
		return present.concat(empty);
	};
});

// filter that puts in progress and queued projects to the top
plugin.filter("progressToFront", function () {
	return function (array, key) {
		if(!angular.isArray(array)) return;
        var inProgress = array.filter(function (item) {
            return item[key]["currentBuild"]["cdpipelineState"] == "CD_IN_PROGRESS";
        });
        var queued = array.filter(function (item) {
        	return item[key]["currentBuild"]["cdpipelineState"] == "CD_QUEUED";
        });
        var finished = array.filter(function (item) {
            return item[key]["currentBuild"]["cdpipelineState"] != "CD_IN_PROGRESS" && item[key]["currentBuild"]["cdpipelineState"] != "CD_QUEUED";
        });
		return inProgress.concat(queued).concat(finished);
	};
});

// The search button on the menu bar
plugin.filter('searchFor', keywordSearch);

// Helper method for the search button on the menu bar
function keywordSearch(){

	// All filters must return a function. The first parameter
	// is the data that is to be filtered, and the second is an
	// argument that may be passed with a colon (searchFor:searchString)

	return function(arr, searchString){

		if(!searchString){
			return arr;
		}
		var result = [];
		searchString = searchString.toLowerCase();
		// Using the forEach helper method to loop through the array
		angular.forEach(arr, function(item){
            if(item.cdresult.projectName.toLowerCase().indexOf(searchString) !== -1 |
                item.cdresult.planName.toLowerCase().indexOf(searchString) !== -1) {
                    result.push(item);
            }
        });

		return result;
	};
}

// Filter that deals with edge case of the pipeline
// (when there's only one stage)
plugin.filter('pipelineWidth', function(){
  return function(input){
    if(input > 1) {
      return (1 / (input - 1));
    } else {
      return 0;
    }
  };
});

plugin.filter('percentageLimit', function(){
	return function(input){
		if(input <= 100) {
			return input;
		} else {
			return 100;
		}
	};
});

// Filter that strips the '+' or '-' of letter grades.
// E.g. from B+ to B.
plugin.filter('letterOnly', function() {
	return function(input){
		return input.substring(0, 1);
	};
});<|endoftext|>