<commit_before>/**
 * @file VerticalPointStepItem component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

export default class VerticalPointStepItem extends Component {

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.getRightBarClassName = ::this.getRightBarClassName;
        this.touchTapHandler = ::this.touchTapHandler;

    }

    getRightBarClassName() {

        const {activatedStep, finishedStep, index} = this.props;

        if (finishedStep > index || activatedStep > index) {
            return ' full';
        }

        if (activatedStep === index || finishedStep === index) {
            return '';
        }

        return ' hidden';

    }

    touchTapHandler(e) {
        e.preventDefault();
        const {activatedStep, finishedStep, index, disabled, onTouchTap} = this.props;
        !disabled && activatedStep !== index && finishedStep >= index && onTouchTap && onTouchTap(index, e);
    }

    render() {

        const {className, style, activatedStep, finishedStep, index, value, isFirst, isLast, disabled} = this.props,

            itemClassName = (isFirst ? ' first' : '') + (isLast ? ' last' : '')
                + (activatedStep == index ? ' activated' : (finishedStep >= index ? ' finished' : ''))
                + (disabled ? ' disabled' : '') + (className ? ' ' + className : '');

        return (

                    {value.title}

        );

    }
};

VerticalPointStepItem.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    activatedStep: PropTypes.number,
    finishedStep: PropTypes.number,
    index: PropTypes.number,
    value: PropTypes.object,
    isFirst: PropTypes.bool,
    isLast: PropTypes.bool,

    disabled: PropTypes.bool,

    onTouchTap: PropTypes.func

};

VerticalPointStepItem.defaultProps = {

    className: '',
    style: null,

    activatedStep: 0,
    finishedStep: 0,
    index: 0,
    value: {},
    isFirst: true,
    isLast: false,

    disabled: false

};<commit_msg>update VerticalPointStepItem<commit_after>/**
 * @file VerticalPointStepItem component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

export default class VerticalPointStepItem extends Component {

    static propTypes = {

        className: PropTypes.string,
        style: PropTypes.object,

        activatedStep: PropTypes.number,
        finishedStep: PropTypes.number,
        index: PropTypes.number,
        value: PropTypes.object,
        isFirst: PropTypes.bool,
        isLast: PropTypes.bool,

        disabled: PropTypes.bool,

        onTouchTap: PropTypes.func

    };
    static defaultProps = {

        className: '',
        style: null,

        activatedStep: 0,
        finishedStep: 0,
        index: 0,
        value: {},
        isFirst: true,
        isLast: false,

        disabled: false

    };

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.getRightBarClassName = ::this.getRightBarClassName;
        this.touchTapHandler = ::this.touchTapHandler;

    }

    getRightBarClassName() {

        const {activatedStep, finishedStep, index} = this.props;

        if (finishedStep > index || activatedStep > index) {
            return ' full';
        }

        if (activatedStep === index || finishedStep === index) {
            return '';
        }

        return ' hidden';

    }

    touchTapHandler(e) {
        e.preventDefault();
        const {activatedStep, finishedStep, index, disabled, onTouchTap} = this.props;
        !disabled && activatedStep !== index && finishedStep >= index && onTouchTap && onTouchTap(index, e);
    }

    render() {

        const {className, style, activatedStep, finishedStep, index, value, isFirst, isLast, disabled} = this.props,

            itemClassName = (isFirst ? ' first' : '') + (isLast ? ' last' : '')
                + (activatedStep == index ? ' activated' : (finishedStep >= index ? ' finished' : ''))
                + (disabled ? ' disabled' : '') + (className ? ' ' + className : '');

        return (

                    {value.title}

        );

    }
};<|endoftext|>


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

  angular.module('fsCloneShared').factory('Family', function(_,fsApi, $q, fsLocation) {
    function coerce2PersonId(thing) {
      if (_.isNull(thing) || _.isUndefined(thing)) {
        return thing;
      }

      if (_.isString(thing)) {
        return thing;
      }

      if (thing.id) {
        return thing.id;
      }

      return thing.toString();
    }

    function getExplicitAndImpliedSpouses(personWithRelationships) {
      var explicitSpouses = personWithRelationships.getSpouses();
      var personId = personWithRelationships.getPrimaryPerson().id;

      var allSpouses = _(personWithRelationships.getChildRelationships())
        .map(function(parentChildRelationship){
          return personWithRelationships.getPerson(
                    parentChildRelationship.$getFatherId()===personId ? parentChildRelationship.$getMotherId() : parentChildRelationship.$getFatherId()
          );
        })
        .reject(function(spouse) { return !spouse; })
        .union(explicitSpouses)
        .uniq('id')
        .valueOf();
      return allSpouses;
    }

    function FamilyConstructor(rootPerson, spouseId) {
      if ( rootPerson ) {
        var personId = coerce2PersonId(rootPerson);

        this.initPerson(personId)
          .then(_.bind(this.initSpouse,this, spouseId))
          .then(_.bind(this.initAncestry,this) )
          .then(_.bind(this.initDescendancy,this));
      }
    }

    FamilyConstructor.prototype = {

      initPerson: function(personId) {
        var theFamily = this;
        return fsApi.getPersonWithRelationships(personId, {persons: true}).then(function(response) {
          theFamily.personWithRelationships = response;
          theFamily.person = response.getPrimaryPerson();
          return response;
        });

      },

      initSpouse: function(spouseId) {
        if ( spouseId==='unknown') {
          return $q.when(null);
        }

        var theFamily = this;
        var personId = theFamily.personWithRelationships.getPrimaryPerson().id;
        var spouses = getExplicitAndImpliedSpouses(theFamily.personWithRelationships);
        if (spouses && spouses.length === 1) {
          theFamily.spouse = spouses[0];
          return $q.when(spouses[0]);
        }

        return fsApi.getPreferredSpouse(personId).then(function (response) {
          if (response !== null) {
            var couple = _.find(theFamily.personWithRelationships.getSpouseRelationships(), function (it) {
              return it.id === response;
            });
            if (couple) {
              theFamily.spouse = theFamily.personWithRelationships.getPerson(couple.$getSpouseId(personId));
              return theFamily.spouse;
            }
          }
          if (spouses.length) {
            theFamily.spouse = spouses[0];
            return spouses[0];
          }
        });
      },

      initAncestry: function() {
        var theFamily = this;
        if ( theFamily.ancestry ) {
          return $q.when(theFamily.ancestry);
        }
        if ( !theFamily.getPerson() ) {
          return $q.when(null);
        }
        var personId = theFamily.getPerson().id;
        return fsApi.getAncestry(personId, {generations:4, spouse: theFamily.spouse?theFamily.spouse.id:null, personDetails:true}).then(function(response){
          theFamily.ancestry = response;
          theFamily.initParentFamilies();
          return theFamily.ancestry;
        });
      },

      initParentFamilies: function() {
        var theFamily = this;

        function buildFamily(ancestryNumber, ancestorForReferenceNumber ) {
          var result = new FamilyConstructor();
          var father = theFamily.ancestry.getPerson(ancestryNumber);
          var mother = theFamily.ancestry.getPerson(ancestryNumber+1);
          var referenceId = theFamily.ancestry.getPerson(ancestorForReferenceNumber) ? theFamily.ancestry.getPerson(ancestorForReferenceNumber).id : null;
          result.person = father;
          result.spouse = mother;
          result.referenceId = referenceId;
          return result;
        }

        function buildParentFamilies(aFamily, ancestryNumber, recursionDepth) {
          aFamily.cachedFamilyOfHusbandsParents = buildFamily(ancestryNumber*2,ancestryNumber);
          aFamily.cachedFamilyOfWifesParents = buildFamily((ancestryNumber+1)*2,ancestryNumber+1);

          if ( recursionDepth>0 ) {
            buildParentFamilies(aFamily.cachedFamilyOfHusbandsParents, ancestryNumber*2, recursionDepth -1);
            buildParentFamilies(aFamily.cachedFamilyOfWifesParents, (ancestryNumber+1)*2, recursionDepth -1);

          }
        }

        buildParentFamilies(theFamily,2,2);
      },

      initDescendancy: function() {
        var theFamily = this;
        if ( theFamily.descendancy ) {
          return $q.when(theFamily.descendancy);
        }
        var personId = theFamily.personWithRelationships.getPrimaryPerson().id;
        var request = {generations:2, spouse: theFamily.spouse?theFamily.spouse.id:null, personDetails:true };
        return fsApi.getDescendancy(personId, request).then(function(response){
          theFamily.descendancy = response;
          theFamily.initChildFamilies();
          return theFamily.descendancy;
        });
      },

      initChildFamilies: function() {
        var theFamily = this;

        function familiesOf(parentId ) {
          var result = [];

          var childNumber = 1;
          while( theFamily.descendancy.exists(parentId+'.'+childNumber)) {
            var childId = parentId+'.'+childNumber;
            var aFamily = new FamilyConstructor();
            var person = theFamily.descendancy.getPerson(childId);
            var spouse = theFamily.descendancy.getPerson(childId+'-S');
            aFamily.person = person;
            aFamily.spouse = spouse;
            aFamily.descendancyNumber = childId;
            result.push(aFamily);
            childNumber = childNumber +1;
          }

          return result;
        }

        this.cachedChildFamilies = familiesOf('1');
        _.forEach(this.cachedChildFamilies,function(childFamily){
          childFamily.cachedChildFamilies = familiesOf(childFamily.descendancyNumber);
        });
      },

      initHoverData: function() {
        var theFamily = this;
        var promises = [];

        if ( theFamily.getPerson() && !theFamily.personWithRelationships && !theFamily.didPersonAlternates ) {
          promises.push(
            fsApi.getPersonWithRelationships(theFamily.getPerson().id, {persons: true}).then(function(response) {
              theFamily.personWithRelationships = response;
            })
          );
        }

        if ( theFamily.getSpouse() && !theFamily.spouseWithRelationships && !theFamily.didSpouseAlternates ) {
          promises.push(
            fsApi.getPersonWithRelationships(theFamily.getSpouse().id, {persons: true}).then(function(response) {
            theFamily.spouseWithRelationships = response;
            })
          );
        }

        $q.all(promises).then(function(){
          if ( !theFamily.personWithRelationships ) {
            return null;
          }
          theFamily.cachedChildren = theFamily.personWithRelationships.getChildrenOf( theFamily.spouse ? theFamily.spouse.id : null);
        });
      },

      getPerson: function() {
        return this.person;
      },

      getSpouse: function() {
        return this.spouse;
      },

      primaryPersonIsHusband: function() {
        if ( this.getPerson() && this.getPerson()._isMale() ) {
          return true;
        }

        if ( this.getSpouse() ) {
          return !this.getSpouse()._isMale();
        }

        return false;
      },

      primaryPersonIsWife: function() {
        return this.getPerson() && !this.getPerson()._isMale();
      },

      spouseIsHusband: function() {
        return this.getSpouse() && this.getSpouse()._isMale();
      },

      spouseIsWife: function() {
        return this.getSpouse() && !this.getSpouse()._isMale();
      },

      // ------------------------------------
      // Husband stuff
      // ------------------------------------
      hasHusband: function() {
        return this.primaryPersonIsHusband() || this.spouseIsHusband();
      },

      getHusband: function() {
        return this.primaryPersonIsHusband() ? this.getPerson() : this.getSpouse();
      },

      getHusbandWithRelationships: function() {
        return this.primaryPersonIsHusband() ? this.personWithRelationships : this.spouseWithRelationships;
      },

      getHusbandName: function() {
        return this.getHusband() ? this.getHusband().$getPreferredName().$getFullText() : '';
      },

      parentFamilyOfHusband: function() {
        return this.cachedFamilyOfHusbandsParents;
      },

      hasAlternateHusbands: function() {
        return this.alternateHusbands().length > 1;
      },

      alternateHusbands: function() {
        if ( !_.isUndefined(this.cachedAlternateHusbands) ) {
          return this.cachedAlternateHusbands;
        }

        if ( !this.getWifeWithRelationships() ) {
          return [];
        }

        this.cachedAlternateHusbands = this.getWifeWithRelationships().getSpouses();
        return this.cachedAlternateHusbands;
      },

      alternatePaternalParents: function() {
        if (!_.isUndefined(this.cachedAlternatePaternalParents) ) {
          return this.cachedAlternatePaternalParents;
        }
        if ( !this.getHusbandWithRelationships() ) {
          return [];
        }

        var husbandRelationships = this.getHusbandWithRelationships();
        this.cachedAlternatePaternalParents = _.toArray(
          _.map(husbandRelationships.getParentRelationships(),function(onePairOfParents){
            return {
              father:  onePairOfParents.$getFatherId() ? husbandRelationships.getPerson( onePairOfParents.$getFatherId() ) : null,
              mother: onePairOfParents.$getMotherId() ? husbandRelationships.getPerson( onePairOfParents.$getMotherId() ) : null
            };
          })
        );
        return this.cachedAlternatePaternalParents;
      },

      hasAlternatePaternalParents: function() {
        return this.alternatePaternalParents().length > 1 ;
      },

      switchPaternalParents: function(newParents) {

        var theFamily = this;
        var father = newParents.father ? theFamily.getHusbandWithRelationships().getPerson(newParents.father.id) : null;
        var mother = newParents.mother ? theFamily.getHusbandWithRelationships().getPerson(newParents.mother.id) : null;

        var newFamily = new FamilyConstructor();
        if ( father ) {
          newFamily.person = father;
          newFamily.spouse = mother;
          newFamily.referenceId = theFamily.getHusband().id;
        } else {
          newFamily.person = mother;
          newFamily.spouse = father;
          newFamily.referenceId = theFamily.getHusband().id;
        }
        newFamily.initAncestry().then(function(){
          theFamily.cachedFamilyOfHusbandsParents = newFamily;
        });
      },

      // ------------------------------------
      // Wife stuff
      // ------------------------------------
      hasWife: function() {
        return this.primaryPersonIsWife() || this.spouseIsWife();
      },

      getWife: function() {
        return this.primaryPersonIsWife() ? this.getPerson() : this.getSpouse();
      },

      getWifeWithRelationships: function() {
        return this.primaryPersonIsWife() ? this.personWithRelationships : this.spouseWithRelationships;
      },

      getWifeName: function() {
        return this.getWife() ? this.getWife().$getPreferredName().$getFullText() : '';
      },

      parentFamilyOfWife: function() {
        return this.cachedFamilyOfWifesParents;
      },

      hasAlternateWives: function() {
        return this.alternateWives().length > 1;
      },

      alternateWives: function() {
        if ( !_.isUndefined(this.cachedAlternateWives) ) {
          return this.cachedAlternateWives;
        }

        if ( !this.getHusbandWithRelationships() ) {
          return [];
        }

        this.cachedAlternateWives = this.getHusbandWithRelationships().getSpouses();
        return this.cachedAlternateWives;
      },

      hasAlternateMaternalParents: function() {
        return this.alternateMaternalParents().length > 1 ;
      },

      alternateMaternalParents: function() {
        if (!_.isUndefined(this.cachedAlternateMaternalParents) ) {
          return this.cachedAlternateMaternalParents;
        }
        if ( !this.getWifeWithRelationships() ) {
          return [];
        }

        var wifeRelationships = this.getWifeWithRelationships();
        this.cachedAlternateMaternalParents = _.toArray(
          _.map(wifeRelationships.getParentRelationships(),function(onePairOfParents){
            return {
              father:  onePairOfParents.$getFatherId() ? wifeRelationships.getPerson( onePairOfParents.$getFatherId() ) : null,
              mother: onePairOfParents.$getMotherId() ? wifeRelationships.getPerson( onePairOfParents.$getMotherId() ) : null
            };
          })
        );
        return this.cachedAlternateMaternalParents;
      },

      switchMaternalParents: function(newParents) {
        var theFamily = this;
        var father = newParents.father ? theFamily.getWifeWithRelationships().getPerson(newParents.father.id) : null;
        var mother = newParents.mother ? theFamily.getWifeWithRelationships().getPerson(newParents.mother.id) : null;

        var newFamily = new FamilyConstructor();
        if ( father ) {
          newFamily.person = father;
          newFamily.spouse = mother;
          newFamily.referenceId = theFamily.getWife().id;
        } else {
          newFamily.person = mother;
          newFamily.spouse = father;
          newFamily.referenceId = theFamily.getWife().id;
        }
        newFamily.initAncestry().then(function(){
          theFamily.cachedFamilyOfWifesParents = newFamily;
        });
      },

      // ------------------------------------
      // Children stuff
      // ------------------------------------
      hasChildren: function() {
        return this.children().length > 0;
      },

      hasChildrenWithUnknownMother: function() {
        return this.getHusbandWithRelationships() && this.getHusbandWithRelationships().getChildrenOf(null).length;
      },

      hrefForUnknownMother:  function() {
        return this.hasChildrenWithUnknownMother() ?
          fsLocation.getTreeUrl(this.getHusband().id,{spouseId:'unknown'})
          : '';
      },

      hasChildrenWithUnknownFather: function() {
        return this.getWifeWithRelationships() && this.getWifeWithRelationships().getChildrenOf(null).length;
      },

      hrefForUnknownFather:  function() {
        return this.hasChildrenWithUnknownFather() ?
          fsLocation.getTreeUrl(this.getWife().id,{spouseId:'unknown'})
          : '';
      },

      children: function() {
        if ( this.cachedChildren ) {
          return this.cachedChildren;
        }
        return [];
      },

      hasChildFamilies: function() {
        return this.childFamilies().length > 0;
      },

      childFamilies: function() {
        if ( this.cachedChildFamilies ) {
          return this.cachedChildFamilies;
        }
        return [];
      },

      isUseless: function() {
        return !this.person && !this.personWithRelationships && !this.spouse && !this.spouseWithRelationships && !this.referenceId;
      }

    };

    return FamilyConstructor;
  });

})();<commit_msg>remove personDetails parameter from getAncestry and getDescendancy to make them return more quickly<commit_after>(function() {
  'use strict';

  angular.module('fsCloneShared').factory('Family', function(_,fsApi, $q, fsLocation) {
    function coerce2PersonId(thing) {
      if (_.isNull(thing) || _.isUndefined(thing)) {
        return thing;
      }

      if (_.isString(thing)) {
        return thing;
      }

      if (thing.id) {
        return thing.id;
      }

      return thing.toString();
    }

    function getExplicitAndImpliedSpouses(personWithRelationships) {
      var explicitSpouses = personWithRelationships.getSpouses();
      var personId = personWithRelationships.getPrimaryPerson().id;

      var allSpouses = _(personWithRelationships.getChildRelationships())
        .map(function(parentChildRelationship){
          return personWithRelationships.getPerson(
                    parentChildRelationship.$getFatherId()===personId ? parentChildRelationship.$getMotherId() : parentChildRelationship.$getFatherId()
          );
        })
        .reject(function(spouse) { return !spouse; })
        .union(explicitSpouses)
        .uniq('id')
        .valueOf();
      return allSpouses;
    }

    function FamilyConstructor(rootPerson, spouseId) {
      if ( rootPerson ) {
        var personId = coerce2PersonId(rootPerson);

        this.initPerson(personId)
          .then(_.bind(this.initSpouse,this, spouseId))
          .then(_.bind(this.initAncestry,this) )
          .then(_.bind(this.initDescendancy,this));
      }
    }

    FamilyConstructor.prototype = {

      initPerson: function(personId) {
        var theFamily = this;
        return fsApi.getPersonWithRelationships(personId, {persons: true}).then(function(response) {
          theFamily.personWithRelationships = response;
          theFamily.person = response.getPrimaryPerson();
          return response;
        });

      },

      initSpouse: function(spouseId) {
        if ( spouseId==='unknown') {
          return $q.when(null);
        }

        var theFamily = this;
        var personId = theFamily.personWithRelationships.getPrimaryPerson().id;
        var spouses = getExplicitAndImpliedSpouses(theFamily.personWithRelationships);
        if (spouses && spouses.length === 1) {
          theFamily.spouse = spouses[0];
          return $q.when(spouses[0]);
        }

        return fsApi.getPreferredSpouse(personId).then(function (response) {
          if (response !== null) {
            var couple = _.find(theFamily.personWithRelationships.getSpouseRelationships(), function (it) {
              return it.id === response;
            });
            if (couple) {
              theFamily.spouse = theFamily.personWithRelationships.getPerson(couple.$getSpouseId(personId));
              return theFamily.spouse;
            }
          }
          if (spouses.length) {
            theFamily.spouse = spouses[0];
            return spouses[0];
          }
        });
      },

      initAncestry: function() {
        var theFamily = this;
        if ( theFamily.ancestry ) {
          return $q.when(theFamily.ancestry);
        }
        if ( !theFamily.getPerson() ) {
          return $q.when(null);
        }
        var personId = theFamily.getPerson().id;
        return fsApi.getAncestry(personId, {generations:4, spouse: theFamily.spouse?theFamily.spouse.id:null}).then(function(response){
          theFamily.ancestry = response;
          theFamily.initParentFamilies();
          return theFamily.ancestry;
        });
      },

      initParentFamilies: function() {
        var theFamily = this;

        function buildFamily(ancestryNumber, ancestorForReferenceNumber ) {
          var result = new FamilyConstructor();
          var father = theFamily.ancestry.getPerson(ancestryNumber);
          var mother = theFamily.ancestry.getPerson(ancestryNumber+1);
          var referenceId = theFamily.ancestry.getPerson(ancestorForReferenceNumber) ? theFamily.ancestry.getPerson(ancestorForReferenceNumber).id : null;
          result.person = father;
          result.spouse = mother;
          result.referenceId = referenceId;
          return result;
        }

        function buildParentFamilies(aFamily, ancestryNumber, recursionDepth) {
          aFamily.cachedFamilyOfHusbandsParents = buildFamily(ancestryNumber*2,ancestryNumber);
          aFamily.cachedFamilyOfWifesParents = buildFamily((ancestryNumber+1)*2,ancestryNumber+1);

          if ( recursionDepth>0 ) {
            buildParentFamilies(aFamily.cachedFamilyOfHusbandsParents, ancestryNumber*2, recursionDepth -1);
            buildParentFamilies(aFamily.cachedFamilyOfWifesParents, (ancestryNumber+1)*2, recursionDepth -1);

          }
        }

        buildParentFamilies(theFamily,2,2);
      },

      initDescendancy: function() {
        var theFamily = this;
        if ( theFamily.descendancy ) {
          return $q.when(theFamily.descendancy);
        }
        var personId = theFamily.personWithRelationships.getPrimaryPerson().id;
        var request = {generations:2, spouse: theFamily.spouse?theFamily.spouse.id:null};
        return fsApi.getDescendancy(personId, request).then(function(response){
          theFamily.descendancy = response;
          theFamily.initChildFamilies();
          return theFamily.descendancy;
        });
      },

      initChildFamilies: function() {
        var theFamily = this;

        function familiesOf(parentId ) {
          var result = [];

          var childNumber = 1;
          while( theFamily.descendancy.exists(parentId+'.'+childNumber)) {
            var childId = parentId+'.'+childNumber;
            var aFamily = new FamilyConstructor();
            var person = theFamily.descendancy.getPerson(childId);
            var spouse = theFamily.descendancy.getPerson(childId+'-S');
            aFamily.person = person;
            aFamily.spouse = spouse;
            aFamily.descendancyNumber = childId;
            result.push(aFamily);
            childNumber = childNumber +1;
          }

          return result;
        }

        this.cachedChildFamilies = familiesOf('1');
        _.forEach(this.cachedChildFamilies,function(childFamily){
          childFamily.cachedChildFamilies = familiesOf(childFamily.descendancyNumber);
        });
      },

      initHoverData: function() {
        var theFamily = this;
        var promises = [];

        if ( theFamily.getPerson() && !theFamily.personWithRelationships && !theFamily.didPersonAlternates ) {
          promises.push(
            fsApi.getPersonWithRelationships(theFamily.getPerson().id, {persons: true}).then(function(response) {
              theFamily.personWithRelationships = response;
            })
          );
        }

        if ( theFamily.getSpouse() && !theFamily.spouseWithRelationships && !theFamily.didSpouseAlternates ) {
          promises.push(
            fsApi.getPersonWithRelationships(theFamily.getSpouse().id, {persons: true}).then(function(response) {
            theFamily.spouseWithRelationships = response;
            })
          );
        }

        $q.all(promises).then(function(){
          if ( !theFamily.personWithRelationships ) {
            return null;
          }
          theFamily.cachedChildren = theFamily.personWithRelationships.getChildrenOf( theFamily.spouse ? theFamily.spouse.id : null);
        });
      },

      getPerson: function() {
        return this.person;
      },

      getSpouse: function() {
        return this.spouse;
      },

      primaryPersonIsHusband: function() {
        if ( this.getPerson() && this.getPerson()._isMale() ) {
          return true;
        }

        if ( this.getSpouse() ) {
          return !this.getSpouse()._isMale();
        }

        return false;
      },

      primaryPersonIsWife: function() {
        return this.getPerson() && !this.getPerson()._isMale();
      },

      spouseIsHusband: function() {
        return this.getSpouse() && this.getSpouse()._isMale();
      },

      spouseIsWife: function() {
        return this.getSpouse() && !this.getSpouse()._isMale();
      },

      // ------------------------------------
      // Husband stuff
      // ------------------------------------
      hasHusband: function() {
        return this.primaryPersonIsHusband() || this.spouseIsHusband();
      },

      getHusband: function() {
        return this.primaryPersonIsHusband() ? this.getPerson() : this.getSpouse();
      },

      getHusbandWithRelationships: function() {
        return this.primaryPersonIsHusband() ? this.personWithRelationships : this.spouseWithRelationships;
      },

      getHusbandName: function() {
        return this.getHusband() ? this.getHusband().$getPreferredName().$getFullText() : '';
      },

      parentFamilyOfHusband: function() {
        return this.cachedFamilyOfHusbandsParents;
      },

      hasAlternateHusbands: function() {
        return this.alternateHusbands().length > 1;
      },

      alternateHusbands: function() {
        if ( !_.isUndefined(this.cachedAlternateHusbands) ) {
          return this.cachedAlternateHusbands;
        }

        if ( !this.getWifeWithRelationships() ) {
          return [];
        }

        this.cachedAlternateHusbands = this.getWifeWithRelationships().getSpouses();
        return this.cachedAlternateHusbands;
      },

      alternatePaternalParents: function() {
        if (!_.isUndefined(this.cachedAlternatePaternalParents) ) {
          return this.cachedAlternatePaternalParents;
        }
        if ( !this.getHusbandWithRelationships() ) {
          return [];
        }

        var husbandRelationships = this.getHusbandWithRelationships();
        this.cachedAlternatePaternalParents = _.toArray(
          _.map(husbandRelationships.getParentRelationships(),function(onePairOfParents){
            return {
              father:  onePairOfParents.$getFatherId() ? husbandRelationships.getPerson( onePairOfParents.$getFatherId() ) : null,
              mother: onePairOfParents.$getMotherId() ? husbandRelationships.getPerson( onePairOfParents.$getMotherId() ) : null
            };
          })
        );
        return this.cachedAlternatePaternalParents;
      },

      hasAlternatePaternalParents: function() {
        return this.alternatePaternalParents().length > 1 ;
      },

      switchPaternalParents: function(newParents) {

        var theFamily = this;
        var father = newParents.father ? theFamily.getHusbandWithRelationships().getPerson(newParents.father.id) : null;
        var mother = newParents.mother ? theFamily.getHusbandWithRelationships().getPerson(newParents.mother.id) : null;

        var newFamily = new FamilyConstructor();
        if ( father ) {
          newFamily.person = father;
          newFamily.spouse = mother;
          newFamily.referenceId = theFamily.getHusband().id;
        } else {
          newFamily.person = mother;
          newFamily.spouse = father;
          newFamily.referenceId = theFamily.getHusband().id;
        }
        newFamily.initAncestry().then(function(){
          theFamily.cachedFamilyOfHusbandsParents = newFamily;
        });
      },

      // ------------------------------------
      // Wife stuff
      // ------------------------------------
      hasWife: function() {
        return this.primaryPersonIsWife() || this.spouseIsWife();
      },

      getWife: function() {
        return this.primaryPersonIsWife() ? this.getPerson() : this.getSpouse();
      },

      getWifeWithRelationships: function() {
        return this.primaryPersonIsWife() ? this.personWithRelationships : this.spouseWithRelationships;
      },

      getWifeName: function() {
        return this.getWife() ? this.getWife().$getPreferredName().$getFullText() : '';
      },

      parentFamilyOfWife: function() {
        return this.cachedFamilyOfWifesParents;
      },

      hasAlternateWives: function() {
        return this.alternateWives().length > 1;
      },

      alternateWives: function() {
        if ( !_.isUndefined(this.cachedAlternateWives) ) {
          return this.cachedAlternateWives;
        }

        if ( !this.getHusbandWithRelationships() ) {
          return [];
        }

        this.cachedAlternateWives = this.getHusbandWithRelationships().getSpouses();
        return this.cachedAlternateWives;
      },

      hasAlternateMaternalParents: function() {
        return this.alternateMaternalParents().length > 1 ;
      },

      alternateMaternalParents: function() {
        if (!_.isUndefined(this.cachedAlternateMaternalParents) ) {
          return this.cachedAlternateMaternalParents;
        }
        if ( !this.getWifeWithRelationships() ) {
          return [];
        }

        var wifeRelationships = this.getWifeWithRelationships();
        this.cachedAlternateMaternalParents = _.toArray(
          _.map(wifeRelationships.getParentRelationships(),function(onePairOfParents){
            return {
              father:  onePairOfParents.$getFatherId() ? wifeRelationships.getPerson( onePairOfParents.$getFatherId() ) : null,
              mother: onePairOfParents.$getMotherId() ? wifeRelationships.getPerson( onePairOfParents.$getMotherId() ) : null
            };
          })
        );
        return this.cachedAlternateMaternalParents;
      },

      switchMaternalParents: function(newParents) {
        var theFamily = this;
        var father = newParents.father ? theFamily.getWifeWithRelationships().getPerson(newParents.father.id) : null;
        var mother = newParents.mother ? theFamily.getWifeWithRelationships().getPerson(newParents.mother.id) : null;

        var newFamily = new FamilyConstructor();
        if ( father ) {
          newFamily.person = father;
          newFamily.spouse = mother;
          newFamily.referenceId = theFamily.getWife().id;
        } else {
          newFamily.person = mother;
          newFamily.spouse = father;
          newFamily.referenceId = theFamily.getWife().id;
        }
        newFamily.initAncestry().then(function(){
          theFamily.cachedFamilyOfWifesParents = newFamily;
        });
      },

      // ------------------------------------
      // Children stuff
      // ------------------------------------
      hasChildren: function() {
        return this.children().length > 0;
      },

      hasChildrenWithUnknownMother: function() {
        return this.getHusbandWithRelationships() && this.getHusbandWithRelationships().getChildrenOf(null).length;
      },

      hrefForUnknownMother:  function() {
        return this.hasChildrenWithUnknownMother() ?
          fsLocation.getTreeUrl(this.getHusband().id,{spouseId:'unknown'})
          : '';
      },

      hasChildrenWithUnknownFather: function() {
        return this.getWifeWithRelationships() && this.getWifeWithRelationships().getChildrenOf(null).length;
      },

      hrefForUnknownFather:  function() {
        return this.hasChildrenWithUnknownFather() ?
          fsLocation.getTreeUrl(this.getWife().id,{spouseId:'unknown'})
          : '';
      },

      children: function() {
        if ( this.cachedChildren ) {
          return this.cachedChildren;
        }
        return [];
      },

      hasChildFamilies: function() {
        return this.childFamilies().length > 0;
      },

      childFamilies: function() {
        if ( this.cachedChildFamilies ) {
          return this.cachedChildFamilies;
        }
        return [];
      },

      isUseless: function() {
        return !this.person && !this.personWithRelationships && !this.spouse && !this.spouseWithRelationships && !this.referenceId;
      }

    };

    return FamilyConstructor;
  });

})();<|endoftext|>


<commit_before>const intialState = ['hotels', 'points of interest', 'museums', 'nightlife', 'restaurants'];

const branchTitles = (state = intialState, action) => {
  switch (action.type) {
    case 'UPDATE_BRANCH_TITLES':
      return Object.assign({}, state, {
        branchTitles: action.payload,
      });
    default:
      return state;
  }
};

export default branchTitles;
<commit_msg>Change initial state of branchTitles<commit_after>const intialState = [
  { name: 'hotels', query: 'hotel' },
  { name: 'points of interest', query: 'point of interest' },
  { name: 'museums', query: 'museum' },
  { name: 'nightlife', query: 'night club' },
  { name: 'restaurants', query: 'restaurant' },
];

const branchTitles = (state = intialState, action) => {
  switch (action.type) {
    case 'UPDATE_BRANCH_TITLES':
      return Object.assign({}, state, {
        branchTitles: action.payload,
      });
    default:
      return state;
  }
};

export default branchTitles;
<|endoftext|>


<commit_before>import React from 'react';
import { addStoryInGroup, MID_LEVEL_BLOCKS } from '../../../.storybook/utils';
import { boolean, select, text } from '@storybook/addon-knobs';
import { TextBody } from '../typography';
import SilentBanner from './SilentBanner';
import Link from '../link';

const statusValues = ['info', 'error', 'success', 'warning'];

export default {
  component: SilentBanner,
  title: addStoryInGroup(MID_LEVEL_BLOCKS, 'Silent banners'),

  parameters: {
    design: {
      type: 'figma',
      url: 'https://www.figma.com/file/LHH25GN90ljQaBEUNMsdJn/Desktop-components?node-id=1225%3A0',
    },
    info: {
      propTables: [SilentBanner],
    },
  },
};

export const basic = () => (
  <SilentBanner inline={boolean('Inline', false)} title={text('Title', 'I am the title of this message')}>
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);

export const dismissable = () => (
  <SilentBanner
    inline={boolean('Inline', false)}
    onClose={() => console.log('onClose click handler')}
    title={text('Title', 'I am the title of this message')}
  >
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);

export const withActions = () => (
  <SilentBanner
    inline={boolean('Inline', false)}
    primaryAction={{
      label: text('Primary action label', 'Primary action'),
      onClick: () => console.log('primaryAction.onClick'),
    }}
    secondaryAction={{
      label: text('Secondary action label', 'Secondary action'),
      onClick: () => console.log('secondaryAction.onClick'),
    }}
    title={text('Title', 'I am the title of this message')}
  >
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);

export const withStatus = () => (
  <SilentBanner
    inline={boolean('Inline', false)}
    showIcon={boolean('Show icon', false)}
    status={select('Status', statusValues, 'success')}
    title={text('Title', 'I am the title of this message')}
  >
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);

export const fullOption = () => (
  <SilentBanner
    inline={boolean('Inline', false)}
    onClose={() => console.log('onClose click handler')}
    primaryAction={{
      label: text('Primary action label', 'Primary action'),
      onClick: () => console.log('primaryAction.onClick'),
    }}
    secondaryAction={{
      label: text('Secondary action label', 'Secondary action'),
      onClick: () => console.log('secondaryAction.onClick'),
    }}
    showIcon={boolean('Show icon', true)}
    status={select('Status', statusValues, 'success')}
    title={text('Title', 'I am the title of this message')}
  >
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);
<commit_msg>SilentBanner: updated stories<commit_after>import React from 'react';
import { addStoryInGroup, MID_LEVEL_BLOCKS } from '../../../.storybook/utils';
import { TextBody } from '../typography';
import SilentBanner from './SilentBanner';
import Link from '../link';

export default {
  component: SilentBanner,
  title: addStoryInGroup(MID_LEVEL_BLOCKS, 'Silent banners'),

  parameters: {
    design: {
      type: 'figma',
      url: 'https://www.figma.com/file/LHH25GN90ljQaBEUNMsdJn/Desktop-components?node-id=1225%3A0',
    },
  },
};

export const FullOption = (args) => (
  <SilentBanner {...args}>
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);

FullOption.args = {
  onClose: () => console.log('onClose click handler'),
  primaryAction: {
    label: 'Primary action',
    onClick: () => console.log('primaryAction.onClick'),
  },
  secondaryAction: {
    label: 'Secondary action',
    onClick: () => console.log('secondaryAction.onClick'),
  },
  showIcon: true,
  status: 'success',
  title: 'I am the title of this message',
};

export const Basic = () => (
  <SilentBanner title="I am the title of this message">
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);

export const Dismissable = () => (
  <SilentBanner onClose={() => console.log('onClose click handler')} title="I am the title of this message">
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);

export const WithActions = () => (
  <SilentBanner
    primaryAction={{
      label: 'Primary action',
      onClick: () => console.log('primaryAction.onClick'),
    }}
    secondaryAction={{
      label: 'Secondary action',
      onClick: () => console.log('secondaryAction.onClick'),
    }}
    title="I am the title of this message"
  >
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);

export const WithStatus = () => (
  <SilentBanner status="warning" title="I am the title of this message">
    <TextBody color="teal">
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam <Link inherit={false}>nonumy eirmod</Link>{' '}
      tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    </TextBody>
  </SilentBanner>
);
<|endoftext|>


<commit_before>import React from 'react';
import './app.css';
import jsyaml from 'js-yaml';
import { Heading, Divider, Badge, Space, Button,
         Text, Message, Footer } from 'rebass';
import sections from 'sections';
import ReactMarkdown from 'react-markdown';
import DemoBlock from './demoblock';
import packageinfo from '../../package.json';
import readme from 'raw-loader!../../README.md';

class SidebarLink extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (

          <ReactMarkdown source={this.props.section.title}/>

    );
  }
}

class Section extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (

        <Divider width={50} />
        <ReactMarkdown source={this.props.section.heading}/>
        <ReactMarkdown
          source={this.props.section.body}
          renderers={{
            CodeBlock: DemoBlock,
          }}
        />

    );
  }
}

export default class App extends React.Component {
  constructor(props) {
    super(props);

    const parsed = sections.parse(readme);
    this.demos = [];
    this.interfaceExample;
    let active = false;
    for (let section of parsed.sections) {
      section.anchor = section.title;
      if (active) {
        if (section.level === 1) {
          break;
        }
        this.demos.push(section);
      } else if (section.heading === '# Language') {
        active = true;
      } else if (section.heading === '# Interface') {
        this.interfaceExample = section;
      }
    }

    const params = new URLSearchParams(document.location.search.substring(1));
    let tmpl = '{}';
    let ctx = '{}';
    if (params.get('template') && params.get('context')) {
      try {
        tmpl = jsyaml.safeDump(jsyaml.safeLoad(params.get('template')));
        ctx = jsyaml.safeDump(jsyaml.safeLoad(params.get('context')));
      } catch (err) {
        if (err.name !== 'YAMLException') {
          throw err;
        }
      }
    }
    this.playground = {
      anchor: 'playground',
      title: 'Playground',
      heading: '## Playground',
      body: `
You can experiment with it here and view examples of all of the language
features below!
\`\`\`yaml
template:
  ${tmpl}
context:
  ${ctx}
result: {}
\`\`\`
      `,
    };
  }

  render() {
    return (

            <Heading level={1}>
              JSON-e
              <Space x={1} />
              <Badge rounded pill theme="info">v{packageinfo.version}</Badge>
            </Heading>
            <Text>
              A data-structure parameterization system for embedding context in JSON objects
            </Text>
            <Divider width={'100%'}/>

              <SidebarLink section={this.interfaceExample}/>
              <SidebarLink section={this.playground}/>
              {
                this.demos.map(demo => <SidebarLink key={demo.anchor} section={demo}/>)
              }

              <Text small>
              Brought to you by the Mozillians behind Taskcluster.
              </Text>
              <Space x={1} />

              <Button rounded href={'https://www.mozilla.org/en-US/MPL/'}>
               License
              </Button>
              <Space x={1} />
              <Button rounded href={'https://github.com/taskcluster/json-e'}>
               Github
              </Button>

              <Button rounded href={'https://www.mozilla.org/en-US/MPL/'}>
               MPL License
              </Button>
              <Space x={1} />
              <Button rounded href={'https://github.com/taskcluster/json-e'}>
               Github
              </Button>

              JSON-e is a data-structure parameterization system written for embedding context in JSON objects.

              The central idea is to treat a data structure as a "template" and transform it, using another data structure as context, to produce an output data structure.

              There are countless libraries to do this with strings, such as mustache. What makes JSON-e unique is that it operates on data structures, not on their textual representation. This allows input to be written in a number of formats (JSON, YAML, etc.) or even generated dynamically. It also means that the output cannot be "invalid", even when including large chunks of contextual data.

              JSON-e is also designed to be safe for use on untrusted data. It never uses eval or any other function that might result in arbitrary code execution. It also disallows unbounded iteration, so any JSON-e rendering operation will finish in finite time.

            {
              this.demos.map(demo =>
)
            }

    );
  }
}
<commit_msg>Fix linked examples<commit_after>import React from 'react';
import './app.css';
import jsyaml from 'js-yaml';
import { Heading, Divider, Badge, Space, Button,
         Text, Message, Footer } from 'rebass';
import sections from 'sections';
import ReactMarkdown from 'react-markdown';
import DemoBlock from './demoblock';
import packageinfo from '../../package.json';
import readme from 'raw-loader!../../README.md';

class SidebarLink extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (

          <ReactMarkdown source={this.props.section.title}/>

    );
  }
}

class Section extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (

        <Divider width={50} />
        <ReactMarkdown source={this.props.section.heading}/>
        <ReactMarkdown
          source={this.props.section.body}
          renderers={{
            CodeBlock: DemoBlock,
          }}
        />

    );
  }
}

export default class App extends React.Component {
  constructor(props) {
    super(props);

    const parsed = sections.parse(readme);
    this.demos = [];
    this.interfaceExample;
    let active = false;
    for (let section of parsed.sections) {
      section.anchor = section.title;
      if (active) {
        if (section.level === 1) {
          break;
        }
        this.demos.push(section);
      } else if (section.heading === '# Language') {
        active = true;
      } else if (section.heading === '# Interface') {
        this.interfaceExample = section;
      }
    }

    const params = new URLSearchParams(document.location.search.substring(1));
    let tmpl = '{}';
    let ctx = '{}';
    if (params.get('template') && params.get('context')) {
      try {
        tmpl = JSON.stringify(jsyaml.safeLoad(params.get('template')));
        ctx = JSON.stringify(jsyaml.safeLoad(params.get('context')));
      } catch (err) {
        if (err.name !== 'YAMLException') {
          throw err;
        }
      }
    }
    this.playground = {
      anchor: 'playground',
      title: 'Playground',
      heading: '## Playground',
      body: `
You can experiment with it here and view examples of all of the language
features below!
\`\`\`yaml
template:
  ${tmpl}
context:
  ${ctx}
result: {}
\`\`\`
      `,
    };
  }

  render() {
    return (

            <Heading level={1}>
              JSON-e
              <Space x={1} />
              <Badge rounded pill theme="info">v{packageinfo.version}</Badge>
            </Heading>
            <Text>
              A data-structure parameterization system for embedding context in JSON objects
            </Text>
            <Divider width={'100%'}/>

              <SidebarLink section={this.interfaceExample}/>
              <SidebarLink section={this.playground}/>
              {
                this.demos.map(demo => <SidebarLink key={demo.anchor} section={demo}/>)
              }

              <Text small>
              Brought to you by the Mozillians behind Taskcluster.
              </Text>
              <Space x={1} />

              <Button rounded href={'https://www.mozilla.org/en-US/MPL/'}>
               License
              </Button>
              <Space x={1} />
              <Button rounded href={'https://github.com/taskcluster/json-e'}>
               Github
              </Button>

              <Button rounded href={'https://www.mozilla.org/en-US/MPL/'}>
               MPL License
              </Button>
              <Space x={1} />
              <Button rounded href={'https://github.com/taskcluster/json-e'}>
               Github
              </Button>

              JSON-e is a data-structure parameterization system written for embedding context in JSON objects.

              The central idea is to treat a data structure as a "template" and transform it, using another data structure as context, to produce an output data structure.

              There are countless libraries to do this with strings, such as mustache. What makes JSON-e unique is that it operates on data structures, not on their textual representation. This allows input to be written in a number of formats (JSON, YAML, etc.) or even generated dynamically. It also means that the output cannot be "invalid", even when including large chunks of contextual data.

              JSON-e is also designed to be safe for use on untrusted data. It never uses eval or any other function that might result in arbitrary code execution. It also disallows unbounded iteration, so any JSON-e rendering operation will finish in finite time.

            {
              this.demos.map(demo =>
)
            }

    );
  }
}
<|endoftext|>


<commit_before>import React from "react";
import XYGraph from "../XYGraph";

import {
    axisBottom,
    axisLeft,
    extent,
    format,
    nest,
    scaleBand,
    scaleTime,
    select,
    map,
    min
} from "d3";

import {properties} from "./default.config"

export default class HeatmapGraph extends XYGraph {

    constructor(props) {
        super(props, properties);
    }

    render() {
        const {
            data,
            width,
            height
        } = this.props;

        if (!data || !data.length)
            return;

        const {
          chartHeightToPixel,
          chartWidthToPixel,
          circleToPixel,
          colorColumn,
          colors,
          legend,
          margin,
          padding,
          stroke,
          xColumn,
          xLabel,
          xTickFormat,
          xTickGrid,
          xTicks,
          xTickSizeInner,
          xTickSizeOuter,
          yColumn,
          yTickFormat,
          yTickGrid,
          yTicks,
          yTickSizeInner,
          yTickSizeOuter,
          legendColumn
        } = this.getConfiguredProperties();

        const isVerticalLegend = legend.orientation === 'vertical';
        const xLabelFn         = (d) => d[xColumn];
        const yLabelFn         = (d) => d[yColumn];
        const legendFn         = (d) => d[legendColumn];
        const label            = (d) => d["key"];
        const scale            = this.scaleColor(data, legendColumn);
        const getColor         = (d) => scale ? scale(d[colorColumn] || d[legendColumn] || d["key"]) : stroke.color || colors[0];

        const cellColumnsData  = nest()
            .key((d) => legendColumn ? d[legendColumn] : "Cell")
            .entries(data);

        let xAxisHeight       = xLabel ? chartHeightToPixel : 0;
        let legendWidth       = legend.show && cellColumnsData.length > 1 ? this.longestLabelLength(data, legendFn) * chartWidthToPixel : 0;

        let yLabelWidth       = this.longestLabelLength(data, yLabelFn) * chartWidthToPixel;

        let leftMargin        = margin.left + yLabelWidth;
        let availableWidth    = width - (margin.left + margin.right + yLabelWidth);
        let availableHeight   = height - (margin.top + margin.bottom + chartHeightToPixel + xAxisHeight);

        if (legend.show) {
            legend.width = legendWidth;

            // Compute the available space considering a legend
            if (isVerticalLegend)
            {
                leftMargin      +=  legend.width;
                availableWidth  -=  legend.width;
            }
            else {
                const nbElementsPerLine  = parseInt(availableWidth / legend.width, 10);
                const nbLines            = parseInt(cellColumnsData.length / nbElementsPerLine, 10);
                availableHeight         -= nbLines * legend.circleSize * circleToPixel + chartHeightToPixel;
            }
        }

        //For Making xAxis BANDSCALE
        const xBandScale = scaleBand()
            .domain(map(data, xLabelFn).keys().sort());
        xBandScale.rangeRound([0, availableWidth]);

        const xScale = scaleTime()
          .domain(extent(data, xLabelFn));

        const yScale = scaleBand()
          .domain(map(data, yLabelFn).keys().sort());

        xScale.range([0, availableWidth], 0.1);
        yScale.rangeRound([availableHeight, 0]).padding(padding);

        const xAxis = axisBottom(xScale)
          .tickSizeInner(xTickGrid ? -availableHeight : xTickSizeInner)
          .tickSizeOuter(xTickSizeOuter);

        if(xTickFormat){
            xAxis.tickFormat(format(xTickFormat));
        }

        if(xTicks){
            xAxis.ticks(xTicks);
        }

        const yAxis = axisLeft(yScale)
          .tickSizeInner(yTickGrid ? -availableWidth : yTickSizeInner)
          .tickSizeOuter(yTickSizeOuter);

        if(yTickFormat){
            yAxis.tickFormat(format(yTickFormat));
        }

        if(yTicks){
            yAxis.ticks(yTicks);
        }

        let xTitlePosition = {
            left: leftMargin + availableWidth / 2,
            top: margin.top + availableHeight + chartHeightToPixel + xAxisHeight
        }

        let yTitlePosition = {
            // We use chartWidthToPixel to compensate the rotation of the title
            left: margin.left + chartWidthToPixel + (isVerticalLegend ? legend.width : 0),
            top: margin.top + availableHeight / 2
        }

        let boxSize = min([xBandScale.bandwidth(), yScale.bandwidth()])
        return (

                {this.tooltip}
                <svg width={width} height={height}>
                    {this.axisTitles(xTitlePosition, yTitlePosition)}
                    <g transform={ `translate(${leftMargin},${margin.top})` } >
                        <g
                            key="xAxis"
                            ref={ (el) => select(el).call(xAxis) }
                            transform={ `translate(0,${availableHeight})` }
                        />
                        <g
                            key="yAxis"
                            ref={ (el) => select(el).call(yAxis) }
                        />
                        {data.map((d, i) => {
                            // Compute rectangle depending on orientation (vertical or horizontal).
                            const {
                                x,
                                y,
                                width,
                                height
                            } = (
                                {
                                    x: xScale(d[xColumn]),
                                    y: yScale(d[yColumn]) + yScale.bandwidth() / 2 - boxSize / 2,
                                    width: boxSize,
                                    height: boxSize
                                }
                            );

                            return (
                              <g
                                  { ...this.tooltipProps(d) }
                                  data-effect="solid"
                              >
                                <rect
                                    x={ x }
                                    y={ y }
                                    width={ width }
                                    height={ height }
                                    fill={ getColor(d) }
                                    key={ i }
                                    stroke={ stroke.color }
                                    strokeWidth={ stroke.width }
                                    { ...this.tooltipProps(d) }
                                />
                              </g>
                            );
                        })}
                    </g>
                    {this.renderLegend(cellColumnsData, legend, getColor, label)}
                </svg>

        );
    }
}

HeatmapGraph.propTypes = {
  configuration: React.PropTypes.object,
  response: React.PropTypes.object
};
<commit_msg>Fixed the Heatmap Boundary contact by offseting the max time<commit_after>import React from "react";
import XYGraph from "../XYGraph";

import {
    axisBottom,
    axisLeft,
    extent,
    format,
    nest,
    scaleBand,
    scaleTime,
    select,
    map,
    min,
    utcHour
} from "d3";

import {properties} from "./default.config"

export default class HeatmapGraph extends XYGraph {

    constructor(props) {
        super(props, properties);
    }

    render() {
        const {
            data,
            width,
            height
        } = this.props;

        if (!data || !data.length)
            return;

        const {
          chartHeightToPixel,
          chartWidthToPixel,
          circleToPixel,
          colorColumn,
          colors,
          legend,
          margin,
          padding,
          stroke,
          xColumn,
          xLabel,
          xTickFormat,
          xTickGrid,
          xTicks,
          xTickSizeInner,
          xTickSizeOuter,
          yColumn,
          yTickFormat,
          yTickGrid,
          yTicks,
          yTickSizeInner,
          yTickSizeOuter,
          legendColumn
        } = this.getConfiguredProperties();

        const isVerticalLegend = legend.orientation === 'vertical';
        const xLabelFn         = (d) => d[xColumn];
        const yLabelFn         = (d) => d[yColumn];
        const legendFn         = (d) => d[legendColumn];
        const label            = (d) => d["key"];
        const scale            = this.scaleColor(data, legendColumn);
        const getColor         = (d) => scale ? scale(d[colorColumn] || d[legendColumn] || d["key"]) : stroke.color || colors[0];

        const cellColumnsData  = nest()
            .key((d) => legendColumn ? d[legendColumn] : "Cell")
            .entries(data);

        let xAxisHeight       = xLabel ? chartHeightToPixel : 0;
        let legendWidth       = legend.show && cellColumnsData.length > 1 ? this.longestLabelLength(data, legendFn) * chartWidthToPixel : 0;

        let yLabelWidth       = this.longestLabelLength(data, yLabelFn) * chartWidthToPixel;

        let leftMargin        = margin.left + yLabelWidth;
        let availableWidth    = width - (margin.left + margin.right + yLabelWidth);
        let availableHeight   = height - (margin.top + margin.bottom + chartHeightToPixel + xAxisHeight);

        if (legend.show) {
            legend.width = legendWidth;

            // Compute the available space considering a legend
            if (isVerticalLegend)
            {
                leftMargin      +=  legend.width;
                availableWidth  -=  legend.width;
            }
            else {
                const nbElementsPerLine  = parseInt(availableWidth / legend.width, 10);
                const nbLines            = parseInt(cellColumnsData.length / nbElementsPerLine, 10);
                availableHeight         -= nbLines * legend.circleSize * circleToPixel + chartHeightToPixel;
            }
        }

        //For Making xAxis BANDSCALE
        const xBandScale = scaleBand()
            .domain(map(data, xLabelFn).keys().sort());
        xBandScale.rangeRound([0, availableWidth]);

        let xValues = extent(data, xLabelFn);

        const xScale = scaleTime()
          .domain([xValues[0], utcHour.offset(xValues[1], 1)]);

        const yScale = scaleBand()
          .domain(map(data, yLabelFn).keys().sort());

        xScale.range([0, availableWidth], 0.1);
        yScale.rangeRound([availableHeight, 0]).padding(padding);

        const xAxis = axisBottom(xScale)
          .tickSizeInner(xTickGrid ? -availableHeight : xTickSizeInner)
          .tickSizeOuter(xTickSizeOuter);

        if(xTickFormat){
            xAxis.tickFormat(format(xTickFormat));
        }

        if(xTicks){
            xAxis.ticks(xTicks);
        }

        const yAxis = axisLeft(yScale)
          .tickSizeInner(yTickGrid ? -availableWidth : yTickSizeInner)
          .tickSizeOuter(yTickSizeOuter);

        if(yTickFormat){
            yAxis.tickFormat(format(yTickFormat));
        }

        if(yTicks){
            yAxis.ticks(yTicks);
        }

        let xTitlePosition = {
            left: leftMargin + availableWidth / 2,
            top: margin.top + availableHeight + chartHeightToPixel + xAxisHeight
        }

        let yTitlePosition = {
            // We use chartWidthToPixel to compensate the rotation of the title
            left: margin.left + chartWidthToPixel + (isVerticalLegend ? legend.width : 0),
            top: margin.top + availableHeight / 2
        }

        let boxSize = min([xBandScale.bandwidth(), yScale.bandwidth()])
        return (

                {this.tooltip}
                <svg width={width} height={height}>
                    {this.axisTitles(xTitlePosition, yTitlePosition)}
                    <g transform={ `translate(${leftMargin},${margin.top})` } >
                        <g
                            key="xAxis"
                            ref={ (el) => select(el).call(xAxis) }
                            transform={ `translate(0,${availableHeight})` }
                        />
                        <g
                            key="yAxis"
                            ref={ (el) => select(el).call(yAxis) }
                        />
                        {data.map((d, i) => {
                            // Compute rectangle depending on orientation (vertical or horizontal).
                            const {
                                x,
                                y,
                                width,
                                height
                            } = (
                                {
                                    x: xScale(d[xColumn]),
                                    y: yScale(d[yColumn]) + yScale.bandwidth() / 2 - boxSize / 2,
                                    width: boxSize,
                                    height: boxSize
                                }
                            );

                            return (
                              <g
                                  { ...this.tooltipProps(d) }
                                  data-effect="solid"
                              >
                                <rect
                                    x={ x }
                                    y={ y }
                                    width={ width }
                                    height={ height }
                                    fill={ getColor(d) }
                                    key={ i }
                                    stroke={ stroke.color }
                                    strokeWidth={ stroke.width }
                                    { ...this.tooltipProps(d) }
                                />
                              </g>
                            );
                        })}
                    </g>
                    {this.renderLegend(cellColumnsData, legend, getColor, label)}
                </svg>

        );
    }
}

HeatmapGraph.propTypes = {
  configuration: React.PropTypes.object,
  response: React.PropTypes.object
};
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import {connect} from 'react-redux';
import css from './Notification.scss';
import {removeNotification} from '../../store/notifications';

// default className for Notification component
export const className = {
  main: css['notification'],
  meta: css['notification-meta'],
  title: css['notification-title'],
  message: css['notification-message'],
  icon: `fa ${css['notification-icon']}`,
  status: (status) => {
    return css[`notification--${status}`];
  },
  dismissible: css['notification--dismissible'],
  // `fa` corresponds to font-awesome's class name
  actions: (count) => {
    if (count === 1) {
      return css['notification--actions-1'];
    }
    else if (count === 2) {
      return css['notification--actions-2'];
    }
    return css['notification-actions'];
  },
  action: css['notification-action']
};

export class Notification extends Component {
  // Default properties
  static defaultProps = {
    className: className,
    onAdd: () => {
    },
    onRemove: () => {
    },
    actions: []
  };

  // Properties types
  static propTypes = {
    id: React.PropTypes.number.isRequired,
    title: React.PropTypes.string,
    message: React.PropTypes.string,
    status: React.PropTypes.oneOfType([
      React.PropTypes.string.isRequired,
      React.PropTypes.number.isRequired
    ]),
    dismissAfter: React.PropTypes.number.isRequired,
    dismissible: React.PropTypes.bool.isRequired,
    removeNotification: React.PropTypes.func.isRequired,
    onAdd: React.PropTypes.func,
    onRemove: React.PropTypes.func,
    actions: React.PropTypes.arrayOf(
      React.PropTypes.shape({
        name: React.PropTypes.string.isRequired,
        onClick: React.PropTypes.func.isRequired
      })
    ),
    className: React.PropTypes.object.isRequired
  };

  /**
   * Constructor
   * Bind methods
   * @param {Object} props
   * @returns {void}
   */
  constructor(props) {
    super(props);
    this._remove = this._remove.bind(this);
  }

  /**
   * Remove the notification
   * @private
   * @returns {void}
   */
  _remove() {
    const {removeNotification, id} = this.props;
    removeNotification(id);
  }

  /**
   * Run `onAdd` callback function when component is mounted
   * @returns {void}
   */
  componentDidMount() {
    const {id, onAdd, actions} = this.props;
    // update the component to render correctly the action buttons
    if (actions.length && this.refs[id]) {
      this.forceUpdate();
    }
    onAdd();
  }

  /**
   * Run `onRemove` callback function when component will unmount
   * @returns {void}
   */
  componentWillUnmount() {
    const {onRemove} = this.props;
    onRemove();
  }

  /**
   * Render action button(s)
   * @returns {*}
   */
  _renderActions() {
    const {actions, className} = this.props;
    return actions.map((action) => {
      return (
        <button key={action.name} className={className.action}
                onClick={action.onClick}>
          {(action.primary
            ? {action.name}
            : action.name)}
        </button>
      );
    });
  }

  /**
   * Render
   * @returns {XML}
   */
  render() {
    const {id, title, message, status, dismissAfter, dismissible, className, actions} = this.props;
    const isDismissible = (dismissible && actions.length === 0);
    let titleDiv = null;
    let messageDiv = null;
    let actionDiv = null;
    let style = {};
    // add title
    if (title) {
      titleDiv =
{title}
;
    }
    // add message
    if (message) {
      messageDiv =
{message}
;
    }
    // add action button(s)
    if (actions.length) {
      // We use `ref` to get height of notification.
      // We simulate a height of 100% or 50% for buttons depending on number of actions
      if (this.refs[id]) {
        style = {
          height: this.refs[id].clientHeight
        };
      }
      actionDiv = (

          {this._renderActions()}

      );
    }
    // if there is no actions, it remove automatically
    // the notification after `dismissAfter` duration
    else if (dismissAfter > 0) {
      setTimeout(() => this._remove(), dismissAfter);
    }

    return (
      <div ref={id} className={
           `${className.main} ${className.status(status)} ${(isDismissible ? className.dismissible : '')} ${className.actions(actions.length)}`}
           onClick={isDismissible ? this._remove : ''}>

          {titleDiv}
          {messageDiv}

        {actionDiv}

    );
  }
}

