<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { withTheme } from 'styled-components';
import I18n from 'i18n-js';
import {
  PagerNavigationStyles,
  PagerNavInnerStyles,
  PagerNoSelectStyles,
  PagerButtonWrapperStyles,
  PagerLinkStyles
} from './pager.styles';
import Icon from '../icon';
import NumberComponent from '../number';
import Events from '../../utils/helpers/events';

const PagerNavigation = (props) => {
  const updatePageFromInput = (ev) => {
    let newPage = Math.abs(Number(ev.target.value));

    if (Number.isNaN(newPage)) { newPage = '1'; }
    if (newPage > maxPages()) { newPage = String(maxPages()); }

    props.onPagination(String(newPage), props.pageSize, 'input');
  };

  function maxPages() {
    const totalRecordsCount = props.totalRecords >= 0 ? props.totalRecords : 0;

    if (props.pageSize && props.pageSize !== '0' && totalRecordsCount > 0) {
      return Math.ceil(totalRecordsCount / props.pageSize);
    }
    return 1;
  }

  function navArrowChange(step) {
    const newPage = String(Number(props.currentPage) + step);
    const desc = step === 1 ? 'next' : 'previous';
    props.onPagination(newPage, props.pageSize, desc);
  }

  function navArrow(step) {
    const arrowProps = {
      'data-element': 'next-page',
      type: 'dropdown'
    };

    function disabled() {
      if (step === -1) {
        return props.currentPage === '1';
      }
      return props.currentPage === String(maxPages());
    }

    return (
      <PagerButtonWrapperStyles disabled={ disabled() } next={ step === 1 }>
        <Icon
          onClick={ () => {
            if (!disabled()) { navArrowChange(step); }
          } }
          { ...arrowProps }
        />
      </PagerButtonWrapperStyles>
    );
  }

  function navLink(type) {
    const currentPage = Number(props.currentPage);
    const navLinkConfig = {
      first: {
        text: 'First',
        destination: '1'
      },
      last: {
        text: 'Last',
        destination: String(maxPages())
      },
      next: {
        text: 'Next',
        destination: String(currentPage + 1)
      },
      back: {
        text: 'Back',
        destination: String(currentPage - 1)
      }
    };

    function disabled() {
      if (currentPage === 1) {
        return type === 'back' || type === 'first';
      }
      if (currentPage === maxPages()) {
        return type === 'next' || type === 'last';
      }
      return false;
    }

    return (
      <PagerLinkStyles
        isDisabled={ disabled() }
        onClick={ () => {
          if (disabled()) {
            return false;
          }
          return props.onPagination(navLinkConfig[type].destination, props.pageSize, type);
        } }
      >
        {navLinkConfig[type].text}
      </PagerLinkStyles>
    );
  }

  function currentPageInput() {
    const currentPageInputProps = {
      value: props.currentPage,
      className: 'carbon-pager__current-page',
      'data-element': 'current-page',
      onChange: (ev) => {
        props.setCurrentPage(ev.target.value);
      },
      onBlur: updatePageFromInput,
      onKeyUp: (ev) => {
        if (!Events.isEnterKey(ev)) {
          return false;
        }
        return updatePageFromInput(ev);
      }
    };

    return <NumberComponent { ...currentPageInputProps } />;
  }

  const { theme } = props;
  if (theme && theme.name === 'classic') {
    return (
      <PagerNavigationStyles>
        { navArrow(-1) }
        <PagerNoSelectStyles>
          { I18n.t('pager.page_x', { defaultValue: 'Page ' }) }
        </PagerNoSelectStyles>
        { currentPageInput() }
        <PagerNoSelectStyles>
          { I18n.t('pager.of_y', { defaultValue: ' of ' }) }{ maxPages() }
        </PagerNoSelectStyles>
        { navArrow(1) }
      </PagerNavigationStyles>
    );
  }
  return (
    <PagerNavigationStyles>
      { navLink('first') }
      { navLink('back') }
      <PagerNavInnerStyles>
        <PagerNoSelectStyles>
          { I18n.t('pager.page_x', { defaultValue: 'Page ' }) }
        </PagerNoSelectStyles>
        { currentPageInput() }
        <PagerNoSelectStyles>
          { I18n.t('pager.of_y', { defaultValue: ' of ' }) }{ maxPages() }
        </PagerNoSelectStyles>
      </PagerNavInnerStyles>
      { navLink('next') }
      { navLink('last') }
    </PagerNavigationStyles>
  );
};

PagerNavigation.propTypes = {
  /** Current visible page */
  currentPage: PropTypes.string.isRequired,
  /** Total number of records */
  totalRecords: PropTypes.number.isRequired,
  /** Pagination page size */
  pageSize: PropTypes.string,
  /** Function called when pager changes (PageSize, Current Page) */
  onPagination: PropTypes.func.isRequired,
  /** Sets the current page being shown */
  setCurrentPage: PropTypes.func,
  /** Current theme */
  theme: PropTypes.object
};

export default withTheme(PagerNavigation);
<commit_msg>Fixes Pager Linting Issue<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { withTheme } from 'styled-components';
import I18n from 'i18n-js';
import {
  PagerNavigationStyles,
  PagerNavInnerStyles,
  PagerNoSelectStyles,
  PagerButtonWrapperStyles,
  PagerLinkStyles
} from './pager.styles';
import Icon from '../icon';
import NumberComponent from '../number';
import Events from '../../utils/helpers/events';

const PagerNavigation = (props) => {
  const updatePageFromInput = (ev) => {
    let newPage = Math.abs(Number(ev.target.value));

    if (Number.isNaN(newPage)) { newPage = '1'; }
    if (newPage > maxPages()) { newPage = String(maxPages()); }

    props.onPagination(String(newPage), props.pageSize, 'input');
  };

  function maxPages() {
    const totalRecordsCount = props.totalRecords >= 0 ? props.totalRecords : 0;

    if (props.pageSize && props.pageSize !== '0' && totalRecordsCount > 0) {
      return Math.ceil(totalRecordsCount / props.pageSize);
    }
    return 1;
  }

  function navArrowChange(step) {
    const newPage = String(Number(props.currentPage) + step);
    const desc = step === 1 ? 'next' : 'previous';
    props.onPagination(newPage, props.pageSize, desc);
  }

  function navArrow(step) {
    const arrowProps = {
      'data-element': 'next-page',
      type: 'dropdown'
    };

    function disabled() {
      if (step === -1) {
        return props.currentPage === '1';
      }
      return props.currentPage === String(maxPages());
    }

    return (
      <PagerButtonWrapperStyles disabled={ disabled() } next={ step === 1 }>
        <Icon
          onClick={ () => {
            if (!disabled()) { navArrowChange(step); }
          } }
          { ...arrowProps }
        />
      </PagerButtonWrapperStyles>
    );
  }

  function navLink(type) {
    const currentPage = Number(props.currentPage);
    const navLinkConfig = {
      first: {
        text: 'First',
        destination: '1'
      },
      last: {
        text: 'Last',
        destination: String(maxPages())
      },
      next: {
        text: 'Next',
        destination: String(currentPage + 1)
      },
      back: {
        text: 'Back',
        destination: String(currentPage - 1)
      }
    };

    function disabled() {
      if (currentPage === 1) {
        return type === 'back' || type === 'first';
      }
      if (currentPage === maxPages()) {
        return type === 'next' || type === 'last';
      }
      return false;
    }

    return (
      <PagerLinkStyles
        isDisabled={ disabled() }
        onClick={ () => {
          if (disabled()) {
            return false;
          }
          return props.onPagination(navLinkConfig[type].destination, props.pageSize, type);
        } }
      >
        {navLinkConfig[type].text}
      </PagerLinkStyles>
    );
  }

  function handlePageInputChange(ev) {
    props.setCurrentPage(ev.target.value);
  }

  function currentPageInput() {
    const currentPageInputProps = {
      value: props.currentPage,
      className: 'carbon-pager__current-page',
      'data-element': 'current-page',
      onChange: handlePageInputChange,
      onBlur: updatePageFromInput,
      onKeyUp: (ev) => {
        if (!Events.isEnterKey(ev)) {
          return false;
        }
        return updatePageFromInput(ev);
      }
    };

    return <NumberComponent { ...currentPageInputProps } />;
  }

  const { theme } = props;
  if (theme && theme.name === 'classic') {
    return (
      <PagerNavigationStyles>
        { navArrow(-1) }
        <PagerNoSelectStyles>
          { I18n.t('pager.page_x', { defaultValue: 'Page ' }) }
        </PagerNoSelectStyles>
        { currentPageInput() }
        <PagerNoSelectStyles>
          { I18n.t('pager.of_y', { defaultValue: ' of ' }) }{ maxPages() }
        </PagerNoSelectStyles>
        { navArrow(1) }
      </PagerNavigationStyles>
    );
  }
  return (
    <PagerNavigationStyles>
      { navLink('first') }
      { navLink('back') }
      <PagerNavInnerStyles>
        <PagerNoSelectStyles>
          { I18n.t('pager.page_x', { defaultValue: 'Page ' }) }
        </PagerNoSelectStyles>
        { currentPageInput() }
        <PagerNoSelectStyles>
          { I18n.t('pager.of_y', { defaultValue: ' of ' }) }{ maxPages() }
        </PagerNoSelectStyles>
      </PagerNavInnerStyles>
      { navLink('next') }
      { navLink('last') }
    </PagerNavigationStyles>
  );
};

PagerNavigation.propTypes = {
  /** Current visible page */
  currentPage: PropTypes.string.isRequired,
  /** Total number of records */
  totalRecords: PropTypes.number.isRequired,
  /** Pagination page size */
  pageSize: PropTypes.string,
  /** Function called when pager changes (PageSize, Current Page) */
  onPagination: PropTypes.func.isRequired,
  /** Sets the current page being shown */
  setCurrentPage: PropTypes.func,
  /** Current theme */
  theme: PropTypes.object
};

export default withTheme(PagerNavigation);
<|endoftext|>


<commit_before>'use strict';

angular.module('b4f.userRental', ['ngRoute', 'ngStorage'])