export default connect(null, {removeNotification})(Notification);
<commit_msg>minor improvements in render() of Notification component<commit_after>import React, {Component} from 'react';
import {connect} from 'react-redux';
import css from './Notification.scss';
import {removeNotification} from '../../store/notifications';

// default className for Notification component
export const className = {
  main: css['notification'],
  meta: css['notification-meta'],
  title: css['notification-title'],
  message: css['notification-message'],
  icon: `fa ${css['notification-icon']}`,
  status: (status) => {
    return css[`notification--${status}`];
  },
  dismissible: css['notification--dismissible'],
  // `fa` corresponds to font-awesome's class name
  actions: (count) => {
    if (count === 1) {
      return css['notification--actions-1'];
    }
    else if (count === 2) {
      return css['notification--actions-2'];
    }
    return css['notification-actions'];
  },
  action: css['notification-action']
};

export class Notification extends Component {
  // Default properties
  static defaultProps = {
    className: className,
    onAdd: () => {
    },
    onRemove: () => {
    },
    actions: []
  };

  // Properties types
  static propTypes = {
    id: React.PropTypes.number.isRequired,
    title: React.PropTypes.string,
    message: React.PropTypes.string,
    status: React.PropTypes.oneOfType([
      React.PropTypes.string.isRequired,
      React.PropTypes.number.isRequired
    ]),
    dismissAfter: React.PropTypes.number.isRequired,
    dismissible: React.PropTypes.bool.isRequired,
    removeNotification: React.PropTypes.func.isRequired,
    onAdd: React.PropTypes.func,
    onRemove: React.PropTypes.func,
    actions: React.PropTypes.arrayOf(
      React.PropTypes.shape({
        name: React.PropTypes.string.isRequired,
        onClick: React.PropTypes.func.isRequired
      })
    ),
    className: React.PropTypes.object.isRequired
  };