.config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/urental', {
            templateUrl: 'modules/user-rental/user-rental.html',
            controller: 'usrRentalCtrl',
            resolve: {
                "logged": ['$localStorage', '$location', function ($localStorage, $location) {
                    if ($localStorage.userInfo == undefined) {
                        $location.path('/login');
                    } else if ($localStorage.userInfo.role != "client") {
                        $location.path('/dashboard');
                    }
                }]
            }
        });
    }])
    .controller('usrRentalCtrl', ['$scope', '$http', '$localStorage', '$location', '$route', '$uibModal', function ($scope, $http, $localStorage, $location, $route, $uibModal) {

        var auth = $localStorage.userInfo != null && $localStorage.userInfo != undefined ? $localStorage.userInfo.token : undefined;
        var id = $localStorage.userInfo != null && $localStorage.userInfo != undefined ? $localStorage.userInfo.id : undefined;

        $scope.loading = $http({
            method: 'GET',
            url: 'http://bikes4freeg5.herokuapp.com/rental/'+id,
            headers: {
                Authorization: auth
            }
//            ,data: JSON.stringify($scope.loginForm)
        }).then(function successCallback(response) {
            $scope.rentals = response.data;
        }, function errorCallback(response) {
            console.error(response.data);
            $scope.error = "You have no rentals";
        });

        $scope.formatStartDate = function(date){
            return moment(date).startOf('hour').fromNow();
//            return moment(date).calendar();
        }

        $scope.formatPastDates = function(date){
            //            return moment(date).startOf('hour').fromNow();
            return moment(date).calendar();
        }

        $scope.authorizeUser = function (rental) {

//            var inx = $scope.rentals.indexOf(rental);
//            if (inx>-1){
//                $scope.rentals.splice(inx, 1);
//            }
            var modalInstance = $uibModal.open({
                animation: true,
                templateUrl: 'add-user.html',
                controller: function ($scope, $location, $uibModalInstance, $http, $filter, $localStorage, rental) {

                    $scope.client = {
                        mail: "",
                    };

                    $scope.rental = rental;

                    $scope.okAdd = function () {

                        var accessToken = $localStorage.userInfo !== undefined ? $localStorage.userInfo.accessToken : null;
                        $scope.addingUser = $http({
                            method: 'PUT',
//                            url: 'http://bikes4freeg5.herokuapp.com/rental/'+rental.id,
                            url: 'http://localhost:8080/rental/'+rental.id,
                            data: $scope.client,
                            headers: {
                                "Authorization": accessToken
                            }
                        }).then(function successCallback(response) {
                            $uibModalInstance.dismiss();
                        }, function errorCallback(response) {
                            $scope.error = response.data;
                        }).finally(function () {
                            $route.reload();
                        });

                    };

                    $scope.dismiss = function () {
                        $uibModalInstance.dismiss('cancel');
                    };
                },
                size: 'lg',
                resolve: {
                    rental: function(){
                        return rental;
                    }
                }
            });

            modalInstance.result.then(function (rental) {

            }, function () {

            });

        };

    }]);<commit_msg>url fix<commit_after>'use strict';

angular.module('b4f.userRental', ['ngRoute', 'ngStorage'])

.config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/urental', {
            templateUrl: 'modules/user-rental/user-rental.html',
            controller: 'usrRentalCtrl',
            resolve: {
                "logged": ['$localStorage', '$location', function ($localStorage, $location) {
                    if ($localStorage.userInfo == undefined) {
                        $location.path('/login');
                    } else if ($localStorage.userInfo.role != "client") {
                        $location.path('/dashboard');
                    }
                }]
            }
        });
    }])
    .controller('usrRentalCtrl', ['$scope', '$http', '$localStorage', '$location', '$route', '$uibModal', function ($scope, $http, $localStorage, $location, $route, $uibModal) {

        var auth = $localStorage.userInfo != null && $localStorage.userInfo != undefined ? $localStorage.userInfo.token : undefined;
        var id = $localStorage.userInfo != null && $localStorage.userInfo != undefined ? $localStorage.userInfo.id : undefined;

        $scope.loading = $http({
            method: 'GET',
            url: 'http://bikes4freeg5.herokuapp.com/rental/'+id,
            headers: {
                Authorization: auth
            }
//            ,data: JSON.stringify($scope.loginForm)
        }).then(function successCallback(response) {
            $scope.rentals = response.data;
        }, function errorCallback(response) {
            console.error(response.data);
            $scope.error = "You have no rentals";
        });

        $scope.formatStartDate = function(date){
            return moment(date).startOf('hour').fromNow();
//            return moment(date).calendar();
        }

        $scope.formatPastDates = function(date){
            //            return moment(date).startOf('hour').fromNow();
            return moment(date).calendar();
        }

        $scope.authorizeUser = function (rental) {

//            var inx = $scope.rentals.indexOf(rental);
//            if (inx>-1){
//                $scope.rentals.splice(inx, 1);
//            }
            var modalInstance = $uibModal.open({
                animation: true,
                templateUrl: 'add-user.html',
                controller: function ($scope, $location, $uibModalInstance, $http, $filter, $localStorage, rental) {

                    $scope.client = {
                        mail: "",
                    };

                    $scope.rental = rental;

                    $scope.okAdd = function () {

                        var accessToken = $localStorage.userInfo !== undefined ? $localStorage.userInfo.accessToken : null;
                        $scope.addingUser = $http({
                            method: 'PUT',
                            url: 'http://bikes4freeg5.herokuapp.com/rental/'+rental.id,
//                            url: 'http://localhost:8080/rental/'+rental.id,
                            data: $scope.client,
                            headers: {
                                "Authorization": accessToken
                            }
                        }).then(function successCallback(response) {
                            $uibModalInstance.dismiss();
                        }, function errorCallback(response) {
                            $scope.error = response.data;
                        }).finally(function () {
                            $route.reload();
                        });

                    };

                    $scope.dismiss = function () {
                        $uibModalInstance.dismiss('cancel');
                    };
                },
                size: 'lg',
                resolve: {
                    rental: function(){
                        return rental;
                    }
                }
            });

            modalInstance.result.then(function (rental) {

            }, function () {

            });

        };

    }]);<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import {Component} from 'react';

/**
 * ConfirmDialog is used to display the browser's native "confirm" modal,
 * with an optional message and two buttons ("OK" and "Cancel").
 * This ConfirmDialog can be used in conjunction with buttons when the user
 * is performing an action that should require an extra step of verification.
 */
export default class ConfirmDialog extends Component {
    constructor(props) {
        super(props);
    }

    componentDidUpdate(prevProps) {
        this._update(!prevProps.displayed && this.props.displayed);
    }

    componentDidMount() {
        this._update(this.props.displayed);
    }

    _update(shouldTriggerDisplay) {
        const {message, setProps, cancel_n_clicks, submit_n_clicks} = this.props;

        if (shouldTriggerDisplay) {
            new Promise(resolve => resolve(window.confirm(message))).then(
                result => {
                    if (result) {
                        setProps({
                            submit_n_clicks: submit_n_clicks + 1,
                            submit_n_clicks_timestamp: Date.now(),
                            displayed: false,
                        });
                    } else {
                        setProps({
                            cancel_n_clicks: cancel_n_clicks + 1,
                            cancel_n_clicks_timestamp: Date.now(),
                            displayed: false,
                        });
                    }
                }
            );
        }
    }

    render() {
        return null;
    }
}

ConfirmDialog.defaultProps = {
    submit_n_clicks: 0,
    submit_n_clicks_timestamp: -1,
    cancel_n_clicks: 0,
    cancel_n_clicks_timestamp: -1,
};

ConfirmDialog.propTypes = {
    id: PropTypes.string,

    /**
     * Message to show in the popup.
     */
    message: PropTypes.string,
    /**
     * Number of times the submit button was clicked
     */
    submit_n_clicks: PropTypes.number,
    /**
     * Last time the submit button was clicked.
     */
    submit_n_clicks_timestamp: PropTypes.number,
    /**
     * Number of times the popup was canceled.
     */
    cancel_n_clicks: PropTypes.number,
    /**
     * Last time the cancel button was clicked.
     */
    cancel_n_clicks_timestamp: PropTypes.number,
    /**
     *  Set to true to send the ConfirmDialog.
     */
    displayed: PropTypes.bool,
    key: PropTypes.string,

    /**
     * Dash-assigned callback that gets fired when the value changes.
     */
    setProps: PropTypes.func,
};
<commit_msg>prettier<commit_after>import PropTypes from 'prop-types';
import {Component} from 'react';

/**
 * ConfirmDialog is used to display the browser's native "confirm" modal,
 * with an optional message and two buttons ("OK" and "Cancel").
 * This ConfirmDialog can be used in conjunction with buttons when the user
 * is performing an action that should require an extra step of verification.
 */
export default class ConfirmDialog extends Component {
    constructor(props) {
        super(props);
    }

    componentDidUpdate(prevProps) {
        this._update(!prevProps.displayed && this.props.displayed);
    }

    componentDidMount() {
        this._update(this.props.displayed);
    }

    _update(shouldTriggerDisplay) {
        const {
            message,
            setProps,
            cancel_n_clicks,
            submit_n_clicks,
        } = this.props;

        if (shouldTriggerDisplay) {
            new Promise(resolve => resolve(window.confirm(message))).then(
                result => {
                    if (result) {
                        setProps({
                            submit_n_clicks: submit_n_clicks + 1,
                            submit_n_clicks_timestamp: Date.now(),
                            displayed: false,
                        });
                    } else {
                        setProps({
                            cancel_n_clicks: cancel_n_clicks + 1,
                            cancel_n_clicks_timestamp: Date.now(),
                            displayed: false,
                        });
                    }
                }
            );
        }
    }

    render() {
        return null;
    }
}

ConfirmDialog.defaultProps = {
    submit_n_clicks: 0,
    submit_n_clicks_timestamp: -1,
    cancel_n_clicks: 0,
    cancel_n_clicks_timestamp: -1,
};

ConfirmDialog.propTypes = {
    id: PropTypes.string,

    /**
     * Message to show in the popup.
     */
    message: PropTypes.string,
    /**
     * Number of times the submit button was clicked
     */
    submit_n_clicks: PropTypes.number,
    /**
     * Last time the submit button was clicked.
     */
    submit_n_clicks_timestamp: PropTypes.number,
    /**
     * Number of times the popup was canceled.
     */
    cancel_n_clicks: PropTypes.number,
    /**
     * Last time the cancel button was clicked.
     */
    cancel_n_clicks_timestamp: PropTypes.number,
    /**
     *  Set to true to send the ConfirmDialog.
     */
    displayed: PropTypes.bool,
    key: PropTypes.string,

    /**
     * Dash-assigned callback that gets fired when the value changes.
     */
    setProps: PropTypes.func,
};
<|endoftext|>


<commit_before>/**
 * Copyright reelyActive 2016
 * We believe in an open Internet of Things
 */

angular.module('reelyactive.beaver', [])

  .factory('beaver', function beaverFactory() {

    var devices = {};
    var stats = { appearances: 0, displacements: 0, keepalives: 0,
                  disappearances: 0 };
    var eventCallbacks = {};

    function updateDevice(type, event) {
      if(!isValidEvent) {
        return;
      }

      if(!event.hasOwnProperty('deviceId') && event.hasOwnProperty('tiraid')) {
        updateLegacyEvent(event);
      }

      var deviceId = event.deviceId;
      if(type === 'appearance') { stats.appearances++; }
      if(type === 'displacement') { stats.displacements++; }
      if(type === 'keep-alive') { stats.keepalives++; }
      if(type === 'disappearance') {
        if(devices.hasOwnProperty(deviceId)) {
          delete devices[deviceId];
        }
        stats.disappearances++;
        handleEventCallback(type, event);
        return;
      }

      if(!devices.hasOwnProperty(deviceId)) {
        devices[deviceId] = event;
      }
      else {
        mergeDeviceEvents(devices[deviceId], event);
      }

      handleEventCallback(type, event);
    }

    function isValidEvent(event) {
      if(!event) {
        return false;
      }
      if(!((event.deviceId && event.receiverId && event.rssi && event.time) ||
           (event.tiraid))) {
        return false;
      }
      return true;
    }

    function updateLegacyEvent(event) {
      event.deviceId = event.tiraid.identifier.value;
      event.time = new Date(event.tiraid.timestamp);
      event.receiverId = event.tiraid.radioDecodings[0].identifier.value;
      event.rssi = event.tiraid.radioDecodings[0].rssi;
      return;
    }

    function mergeDeviceEvents(device, event) {
      device.deviceAssociationIds = event.deviceAssociationIds ||
                                    device.deviceAssociationIds;
      device.deviceUrl = event.deviceUrl || device.deviceUrl;
      device.deviceTags = event.deviceTags || device.deviceTags;
      device.receiverId = event.receiverId;
      device.receiverUrl = event.receiverUrl;
      device.receiverTags = event.receiverTags;
      device.receiverDirectory = event.receiverDirectory;
      device.rssi = event.rssi;
      device.rssiType = event.rssiType;
    }

    function handleEventCallback(type, device) {
      var callback = eventCallbacks[type];
      if(callback) {
        callback(device);
      }
    }

    var setEventCallback = function(event, callback) {
      if(callback && (typeof callback === 'function')) {
        eventCallbacks[event] = callback;
      }
    }

    var handleSocketEvents = function(Socket) {

      Socket.on('appearance', function(event) {
        updateDevice('appearance', event);
      });

      Socket.on('displacement', function(event) {
        updateDevice('displacement', event);
      });

      Socket.on('keep-alive', function(event) {
        updateDevice('keep-alive', event);
      });

      Socket.on('disappearance', function(event) {
        updateDevice('disappearance', event);
      });

      Socket.on('error', function(err, data) {
      });
    };

    return {
      listen: handleSocketEvents,
      on: setEventCallback,
      getDevices: function() { return devices; },
      getStats: function() { return stats; }
    }
  });
<commit_msg>Updated to latest version<commit_after>/**
 * Copyright reelyActive 2016
 * We believe in an open Internet of Things
 */

angular.module('reelyactive.beaver', [])

  .factory('beaver', function beaverFactory() {

    var devices = {};
    var directories = {};
    var stats = { appearances: 0, displacements: 0, keepalives: 0,
                  disappearances: 0 };
    var eventCallbacks = {};

    // Use the given event to update the status of the corresponding device
    function updateDevice(type, event) {
      if(!isValidEvent) {
        return;
      }

      if(!event.hasOwnProperty('deviceId') && event.hasOwnProperty('tiraid')) {
        updateLegacyEvent(event);
      }

      var deviceId = event.deviceId;
      if(!devices.hasOwnProperty(deviceId)) {
        type = 'appearance';
      }

      if(type === 'appearance') { stats.appearances++; }
      if(type === 'displacement') { stats.displacements++; }
      if(type === 'keep-alive') { stats.keepalives++; }
      if(type === 'disappearance') {
        if(devices.hasOwnProperty(deviceId)) {
          delete devices[deviceId];
        }
        stats.disappearances++;
        handleEventCallback(type, event);
        return;
      }

      if(!devices.hasOwnProperty(deviceId)) {
        devices[deviceId] = { event:  event };
      }
      else {
        mergeDeviceEvents(devices[deviceId], event);
      }

      handleEventCallback(type, event);
    }

    // Verify if the given event is valid
    function isValidEvent(event) {
      if(!event) {
        return false;
      }
      if(!((event.deviceId && event.receiverId && event.rssi && event.time) ||
           (event.tiraid))) {
        return false;
      }
      return true;
    }

    // Update the given event to the current format
    function updateLegacyEvent(event) {
      event.deviceId = event.tiraid.identifier.value;
      event.time = new Date(event.tiraid.timestamp);
      event.receiverId = event.tiraid.radioDecodings[0].identifier.value;
      event.rssi = event.tiraid.radioDecodings[0].rssi;
      return;
    }

    // Merge any previous device event with the given one
    function mergeDeviceEvents(device, event) {
      device.event.deviceAssociationIds = event.deviceAssociationIds ||
                                          device.event.deviceAssociationIds;
      device.event.deviceUrl = event.deviceUrl || device.event.deviceUrl;
      device.event.deviceTags = event.deviceTags || device.event.deviceTags;
      device.event.receiverId = event.receiverId;
      device.event.receiverUrl = event.receiverUrl;
      device.event.receiverTags = event.receiverTags;
      device.event.receiverDirectory = event.receiverDirectory;
      device.event.rssi = event.rssi;
      device.event.rssiType = event.rssiType;
    }

    // Update the directories of devices
    function updateDirectories(event) {
      var directory = event.receiverDirectory;
      var deviceId = event.deviceId;

      for(cDirectory in directories) {
        if((directory === cDirectory) && (event.event !== 'disappearance')) {
          addReceiver(directory, event);
          directories[cDirectory].devices[deviceId] = devices[deviceId];
        }
        else if(directories[cDirectory].devices.hasOwnProperty(deviceId)) {
          delete directories[cDirectory].devices[deviceId];
        }
      }

      if(!directories.hasOwnProperty(directory)) {
        directories[directory] = { receivers: {}, devices: {} };
        addReceiver(directory, event);
        directories[directory].devices[deviceId] = devices[deviceId];
      }
    }

    // Add the receiver to the given directory
    function addReceiver(directory, event) {
      if(!directories[directory].receivers.hasOwnProperty(event.receiverId)) {
        directories[directory].receivers[event.receiverId] = {
          receiverId: event.receiverId,
          receiverTags: event.receiverTags,
          receiverDirectory: directory,
          receiverUrl: event.receiverUrl
        };
      }
    }

    // Handle any registered callbacks for the given event type
    function handleEventCallback(type, device) {
      var callback = eventCallbacks[type];
      if(callback) {
        callback(device);
      }
    }

    // Register a callback for the given event type
    var setEventCallback = function(event, callback) {
      if(callback && (typeof callback === 'function')) {
        eventCallbacks[event] = callback;
      }
    }

    // Add the given property to the given device
    function addDeviceProperty(deviceId, property, value) {
      if(!devices.hasOwnProperty(deviceId) || !property ||
         (typeof(property) !== 'string')) {
        return false;
      }
      devices[deviceId][property] = value;
      return true;
    }

    // Add the given property to the given directory
    function addDirectoryProperty(directory, property, value) {
      if(!directories.hasOwnProperty(directory) || !property ||
         (typeof(property) !== 'string')) {
        return false;
      }
      directories[directory][property] = value;
      return true;
    }

    // Handle incoming socket events by type
    var handleSocketEvents = function(Socket) {

      Socket.on('appearance', function(event) {
        updateDevice('appearance', event);
        updateDirectories(event);
      });

      Socket.on('displacement', function(event) {
        updateDevice('displacement', event);
        updateDirectories(event);
      });

      Socket.on('keep-alive', function(event) {
        updateDevice('keep-alive', event);
        updateDirectories(event);
      });

      Socket.on('disappearance', function(event) {
        updateDevice('disappearance', event);
        updateDirectories(event);
      });

      Socket.on('error', function(err, data) {
      });
    };

    return {
      listen: handleSocketEvents,
      on: setEventCallback,
      addDeviceProperty: addDeviceProperty,
      addDirectoryProperty: addDirectoryProperty,
      getDevices: function() { return devices; },
      getDirectories: function() { return directories; },
      getStats: function() { return stats; }
    }
  });
<|endoftext|>


<commit_before>import { color } from 'd3-color';
import * as PIXI from 'pixi.js';

import PixiTrack from './PixiTrack';
import ChromosomeInfo from './ChromosomeInfo';

class Chromosome2DAnnotations extends PixiTrack {
  constructor(scene, chromInfoPath, options) {
    super(scene, options);

    this.drawnRects = new Set();

    ChromosomeInfo(chromInfoPath, (newChromInfo) => {
      this.chromInfo = newChromInfo;
      this.draw();
    });
  }

  draw() {
    if (!this.chromInfo) { return; }

    this.drawnRects.clear();

    const minRectWidth = this.options.minRectWidth ? this.options.minRectWidth : 10;
    const minRectHeight = this.options.minRectWidth ? this.options.minRectHeight : 10;

    super.draw();
    const graphics = this.pMain;
    graphics.clear();

    // Regions have to follow the following form:
    // chrom1, start1, end1, chrom2, start2, end2, color-fill, color-line, min-width, min-height
    // If `color-line` is not given, `color-fill` is used
    for (const region of this.options.regions) {
      const colorFill = color(region[6]);
      let colorLine = color(region[7]);

      if (!colorLine) { colorLine = colorFill; }

      const colorFillHex = PIXI.utils.rgb2hex(
        [colorFill.r / 255.0, colorFill.g / 255.0, colorFill.b / 255.0],
      );
      const colorLineHex = PIXI.utils.rgb2hex(
        [colorLine.r / 255.0, colorLine.g / 255.0, colorLine.b / 255.0],
      );

      graphics.lineStyle(1, colorLineHex, colorLine.opacity);
      graphics.beginFill(colorFillHex, colorFill.opacity);

      // console.log('region:', region);
      let startX = this._xScale(this.chromInfo.chrPositions[region[0]].pos + +region[1]);
      const endX = this._xScale(this.chromInfo.chrPositions[region[0]].pos + +region[2]);

      let startY = this._yScale(this.chromInfo.chrPositions[region[3]].pos + +region[4]);
      const endY = this._yScale(this.chromInfo.chrPositions[region[3]].pos + +region[5]);

      let width = endX - startX;
      let height = endY - startY;

      const _minRectWidth = typeof region[8] !== 'undefined' ? region[8] : minRectWidth;
      const _minRectHeight = typeof region[9] !== 'undefined' ? region[9] : minRectHeight;

      if (width < _minRectWidth) {
        // this region is too small to draw so center it on the location
        // where it would be drawn
        startX = ((startX + endX) / 2) - (_minRectWidth / 2);
        width = _minRectWidth;
      }

      if (height < _minRectHeight) {
        startY = ((startY + endY) / 2) - (_minRectHeight / 2);
        height = _minRectHeight;
      }

      graphics.drawRect(startX, startY, width, height);
    }
  }