  /**
   * Constructor
   * Bind methods
   * @param {Object} props
   * @returns {void}
   */
  constructor(props) {
    super(props);
    this._remove = this._remove.bind(this);
  }

  /**
   * Remove the notification
   * @private
   * @returns {void}
   */
  _remove() {
    const {removeNotification, id} = this.props;
    removeNotification(id);
  }

  /**
   * Run `onAdd` callback function when component is mounted
   * @returns {void}
   */
  componentDidMount() {
    const {id, onAdd, actions} = this.props;
    // update the component to render correctly the action buttons
    if (actions.length && this.refs[id]) {
      this.forceUpdate();
    }
    onAdd();
  }

  /**
   * Run `onRemove` callback function when component will unmount
   * @returns {void}
   */
  componentWillUnmount() {
    const {onRemove} = this.props;
    onRemove();
  }

  /**
   * Render action button(s)
   * @returns {*}
   */
  _renderActions() {
    const {actions, className} = this.props;
    return actions.map((action) => {
      return (
        <button key={action.name} className={className.action}
                onClick={action.onClick}>
          {(action.primary
            ? {action.name}
            : action.name)}
        </button>
      );
    });
  }

  /**
   * Render
   * @returns {XML}
   */
  render() {
    const {id, title, message, status, dismissAfter, dismissible, className, actions} = this.props;
    const isDismissible = (dismissible && actions.length === 0);
    let actionDiv = null;
    let style = {};

    // add action button(s)
    if (actions.length) {
      // We use `ref` to get height of notification.
      // We simulate a height of 100% or 50% for buttons depending on number of actions
      if (this.refs[id]) {
        style = {
          height: this.refs[id].clientHeight
        };
      }
      actionDiv = (

          {this._renderActions()}

      );
    }
    // if there is no actions, it remove automatically
    // the notification after `dismissAfter` duration
    else if (dismissAfter > 0) {
      setTimeout(() => this._remove(), dismissAfter);
    }

    return (
      <div ref={id} className={
           `${className.main} ${className.status(status)} ${(isDismissible ? className.dismissible : '')} ${className.actions(actions.length)}`}
           onClick={isDismissible ? this._remove : ''}>

          {(title
            ?
{title}

            : '')}
          {(message
          ?
{message}

          : '')}

        {actionDiv}

    );
  }
}