  setPosition(newPosition) {
    super.setPosition(newPosition);

    this.pMain.position.y = this.position[1];
    this.pMain.position.x = this.position[0];
  }

  zoomed(newXScale, newYScale) {
    this.xScale(newXScale);
    this.yScale(newYScale);

    this.draw();
  }
}

export default Chromosome2DAnnotations;
<commit_msg>Make clickable<commit_after>import { color } from 'd3-color';
import * as PIXI from 'pixi.js';

import PixiTrack from './PixiTrack';
import ChromosomeInfo from './ChromosomeInfo';

import pubSub from './services/pub-sub';

// Maximum delay in ms between mousedown and mouseup that is registered as a
// click. Note we need to use mousedown and mouseup as PIXI doesn't recognize
// click events with out current setup. Since most UIs treat long clicks as
// either something special or a cancelation we follow best practices and
// implement a threshold on the delay as well.
const MAX_CLICK_DELAY = 300;

class Chromosome2DAnnotations extends PixiTrack {
  constructor(scene, chromInfoPath, options) {
    super(scene, options);

    this.rects = {};

    ChromosomeInfo(chromInfoPath, (newChromInfo) => {
      this.chromInfo = newChromInfo;
      this.draw();
    });
  }

  draw() {
    if (!this.chromInfo) { return; }

    const minRectWidth = this.options.minRectWidth ? this.options.minRectWidth : 10;
    const minRectHeight = this.options.minRectWidth ? this.options.minRectHeight : 10;

    super.draw();
    const graphics = this.pMain;
    graphics.clear();

    // The time stamp is used to keep track which rectangles have been drawn per
    // draw call. Each rectangle previously drawn that is not visible anymore
    // (i.e., is not drawn in the current draw call) will be removed at the end
    // by checking against the time stamp.
    const timeStamp = performance.now();

    // Regions have to follow the following form:
    // chrom1, start1, end1, chrom2, start2, end2, color-fill, color-line, min-width, min-height
    // If `color-line` is not given, `color-fill` is used
    this.options.regions.forEach((region) => {
      const id = region.slice(0, 6).join('-');

      if (!this.rects[id]) {
        this.rects[id] = { graphics: new PIXI.Graphics() };
        graphics.addChild(this.rects[id].graphics);
      }

      this.rects[id].timeStamp = timeStamp;

      const colorFill = color(region[6]);
      let colorLine = color(region[7]);

      if (!colorLine) { colorLine = colorFill; }

      const colorFillHex = PIXI.utils.rgb2hex(
        [colorFill.r / 255.0, colorFill.g / 255.0, colorFill.b / 255.0],
      );
      const colorLineHex = PIXI.utils.rgb2hex(
        [colorLine.r / 255.0, colorLine.g / 255.0, colorLine.b / 255.0],
      );

      graphics.lineStyle(1, colorLineHex, colorLine.opacity);
      graphics.beginFill(colorFillHex, colorFill.opacity);

      // console.log('region:', region);
      let startX = this._xScale(this.chromInfo.chrPositions[region[0]].pos + +region[1]);
      const endX = this._xScale(this.chromInfo.chrPositions[region[0]].pos + +region[2]);

      let startY = this._yScale(this.chromInfo.chrPositions[region[3]].pos + +region[4]);
      const endY = this._yScale(this.chromInfo.chrPositions[region[3]].pos + +region[5]);

      let width = endX - startX;
      let height = endY - startY;

      const _minRectWidth = typeof region[8] !== 'undefined' ? region[8] : minRectWidth;
      const _minRectHeight = typeof region[9] !== 'undefined' ? region[9] : minRectHeight;

      if (width < _minRectWidth) {
        // this region is too small to draw so center it on the location
        // where it would be drawn
        startX = ((startX + endX) / 2) - (_minRectWidth / 2);
        width = _minRectWidth;
      }

      if (height < _minRectHeight) {
        startY = ((startY + endY) / 2) - (_minRectHeight / 2);
        height = _minRectHeight;
      }

      graphics.drawRect(startX, startY, width, height);

      // Make annotation clickable
      this.rects[id].graphics.clear();
      this.rects[id].graphics.interactive = true;
      this.rects[id].graphics.buttonMode = true;
      this.rects[id].graphics.hitArea = new PIXI.Rectangle(
        startX, startY, width, height
      );

      this.rects[id].graphics.mousedown = () => {
        this.rects[id].mouseDownTime = performance.now();
      };

      this.rects[id].graphics.mouseup = (event) => {
        if (performance.now() - this.rects[id].mouseDownTime < MAX_CLICK_DELAY) {
          pubSub.publish('app.click', {
            type: 'annotation',
            event,
            payload: region
          });
        }
      };
    });
  }

  setPosition(newPosition) {
    super.setPosition(newPosition);

    this.pMain.position.y = this.position[1];
    this.pMain.position.x = this.position[0];
  }

  zoomed(newXScale, newYScale) {
    this.xScale(newXScale);
    this.yScale(newYScale);

    this.draw();
  }
}

export default Chromosome2DAnnotations;
<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react';
import { Row, Panel, ButtonToolbar, DropdownButton, MenuItem } from 'react-bootstrap';

import LeagueTable from '../LeagueTable';

class Divisions extends Component {

  constructor(props) {
    super(props);
    this.state = {
			divisions: this.getDivisions(props.seasons[0])
		};
  }

  getDivisions = (season) => {
    let divisions = [];
    season.table.forEach(p => {
      while (p.division > divisions.length) {
        divisions.push({
          name: 'Division ' + (divisions.length + 1),
          table: []
        });
      }
      let table = divisions[p.division - 1].table;
      p.rank = table.length + 1;
      table.push(p);
    });
    return divisions;
  }

  handleSelect = (evt, index) => {
    this.setState({
      divisions: this.getDivisions(this.props.seasons[index])
    });
  }

  render = () => {
    let opts = this.props.seasons.map((s, index) => {
      return (
        <MenuItem eventKey={index}>{s.date.month + '-' + s.date.year}</MenuItem>
      );
    });
    let divs = this.state.divisions.map(d => {
      return (
        <Panel header={d.name}>
          <LeagueTable data={d.table}/>
        </Panel>
      );
    });
    return (

        <Panel>
          <ButtonToolbar>
            <DropdownButton bsStyle='primary' title='Season' onSelect={this.handleSelect}>
              {opts}
            </DropdownButton>
          </ButtonToolbar>
        </Panel>
        {divs}

    );
  }
}

export default Divisions;
<commit_msg>Format season dates using Moment.<commit_after>import React, { PropTypes, Component } from 'react';
import { Row, Panel, ButtonToolbar, DropdownButton, MenuItem } from 'react-bootstrap';
import moment from 'moment';

import LeagueTable from '../LeagueTable';

class Divisions extends Component {

  constructor(props) {
    super(props);
    this.state = {
			divisions: this.getDivisions(props.seasons[0])
		};
  }

  getDivisions = (season) => {
    let divisions = [];
    season.table.forEach(p => {
      while (p.division > divisions.length) {
        divisions.push({
          name: 'Division ' + (divisions.length + 1),
          table: []
        });
      }
      let table = divisions[p.division - 1].table;
      p.rank = table.length + 1;
      table.push(p);
    });
    return divisions;
  }

  handleSelect = (evt, index) => {
    this.setState({
      divisions: this.getDivisions(this.props.seasons[index])
    });
  }

  render = () => {
    let opts = this.props.seasons.map((s, index) => {
      return (
        <MenuItem eventKey={index}>{moment({ year: s.date.year, month: s.date.month}).format('YYYY-MM')}</MenuItem>
      );
    });
    let divs = this.state.divisions.map(d => {
      return (
        <Panel header={d.name}>
          <LeagueTable data={d.table}/>
        </Panel>
      );
    });
    return (

        <ButtonToolbar>
          <DropdownButton bsStyle='default' title='Season' onSelect={this.handleSelect}>
            {opts}
          </DropdownButton>
        </ButtonToolbar>
        {divs}

    );
  }
}

export default Divisions;
<|endoftext|>


<commit_before>/*
 * File to store and export reusable constant values
 */

/*
 * Teaser length is constrained to 156 characters so
 * that the teaser is not cut off by search engines
 */
export const MAX_TEASER_LENGTH = 156;
<commit_msg>Change max teaser length to 250<commit_after>/*
 * File to store and export reusable constant values
 */

/*
 * Teaser length is constrained to 250 characters so
 * that the teaser is not cut off by search engines
 */
export const MAX_TEASER_LENGTH = 250;
<|endoftext|>


<commit_before>'use strict';
angular.module('testReporterApp')
  .directive('errorReport', [ '$http', '$q','SolrSearch','$rootScope', function ($http, $q, SolrSearch, $rootScope) {
    return {
        templateUrl: '/views/directives/error-report.html',
        restrict: 'A',
        scope: {
          errorReport: '='
        },
        link: function ($scope) {
          $scope.$watch('errorReport', function (testReport) {
              if(!testReport) {
                return;
              }
              var erroredExecutions = [];
              var errors = [];
              testReport.cases.forEach(function (tc) {
                tc.executions.forEach(function (te) {
                  if(!te.passing && !te.skipped) {
                    erroredExecutions.push(te);
                  }
                });
              });

              var failingTest = erroredExecutions.shift();
              SolrSearch.getSimilarDocuments(failingTest)
                .then(function _(response) {
                  var error = {
                    error: response.test.error,
                    interestingTerms: response.data.interestingTerms,
                    url: response.url,
                    affectedTests: [response.test]
                  };
                  var docs = response.data.response.docs;

                  docs.forEach(function (doc) {

                    if(doc.id == response.test.id) {
                      error.affectedTests.push(doc);
                    }

                    var match = erroredExecutions.findIndex(function(te) {
                      return te.id == doc.id;
                    });

                    if(match !== -1) {
                      error.affectedTests.push(erroredExecutions.splice(match, 1)[0]);
                    }
                  });

                  errors.push(error);
                  var nextError = erroredExecutions.shift();
                  if(nextError) {
                    return SolrSearch.getSimilarDocuments(nextError)
                    .then(_)
                  }
                })
                .then(function() {
                  $rootScope.$broadcast('error-report', errors);
                  $scope.errorDetails = errors.sort(function (a, b) {
                    return b.affectedTests.length - a.affectedTests.length;
                  });
                });
          });
        }
    }
  }]);