export default connect(null, {removeNotification})(Notification);
<|endoftext|>


<commit_before>require('../../stylus/components/_bottom-sheets.styl')

import VDialog from '../VDialog/VDialog'

export default {
  name: 'v-bottom-sheet',

  mixins: [VDialog],

  props: {
    inset: Boolean,
    value: null
  },

  render (h) {
    const activator = h('template', {
      slot: 'activator'
    }, this.$slots.activator)

    const contentClass = [
      'bottom-sheet',
      this.inset ? 'bottom-sheet--inset' : ''
    ].join(' ')

    return h(VDialog, {
      attrs: {
        ...this.$attrs
      },
      on: {
        ...this.$listeners
      },
      props: {
        contentClass: contentClass,
        transition: 'bottom-sheet-transition',
        value: this.value
      }
    }, [activator, this.$slots.default])
  }
}
<commit_msg>refactor(v-bottom-sheet): changed how properties were derived<commit_after>require('../../stylus/components/_bottom-sheets.styl')

import VDialog from '../VDialog/VDialog'

export default {
  name: 'v-bottom-sheet',

  props: {
    disabled: Boolean,
    fullWidth: Boolean,
    inset: Boolean,
    lazy: Boolean,
    maxWidth: {
      type: [String, Number],
      default: 'auto'
    },
    persistent: Boolean,
    value: null
  },

  render (h) {
    const activator = h('template', {
      slot: 'activator'
    }, this.$slots.activator)

    const contentClass = [
      'bottom-sheet',
      this.inset ? 'bottom-sheet--inset' : ''
    ].join(' ')

    return h(VDialog, {
      attrs: {
        ...this.$props
      },
      on: {
        ...this.$listeners
      },
      props: {
        contentClass: contentClass,
        transition: 'bottom-sheet-transition',
        value: this.value
      }
    }, [activator, this.$slots.default])
  }
}
<|endoftext|>


<commit_before>import Component from 'base/component';
import * as utils from 'base/utils';

/*!
 * VIZABI GENERIC SLIDER CONTROL
 * Reusable SLIDER
 */

var SimpleSlider = Component.extend({

    init: function (config, context) {
      this.template = '
<input type="range" id="vzb-ss-slider" class="vzb-ss-slider" step="1">
';

      this.model_expects = [{
        name: "submodel"
      }];

      var _this = this;
      this.name = 'gapminder-simpleSlider';

      this.arg = config.arg;
      this.thumb_size = config.thumb_size;
      this.slider_properties = config.properties;

      this.model_binds = {};
      this.model_binds["change:submodel." + this.arg] = function (evt) {
        _this.updateView();
      };

      //contructor is the same as any component
      this._super(config, context);

      this._setModel = utils.throttle(this._setModel, 50);
    },

    /**
     * Executes after the template is loaded and rendered.
     * Ideally, it contains HTML instantiations related to template
     * At this point, this.element and this.placeholder are available as a d3 object
     */
    readyOnce: function () {

      //default values
      var min = 0;
      var max = 1;
      var step = 0.1;
      var value = min;

      //selecting elements
      var _this = this;
      this.element = d3.select(this.element);
      this.slider = this.element.selectAll('#vzb-ss-slider');

      this.elementSize = this.element.node().getBoundingClientRect();
      this.sliderSize = this.slider.node().getBoundingClientRect();
      this.slider.style('left', (this.elementSize.left - this.sliderSize.left) + 'px');

      //TODO: replace this with utils.extend
      if(this.slider_properties){
        if(this.slider_properties.min != null) min = this.slider_properties.min;
        if(this.slider_properties.max != null) max = this.slider_properties.max;
        if(this.slider_properties.step != null) step = this.slider_properties.step;

        if(this.slider_properties.scale){
          value = this.slider_properties.scale(min);
        }
      }

      //check and change the slider's thumb size
      if(this.thumb_size){
        this.slider.classed('vzb-ss-slider', false);
        this.slider.classed('vzb-ss-slider-'+this.thumb_size, true);
      }

      this.slider
        .attr('min', min)
        .attr('max', max)
        .attr('step', step)
        .attr('value', value)
        .on('input', function () {
          var value = +d3.event.target.value;
          _this._setModel(value, false, false); // on drag - non-persistent changes while dragging
        })
        .on('change', function() {
          var value = +d3.event.target.value;
          _this._setModel(value, true); // on drag end - value is probably same as last 'input'-event, so force change
        });

      this.updateView();
    },

    updateView: function () {
      var value = this.model.submodel[this.arg];
      var slider_properties = this.slider_properties;
      var scale;

      if(slider_properties){
        scale = slider_properties.scale;
      }
      if (scale){
        value = scale.invert(value);
      }

      //this.slider.attr('value', value);
      this.slider.node().value = value;
    },

    _setModel: function (value, force, persistent) {
      // rescale value if scale is supplied in slider_properties
      if(this.slider_properties && this.slider_properties.scale) value = this.slider_properties.scale(value);

      this.model.submodel.getModelObject(this.arg).set(value, force, persistent);
    }

  });