<commit_msg>Removing unnecessary item from the affected tests array<commit_after>'use strict';
angular.module('testReporterApp')
  .directive('errorReport', [ '$http', '$q','SolrSearch','$rootScope', function ($http, $q, SolrSearch, $rootScope) {
    return {
        templateUrl: '/views/directives/error-report.html',
        restrict: 'A',
        scope: {
          errorReport: '='
        },
        link: function ($scope) {
          $scope.$watch('errorReport', function (testReport) {
              if(!testReport) {
                return;
              }
              var erroredExecutions = [];
              var errors = [];
              testReport.cases.forEach(function (tc) {
                tc.executions.forEach(function (te) {
                  if(!te.passing && !te.skipped) {
                    erroredExecutions.push(te);
                  }
                });
              });

              var failingTest = erroredExecutions.shift();
              SolrSearch.getSimilarDocuments(failingTest)
                .then(function _(response) {
                  var error = {
                    error: response.test.error,
                    interestingTerms: response.data.interestingTerms,
                    url: response.url,
                    affectedTests: [response.test]
                  };
                  var docs = response.data.response.docs;

                  docs.forEach(function (doc) {
                    var match = erroredExecutions.findIndex(function(te) {
                      return te.id == doc.id;
                    });

                    if(match !== -1) {
                      error.affectedTests.push(erroredExecutions.splice(match, 1)[0]);
                    }
                  });

                  errors.push(error);
                  var nextError = erroredExecutions.shift();
                  if(nextError) {
                    return SolrSearch.getSimilarDocuments(nextError)
                    .then(_)
                  }
                })
                .then(function() {
                  $rootScope.$broadcast('error-report', errors);
                  $scope.errorDetails = errors.sort(function (a, b) {
                    return b.affectedTests.length - a.affectedTests.length;
                  });
                });
          });
        }
    }
  }]);
<|endoftext|>


<commit_before>///<reference path="test-syncable.html" />

(function () {
    module("tests-syncprovider");

    asyncTest("testWebSocketSyncServer", function () {
        var server = new SyncServer(1234);
        server.start();
        server.stop();

        var ws = new WebSocket("http://dummy:1234");
        ws.onopen = function () {
            ok(true, "WebSocket opened");
            ws.send(JSON.stringify({
                type: "clientIdentity",
                clientIdentity: null
            }));
            ws.send(JSON.stringify({
                type: "subscribe",
                syncedRevision: null
            }));
        }
        ws.onclose = function (reason) {
            ok(true, "WebSocket closed. Reason: " + reason);
            start();
        }
        ws.onerror = function (event) {
            ok(false, "Error: " + event.reason);
            start();
        }

        ws.onmessage = function (event) {
            var requestFromServer = JSON.parse(event.data);
            if (requestFromServer.type === "clientIdentity") {
                ok(true, "Got client identity: " + requestFromServer.clientIdentity);
                // Now send changes to server
                ws.send(JSON.stringify({
                    type: "changes",
                    changes: [],
                    partial: false,
                    baseRevision: null,
                    requestId: 1
                }));
            } else if (requestFromServer.type == "ack") {
                ok(true, "Got ack from server: " + requestFromServer.requestId);
                equal(requestFromServer.requestId, 1, "The request ID 1 was acked");

                // Now connect another WebSocket and send its changes to server so that server will react and send us the changes:
                var ws2 = new WebSocket("http://dummy:1234");
                ws2.onopen = function () {
                    ws2.send(JSON.stringify({
                        type: "clientIdentity",
                        clientIdentity: null
                    }));
                    ws2.send(JSON.stringify({
                        type: "changes",
                        changes: [{ type: 1, table: "UllaBella", key: "apa", obj: {name: "Apansson"}}],
                        partial: false,
                        baseRevision: null,
                        requestId: 1
                    }));
                }
            } else if (requestFromServer.type == "changes") {
                if (requestFromServer.currentRevision == 0) {
                    ok(true, "Got initial changes sent to us with current revision 0");
                } else {
                    ok(true, "Got changes from server: " + JSON.stringify(requestFromServer.changes));
                    equal(JSON.stringify(requestFromServer.changes), JSON.stringify([
                        {
                            rev: 1,
                            source: 2, // WebSocket2 was the source of the changes.
                            type: 1,
                            table: "UllaBella",
                            key: "apa",
                            obj: { name: "Apansson" }
                        }
                    ]), "Changes where the same as the ones sent by WebSocket2");
                    start();
                }
            }
        }

    });

})();<commit_msg>Error in unit test<commit_after>///<reference path="test-syncable.html" />

(function () {
    module("tests-syncprovider");

    asyncTest("testWebSocketSyncServer", function () {
        var server = new SyncServer(1234);
        server.start();

        var ws = new WebSocket("http://dummy:1234");
        ws.onopen = function () {
            ok(true, "WebSocket opened");
            ws.send(JSON.stringify({
                type: "clientIdentity",
                clientIdentity: null
            }));
            ws.send(JSON.stringify({
                type: "subscribe",
                syncedRevision: null
            }));
        }
        ws.onclose = function (reason) {
            ok(true, "WebSocket closed. Reason: " + reason);
            start();
        }
        ws.onerror = function (event) {
            ok(false, "Error: " + event.reason);
            start();
        }

        ws.onmessage = function (event) {
            var requestFromServer = JSON.parse(event.data);
            if (requestFromServer.type === "clientIdentity") {
                ok(true, "Got client identity: " + requestFromServer.clientIdentity);
                // Now send changes to server
                ws.send(JSON.stringify({
                    type: "changes",
                    changes: [],
                    partial: false,
                    baseRevision: null,
                    requestId: 1
                }));
            } else if (requestFromServer.type == "ack") {
                ok(true, "Got ack from server: " + requestFromServer.requestId);
                equal(requestFromServer.requestId, 1, "The request ID 1 was acked");

                // Now connect another WebSocket and send its changes to server so that server will react and send us the changes:
                var ws2 = new WebSocket("http://dummy:1234");
                ws2.onopen = function () {
                    ws2.send(JSON.stringify({
                        type: "clientIdentity",
                        clientIdentity: null
                    }));
                    ws2.send(JSON.stringify({
                        type: "changes",
                        changes: [{ type: 1, table: "UllaBella", key: "apa", obj: {name: "Apansson"}}],
                        partial: false,
                        baseRevision: null,
                        requestId: 1
                    }));
                }
            } else if (requestFromServer.type == "changes") {
                if (requestFromServer.currentRevision == 0) {
                    ok(true, "Got initial changes sent to us with current revision 0");
                } else {
                    ok(true, "Got changes from server: " + JSON.stringify(requestFromServer.changes));
                    equal(JSON.stringify(requestFromServer.changes), JSON.stringify([
                        {
                            rev: 1,
                            source: 2, // WebSocket2 was the source of the changes.
                            type: 1,
                            table: "UllaBella",
                            key: "apa",
                            obj: { name: "Apansson" }
                        }
                    ]), "Changes where the same as the ones sent by WebSocket2");
                    start();
                }
            }
        }

    });

})();<|endoftext|>


<commit_before>/* eslint-disable react/no-did-mount-set-state, no-param-reassign */

import React from 'react'
import reactCSS from 'reactcss'
import color from '../../helpers/color'

import { EditableInput } from '../common'
import UnfoldMoreHorizontalIcon from '@icons/material/UnfoldMoreHorizontalIcon'

export class ChromeFields extends React.Component {
  state = {
    view: '',
  }

  componentDidMount() {
    if (this.props.hsl.a === 1 && this.state.view !== 'hex') {
      this.setState({ view: 'hex' })
    } else if (this.state.view !== 'rgb' && this.state.view !== 'hsl') {
      this.setState({ view: 'rgb' })
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.hsl.a !== 1 && this.state.view === 'hex') {
      this.setState({ view: 'rgb' })
    }
  }

  toggleViews = () => {
    if (this.state.view === 'hex') {
      this.setState({ view: 'rgb' })
    } else if (this.state.view === 'rgb') {
      this.setState({ view: 'hsl' })
    } else if (this.state.view === 'hsl') {
      if (this.props.hsl.a === 1) {
        this.setState({ view: 'hex' })
      } else {
        this.setState({ view: 'rgb' })
      }
    }
  }

  handleChange = (data, e) => {
    if (data.hex) {
      color.isValidHex(data.hex) && this.props.onChange({
        hex: data.hex,
        source: 'hex',
      }, e)
    } else if (data.r || data.g || data.b) {
      this.props.onChange({
        r: data.r || this.props.rgb.r,
        g: data.g || this.props.rgb.g,
        b: data.b || this.props.rgb.b,
        source: 'rgb',
      }, e)
    } else if (data.a) {
      if (data.a < 0) {
        data.a = 0
      } else if (data.a > 1) {
        data.a = 1
      }

      this.props.onChange({
        h: this.props.hsl.h,
        s: this.props.hsl.s,
        l: this.props.hsl.l,
        a: Math.round(data.a * 100) / 100,
        source: 'rgb',
      }, e)
    } else if (data.h || data.s || data.l) {
      this.props.onChange({
        h: data.h || this.props.hsl.h,
        s: Number((data.s && data.s) || this.props.hsl.s),
        l: Number((data.l && data.l) || this.props.hsl.l),
        source: 'hsl',
      }, e)
    }
  }

  showHighlight = (e) => {
    e.target.style.background = '#eee'
  }

  hideHighlight = (e) => {
    e.target.style.background = 'transparent'
  }

  render() {
    const styles = reactCSS({
      'default': {
        wrap: {
          paddingTop: '16px',
          display: 'flex',
        },
        fields: {
          flex: '1',
          display: 'flex',
          marginLeft: '-6px',
        },
        field: {
          paddingLeft: '6px',
          width: '100%',
        },
        alpha: {
          paddingLeft: '6px',
          width: '100%',
        },
        toggle: {
          width: '32px',
          textAlign: 'right',
          position: 'relative',
        },
        icon: {
          marginRight: '-4px',
          marginTop: '12px',
          cursor: 'pointer',
          position: 'relative',
        },
        iconHighlight: {
          position: 'absolute',
          width: '24px',
          height: '28px',
          background: '#eee',
          borderRadius: '4px',
          top: '10px',
          left: '12px',
          display: 'none',
        },
        input: {
          fontSize: '11px',
          color: '#333',
          width: '100%',
          borderRadius: '2px',
          border: 'none',
          boxShadow: 'inset 0 0 0 1px #dadada',
          height: '21px',
          textAlign: 'center',
        },
        label: {
          textTransform: 'uppercase',
          fontSize: '11px',
          lineHeight: '11px',
          color: '#969696',
          textAlign: 'center',
          display: 'block',
          marginTop: '12px',
        },
        svg: {
          fill: '#333',
          width: '24px',
          height: '24px',
          border: '1px transparent solid',
          borderRadius: '5px',
        },
      },
      'disableAlpha': {
        alpha: {
          display: 'none',
        },
      },
    }, this.props, this.state)

    let fields
    if (this.state.view === 'hex') {
      fields = (

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="hex" value={ this.props.hex }
            onChange={ this.handleChange }
          />

)
    } else if (this.state.view === 'rgb') {
      fields = (

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="r"
            value={ this.props.rgb.r }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="g"
            value={ this.props.rgb.g }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="b"
            value={ this.props.rgb.b }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="a"
            value={ this.props.rgb.a }
            arrowOffset={ 0.01 }
            onChange={ this.handleChange }
          />

)
    } else if (this.state.view === 'hsl') {
      fields = (

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="h"
            value={ Math.round(this.props.hsl.h) }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="s"
            value={ `${ Math.round(this.props.hsl.s * 100) }%` }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="l"
            value={ `${ Math.round(this.props.hsl.l * 100) }%` }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="a"
            value={ this.props.hsl.a }
            arrowOffset={ 0.01 }
            onChange={ this.handleChange }
          />

)
    }

    return (

        { fields }

 this.icon = icon }>
            <UnfoldMoreHorizontalIcon
              style={ styles.svg }
              onMouseOver={ this.showHighlight }
              onMouseEnter={ this.showHighlight }
              onMouseOut={ this.hideHighlight }
            />

    )
  }
}

export default ChromeFields
<commit_msg>Proposed fix for issue #528 (#529)<commit_after>/* eslint-disable react/no-did-mount-set-state, no-param-reassign */

import React from 'react'
import reactCSS from 'reactcss'
import color from '../../helpers/color'

import { EditableInput } from '../common'
import UnfoldMoreHorizontalIcon from '@icons/material/UnfoldMoreHorizontalIcon'

export class ChromeFields extends React.Component {
  state = {
    view: '',
  }

  componentDidMount() {
    if (this.props.hsl.a === 1 && this.state.view !== 'hex') {
      this.setState({ view: 'hex' })
    } else if (this.state.view !== 'rgb' && this.state.view !== 'hsl') {
      this.setState({ view: 'rgb' })
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.hsl.a !== 1 && this.state.view === 'hex') {
      this.setState({ view: 'rgb' })
    }
  }

  toggleViews = () => {
    if (this.state.view === 'hex') {
      this.setState({ view: 'rgb' })
    } else if (this.state.view === 'rgb') {
      this.setState({ view: 'hsl' })
    } else if (this.state.view === 'hsl') {
      if (this.props.hsl.a === 1) {
        this.setState({ view: 'hex' })
      } else {
        this.setState({ view: 'rgb' })
      }
    }
  }

  handleChange = (data, e) => {
    if (data.hex) {
      color.isValidHex(data.hex) && this.props.onChange({
        hex: data.hex,
        source: 'hex',
      }, e)
    } else if (data.r || data.g || data.b) {
      this.props.onChange({
        r: data.r || this.props.rgb.r,
        g: data.g || this.props.rgb.g,
        b: data.b || this.props.rgb.b,
        source: 'rgb',
      }, e)
    } else if (data.a) {
      if (data.a < 0) {
        data.a = 0
      } else if (data.a > 1) {
        data.a = 1
      }

      this.props.onChange({
        h: this.props.hsl.h,
        s: this.props.hsl.s,
        l: this.props.hsl.l,
        a: Math.round(data.a * 100) / 100,
        source: 'rgb',
      }, e)
    } else if (data.h || data.s || data.l) {
      // Remove any occurances of '%'.
      if (typeof(data.s) === 'string' && data.s.includes('%')) { data.s = data.s.replace('%', '') }
      if (typeof(data.l) === 'string' && data.l.includes('%')) { data.l = data.l.replace('%', '') }

      this.props.onChange({
        h: data.h || this.props.hsl.h,
        s: Number((data.s && data.s) || this.props.hsl.s),
        l: Number((data.l && data.l) || this.props.hsl.l),
        source: 'hsl',
      }, e)
    }
  }

  showHighlight = (e) => {
    e.target.style.background = '#eee'
  }

  hideHighlight = (e) => {
    e.target.style.background = 'transparent'
  }

  render() {
    const styles = reactCSS({
      'default': {
        wrap: {
          paddingTop: '16px',
          display: 'flex',
        },
        fields: {
          flex: '1',
          display: 'flex',
          marginLeft: '-6px',
        },
        field: {
          paddingLeft: '6px',
          width: '100%',
        },
        alpha: {
          paddingLeft: '6px',
          width: '100%',
        },
        toggle: {
          width: '32px',
          textAlign: 'right',
          position: 'relative',
        },
        icon: {
          marginRight: '-4px',
          marginTop: '12px',
          cursor: 'pointer',
          position: 'relative',
        },
        iconHighlight: {
          position: 'absolute',
          width: '24px',
          height: '28px',
          background: '#eee',
          borderRadius: '4px',
          top: '10px',
          left: '12px',
          display: 'none',
        },
        input: {
          fontSize: '11px',
          color: '#333',
          width: '100%',
          borderRadius: '2px',
          border: 'none',
          boxShadow: 'inset 0 0 0 1px #dadada',
          height: '21px',
          textAlign: 'center',
        },
        label: {
          textTransform: 'uppercase',
          fontSize: '11px',
          lineHeight: '11px',
          color: '#969696',
          textAlign: 'center',
          display: 'block',
          marginTop: '12px',
        },
        svg: {
          fill: '#333',
          width: '24px',
          height: '24px',
          border: '1px transparent solid',
          borderRadius: '5px',
        },
      },
      'disableAlpha': {
        alpha: {
          display: 'none',
        },
      },
    }, this.props, this.state)

    let fields
    if (this.state.view === 'hex') {
      fields = (

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="hex" value={ this.props.hex }
            onChange={ this.handleChange }
          />

)
    } else if (this.state.view === 'rgb') {
      fields = (

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="r"
            value={ this.props.rgb.r }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="g"
            value={ this.props.rgb.g }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="b"
            value={ this.props.rgb.b }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="a"
            value={ this.props.rgb.a }
            arrowOffset={ 0.01 }
            onChange={ this.handleChange }
          />

)
    } else if (this.state.view === 'hsl') {
      fields = (

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="h"
            value={ Math.round(this.props.hsl.h) }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="s"
            value={ `${ Math.round(this.props.hsl.s * 100) }%` }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="l"
            value={ `${ Math.round(this.props.hsl.l * 100) }%` }
            onChange={ this.handleChange }
          />

          <EditableInput
            style={{ input: styles.input, label: styles.label }}
            label="a"
            value={ this.props.hsl.a }
            arrowOffset={ 0.01 }
            onChange={ this.handleChange }
          />

)
    }

    return (

        { fields }

 this.icon = icon }>
            <UnfoldMoreHorizontalIcon
              style={ styles.svg }
              onMouseOver={ this.showHighlight }
              onMouseEnter={ this.showHighlight }
              onMouseOut={ this.hideHighlight }
            />

    )
  }
}

export default ChromeFields
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react';

const ImageUpload = ({onUploadFileChanged, onSubmitClicked}) => {
  return (

      <input className="image-editor-upload__filename btn" type="file" onChange={onUploadFileChanged} name="image-upload"/>
      <input className="image-editor-upload__submit btn btn-primary" type="submit" onClick={onSubmitClicked} value="Upload Image" name="submit"/>

  );
};

export default ImageUpload;<commit_msg>Thumbnail upload<commit_after>import React, {PropTypes} from 'react';

const ImageUpload = ({onUploadFileChanged, onSubmitClicked}) => {
  return (

      <input className="image-editor-upload__filename btn" type="file" onChange={onUploadFileChanged} name="image-upload"/>
      <input className="image-editor-upload__submit btn btn-primary" type="submit" onClick={onSubmitClicked} value="Upload Image" name="submit"/>

  );
};

export default ImageUpload;<|endoftext|>


<commit_before>"use strict";