export default SimpleSlider;
<commit_msg>Adjust the precision of simple slider. Remove unnecessary properties from time model<commit_after>import Component from 'base/component';
import * as utils from 'base/utils';

/*!
 * VIZABI GENERIC SLIDER CONTROL
 * Reusable SLIDER
 */

var SimpleSlider = Component.extend({

    init: function (config, context) {
      this.template = '
<input type="range" id="vzb-ss-slider" class="vzb-ss-slider" step="1">
';

      this.model_expects = [{
        name: "submodel"
      }];

      var _this = this;
      this.name = 'gapminder-simpleSlider';

      this.arg = config.arg;
      this.thumb_size = config.thumb_size;
      this.slider_properties = config.properties;

      this.model_binds = {};
      this.model_binds["change:submodel." + this.arg] = function (evt) {
        _this.updateView();
      };

      //contructor is the same as any component
      this._super(config, context);

      this._setModel = utils.throttle(this._setModel, 50);
    },

    /**
     * Executes after the template is loaded and rendered.
     * Ideally, it contains HTML instantiations related to template
     * At this point, this.element and this.placeholder are available as a d3 object
     */
    readyOnce: function () {

      //default values
      var min = 0;
      var max = 1;
      var step = 0.1;
      var value = min;

      //selecting elements
      var _this = this;
      this.element = d3.select(this.element);
      this.slider = this.element.selectAll('#vzb-ss-slider');

      this.elementSize = this.element.node().getBoundingClientRect();
      this.sliderSize = this.slider.node().getBoundingClientRect();
      this.slider.style('left', (this.elementSize.left - this.sliderSize.left) + 'px');

      //TODO: replace this with utils.extend
      if(this.slider_properties){
        if(this.slider_properties.min != null) min = this.slider_properties.min;
        if(this.slider_properties.max != null) max = this.slider_properties.max;
        if(this.slider_properties.step != null) step = this.slider_properties.step;

        if(this.slider_properties.scale){
          value = this.slider_properties.scale(min);
        }
      }

      //step also defines the rounding of values that willbe sent to model: 0.1 --> 1 digit, 0.01 --> 2, 1 and up --> 0
      this.roundTo = step > 1 ? 0 : Math.round(Math.abs(Math.log(step)/Math.LN10));

      //check and change the slider's thumb size
      if(this.thumb_size){
        this.slider.classed('vzb-ss-slider', false);
        this.slider.classed('vzb-ss-slider-'+this.thumb_size, true);
      }

      this.slider
        .attr('min', min)
        .attr('max', max)
        .attr('step', step)
        .attr('value', value)
        .on('input', function () {
          var value = +d3.event.target.value;
          _this._setModel(value, false, false); // on drag - non-persistent changes while dragging
        })
        .on('change', function() {
          var value = +d3.event.target.value;
          _this._setModel(value, true); // on drag end - value is probably same as last 'input'-event, so force change
        });

      this.updateView();
    },

    updateView: function () {
      var value = this.model.submodel[this.arg];
      var slider_properties = this.slider_properties;
      var scale;

      if(slider_properties){
        scale = slider_properties.scale;
      }
      if (scale){
        value = scale.invert(value);
      }

      //this.slider.attr('value', value);
      this.slider.node().value = value;
    },

    _setModel: function (value, force, persistent) {
      // rescale value if scale is supplied in slider_properties
      if(this.slider_properties && this.slider_properties.scale) value = this.slider_properties.scale(value);

      this.model.submodel.getModelObject(this.arg).set(value.toFixed(this.roundTo), force, persistent);
    }

  });