app.factory('LocationLogicService', function(OpeningTimesService, UtilService, I18nService) {

    var veganCategories = [];
    veganCategories[5] = "vegan";
    veganCategories[4] = "vegetarian";
    veganCategories[2] = "omnivorous";
    var i18n = I18nService.getI18n();
    var service = {};

    service.enhanceLocations = function(locations) {
        for (var i = 0; i < locations.length; i++) {
            enhanceLocation(locations[i]);
        }
    };

    function enhanceLocation(location) {

        location.tags = location.tags.sort();

        if (location.comment) {
            location.commentWithoutFormatting = removeFormatting(location.comment);
        }

        if (location.commentEnglish) {
            location.commentEnglishWithoutFormatting = removeFormatting(location.commentEnglish);
        }

        if (location.reviewURL) {
            // Possibly not necessary in production
            location.reviewURL = "http://www.berlin-vegan.de/essen-und-trinken/kritiken/" + location.reviewURL;
        }

        location.openingTimes = [
            new OpeningTime(0, location.otSun),
            new OpeningTime(1, location.otMon),
            new OpeningTime(2, location.otTue),
            new OpeningTime(3, location.otWed),
            new OpeningTime(4, location.otThu),
            new OpeningTime(5, location.otFri),
            new OpeningTime(6, location.otSat)
        ];

        location.getOpeningTimeTodayFriendly = function() {

            var otIntervalToday = this.openingTimes[new Date().getDay()].interval;

            if (otIntervalToday.isOpen) {
                return i18n.openingTimes.isOpenToday + ": " + otIntervalToday.friendly;
            } else {
                return i18n.openingTimes.isClosedToday;
            }
        }

        location.isOpen = function(weekDay, timeAsDate) {
            return OpeningTimesService.isOpen(this.openingTimes, weekDay, timeAsDate);
        }

        location.getOpenComment = function(language) {
            return language === "en" ?
                "Please see location website for opening time details!" :  this.openComment;
        };

        location.getOpeningTimesCompressed = function() {

            var compressedOts = [];

            for (var day = 1; day <= 7; day++) {

                var ot = this.openingTimes[day === 7 ? 0 : day];

                if (day > 1) {

                    var lastGroup = compressedOts[compressedOts.length - 1];

                    if (lastGroup[0].interval.friendly === ot.interval.friendly) {
                        lastGroup.push(ot);
                        continue;
                    }
                }

                var group = [];
                group.push(ot);
                compressedOts.push(group);
            }

            return compressedOts;
        }

        location.getDistanceToPositionInKm = function(position) {

            return UtilService.getDistanceFromLatLonInKm(
                position.lat(),
                position.lng(),
                parseFloat(this.latCoord),
                parseFloat(this.longCoord)
            )
        };

        location.getVeganCategory = function() {
            var veganCategory = veganCategories[this.vegan];
            if (!veganCategory) {
                throw new Error("Unexpected value for vegan: " + this.vegan);
            }
            return veganCategory;
        }
    }

    function removeFormatting(locationComment) {
        return locationComment.replace(//g, "").replace(/<br\/>/g, " ");
    }

    function OpeningTime(dayIndex, otString) {
        this.dayIndex = dayIndex;
        this.friendlyDay = i18n.enums.weekday[dayIndex + ""];
        this.friendlyDayShort = I18nService.abbreviateWeekDay(this.friendlyDay);
        this.interval = new OpeningTimeInterval(otString);
    }

    function OpeningTimeInterval(otString) {

        this.otString = otString;
        this.isOpen = (otString !== "");

        if (this.isOpen) {

            var date = { year: 2000, month: 1, day: 1 }; // Arbitrary
            var otParts = otString.split(" - ");

            var beginTime = UtilService.getTime(otParts[0]);
            this.begin = UtilService.newDate(date, beginTime);

            var endTime = UtilService.getTime(otParts[1]);
            this.end = UtilService.newDate(date, endTime);

            this.friendly = I18nService.formatTimeInterval(this.begin, this.end);
        } else {
            this.friendly = i18n.openingTimes.isClosed;
        }
    }

    service.getSortedTags = function(locations) {

        // var pseudoSet = {};
        //
        // for (var i = 0; i < locations.length; i++) {
        //     for (var j = 0; j < locations[i].tags.length; j++) {
        //         pseudoSet[locations[i].tags[j]] = "";
        //     }
        // }
        //
        // return pseudoSetToSortedArray(pseudoSet);

        // Since we know that these are fixed, we can optimize performance by using a shortcut.
        // It would probably be better to have this list generated into JSON. TODO
        return ["Cafe", "Eiscafe", "Imbiss", "Restaurant"];
    }

    function pseudoSetToSortedArray(pseudoSet) {

        var array = [];

        for (var entry in pseudoSet) {
            array.push(entry);
        }

        array.sort();
        return array;
    }

    service.getSortedVeganCategories = function() {
        return veganCategories.filter(function(it) { return !!it; } ).reverse();
    }

    return {
        enhanceLocations: function(locations) {
            return service.enhanceLocations(locations);
        },
        getSortedTags: function(locations) {
            return service.getSortedTags(locations);
        },
        getSortedVeganCategories: function() {
            return service.getSortedVeganCategories();
        },
    };
});<commit_msg>Workaround for a build problem<commit_after>"use strict";

app.factory('LocationLogicService', function(OpeningTimesService, UtilService, I18nService) {

    var veganCategories = [];
    veganCategories[5] = "vegan";
    veganCategories[4] = "vegetarian";
    veganCategories[2] = "omnivorous";
    var i18n = I18nService.getI18n();
    var service = {};

    service.enhanceLocations = function(locations) {
        for (var i = 0; i < locations.length; i++) {
            enhanceLocation(locations[i]);
        }
    };

    function enhanceLocation(location) {

        location.tags = location.tags.sort();

        if (location.comment) {
            location.commentWithoutFormatting = removeFormatting(location.comment);
        }

        if (location.commentEnglish) {
            location.commentEnglishWithoutFormatting = removeFormatting(location.commentEnglish);
        }

        if (location.reviewURL) {
            // Possibly not necessary in production
            location.reviewURL = "http://www.berlin-vegan.de/essen-und-trinken/kritiken/" + location.reviewURL;
        }

        location.openingTimes = [
            new OpeningTime(0, location.otSun),
            new OpeningTime(1, location.otMon),
            new OpeningTime(2, location.otTue),
            new OpeningTime(3, location.otWed),
            new OpeningTime(4, location.otThu),
            new OpeningTime(5, location.otFri),
            new OpeningTime(6, location.otSat)
        ];

        location.getOpeningTimeTodayFriendly = function() {

            var otIntervalToday = this.openingTimes[new Date().getDay()].interval;

            if (otIntervalToday.isOpen) {
                return i18n.openingTimes.isOpenToday + ": " + otIntervalToday.friendly;
            } else {
                return i18n.openingTimes.isClosedToday;
            }
        }

        location.isOpen = function(weekDay, timeAsDate) {
            return OpeningTimesService.isOpen(this.openingTimes, weekDay, timeAsDate);
        }

        location.getOpenComment = function(language) {
            return language === "en" ?
                "Please see location website for opening time details!" :  this.openComment;
        };

        location.getOpeningTimesCompressed = function() {

            var compressedOts = [];

            for (var day = 1; day <= 7; day++) {

                var ot = this.openingTimes[day === 7 ? 0 : day];

                if (day > 1) {

                    var lastGroup = compressedOts[compressedOts.length - 1];

                    if (lastGroup[0].interval.friendly === ot.interval.friendly) {
                        lastGroup.push(ot);
                        continue;
                    }
                }

                var group = [];
                group.push(ot);
                compressedOts.push(group);
            }

            return compressedOts;
        }

        location.getDistanceToPositionInKm = function(position) {

            return UtilService.getDistanceFromLatLonInKm(
                position.lat(),
                position.lng(),
                parseFloat(this.latCoord),
                parseFloat(this.longCoord)
            )
        };

        location.getVeganCategory = function() {
            var veganCategory = veganCategories[this.vegan];
            if (!veganCategory) {
                throw new Error("Unexpected value for vegan: " + this.vegan);
            }
            return veganCategory;
        }
    }

    function removeFormatting(locationComment) {
        return locationComment.replace(//g, "").replace(/<br\/>/g, " ");
    }

    function OpeningTime(dayIndex, otString) {
        this.dayIndex = dayIndex;
        this.friendlyDay = i18n.enums.weekday[dayIndex + ""];
        this.friendlyDayShort = I18nService.abbreviateWeekDay(this.friendlyDay);
        this.interval = new OpeningTimeInterval(otString);
    }

    function OpeningTimeInterval(otString) {

        this.otString = otString;
        this.isOpen = (otString !== "");

        if (this.isOpen) {

            var date = { year: 2000, month: 1, day: 1 }; // Arbitrary
            var otParts = otString.split(" - ");

            var beginTime = UtilService.getTime(otParts[0]);
            this.begin = UtilService.newDate(date, beginTime);

            var endTime = UtilService.getTime(otParts[1]);
            this.end = UtilService.newDate(date, endTime);

            this.friendly = I18nService.formatTimeInterval(this.begin, this.end);
        } else {
            this.friendly = i18n.openingTimes.isClosed;
        }
    }

    service.getSortedTags = function(locations) {

        // var pseudoSet = {};
        //
        // for (var i = 0; i < locations.length; i++) {
        //     for (var j = 0; j < locations[i].tags.length; j++) {
        //         pseudoSet[locations[i].tags[j]] = "";
        //     }
        // }
        //
        // return pseudoSetToSortedArray(pseudoSet);

        // Since we know that these are fixed, we can optimize performance by using a shortcut.
        // It would probably be better to have this list generated into JSON. TODO
        return ["Cafe", "Eiscafe", "Imbiss", "Restaurant"];
    }

    function pseudoSetToSortedArray(pseudoSet) {

        var array = [];

        for (var entry in pseudoSet) {
            array.push(entry);
        }

        array.sort();
        return array;
    }

    service.getSortedVeganCategories = function() {
        return onlyDefined(veganCategories).reverse();

        // Build process seems to have a problem with an array's filter funtion,
        // so we use this workaround: (TODO: Refactor to UtilService)
        function onlyDefined(arr) {
            var result = [];
            for (var i = 0; i < arr.length; i++) {
                if (arr[i]) {
                    result.push(arr[i]);
                }
            }
            return result;
        }
    }

    return {
        enhanceLocations: function(locations) {
            return service.enhanceLocations(locations);
        },
        getSortedTags: function(locations) {
            return service.getSortedTags(locations);
        },
        getSortedVeganCategories: function() {
            return service.getSortedVeganCategories();
        },
    };
});<|endoftext|>


<commit_before>/* eslint-disable no-undef,react/no-did-update-set-state,no-magic-numbers */
import R from 'ramda';
import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {getReloadHash} from '../../actions/api';

class Reloader extends React.Component {
    constructor(props) {
        super(props);
        if (props.config.hot_reload) {
            const {interval, max_retry} = props.config.hot_reload;
            this.state = {
                hash: null,
                interval,
                disabled: false,
                intervalId: null,
                packages: null,
                max_retry
            };
        } else {
            this.state = {
                disabled: true,
            };
        }
        this._retry = 0;
        this._head = document.querySelector('head');
    }

    componentDidUpdate() {
        const {reloadRequest, dispatch} = this.props;
        if (reloadRequest.status === 200) {
            if (this.state.hash === null) {
                this.setState({
                    hash: reloadRequest.content.reloadHash,
                    packages: reloadRequest.content.packages,
                });
                return;
            }
            if (reloadRequest.content.reloadHash !== this.state.hash) {
                if (
                    reloadRequest.content.hard ||
                    reloadRequest.content.packages.length !==
                        this.state.packages.length ||
                    !R.all(
                        R.map(
                            x => R.contains(x, this.state.packages),
                            reloadRequest.content.packages
                        )
                    )
                ) {
                    // Look if it was a css file.
                    let was_css = false;
                    for (let a of reloadRequest.content.files) {
                        if (a.is_css) {
                            was_css = true;
                            const nodesToDisable = [];

                            // Search for the old file by xpath.
                            const it = document.evaluate(
                                `//link[contains(@href, "${a.url}")]`,
                                this._head
                            );
                            let node = it.iterateNext();

                            while (node) {
                                nodesToDisable.push(node);
                                node = it.iterateNext();
                            }
                            nodesToDisable.forEach(n =>
                                n.setAttribute('disabled', 'disabled')
                            );

                            if (a.modified > 0) {
                                const link = document.createElement('link');
                                link.href = `${a.url}?m=${a.modified}`;
                                link.type = 'text/css';
                                link.rel = 'stylesheet';
                                this._head.appendChild(link);
                                // Else the file was deleted.
                            }
                        } else {
                            // If there's another kind of file here do a hard reload.
                            was_css = false;
                            break;
                        }
                    }
                    if (!was_css) {
                        // Assets file have changed
                        // or a component lib has been added/removed
                        window.top.location.reload();
                    } else {
                        // Since it's only a css reload,
                        // we just change the hash.
                        this.setState({
                            hash: reloadRequest.content.reloadHash,
                        });
                    }
                } else {
                    // Soft reload
                    window.clearInterval(this.state.intervalId);
                    dispatch({type: 'RELOAD'});
                }
            }
        } else if (reloadRequest.status === 500) {
            if (this._retry > this.state.max_retry) {
                window.clearInterval(this.state.intervalId);
                // Integrate with dev tools ui?!
                window.alert(
                    `
                    Reloader failed after ${this._retry} times.
                    Please check your application for errors.
                    `
                );
            }
            this._retry++;
        }
    }

    componentDidMount() {
        const {dispatch} = this.props;
        const {disabled, interval} = this.state;
        if (!disabled && !this.state.intervalId) {
            const intervalId = setInterval(() => {
                dispatch(getReloadHash());
            }, interval);
            this.setState({intervalId});
        }
    }

    componentWillUnmount() {
        if (!this.state.disabled && this.state.intervalId) {
            window.clearInterval(this.state.intervalId);
        }
    }

    render() {
        return null;
    }
}

Reloader.defaultProps = {};

Reloader.propTypes = {
    id: PropTypes.string,
    config: PropTypes.object,
    reloadRequest: PropTypes.object,
    dispatch: PropTypes.func,
    interval: PropTypes.number,
};

export default connect(
    state => ({
        config: state.config,
        reloadRequest: state.reloadRequest,
    }),
    dispatch => ({dispatch})
)(Reloader);
<commit_msg>Ramda forEach.<commit_after>/* eslint-disable no-undef,react/no-did-update-set-state,no-magic-numbers */
import R from 'ramda';
import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {getReloadHash} from '../../actions/api';

class Reloader extends React.Component {
    constructor(props) {
        super(props);
        if (props.config.hot_reload) {
            const {interval, max_retry} = props.config.hot_reload;
            this.state = {
                hash: null,
                interval,
                disabled: false,
                intervalId: null,
                packages: null,
                max_retry
            };
        } else {
            this.state = {
                disabled: true,
            };
        }
        this._retry = 0;
        this._head = document.querySelector('head');
    }

    componentDidUpdate() {
        const {reloadRequest, dispatch} = this.props;
        if (reloadRequest.status === 200) {
            if (this.state.hash === null) {
                this.setState({
                    hash: reloadRequest.content.reloadHash,
                    packages: reloadRequest.content.packages,
                });
                return;
            }
            if (reloadRequest.content.reloadHash !== this.state.hash) {
                if (
                    reloadRequest.content.hard ||
                    reloadRequest.content.packages.length !==
                        this.state.packages.length ||
                    !R.all(
                        R.map(
                            x => R.contains(x, this.state.packages),
                            reloadRequest.content.packages
                        )
                    )
                ) {
                    // Look if it was a css file.
                    let was_css = false;
                    for (let a of reloadRequest.content.files) {
                        if (a.is_css) {
                            was_css = true;
                            const nodesToDisable = [];

                            // Search for the old file by xpath.
                            const it = document.evaluate(
                                `//link[contains(@href, "${a.url}")]`,
                                this._head
                            );
                            let node = it.iterateNext();

                            while (node) {
                                nodesToDisable.push(node);
                                node = it.iterateNext();
                            }

                            R.forEach(
                                n => n.setAttribute('disabled', 'disabled'),
                                nodesToDisable
                            );

                            if (a.modified > 0) {
                                const link = document.createElement('link');
                                link.href = `${a.url}?m=${a.modified}`;
                                link.type = 'text/css';
                                link.rel = 'stylesheet';
                                this._head.appendChild(link);
                                // Else the file was deleted.
                            }
                        } else {
                            // If there's another kind of file here do a hard reload.
                            was_css = false;
                            break;
                        }
                    }
                    if (!was_css) {
                        // Assets file have changed
                        // or a component lib has been added/removed
                        window.top.location.reload();
                    } else {
                        // Since it's only a css reload,
                        // we just change the hash.
                        this.setState({
                            hash: reloadRequest.content.reloadHash,
                        });
                    }
                } else {
                    // Soft reload
                    window.clearInterval(this.state.intervalId);
                    dispatch({type: 'RELOAD'});
                }
            }
        } else if (reloadRequest.status === 500) {
            if (this._retry > this.state.max_retry) {
                window.clearInterval(this.state.intervalId);
                // Integrate with dev tools ui?!
                window.alert(
                    `
                    Reloader failed after ${this._retry} times.
                    Please check your application for errors.
                    `
                );
            }
            this._retry++;
        }
    }

    componentDidMount() {
        const {dispatch} = this.props;
        const {disabled, interval} = this.state;
        if (!disabled && !this.state.intervalId) {
            const intervalId = setInterval(() => {
                dispatch(getReloadHash());
            }, interval);
            this.setState({intervalId});
        }
    }

    componentWillUnmount() {
        if (!this.state.disabled && this.state.intervalId) {
            window.clearInterval(this.state.intervalId);
        }
    }

    render() {
        return null;
    }
}

Reloader.defaultProps = {};

Reloader.propTypes = {
    id: PropTypes.string,
    config: PropTypes.object,
    reloadRequest: PropTypes.object,
    dispatch: PropTypes.func,
    interval: PropTypes.number,
};

export default connect(
    state => ({
        config: state.config,
        reloadRequest: state.reloadRequest,
    }),
    dispatch => ({dispatch})
)(Reloader);
<|endoftext|>


<commit_before>(function () {
    'use strict';

    /**
     * Socket service.
     */
    angular.module('timax.services.socket', ['btford.socket-io', 'timax.config'])

        .factory('socketService', function ($q, $http, socketFactory, localStorageService, timaxConfig) {
            var token = localStorageService.get('token');

            // TODO check authentication, role, etc...

            var timaxSocket = socketFactory({
                ioSocket: io.connect(timaxConfig.SOCKET, {
                    query: 'token=' + token
                })
            });
            timaxSocket.forward('booking');
            return timaxSocket;
        });
})();<commit_msg>socket service only connects with role admin or manager<commit_after>(function () {
    'use strict';

    /**
     * Socket service.
     */
    angular.module('timax.services.socket', ['btford.socket-io', 'LocalStorageModule', 'timax.services.authorisation', 'timax.config'])

        .factory('socketService', function ($q, $http, socketFactory, localStorageService, authorisationService, timaxConfig) {
            var token = localStorageService.get('token'),
                principal = authorisationService.getPrincipal();

            if (angular.isObject(principal) && (principal.role === 'admin' || principal.role === 'manager')) {
                var timaxSocket = socketFactory({
                    ioSocket: io.connect(timaxConfig.SOCKET, {
                        query: 'token=' + token
                    })
                });
                timaxSocket.forward('booking');
                return timaxSocket;
            } else {
                return false;
            }
        });
})();<|endoftext|>


<commit_before>$('body')
.on('click', '.vimeo-launch', function () {
  var videoID = $(this).data('vimeo-id'),
      $video = '

';
  $('body').append($video);
} )

.on('click', '.vimeo-close', function () {
  $(this).addClass('closing');

  $('#vimeo-pop-container').delay(700).animate({
    height: 0,
    top: '50%'
  }, 'fast', function () {
    $('#vimeo-pop-container').remove();
  });
} );<commit_msg>Update index.js<commit_after>$('body')
.on('click', '.vimeo-launch', function () {
  var videoID = $(this).data('vimeo-id'),
      $video = '

';
  $('body').append($video);
} )

.on('click', '.vimeo-close', function () {
  $(this).addClass('closing');

  $('#vimeo-pop-container').delay(700).animate({
    height: 0,
    top: '50%'
  }, 'fast', function () {
    $('#vimeo-pop-container').remove();
  });
} );
<|endoftext|>


<commit_before>import React from 'react';
import { shallow } from 'enzyme';
import demand from 'must';
import ConfirmationDialog from '../ConfirmationDialog';
import { Modal, ModalBody, ModalFooter, Button } from 'elemental';

describe('<ConfirmationDialog />', () => {
	it('should render a Modal with a body and a footer', () => {
		const component = shallow(<ConfirmationDialog />);
		demand(component.find(Modal).length).equal(1);
		demand(component.find(ModalBody).length).equal(1);
		demand(component.find(ModalFooter).length).equal(1);
	});

	it('should render some passed HTML', () => {
		const HTML = '
Some HTML here!
';
		const component = shallow(
			<ConfirmationDialog
				body={HTML}
			/>
		);

		demand(component.find('div').prop('dangerouslySetInnerHTML')).eql({
			__html: HTML,
		});
	});

	describe('buttons', () => {
		it('should render two buttons', () => {
			const component = shallow(<ConfirmationDialog />);
			demand(component.find(Button).length).equal(2);
		});

		it('should render a button with a confirmation label', () => {
			const confirmationLabel = 'Confirm';
			const component = shallow(
				<ConfirmationDialog
					confirmationLabel={confirmationLabel}
				/>
			);

			demand(component.find(Button).at(0).contains(confirmationLabel)).true();
		});

		it('should render a button with a cancel label', () => {
			const cancelLabel = 'Confirm';
			const component = shallow(
				<ConfirmationDialog
					cancelLabel={cancelLabel}
				/>
			);

			demand(component.find(Button).at(1).contains(cancelLabel)).true();
		});
	});
});
<commit_msg>Fix ConfirmationDialog test<commit_after>import React from 'react';
import { shallow } from 'enzyme';
import demand from 'must';
import ConfirmationDialog from '../ConfirmationDialog';
import { Modal, ModalBody, ModalFooter, Button } from 'elemental';

describe('<ConfirmationDialog />', () => {
	it('should render a Modal with a body and a footer', () => {
		const component = shallow(<ConfirmationDialog />);
		demand(component.find(Modal).length).equal(1);
		demand(component.find(ModalBody).length).equal(1);
		demand(component.find(ModalFooter).length).equal(1);
	});

	it('should render some passed HTML', () => {
		const HTML = '
Some HTML here!
';
		const component = shallow(
			<ConfirmationDialog
				body={HTML}
			/>
		);

		demand(component.find('div').at(0).prop('dangerouslySetInnerHTML')).eql({
			__html: HTML,
		});
	});

	describe('buttons', () => {
		it('should render two buttons', () => {
			const component = shallow(<ConfirmationDialog />);
			demand(component.find(Button).length).equal(2);
		});

		it('should render a button with a confirmation label', () => {
			const confirmationLabel = 'Confirm';
			const component = shallow(
				<ConfirmationDialog
					confirmationLabel={confirmationLabel}
				/>
			);

			demand(component.find(Button).at(0).contains(confirmationLabel)).true();
		});

		it('should render a button with a cancel label', () => {
			const cancelLabel = 'Confirm';
			const component = shallow(
				<ConfirmationDialog
					cancelLabel={cancelLabel}
				/>
			);

			demand(component.find(Button).at(1).contains(cancelLabel)).true();
		});
	});
});
<|endoftext|>