export default SimpleSlider;
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var classNames = require('classnames');
var React = require('react');
var ReactDOM = require('react-dom');

// Shamelessly ripped off Modal.js.  There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and
// pass in a custom control as the actual body.

module.exports = {
    ContextualMenuContainerId: "mx_ContextualMenu_Container",

    propTypes: {
        menuWidth: React.PropTypes.number,
        menuHeight: React.PropTypes.number,
        chevronOffset: React.PropTypes.number,
        menuColour: React.PropTypes.string,
    },

    getOrCreateContainer: function() {
        var container = document.getElementById(this.ContextualMenuContainerId);

        if (!container) {
            container = document.createElement("div");
            container.id = this.ContextualMenuContainerId;
            document.body.appendChild(container);
        }

        return container;
    },

    createMenu: function (Element, props) {
        var self = this;

        var closeMenu = function() {
            ReactDOM.unmountComponentAtNode(self.getOrCreateContainer());

            if (props && props.onFinished) {
                props.onFinished.apply(null, arguments);
            }
        };

        var position = {
            top: props.top,
        };

        var chevronOffset = {};
        if (props.chevronOffset) {
            chevronOffset.top = props.chevronOffset;
        }

        // To overide the deafult chevron colour, if it's been set
        var chevronCSS = "";
        if (props.menuColour) {
            chevronCSS = `
                .mx_ContextualMenu_chevron_left:after {
                    border-right-color: ${props.menuColour};
                }

                .mx_ContextualMenu_chevron_right:after {
                    border-left-color: ${props.menuColour};
                }
            `
        }

        var chevron = null;
        if (props.left) {
            chevron =

            position.left = props.left;
        } else {
            chevron =

            position.right = props.right;
        }

        var className = 'mx_ContextualMenu_wrapper';

        var menuClasses = classNames({
            'mx_ContextualMenu': true,
            'mx_ContextualMenu_left': props.left,
            'mx_ContextualMenu_right': !props.left,
        });

        var menuStyle = {};
        if (props.menuWidth) {
            menuStyle.width = props.menuWidth;
        }

        if (props.menuHeight) {
            menuStyle.height = props.menuHeight;
        }

        if (props.menuColour) {
            menuStyle["background-color"] = props.menuColour;
        }

        // FIXME: If a menu uses getDefaultProps it clobbers the onFinished
        // property set here so you can't close the menu from a button click!
        var menu = (

                    {chevron}
                    <Element {...props} onFinished={closeMenu}/>

        );

        ReactDOM.render(menu, this.getOrCreateContainer());

        return {close: closeMenu};
    },
};
<commit_msg>Bugifx: 'background-color' in react should be 'backgroundColor'<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var classNames = require('classnames');
var React = require('react');
var ReactDOM = require('react-dom');

// Shamelessly ripped off Modal.js.  There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and
// pass in a custom control as the actual body.

module.exports = {
    ContextualMenuContainerId: "mx_ContextualMenu_Container",

    propTypes: {
        menuWidth: React.PropTypes.number,
        menuHeight: React.PropTypes.number,
        chevronOffset: React.PropTypes.number,
        menuColour: React.PropTypes.string,
    },

    getOrCreateContainer: function() {
        var container = document.getElementById(this.ContextualMenuContainerId);

        if (!container) {
            container = document.createElement("div");
            container.id = this.ContextualMenuContainerId;
            document.body.appendChild(container);
        }

        return container;
    },

    createMenu: function (Element, props) {
        var self = this;

        var closeMenu = function() {
            ReactDOM.unmountComponentAtNode(self.getOrCreateContainer());

            if (props && props.onFinished) {
                props.onFinished.apply(null, arguments);
            }
        };

        var position = {
            top: props.top,
        };

        var chevronOffset = {};
        if (props.chevronOffset) {
            chevronOffset.top = props.chevronOffset;
        }

        // To overide the deafult chevron colour, if it's been set
        var chevronCSS = "";
        if (props.menuColour) {
            chevronCSS = `
                .mx_ContextualMenu_chevron_left:after {
                    border-right-color: ${props.menuColour};
                }

                .mx_ContextualMenu_chevron_right:after {
                    border-left-color: ${props.menuColour};
                }
            `
        }

        var chevron = null;
        if (props.left) {
            chevron =

            position.left = props.left;
        } else {
            chevron =

            position.right = props.right;
        }

        var className = 'mx_ContextualMenu_wrapper';

        var menuClasses = classNames({
            'mx_ContextualMenu': true,
            'mx_ContextualMenu_left': props.left,
            'mx_ContextualMenu_right': !props.left,
        });

        var menuStyle = {};
        if (props.menuWidth) {
            menuStyle.width = props.menuWidth;
        }

        if (props.menuHeight) {
            menuStyle.height = props.menuHeight;
        }

        if (props.menuColour) {
            menuStyle["backgroundColor"] = props.menuColour;
        }

        // FIXME: If a menu uses getDefaultProps it clobbers the onFinished
        // property set here so you can't close the menu from a button click!
        var menu = (

                    {chevron}
                    <Element {...props} onFinished={closeMenu}/>

        );

        ReactDOM.render(menu, this.getOrCreateContainer());

        return {close: closeMenu};
    },
};
<|endoftext|>