<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import Overlay from 'react-overlays/lib/Overlay';
import Motion from '../../ui/util/optional_motion';
import spring from 'react-motion/lib/spring';

const messages = defineMessages({
  placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
});

class SearchPopout extends React.PureComponent {

  static propTypes = {
    style: PropTypes.object,
  };

  render () {
    const { style } = this.props;

    return (

        <Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}>
          {({ opacity, scaleX, scaleY }) => (
            <div className='search-popout' style={{ opacity: opacity, transform: `scale(${scaleX}, ${scaleY})` }}>

<FormattedMessage id='search_popout.search_format' defaultMessage='Advanced search format' />

#district1

#100sqm (100sqm≧)

#150sqm (101≦150)

#200sqm (151≦200)

#250sqm (201≦250)

#15usd (15usd≧)

#20usd (16≦20)

#25usd (21≦25)

#30usd (26≦30)

              <FormattedMessage id='search_popout.tips.text' defaultMessage='Simple text returns matching display names, usernames and hashtags' />

          )}
        </Motion>

    );
  }

}

@injectIntl
export default class Search extends React.PureComponent {

  static propTypes = {
    value: PropTypes.string.isRequired,
    submitted: PropTypes.bool,
    onChange: PropTypes.func.isRequired,
    onSubmit: PropTypes.func.isRequired,
    onClear: PropTypes.func.isRequired,
    onShow: PropTypes.func.isRequired,
    intl: PropTypes.object.isRequired,
  };

  state = {
    expanded: false,
  };

  handleChange = (e) => {
    this.props.onChange(e.target.value);
  }

  handleClear = (e) => {
    e.preventDefault();

    if (this.props.value.length > 0 || this.props.submitted) {
      this.props.onClear();
    }
  }

  handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      this.props.onSubmit();
    } else if (e.key === 'Escape') {
      document.querySelector('.ui').parentElement.focus();
    }
  }

  noop () {

  }

  handleFocus = () => {
    this.setState({ expanded: true });
    this.props.onShow();
  }

  handleBlur = () => {
    this.setState({ expanded: false });
  }

  render () {
    const { intl, value, submitted } = this.props;
    const { expanded } = this.state;
    const hasValue = value.length > 0 || submitted;

    return (

          {intl.formatMessage(messages.placeholder)}
          <input
            className='search__input'
            type='text'
            placeholder={intl.formatMessage(messages.placeholder)}
            value={value}
            onChange={this.handleChange}
            onKeyUp={this.handleKeyDown}
            onFocus={this.handleFocus}
            onBlur={this.handleBlur}
          />

          <i className={`fa fa-search ${hasValue ? '' : 'active'}`} />
          <i aria-label={intl.formatMessage(messages.placeholder)} className={`fa fa-times-circle ${hasValue ? 'active' : ''}`} />

        <Overlay show={expanded && !hasValue} placement='bottom' target={this}>
          <SearchPopout />
        </Overlay>

    );
  }

}
<commit_msg>Fixed search example<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import Overlay from 'react-overlays/lib/Overlay';
import Motion from '../../ui/util/optional_motion';
import spring from 'react-motion/lib/spring';

const messages = defineMessages({
  placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
});

class SearchPopout extends React.PureComponent {

  static propTypes = {
    style: PropTypes.object,
  };

  render () {
    const { style } = this.props;

    return (

        <Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}>
          {({ opacity, scaleX, scaleY }) => (
            <div className='search-popout' style={{ opacity: opacity, transform: `scale(${scaleX}, ${scaleY})` }}>

<FormattedMessage id='search_popout.search_format' defaultMessage='Advanced search format' />

#district1 and any district

#100sqm (100sqm≧)

#150sqm (101≦150)

#200sqm (151≦200)

#250sqm (201≦250)

#15usd (15usd≧)

#20usd (16≦20)

#25usd (21≦25)

#30usd (26≦30)

              <FormattedMessage id='search_popout.tips.text' defaultMessage='Simple text returns matching display names, usernames and hashtags' />

          )}
        </Motion>

    );
  }

}

@injectIntl
export default class Search extends React.PureComponent {

  static propTypes = {
    value: PropTypes.string.isRequired,
    submitted: PropTypes.bool,
    onChange: PropTypes.func.isRequired,
    onSubmit: PropTypes.func.isRequired,
    onClear: PropTypes.func.isRequired,
    onShow: PropTypes.func.isRequired,
    intl: PropTypes.object.isRequired,
  };

  state = {
    expanded: false,
  };

  handleChange = (e) => {
    this.props.onChange(e.target.value);
  }

  handleClear = (e) => {
    e.preventDefault();

    if (this.props.value.length > 0 || this.props.submitted) {
      this.props.onClear();
    }
  }

  handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      this.props.onSubmit();
    } else if (e.key === 'Escape') {
      document.querySelector('.ui').parentElement.focus();
    }
  }

  noop () {

  }

  handleFocus = () => {
    this.setState({ expanded: true });
    this.props.onShow();
  }

  handleBlur = () => {
    this.setState({ expanded: false });
  }

  render () {
    const { intl, value, submitted } = this.props;
    const { expanded } = this.state;
    const hasValue = value.length > 0 || submitted;

    return (

          {intl.formatMessage(messages.placeholder)}
          <input
            className='search__input'
            type='text'
            placeholder={intl.formatMessage(messages.placeholder)}
            value={value}
            onChange={this.handleChange}
            onKeyUp={this.handleKeyDown}
            onFocus={this.handleFocus}
            onBlur={this.handleBlur}
          />

          <i className={`fa fa-search ${hasValue ? '' : 'active'}`} />
          <i aria-label={intl.formatMessage(messages.placeholder)} className={`fa fa-times-circle ${hasValue ? 'active' : ''}`} />

        <Overlay show={expanded && !hasValue} placement='bottom' target={this}>
          <SearchPopout />
        </Overlay>

    );
  }

}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2018, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* 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.                                             */
/* -------------------------------------------------------------------------- */

define(function(require){
  var Locale = require("utils/locale");
  var Config = require("sunstone-config");
  var OpenNebula = require("opennebula");
  var OpenNebulaImage = require("opennebula/image");
  var UserInputs = require("utils/user-inputs");
  var WizardFields = require("utils/wizard-fields");
  var DisksResizeTemplate = require("hbs!./disks-resize/html");
  var Humanize = require("utils/humanize");

  return {
    "insert": _insert,
    "retrieve": _retrieve
  };

  function _calculateCost(context, disk_cost, callback){
    var cost = 0;
    var totalSize = 0;

    $(".diskContainer", context).each(function(){
      var size = 0;

      var fields = WizardFields.retrieve(this);

      if (fields.SIZE != undefined){
        size = fields.SIZE;
      } else{
        disk = $(this).data("template_disk");

        if (disk != undefined && disk["SIZE"] != undefined){
          size = disk["SIZE"];
        }
      }
      totalSize += parseFloat(size);
      cost += size * disk_cost;
      cost += $(this).data("disk_snapshot_total_cost");
    });

    $(".cost_value", context).text(cost.toFixed(6));
    $("#quotas-disks", context).text(totalSize.toFixed(2));

    if(callback != undefined){
      callback();
    }
  }

  /**
   * @param {Object} opts - template_json: extended info template (with DISK/SIZE)
   *                      - disksContext: jquery selector, where to place the html
   *                      - force_persistent {bool}: mark all disks as if they
   *                          were persistent, disabling resize inputs
   *                      - cost_callback: function to call when the cost changes
   */
  function _insert(opts) {

    var disksContext = opts.disksContext;

    var template_disk = opts.template_json.VMTEMPLATE.TEMPLATE.DISK;
    var disks = [];
    if ($.isArray(template_disk)) {
      disks = template_disk;
    } else if (!$.isEmptyObject(template_disk)) {
      disks = [template_disk];
    }

    if (opts.template_base_json && opts.template_base_json.VMTEMPLATE) {
      var template_base_disk = opts.template_base_json.VMTEMPLATE.TEMPLATE.DISK;
      var disks_base = [];
      if ($.isArray(template_base_disk)) {
        disks_base = template_base_disk;
      } else if (!$.isEmptyObject(template_base_disk)) {
        disks_base = [template_base_disk];
      }
    }

    if (disks.length > 0) {
      disksContext.html(DisksResizeTemplate());

      var disk_cost = opts.template_json.VMTEMPLATE.TEMPLATE.DISK_COST;

      if (disk_cost == undefined) {
        disk_cost = Config.onedConf.DEFAULT_COST.DISK_COST;
      }

      disksContext.off("change", "input");

      if (Config.isFeatureEnabled("showback")) {
        if(disk_cost != 0){
          $(".provision_create_template_disk_cost_div", disksContext).show();
        }

        disksContext.on("change", "input", function(){
          _calculateCost(disksContext, disk_cost, opts.cost_callback);
        });

        _calculateCost(disksContext, disk_cost, opts.cost_callback);
      } else {
        $(".provision_create_template_disk_cost_div", disksContext).hide();
      }

      var diskContext;
      $(".disksContainer", disksContext).html("");

      $.each(disks, function(disk_id, disk) {
        diskContext = $(
          "
"+
            "
"+
              ""+
            "
"+
            "
" +
            "
" +
          "
").appendTo($(".disksContainer", disksContext));
        if (disks_base) {
          disks_base[disk_id].SIZE = disk.SIZE;
          diskContext.data("template_disk", disks_base[disk_id]);
        }

        var disk_snapshot_total_size = 0;
        if (disk.DISK_SNAPSHOT_TOTAL_SIZE != undefined) {
          disk_snapshot_total_size = parseInt(disk.DISK_SNAPSHOT_TOTAL_SIZE);
        }

        diskContext.data("disk_snapshot_total_size", disk_snapshot_total_size);
        diskContext.data("disk_snapshot_total_cost", disk_snapshot_total_size * disk_cost);

        var volatile = (disk.IMAGE == undefined && disk.IMAGE_ID == undefined);

        var label;

        if (volatile){
          label = Locale.tr("Volatile Disk");
        } else {
          label = disk.IMAGE ? disk.IMAGE : Locale.tr("Image was not found");
        }

        $("label", diskContext).text(Locale.tr("DISK") + " " + disk_id + ": " + label);

        var persistent =
          ( opts.force_persistent ||
            (disk.PERSISTENT && disk.PERSISTENT.toUpperCase() == "YES") );

        var disabled =
          ( persistent ||
            (disk.TYPE && OpenNebulaImage.TYPES[disk.TYPE] == OpenNebulaImage.TYPES.CDROM) );

        if (persistent){
          $("label", diskContext).append("");

        }else{
          $("label", diskContext).append("");

        }

        if (disk.IMAGE_STATE){
          var color_class = OpenNebulaImage.stateColor(disk.IMAGE_STATE) + "-color";

          $("label", diskContext).append("");
        } else if (disk.IMAGE || disk.IMAGE_ID) {
          var color_class = "error-color";

          $("label", diskContext).append("");
        } // else is volatile, does not have state

        var attr;

        if (disabled){
          if (disk.SIZE){
            attr = UserInputs.parse("SIZE","O|fixed|"+label+"||"+disk.SIZE);
          } else {
            attr = UserInputs.parse("SIZE","O|fixed|"+label+"||-");
          }
        } else {
          if (disk.SIZE != undefined){
            // Range from original size to size + 500GB
            var min = parseInt(disk.SIZE);
            var max = min + Humanize.sizeToMB("1024GB");

            attr = UserInputs.parse(
              "SIZE",
              "O|range|"+label+"|"+min+".."+max+"|"+min);
          } else {
            attr = UserInputs.parse(
              "SIZE",
              "M|number|"+label+"||");
          }
        }
        attr.max_value = "";
        if(!opts.uinput_mb){
          $(".diskSlider", diskContext).html(UserInputs.attributeInput(attr));
        } else {
          UserInputs.insertAttributeInputMB(attr, $(".diskSlider", diskContext));
        }
      });

    } else {
      disksContext.html("");
    }
  }

  function _retrieve(context) {
    var disks = [];
    var disk;
    $(".diskContainer", context).each(function(){
      if ($(this).data("template_disk")) {
        disk = $(this).data("template_disk");

        var fields = WizardFields.retrieve(this);

        var size = $.extend(true, [], fields.SIZE);
        var size = size.join("");
        var diskAux = $.extend(true, {}, disk);
        diskAux["SIZE"] = fields.SIZE;
        disks.push(diskAux);
      }
    });

    return disks;
  }
});
<commit_msg>B #2533: Impossible to instantiate a VM w/ RESTRICTED_ATTR DISK/SIZE (#2534)<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2018, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* 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.                                             */
/* -------------------------------------------------------------------------- */

define(function(require){
  var Locale = require("utils/locale");
  var Config = require("sunstone-config");
  var OpenNebula = require("opennebula");
  var OpenNebulaImage = require("opennebula/image");
  var UserInputs = require("utils/user-inputs");
  var WizardFields = require("utils/wizard-fields");
  var DisksResizeTemplate = require("hbs!./disks-resize/html");
  var Humanize = require("utils/humanize");

  return {
    "insert": _insert,
    "retrieve": _retrieve
  };

  function _calculateCost(context, disk_cost, callback){
    var cost = 0;
    var totalSize = 0;

    $(".diskContainer", context).each(function(){
      var size = 0;

      var fields = WizardFields.retrieve(this);

      if (fields.SIZE != undefined){
        size = fields.SIZE;
      } else{
        disk = $(this).data("template_disk");

        if (disk != undefined && disk["SIZE"] != undefined){
          size = disk["SIZE"];
        }
      }
      totalSize += parseFloat(size);
      cost += size * disk_cost;
      cost += $(this).data("disk_snapshot_total_cost");
    });

    $(".cost_value", context).text(cost.toFixed(6));
    $("#quotas-disks", context).text(totalSize.toFixed(2));

    if(callback != undefined){
      callback();
    }
  }

  /**
   * @param {Object} opts - template_json: extended info template (with DISK/SIZE)
   *                      - disksContext: jquery selector, where to place the html
   *                      - force_persistent {bool}: mark all disks as if they
   *                          were persistent, disabling resize inputs
   *                      - cost_callback: function to call when the cost changes
   */
  function _insert(opts) {

    var disksContext = opts.disksContext;

    var template_disk = opts.template_json.VMTEMPLATE.TEMPLATE.DISK;
    var disks = [];
    if ($.isArray(template_disk)) {
      disks = template_disk;
    } else if (!$.isEmptyObject(template_disk)) {
      disks = [template_disk];
    }

    if (opts.template_base_json && opts.template_base_json.VMTEMPLATE) {
      var template_base_disk = opts.template_base_json.VMTEMPLATE.TEMPLATE.DISK;
      var disks_base = [];
      if ($.isArray(template_base_disk)) {
        disks_base = template_base_disk;
      } else if (!$.isEmptyObject(template_base_disk)) {
        disks_base = [template_base_disk];
      }
    }

    if (disks.length > 0) {
      disksContext.html(DisksResizeTemplate());

      var disk_cost = opts.template_json.VMTEMPLATE.TEMPLATE.DISK_COST;

      if (disk_cost == undefined) {
        disk_cost = Config.onedConf.DEFAULT_COST.DISK_COST;
      }

      disksContext.off("change", "input");

      if (Config.isFeatureEnabled("showback")) {
        if(disk_cost != 0){
          $(".provision_create_template_disk_cost_div", disksContext).show();
        }

        disksContext.on("change", "input", function(){
          _calculateCost(disksContext, disk_cost, opts.cost_callback);
        });

        _calculateCost(disksContext, disk_cost, opts.cost_callback);
      } else {
        $(".provision_create_template_disk_cost_div", disksContext).hide();
      }

      var diskContext;
      $(".disksContainer", disksContext).html("");

      $.each(disks, function(disk_id, disk) {
        diskContext = $(
          "
"+
            "
"+
              ""+
            "
"+
            "
" +
            "
" +
          "
").appendTo($(".disksContainer", disksContext));
        if (disks_base) {
          disks_base[disk_id].SIZE = disk.SIZE;
          disks_base[disk_id].ORIGINAL_SIZE = disk.ORIGINAL_SIZE;
          diskContext.data("template_disk", disks_base[disk_id]);
        }

        var disk_snapshot_total_size = 0;
        if (disk.DISK_SNAPSHOT_TOTAL_SIZE != undefined) {
          disk_snapshot_total_size = parseInt(disk.DISK_SNAPSHOT_TOTAL_SIZE);
        }

        diskContext.data("disk_snapshot_total_size", disk_snapshot_total_size);
        diskContext.data("disk_snapshot_total_cost", disk_snapshot_total_size * disk_cost);

        var volatile = (disk.IMAGE == undefined && disk.IMAGE_ID == undefined);

        var label;

        if (volatile){
          label = Locale.tr("Volatile Disk");
        } else {
          label = disk.IMAGE ? disk.IMAGE : Locale.tr("Image was not found");
        }

        $("label", diskContext).text(Locale.tr("DISK") + " " + disk_id + ": " + label);

        var persistent =
          ( opts.force_persistent ||
            (disk.PERSISTENT && disk.PERSISTENT.toUpperCase() == "YES") );

        var disabled =
          ( persistent ||
            (disk.TYPE && OpenNebulaImage.TYPES[disk.TYPE] == OpenNebulaImage.TYPES.CDROM) );

        if (persistent){
          $("label", diskContext).append("");

        }else{
          $("label", diskContext).append("");

        }

        if (disk.IMAGE_STATE){
          var color_class = OpenNebulaImage.stateColor(disk.IMAGE_STATE) + "-color";

          $("label", diskContext).append("");
        } else if (disk.IMAGE || disk.IMAGE_ID) {
          var color_class = "error-color";

          $("label", diskContext).append("");
        } // else is volatile, does not have state

        var attr;

        if (disabled){
          if (disk.SIZE){
            attr = UserInputs.parse("SIZE","O|fixed|"+label+"||"+disk.SIZE);
          } else {
            attr = UserInputs.parse("SIZE","O|fixed|"+label+"||-");
          }
        } else {
          if (disk.SIZE != undefined){
            // Range from original size to size + 500GB
            var min = parseInt(disk.SIZE);
            var max = min + Humanize.sizeToMB("1024GB");

            attr = UserInputs.parse(
              "SIZE",
              "O|range|"+label+"|"+min+".."+max+"|"+min);
          } else {
            attr = UserInputs.parse(
              "SIZE",
              "M|number|"+label+"||");
          }
        }
        attr.max_value = "";
        if(!opts.uinput_mb){
          $(".diskSlider", diskContext).html(UserInputs.attributeInput(attr));
        } else {
          UserInputs.insertAttributeInputMB(attr, $(".diskSlider", diskContext));
        }
      });

    } else {
      disksContext.html("");
    }
  }

  function _retrieve(context) {
    var disks = [];
    var disk;
    $(".diskContainer", context).each(function(){
      if ($(this).data("template_disk")) {
        disk = $(this).data("template_disk");
        var fields = WizardFields.retrieve(this);

        if (disk["SIZE"] && fields["SIZE"] && disk["ORIGINAL_SIZE"] === fields["SIZE"] && fields["SIZE"] === disk["SIZE"]){
          if (disk["IMAGE_ID"] || disk["IMAGE_NAME"]){
            delete disk["SIZE"];
          }
          delete disk["ORIGINAL_SIZE"];
          disks.push(disk);
        } else {
          var diskAux = $.extend(true, {}, disk);
          diskAux["SIZE"] = fields["SIZE"];
          delete diskAux["ORIGINAL_SIZE"];
          disks.push(diskAux);
        }
      }
    });

    return disks;
  }
});
<|endoftext|>


<commit_before>var React           = require('react/addons');
var SequenceViewer  = require('../../partials/SequenceViewer');
var SequenceActions = require('../../../actions/SequenceActions');
var TwoDee          = require('two-dee');

var loners;       // these are nodes which are not part of lists
var lists;        // this is a list of linked lists.  links go forward in the lists
var _sequence;    // contains the sequence (passed through props)
var _editVal;     // contains details on teh node that is being edited
var _dragging;    // whether the user is moving the mouse around
var _clickedNode; // the node that a user initiated an action on
var _mouseDown = false;
var _arrowSet = false;
var _startNode;
var _startPoint;
var _endNode;
var _arrow;

/**
 * initializes the data for the editor
 */
function reset () {
  loners = [];
  lists = [];
  d3.select('g.loners').attr('transform', '');
}

/**
 * updates the sequence
 */
function updateSequence () {
  SequenceActions.update(_sequence);
}

/**
 * adds an operation to the sequence
 */
function addOperation (op) {
  _sequence.operations.push(op);
  updateSequence();
}

var Operations = {
  initialization: {
    label: 'initialization',
    operation: function (viewport, data) {

      reset();

      /**
       * Handler for entry of the initial value field
       */
      function createNode (elem) {
        var d3elem = d3.select(elem);
        if (d3elem.classed('open')) {
          d3elem.classed('open', false);
          addOperation({
            type: 'createNode',
            data: {
              value: elem.value
            }
          });
          elem.value = '';
        }
      }

      /**
       * Handler for actions on the initial value field
       */
      d3.select("#initial-value")
        .on('blur', function () {
          createNode(this);
        })
        .on('keydown', function () {
          if (d3.event.keyCode === 13) {
            createNode(this);
          }
        });

      /**
       * Handler for entry of the edit node field
       */
      function editNode (elem) {
        var d3elem = d3.select(elem);
        if (d3elem.classed('open')) {
          d3elem.classed('open', false);
          _editVal.value = elem.value;
          addOperation({
            type: 'editValue',
            data: _editVal
          });
          elem.value = '';
        }
      }

      /**
       * Handler for actions on the edit node field
       */
      d3.select('#edit-node-value')
        .on('blur', function () {
          editNode(this);
        })
        .on('keydown', function () {
          if (d3.event.keyCode === 13) {
            editNode(this);
          }
        });

      /**
       * Append the loners group
       */
      viewport
        .append('g')
        .classed('loners', true);
    }
  },

  createNode: {
    label: 'Create Node',
    operation: function (viewport, data) {
      var lonersElem = viewport
        .select('g.loners');

      var verticalOffset = 0;
      var horizontalOffset = 0;

      var group = lonersElem
        .append('g');

      group
        .classed('node', true)
        .attr('opacity', '0')
        .transition()
        .duration(1000)
        .attr('opacity', '1');

      loners.push(group);
      var index = loners.length - 1;

      group
        .append('circle')
        .attr('fill', '#ccc')
        .attr('cx', function (d, i) {
          return (index * 100) - horizontalOffset;
        })
        .attr('cy', verticalOffset)
        .attr('r', '20')
        .attr('stroke', '#aaa')
        .attr('stroke-width', '0')
        .style('cursor', 'pointer')
        .on('mouseover', function (d) {
          d3.select(this)
            .attr('stroke-width', '2');
          _endNode = d3.select(this).node();
        })
        .on('mouseout', function (d) {
          d3.select(this)
            .attr('stroke-width', '0');
          _endNode = null;
        })
        .on('mousedown', function (d, i) {
          d3.event.stopPropagation();
          _dragging = false;
          _mouseDown = true;
          _arrowSet = false;
          _startNode = d3.select(this).node();
        })
        .on('mouseup', function (d, i) {
          _mouseDown = false;
        });

      // add the value of the node
      group
        .append('text')
        .attr('fill', '#aaa')
        .style('font-size', '20px')
        .attr('x', function (d, i) {
          return (index * 100) - horizontalOffset;
        })
        .attr('y', verticalOffset + 8)
        .attr('text-anchor', 'middle')
        .text(function () {
          return data.value || '_';
        })
        .style('cursor', 'pointer')
        .on('mouseover', function (d) {
          d3.select(this)
            .attr('fill', 'black');

          _endNode = d3.select(this.parentNode)
            .select('circle')
            .node();
        })
        .on('mouseout', function (d) {
          d3.select(this)
            .attr('fill', '#aaa');
        })
        .on('mousedown', function (d, i) {
          d3.event.stopPropagation();
          _dragging = false;
          _mouseDown = true;
          _arrowSet = false;
          _startNode = d3.select(this).node();
        })
        .on('mouseup', function (d) {
          _mouseDown = false;
          if (!_dragging) {
            var elem = d3.select('#edit-node-value')
              .classed('open', true)
              .style('top', d3.event.clientY)
              .style('left', d3.event.clientX);

            _editVal = {
              list: 'loners',
              index: index
            };

            var node = elem.node();

            node.focus();
            node.value = '';
          }
        });

      // center!
      var bbox = lonersElem.node().getBBox();
      lonersElem
        .transition()
        .duration(1000)
        .attr('transform', 'translate(' + (-bbox.width / 2) + ', 0)');
    }
  },

  editValue: {
    label: 'Edit Value',
    operation: function (viewport, data) {
      var group;
      if (data.list === 'loners') {
        group = d3.select('g.loners');
      } else {

      }

      var nodeGroup = group.selectAll('g.node')[0][data.index];
      d3.select(nodeGroup)
        .select('text')
        .text(data.value || '_')
        .transition()
        .duration(1000)
        .attr('fill', '#000')
        .transition()
        .duration(1000)
        .attr('fill', '#aaa');
    }
  }
};

module.exports = React.createClass({

  addNode: function () {
    var elem = d3.select('#initial-value')
      .classed('open', true)
      .style('top', window.innerHeight / 2)
      .style('left', window.innerWidth / 2);

    var node = elem.node();
    node.focus();
    node.value = '';
  },

  reset: function () {
    reset();
  },

  onChangeStep: function () {

  },

  onMouseUp: function (e) {
    _mouseDown = false;
    if (_arrow) _arrow.remove();
  },

  onMouseMove: function (e) {
    if (_mouseDown) {
      _dragging = true;

      if (!_arrowSet) {
        var startBox = _startNode.getBBox();
        var startRect = _startNode.getBoundingClientRect();
        var offsetLeft = (startBox.width / 2) + startRect.left;
        var offsetTop = (startBox.height / 2) + startRect.top;
        _startPoint = new TwoDee.Point(offsetLeft, offsetTop);

        _arrow = d3.select('svg')
          .insert('g', ':first-child')
          .classed('arrow', true);

        _arrow
          .append('line')
          .attr('x1', _startPoint.x)
          .attr('y1', _startPoint.y)
          .attr('x2', _startPoint.x)
          .attr('y2', _startPoint.y)
          .attr('stroke', '#000')
          .attr('stroke-width', '2');

        _arrow
          .append('polygon')
          .attr('points', '0,0 -10,10 10,10')
          .style('opacity', '0');

        _arrowSet = true;
      }

      // update line
      var destX;
      var destY;
      var line = _arrow.select('line');

      if (_endNode) {
        var circle = d3.select(_endNode);
        var circleNode = circle.node();
        var rect = circleNode.getBoundingClientRect();
        var centerX = rect.left + (rect.width / 2);
        var centerY = rect.top + (rect.height / 2);
        var radius = circle.attr('r');
        var circleCenter = new TwoDee.Point(centerX, centerY);
        var circleObj = new TwoDee.Circle(circleCenter, radius);
        var lineObj = new TwoDee.Line.fromPoints(circleCenter, _startPoint);
        var intersectionPoints = lineObj.intersectionWith(circleObj);
        var closestPoint = _startPoint.closest(intersectionPoints);
        destX = closestPoint.x;
        destY = closestPoint.y;
      } else {
        destX = e.clientX;
        destY = e.clientY;
      }

      if (!isNaN(destX)) {
        line
          .attr('x2', destX)
          .attr('y2', destY);

        // update arrow head
        var polygonTranslate = 'translate(' + destX + ',' + destY + ')';
        var lineX = parseInt(line.attr('x1')) - parseInt(line.attr('x2'));
        var lineY = parseInt(line.attr('y1')) - parseInt(line.attr('y2'));
        var rotatorCuff = Math.atan2(-lineX, lineY);
        var rotatorCuffInDegrees = (180 * rotatorCuff) / Math.PI;
        var rotate = rotatorCuffInDegrees;
        var polygonRotate = 'rotate(' + rotate + ')';

        _arrow
          .select('polygon')
          .attr('transform', polygonTranslate + polygonRotate)
          .style('opacity', '1');
      }
    }
  },

  componentDidMount: function () {
    window.addEventListener('mousemove', this.onMouseMove);
    window.addEventListener('mouseup', this.onMouseUp);
  },

  componentWillUnmount: function () {
    window.removeEventListener('mousemove', this.onMouseMove);
    window.removeEventListener('mouseup', this.onMouseUp);
  },

  render: function () {

    var viewerProps = {
      sequence:   this.props,
      structure:  Operations,
      options: [
        { label: '+', action: this.addNode }
      ],
      onChangeStep: this.onChangeStep,
      reset: this.reset
    };

    _sequence = this.props;

    return (
      <div className="singly-linked-list-editor">
        <input className="value-input" id="initial-value" placeholder="Enter initial node value" />
        <input className="value-input" id="edit-node-value" placeholder="Edit node value" />
        <SequenceViewer {...viewerProps} />
      </div>
    );
  }
});<commit_msg>unfinished commit.. :\<commit_after>var React           = require('react/addons');
var SequenceViewer  = require('../../partials/SequenceViewer');
var SequenceActions = require('../../../actions/SequenceActions');
var TwoDee          = require('two-dee');

var loners;       // these are nodes which are not part of lists
var lists;        // this is a list of linked lists.  links go forward in the lists
var _sequence;    // contains the sequence (passed through props)
var _editVal;     // contains details on teh node that is being edited
var _dragging;    // whether the user is moving the mouse around
var _clickedNode; // the node that a user initiated an action on
var _mouseDown = false;
var _arrowSet = false;
var _startNode;
var _startNodeVal;
var _startPoint;
var _endNode;
var _endNodeVal;
var _arrow;

/**
 * initializes the data for the editor
 */
function reset () {
  loners = [];
  lists = [];
  d3.select('g.loners').attr('transform', '');
}

/**
 * updates the sequence
 */
function updateSequence () {
  SequenceActions.update(_sequence);
}

/**
 * adds an operation to the sequence
 */
function addOperation (op) {
  _sequence.operations.push(op);
  updateSequence();
}

/**
 * centers all the groups
 */
function centerGroups () {

  // center!
  d3.selectAll('g.loners, g.list').each(function () {
    var elem = d3.select(this);
    var bbox = elem.node().getBBox();
    elem
      .transition()
      .duration(1000)
      .attr('transform', 'translate(' + (-bbox.width / 2) + ', 0)');
  });
}

var Operations = {
  initialization: {
    label: 'initialization',
    operation: function (viewport, data) {

      reset();

      /**
       * Handler for entry of the initial value field
       */
      function createNode (elem) {
        var d3elem = d3.select(elem);
        if (d3elem.classed('open')) {
          d3elem.classed('open', false);
          addOperation({
            type: 'createNode',
            data: {
              value: elem.value
            }
          });
          elem.value = '';
        }
      }

      /**
       * Handler for actions on the initial value field
       */
      d3.select("#initial-value")
        .on('blur', function () {
          createNode(this);
        })
        .on('keydown', function () {
          if (d3.event.keyCode === 13) {
            createNode(this);
          }
        });

      /**
       * Handler for entry of the edit node field
       */
      function editNode (elem) {
        var d3elem = d3.select(elem);
        if (d3elem.classed('open')) {
          d3elem.classed('open', false);
          _editVal.value = elem.value;
          addOperation({
            type: 'editValue',
            data: _editVal
          });
          elem.value = '';
        }
      }

      /**
       * Handler for actions on the edit node field
       */
      d3.select('#edit-node-value')
        .on('blur', function () {
          editNode(this);
        })
        .on('keydown', function () {
          if (d3.event.keyCode === 13) {
            editNode(this);
          }
        });

      /**
       * Append the loners group
       */
      viewport
        .append('g')
        .classed('loners', true);
    }
  },

  createNode: {
    label: 'Create Node',
    operation: function (viewport, data) {
      var lonersElem = viewport
        .select('g.loners');

      var verticalOffset = 0;
      var horizontalOffset = 0;

      var group = lonersElem
        .append('g');

      group
        .classed('node', true)
        .attr('opacity', '0')
        .transition()
        .duration(1000)
        .attr('opacity', '1');

      loners.push(group);
      var index = loners.length - 1;

      group
        .append('circle')
        .attr('fill', '#ccc')
        .attr('cx', function (d, i) {
          return (index * 100) - horizontalOffset;
        })
        .attr('cy', verticalOffset)
        .attr('r', '20')
        .attr('stroke', '#aaa')
        .attr('stroke-width', '0')
        .style('cursor', 'pointer')
        .on('mouseover', function (d) {
          d3.select(this)
            .attr('stroke-width', '2');
          _endNode = d3.select(this).node();
          _endNodeVal = {
            list: 'loners',
            index: index
          };
        })
        .on('mouseout', function (d) {
          d3.select(this)
            .attr('stroke-width', '0');
          _endNode = null;
        })
        .on('mousedown', function (d, i) {
          d3.event.stopPropagation();
          _dragging = false;
          _mouseDown = true;
          _arrowSet = false;
          _startNode = d3.select(this).node();
          _startNodeVal = {
            list: 'loners',
            index: index
          };
        })
        .on('mouseup', function (d, i) {
          _mouseDown = false;
        });

      // add the value of the node
      group
        .append('text')
        .attr('fill', '#aaa')
        .style('font-size', '20px')
        .attr('x', function (d, i) {
          return (index * 100) - horizontalOffset;
        })
        .attr('y', verticalOffset + 8)
        .attr('text-anchor', 'middle')
        .text(function () {
          return data.value || '_';
        })
        .style('cursor', 'pointer')
        .on('mouseover', function (d) {
          d3.select(this)
            .attr('fill', 'black');

          _endNode = d3.select(this.parentNode)
            .select('circle')
            .node();
          _endNodeVal = {
            list: 'loners',
            index: index
          };
        })
        .on('mouseout', function (d) {
          d3.select(this)
            .attr('fill', '#aaa');
        })
        .on('mousedown', function (d, i) {
          d3.event.stopPropagation();
          _dragging = false;
          _mouseDown = true;
          _arrowSet = false;
          _startNode = d3.select(this).node();
          _startNodeVal = {
            list: 'loners',
            index: index
          };
        })
        .on('mouseup', function (d) {
          _mouseDown = false;
          if (!_dragging) {
            var elem = d3.select('#edit-node-value')
              .classed('open', true)
              .style('top', d3.event.clientY)
              .style('left', d3.event.clientX);

            _editVal = {
              list: 'loners',
              index: index
            };

            var node = elem.node();

            node.focus();
            node.value = '';
          }
        });

        centerGroups();
    }
  },

  editValue: {
    label: 'Edit Value',
    operation: function (viewport, data) {
      var group;
      if (data.list === 'loners') {
        group = d3.select('g.loners');
      } else {

      }

      var nodeGroup = group.selectAll('g.node')[0][data.index];
      d3.select(nodeGroup)
        .select('text')
        .text(data.value || '_')
        .transition()
        .duration(1000)
        .attr('fill', '#000')
        .transition()
        .duration(1000)
        .attr('fill', '#aaa');
    }
  },

  linkNodes: {
    label: 'Create Link',
    operation: function (viewport, data) {
      var prev = data.previous;
      var next = data.next;
      var prevLength;
      var nodes = [];
      var nextLength;

      if (prev.list === 'loners') {
        nodes.push(loners[prev.index]);
      }

      if (next.list === 'loners') {
        nodes.push(loners[next.index]);
      }

      var group = viewport.append('g');
      group.classed('list', 'true');
      lists.push(group);

      var verticalOffset = lists.length * 70;

      nodes.forEach(function (node, index) {

        var currentOffsetLeft = -120;
        var currentOffsetTop = node.select('circle').attr('cy');
        var nextOffsetLeft = index * 100;
        var nextOffsetTop = verticalOffset;
        console.log('current offset left', currentOffsetLeft);
        console.log('next offset left: ', nextOffsetLeft);

        var translateX = nextOffsetLeft - currentOffsetLeft;
        var translateY = nextOffsetTop - currentOffsetTop;
        var transform = 'translate(' + translateX + ',' + translateY + ')';

        node
          .transition()
          .duration(1000)
          .attr('transform', transform)
          .each('end', function () {

            var removed = node.remove();
            removed.attr('transform', '');
            removed.select('circle')
              .attr('cx', nextOffsetLeft)
              .attr('cy', nextOffsetTop);

            removed.select('text')
              .attr('x', nextOffsetLeft)
              .attr('y', nextOffsetTop + 8);

            group.append(function () {
              return removed.node();
            });

            centerGroups();
          });
      });

    }
  }
};

module.exports = React.createClass({

  addNode: function () {
    var elem = d3.select('#initial-value')
      .classed('open', true)
      .style('top', window.innerHeight / 2)
      .style('left', window.innerWidth / 2);

    var node = elem.node();
    node.focus();
    node.value = '';
  },

  reset: function () {
    reset();
  },

  onChangeStep: function () {

  },

  onMouseUp: function (e) {
    _mouseDown = false;
    if (_arrow) _arrow.remove();
    if (_endNode && _startNode != _endNode) {
      addOperation({
        type: 'linkNodes',
        data: {
          previous: _startNodeVal,
          next:     _endNodeVal,
        }
      });
    }
  },

  onMouseMove: function (e) {
    if (_mouseDown) {
      _dragging = true;

      if (!_arrowSet) {
        var startBox = _startNode.getBBox();
        var startRect = _startNode.getBoundingClientRect();
        var offsetLeft = (startBox.width / 2) + startRect.left;
        var offsetTop = (startBox.height / 2) + startRect.top;
        _startPoint = new TwoDee.Point(offsetLeft, offsetTop);

        _arrow = d3.select('svg')
          .insert('g', ':first-child')
          .classed('arrow', true);

        _arrow
          .append('line')
          .attr('x1', _startPoint.x)
          .attr('y1', _startPoint.y)
          .attr('x2', _startPoint.x)
          .attr('y2', _startPoint.y)
          .attr('stroke', '#000')
          .attr('stroke-width', '2');

        _arrow
          .append('polygon')
          .attr('points', '0,0 -10,10 10,10')
          .style('opacity', '0');

        _arrowSet = true;
      }

      // update line
      var destX;
      var destY;
      var line = _arrow.select('line');

      if (_endNode) {
        var circle = d3.select(_endNode);
        var circleNode = circle.node();
        var rect = circleNode.getBoundingClientRect();
        var centerX = rect.left + (rect.width / 2);
        var centerY = rect.top + (rect.height / 2);
        var radius = circle.attr('r');
        var circleCenter = new TwoDee.Point(centerX, centerY);
        var circleObj = new TwoDee.Circle(circleCenter, radius);
        var lineObj = new TwoDee.Line.fromPoints(circleCenter, _startPoint);
        var intersectionPoints = lineObj.intersectionWith(circleObj);
        var closestPoint = _startPoint.closest(intersectionPoints);
        destX = closestPoint.x;
        destY = closestPoint.y;
      } else {
        destX = e.clientX;
        destY = e.clientY;
      }

      if (!isNaN(destX)) {
        line
          .attr('x2', destX)
          .attr('y2', destY);

        // update arrow head
        var polygonTranslate = 'translate(' + destX + ',' + destY + ')';
        var lineX = parseInt(line.attr('x1')) - parseInt(line.attr('x2'));
        var lineY = parseInt(line.attr('y1')) - parseInt(line.attr('y2'));
        var rotatorCuff = Math.atan2(-lineX, lineY);
        var rotatorCuffInDegrees = (180 * rotatorCuff) / Math.PI;
        var rotate = rotatorCuffInDegrees;
        var polygonRotate = 'rotate(' + rotate + ')';

        _arrow
          .select('polygon')
          .attr('transform', polygonTranslate + polygonRotate)
          .style('opacity', '1');
      }
    }
  },

  componentDidMount: function () {
    window.addEventListener('mousemove', this.onMouseMove);
    window.addEventListener('mouseup', this.onMouseUp);
  },

  componentWillUnmount: function () {
    window.removeEventListener('mousemove', this.onMouseMove);
    window.removeEventListener('mouseup', this.onMouseUp);
  },

  render: function () {

    var viewerProps = {
      sequence:   this.props,
      structure:  Operations,
      options: [
        { label: '+', action: this.addNode }
      ],
      onChangeStep: this.onChangeStep,
      reset: this.reset
    };

    _sequence = this.props;

    return (
      <div className="singly-linked-list-editor">
        <input className="value-input" id="initial-value" placeholder="Enter initial node value" />
        <input className="value-input" id="edit-node-value" placeholder="Edit node value" />
        <SequenceViewer {...viewerProps} />
      </div>
    );
  }
});<|endoftext|>


<commit_before>/*
 * "domui" stylesheet properties.
 */
font_family='Verdana, Geneva, "DejaVu Sans", sans-serif';
font_size="11px";
hdr_font_size="14px";

fixed_font_family='Courier New, Courier, monospace';
fixed_font_size="11px";

defaultbutton_height=23;
window_title_font_size='15px';
<commit_msg>Make both style properties equal<commit_after>/*
 * "blue" stylesheet properties.
 */
font_family='Verdana, Geneva, "DejaVu Sans", sans-serif';
//font_family='Verdana, Tahoma, helvetica, sans-serif';
font_size="11px";
hdr_font_size="14px";

fixed_font_family='Courier New, Courier, monospace';
fixed_font_size="11px";

//special_font = "Verdana, Tahoma, helvetica, sans-serif";
special_font = "Arial, Helvetica, sans-serif";
//special_font = "Biolinum2, Courier, serif";
special_font_size = "13px";

button_font_family='Verdana, Geneva, "DejaVu Sans", sans-serif';
button_font_size="11px";

defaultbutton_height=23;
window_title_font_size='15px';
<|endoftext|>


<commit_before>/* @flow */
import { createStyledComponent, pxToEm } from '../../../../../library/styles';
import _Flex from '../../../../../library/Flex';

type Props = {
  gutterWidth?: number | string,
  theme: Object
};

export const containerStyles = ({
  gutterWidth: propGutterSize,
  theme
}: Props) => {
  const gutterWidth = propGutterSize === undefined ? 'md' : propGutterSize;
  const gutter =
    typeof gutterWidth === 'number'
      ? pxToEm(gutterWidth / 2)
      : `${parseFloat(theme[`space_inline_${gutterWidth}`] || gutterWidth) /
          2}em`;
  const offset = gutterWidth ? `calc(${gutter} - 4px)` : -4;

  return {
    position: 'relative',

    '&::before': {
      border: `1px dotted ${theme.color_theme_30}`,
      bottom: -4,
      content: '""',
      left: offset,
      position: 'absolute',
      right: offset,
      top: -4,
      zIndex: -1
    }
  };
};

export default createStyledComponent(_Flex, (props) => ({
  ...containerStyles(props)
}));
<commit_msg>chore(website): Fix display issue with Layout examples<commit_after>/* @flow */
import { createStyledComponent, pxToEm } from '../../../../../library/styles';
import _Flex from '../../../../../library/Flex';

type Props = {
  gutterWidth?: number | string,
  theme: Object
};

export const containerStyles = ({
  gutterWidth: propGutterSize,
  theme
}: Props) => {
  const gutterWidth = propGutterSize === undefined ? 'md' : propGutterSize;
  const gutter =
    typeof gutterWidth === 'number'
      ? pxToEm(gutterWidth / 2)
      : `${parseFloat(theme[`space_inline_${gutterWidth}`] || gutterWidth) /
          2}em`;
  const offset = gutterWidth ? `calc(${gutter} - 4px)` : -4;

  return {
    position: 'relative',
    zIndex: 1,

    '&::before': {
      border: `1px dotted ${theme.color_theme_30}`,
      bottom: -4,
      content: '""',
      left: offset,
      position: 'absolute',
      right: offset,
      top: -4,
      zIndex: -1
    }
  };
};

export default createStyledComponent(_Flex, (props) => ({
  ...containerStyles(props)
}));
<|endoftext|>


<commit_before>/* eslint-disable react/forbid-prop-types */
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { FormControl } from '../FormControl';
import { PageButton } from '../PageButton';
import { FlexRow } from '../FlexRow';
import { JSONForm } from '../JSONForm/JSONForm';
import { NameNoteActions } from '../../actions/Entities/NameNoteActions';
import { selectNameNoteIsValid, selectCreatingNameNote } from '../../selectors/Entities/nameNote';
import { selectCompletedForm } from '../../selectors/form';
import { PatientActions } from '../../actions/PatientActions';
import globalStyles, { SUSSOL_ORANGE } from '../../globalStyles';
import { generalStrings, modalStrings } from '../../localization/index';

export const PatientEditModalComponent = ({
  isDisabled,
  onSaveForm,
  onCancel,
  inputConfig,
  surveySchema,
  surveyForm,
  onUpdateForm,
  nameNoteIsValid,
}) => (
  <FlexRow style={{ flexDirection: 'column' }} flex={1}>
    <FlexRow flex={1}>
      <FormControl
        canSave={surveySchema ? nameNoteIsValid : true}
        isDisabled={isDisabled}
        onSave={onSaveForm}
        onCancel={onCancel}
        inputConfig={inputConfig}
        showCancelButton={false}
        showSaveButton={false}
      />
      {surveySchema && surveyForm && (
        <View style={styles.formContainer}>
          <JSONForm
            surveySchema={surveySchema}
            formData={surveyForm}
            onChange={({ formData }, validator) => {
              onUpdateForm(formData, validator);
            }}
          >
            <></>
          </JSONForm>
        </View>
      )}
    </FlexRow>
    <FlexRow flex={0} style={{ justifyContent: 'center' }}>
      <View style={styles.buttonsRow}>
        <PageButton
          onPress={onSaveForm}
          style={styles.saveButton}
          isDisabled={surveySchema && surveyForm ? !nameNoteIsValid : isDisabled}
          textStyle={styles.saveButtonTextStyle}
          text={generalStrings.save}
        />
        <PageButton
          onPress={onCancel}
          style={styles.cancelButton}
          textStyle={styles.cancelButtonTextStyle}
          text={modalStrings.cancel}
        />
      </View>
    </FlexRow>
  </FlexRow>
);

const styles = StyleSheet.create({
  buttonsRow: { flex: 1, marginTop: 10, flexDirection: 'row-reverse' },
  formContainer: {
    flex: 1,
    backgroundColor: 'white',
  },
  saveButton: {
    ...globalStyles.button,
    flex: 1,
    backgroundColor: SUSSOL_ORANGE,
    alignSelf: 'center',
  },
  saveButtonTextStyle: {
    ...globalStyles.buttonText,
    color: 'white',
    fontSize: 14,
  },
  cancelButton: {
    ...globalStyles.button,
    flex: 1,
    alignSelf: 'center',
  },
  cancelButtonTextStyle: {
    ...globalStyles.buttonText,
    color: SUSSOL_ORANGE,
    fontSize: 14,
  },
});

PatientEditModalComponent.defaultProps = {
  isDisabled: false,
  surveyForm: null,
  surveySchema: null,
  nameNoteIsValid: true,
};

PatientEditModalComponent.propTypes = {
  isDisabled: PropTypes.bool,
  onSaveForm: PropTypes.func.isRequired,
  onCancel: PropTypes.func.isRequired,
  inputConfig: PropTypes.array.isRequired,
  surveyForm: PropTypes.object,
  nameNoteIsValid: PropTypes.bool,
  surveySchema: PropTypes.object,
  onUpdateForm: PropTypes.func.isRequired,
};

const mergeProps = (stateProps, dispatchProps, ownProps) => {
  const { completedForm } = stateProps;
  const { onSave, onSaveSurvey, ...otherDispatchProps } = dispatchProps;
  const { surveySchema } = ownProps;

  const onSaveForm = () => {
    onSave(completedForm);
    if (surveySchema) onSaveSurvey();
  };

  return {
    ...ownProps,
    ...otherDispatchProps,
    ...stateProps,
    onSaveForm,
  };
};

const stateToProps = state => {
  const nameNoteIsValid = selectNameNoteIsValid(state);
  const nameNote = selectCreatingNameNote(state);
  const completedForm = selectCompletedForm(state);

  return { completedForm, nameNoteIsValid, surveyForm: nameNote?.data ?? null };
};

const dispatchToProps = dispatch => ({
  onSaveSurvey: () => dispatch(NameNoteActions.saveEditing()),
  onUpdateForm: (form, validator) => dispatch(NameNoteActions.updateForm(form, validator)),
  onSave: patientDetails => dispatch(PatientActions.patientUpdate(patientDetails)),
});

export const PatientEditModal = connect(
  stateToProps,
  dispatchToProps,
  mergeProps
)(PatientEditModalComponent);
<commit_msg>Add correction to patient edit modal save state<commit_after>/* eslint-disable react/forbid-prop-types */
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { FormControl } from '../FormControl';
import { PageButton } from '../PageButton';
import { FlexRow } from '../FlexRow';
import { JSONForm } from '../JSONForm/JSONForm';
import { NameNoteActions } from '../../actions/Entities/NameNoteActions';
import { selectNameNoteIsValid, selectCreatingNameNote } from '../../selectors/Entities/nameNote';
import { selectCompletedForm, selectCanSaveForm } from '../../selectors/form';
import { PatientActions } from '../../actions/PatientActions';
import globalStyles, { SUSSOL_ORANGE } from '../../globalStyles';
import { generalStrings, modalStrings } from '../../localization/index';

export const PatientEditModalComponent = ({
  isDisabled,
  onSaveForm,
  onCancel,
  inputConfig,
  surveySchema,
  surveyForm,
  onUpdateForm,
  nameNoteIsValid,
  canSaveForm,
}) => {
  let canSave = canSaveForm;
  if (canSave) {
    canSave = surveySchema && surveyForm ? nameNoteIsValid : !isDisabled;
  }

  return (
    <FlexRow style={{ flexDirection: 'column' }} flex={1}>
      <FlexRow flex={1}>
        <FormControl
          canSave={surveySchema ? nameNoteIsValid : true}
          isDisabled={isDisabled}
          onSave={onSaveForm}
          onCancel={onCancel}
          inputConfig={inputConfig}
          showCancelButton={false}
          showSaveButton={false}
        />
        {surveySchema && surveyForm && (
          <View style={styles.formContainer}>
            <JSONForm
              surveySchema={surveySchema}
              formData={surveyForm}
              onChange={({ formData }, validator) => {
                onUpdateForm(formData, validator);
              }}
            >
              <></>
            </JSONForm>
          </View>
        )}
      </FlexRow>
      <FlexRow flex={0} style={{ justifyContent: 'center' }}>
        <View style={styles.buttonsRow}>
          <PageButton
            onPress={onSaveForm}
            style={styles.saveButton}
            isDisabled={!canSave}
            textStyle={styles.saveButtonTextStyle}
            text={generalStrings.save}
          />
          <PageButton
            onPress={onCancel}
            style={styles.cancelButton}
            textStyle={styles.cancelButtonTextStyle}
            text={modalStrings.cancel}
          />
        </View>
      </FlexRow>
    </FlexRow>
  );
};

const styles = StyleSheet.create({
  buttonsRow: { flex: 1, marginTop: 10, flexDirection: 'row-reverse' },
  formContainer: {
    flex: 1,
    backgroundColor: 'white',
  },
  saveButton: {
    ...globalStyles.button,
    flex: 1,
    backgroundColor: SUSSOL_ORANGE,
    alignSelf: 'center',
  },
  saveButtonTextStyle: {
    ...globalStyles.buttonText,
    color: 'white',
    fontSize: 14,
  },
  cancelButton: {
    ...globalStyles.button,
    flex: 1,
    alignSelf: 'center',
  },
  cancelButtonTextStyle: {
    ...globalStyles.buttonText,
    color: SUSSOL_ORANGE,
    fontSize: 14,
  },
});

PatientEditModalComponent.defaultProps = {
  isDisabled: false,
  surveyForm: null,
  surveySchema: null,
  nameNoteIsValid: true,
};

PatientEditModalComponent.propTypes = {
  isDisabled: PropTypes.bool,
  onSaveForm: PropTypes.func.isRequired,
  onCancel: PropTypes.func.isRequired,
  inputConfig: PropTypes.array.isRequired,
  surveyForm: PropTypes.object,
  nameNoteIsValid: PropTypes.bool,
  surveySchema: PropTypes.object,
  onUpdateForm: PropTypes.func.isRequired,
  canSaveForm: PropTypes.bool.isRequired,
};

const mergeProps = (stateProps, dispatchProps, ownProps) => {
  const { completedForm } = stateProps;
  const { onSave, onSaveSurvey, ...otherDispatchProps } = dispatchProps;
  const { surveySchema } = ownProps;

  const onSaveForm = () => {
    onSave(completedForm);
    if (surveySchema) onSaveSurvey();
  };

  return {
    ...ownProps,
    ...otherDispatchProps,
    ...stateProps,
    onSaveForm,
  };
};

const stateToProps = state => {
  const nameNoteIsValid = selectNameNoteIsValid(state);
  const nameNote = selectCreatingNameNote(state);
  const completedForm = selectCompletedForm(state);
  const canSaveForm = selectCanSaveForm(state);

  return { canSaveForm, completedForm, nameNoteIsValid, surveyForm: nameNote?.data ?? null };
};

const dispatchToProps = dispatch => ({
  onSaveSurvey: () => dispatch(NameNoteActions.saveEditing()),
  onUpdateForm: (form, validator) => dispatch(NameNoteActions.updateForm(form, validator)),
  onSave: patientDetails => dispatch(PatientActions.patientUpdate(patientDetails)),
});

export const PatientEditModal = connect(
  stateToProps,
  dispatchToProps,
  mergeProps
)(PatientEditModalComponent);
<|endoftext|>


<commit_before>'use strict';

const CIO = require('customerio-node');

const BlinkRetryError = require('../errors/BlinkRetryError');
const CustomerIoUpdateCustomerMessage = require('../messages/CustomerIoUpdateCustomerMessage');
const logger = require('../../config/logger');
const removePIITransformer = require('../lib/helpers/logger/transformers/remove-pii');
const Worker = require('./Worker');

class CustomerIoUpdateCustomerWorker extends Worker {
  setup() {
    super.setup({
      queue: this.blink.queues.customerIoUpdateCustomerQ,
    });
    // Setup customer.io client.
    this.cioConfig = this.blink.config.customerio;
    this.cioClient = new CIO(this.cioConfig.apiKey, this.cioConfig.siteId);
  }

  async consume(userMessage) {
    let meta;
    let customerIoUpdateCustomerMessage;
    try {
      customerIoUpdateCustomerMessage = CustomerIoUpdateCustomerMessage.fromUser(userMessage);
    } catch (error) {
      meta = {
        env: this.blink.config.app.env,
        code: 'error_cio_update_cant_convert_user',
        worker: this.constructor.name,
        request_id: userMessage ? userMessage.getRequestId() : 'not_parsed',
      };
      logger.warning(
        `Can't convert user to cio customer: ${userMessage.getData().id} error ${error}`,
        { meta },
      );
    }

    const { id, data } = customerIoUpdateCustomerMessage.getData();

    try {
      await this.cioClient.identify(id, data);
    } catch (error) {
      this.log(
        'warning',
        customerIoUpdateCustomerMessage,
        `${error}`,
        'error_cio_update_cant_update_consumer',
      );
      throw new BlinkRetryError(
        `Unknown customer.io error: ${error}`,
        userMessage,
      );
    }

    this.log(
      'debug',
      customerIoUpdateCustomerMessage,
      'Customer.io updated',
      'success_cio_consumer_updated',
    );

    return true;
  }

  log(level, message, text, code = 'unexpected_code') {
    const meta = {
      env: this.blink.config.app.env,
      code,
      worker: this.constructor.name,
      request_id: message ? message.getRequestId() : 'not_parsed',
    };
    // Todo: log error?
    logger.log(level, `${text}, message ${message.toString(removePIITransformer)}`, { meta });
  }
}

module.exports = CustomerIoUpdateCustomerWorker;
<commit_msg>Exposing success_cio_consumer_updated log as info in for monitoring<commit_after>'use strict';

const CIO = require('customerio-node');

const BlinkRetryError = require('../errors/BlinkRetryError');
const CustomerIoUpdateCustomerMessage = require('../messages/CustomerIoUpdateCustomerMessage');
const logger = require('../../config/logger');
const removePIITransformer = require('../lib/helpers/logger/transformers/remove-pii');
const Worker = require('./Worker');

class CustomerIoUpdateCustomerWorker extends Worker {
  setup() {
    super.setup({
      queue: this.blink.queues.customerIoUpdateCustomerQ,
    });
    // Setup customer.io client.
    this.cioConfig = this.blink.config.customerio;
    this.cioClient = new CIO(this.cioConfig.apiKey, this.cioConfig.siteId);
  }

  async consume(userMessage) {
    let meta;
    let customerIoUpdateCustomerMessage;
    try {
      customerIoUpdateCustomerMessage = CustomerIoUpdateCustomerMessage.fromUser(userMessage);
    } catch (error) {
      meta = {
        env: this.blink.config.app.env,
        code: 'error_cio_update_cant_convert_user',
        worker: this.constructor.name,
        request_id: userMessage ? userMessage.getRequestId() : 'not_parsed',
      };
      logger.warning(
        `Can't convert user to cio customer: ${userMessage.getData().id} error ${error}`,
        { meta },
      );
    }

    const { id, data } = customerIoUpdateCustomerMessage.getData();

    try {
      await this.cioClient.identify(id, data);
    } catch (error) {
      this.log(
        'warning',
        customerIoUpdateCustomerMessage,
        `${error}`,
        'error_cio_update_cant_update_consumer',
      );
      throw new BlinkRetryError(
        `Unknown customer.io error: ${error}`,
        userMessage,
      );
    }

    this.log(
      // exposed as info for monitoring
      'info',
      customerIoUpdateCustomerMessage,
      'Customer.io updated',
      'success_cio_consumer_updated',
    );

    return true;
  }

  log(level, message, text, code = 'unexpected_code') {
    const meta = {
      env: this.blink.config.app.env,
      code,
      worker: this.constructor.name,
      request_id: message ? message.getRequestId() : 'not_parsed',
    };
    // Todo: log error?
    logger.log(level, `${text}, message ${message.toString(removePIITransformer)}`, { meta });
  }
}

module.exports = CustomerIoUpdateCustomerWorker;
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * 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.
 */
({
    CONSTANTS: {
    	TAB_DEF : "markup://ui:tab",
    	TAB_ITEM_DEF : "markup://ui:tabItem"
    },
    /**
     * Set tab as active or deactive
     * @param {Component} cmp An instance of ui:tabset componen.
     * @param {Number} index Index position of the tab to activate.
     */
     setActive: function(cmp, option) {
         var active = option.active;
         var index = option.index;
         var tab = option.tab;
         if (typeof active === "undefined") {
             //default to true
             active = true;
         }
         if (!tab) {
             tab = cmp._tabCollection.getTab(index);
         }
         if (tab) {
            // set active tabItem
            var e = cmp.find('tabBar').get('e.setActive');
            e.setParams({"index": index, "active": active}).fire();
            // activate body
            this.setActiveTabBody(cmp, {"index":index, "active": active, "tab": tab});
         }
    },
    /**
     * Add new tab
     * @param {Number} [index] The index of the new tab to insert to.
     * @param {Object} tab The configuration for the new tab. If the "componentDef" is not defined, "ui:tab" is used.
     */
    addTab: function(cmp, index, tab, callback) {
    	var self = this, size = cmp._tabCollection.getSize();
    	if ($A.util.isUndefined(index) || index < 0 || index > size) {
    		index = size;
    	}
    	this.createTabComponent(cmp, tab, function(newTab) {
	    	// insert tab into current tab list
    	    cmp._tabCollection.insertTab(index, newTab);
    		// add tab into tabBar
    	    var active = newTab.get("v.active");
        	var e = cmp.find("tabBar").get("e.addTab");
        	e.setParams({"index": index, "active": active, "tab": self.getTabItemConfig(cmp, newTab)}).fire();
        	if (newTab.get("v.active")) {
        	    this.setActiveTabBody(cmp, {"tab": newTab, "active": true});
        	}
        	if (typeof callback === "function") {
        	    callback({"tab": newTab});
        	}
    	});
    },
    /**
     * Remove tab
     * @param {Component} cmp
     * @param {Integer} index Index position of tab to remove
     */
    removeTab: function(cmp, index) {
        var self = this, e = cmp.find('tabBar').get('e.closeTab');
        var callback = function(succeed) {
            if (succeed) {
                self.removeTabBody(cmp, index);
            }
        }
        e.setParams({"index": index, "callback": callback}).fire();
    },

    /**
     * Returns the active tab
     */
    getActiveTab: function(cmp) {
        return cmp._activeTab;
    },

    /**
     * @private
     */
    getTabIndexFromEvent: function(cmp, evt) {
        var index = evt.getParam("index"), name = evt.getParam("name"), tab = evt.getParam("tab");
       //work around bug where Integer type param passed in as string
        if ($A.util.isString(index)) {
            index = parseInt(index);
        } else if (!$A.util.isNumber(index)) {
            index = cmp._tabCollection.getTabIndex({"name": name, "tab": tab});
        }
        return index;
    },
    /**
     * @private
     */
    setActiveTabBody: function(cmp, option) {
        // set active tab body;
        var tabList = cmp._tabCollection, tab = option.tab, evt,
            activeTab = tabList.getActiveTab();

        if (!tab.isRendered() && option.active) {
            // manually render tab component instead of setting v.body to avoid rerendering of all the tabs
            this.renderTabBody(cmp, tab);
        }
        if (option.active) {
            //deactivate current tabBody
            if (cmp._activeTab && cmp._activeTab.isValid()) {
                evt = cmp._activeTab.get("e.setActive");
                evt.setParams({"active": false}).fire();
                cmp._activeTab = null;
            }
            //fire event to curent tab to update status
            tab.get('e.setActive').setParams({active: true}).fire();
            //save current active tab
            cmp._activeTab = tab;
        } else if (cmp._activeTab === tab){
            //deactivate tab
            tab.get('e.setActive').setParams({active: false}).fire();
            cmp._activeTab = null;
        }
    },
    /**
     * @private
     */
    removeTabBody: function(cmp, index) {
    	cmp._tabCollection.removeTab(index);
    },
    /**
     * Initialize tabs
     * @private
     */
    initTabs: function(cmp) {
        var tabComponents = [], tabIds = [], tabItems = [];
        var tabConfigs = cmp.get("v.tabs");
        cmp._tabCollection = this.createTabCollection();
        if (tabConfigs.length > 0) {
            this.createTabsFromAttribute(cmp, tabConfigs);
        } else {
            //iterate v.body to find instances of ui:tab
            var result = this.getTabsFromBody(cmp);
            cmp._tabCollection.init(result.tabs, result.tabIds, result.tabNames, result.activeIndex);
            cmp.set('v.tabItems', result.tabItemConfigs);
        }
    },

    /**
     * @private
     */
    createTabsFromAttribute: function(cmp, tabConfigs) {
      //construct tabs from pass-in tab objects
        var tabComponents = [], tabIds = [], tabItems = [], tabNames = [], activeIndex = 0,
            lazyRendering = cmp.get("v.lazyRenderTabs"),
            count = tabConfigs.length;

        var callback = function(newTab) {
            var id = newTab.getGlobalId(),
                name = newTab.get("v.name");

            count--;
            tabIds.push(id);
            tabComponents[id] = newTab;
            tabItems.push(this.getTabItemConfig(cmp, newTab));
            if (name) {
                tabNames[name] = {"tabId": id};
            }
            if (count === 0) {
                cmp._tabCollection.init(tabComponents, tabIds, tabNames, activeIndex);
                cmp.set('v.tabItems', tabItems);
                if (!lazyRendering) {
                    cmp.set('v.body', tabComponents);
                }
            }
        }
        for (var i=0; i<tabConfigs.length; i++) {
            this.createTabComponent(cmp, tabConfigs[i], callback);
        }
    },
    /**
     * @private
     */
    getTabsFromBody: function(cmp) {
    	var tabCmps = [], tabs = [], tabIds = [], tabItemConfigs =[], tabNames = [],
    	    //default active tab to first tab
    	    activeTab = 0;

    	// get all instances of ui:tab in the body
    	tabCmps = this.getTabComponents(cmp.get('v.body'));
    	for (var i=0, len=tabCmps.length; i<len; i++) {
    		var tab = tabCmps[i],
    		    id = tab.getGlobalId(),
    		    name = tab.get("v.name");

    		if (tab.get('v.active')) {
    			activeTab = i;
    		}
    		if (name) {
    		    tabNames[name] = {"tabId": id, "index": i};
    		}
    		tabIds.push(id);
    		tabItemConfigs.push(this.getTabItemConfig(cmp, tab));
    		tabs[id] = tab;
    	}

    	return {"tabs": tabs, "tabIds": tabIds, "activeIndex": activeTab, "tabItemConfigs": tabItemConfigs, "tabNames": tabNames};
    },
    /**
     * @private
     */
    createTabComponent: function(cmp, tabConfig, callback, async) {
        var cd, config;
        if (!$A.util.isObject(tabConfig)) {
            return;
        }
        if (tabConfig.componentDef) {
            cd = tabConfig.componentDef;
            delete tabConfig.componentDef;
        } else {
            cd = this.CONSTANTS.TAB_DEF;
        }
        if (!tabConfig.body) {
            tabConfig.body = [];
        }
        config = {"componentDef": cd, attributes: {values: tabConfig}};
        $A.componentService.newComponentAsync(this, callback, config);
    },
    /**
     * @private
     * Get configurations for ui:tabbar to construct tabItems
     * @param {Object} tab ui:tab component
     */
    getTabItemConfig: function(cmp, tab) {
    	var self = this, config={}, values = {},
    		compService = $A.componentService,
    		tabItemDef = this.CONSTANTS.TAB_ITEM_DEF;

    		// Iterate all the attributes ui:tabItem and find the values in ui:tab component
    		var attrDefs = compService.getDef(tabItemDef).getAttributeDefs();
    		attrDefs.each(function(def){
    			var name = def.getDescriptor().getName();
    			//don't want to pass the body to tabItems
    			if (name != "body") {
    			    values[name] = self.findValue(tab, "v." + name);
    			}
    		});
    		values["ariaControlId"] = tab.getGlobalId();
    		config["attributes"] = {"values": values};
    		config["componentDef"] = tabItemDef;

    	return config;
    },
    /**
     * Find the attribute value in the given component
     * @private
     */
    findValue: function(cmp, expression) {
	    var zuper = cmp , value = null;
	    while(zuper){
	        value = zuper.get(expression);
	        if(!$A.util.isEmpty(value)) {
	            return value;
	        }
	        zuper = zuper.getSuper();
	    }
	    return value;
    },
    /**
     * @private
     */
    getTabComponents: function(body) {
        var desc = "ui:tab";
        var ret = [];
        for(var i=0;i<body.length;i++) {
            var c = body[i];
            if (c.isInstanceOf(desc)) {
                ret.push(c);
            } else if (c.isInstanceOf("aura:iteration")) {
                ret = ret.concat(this.getTabComponents(c.get('v.realBody')));
            } else {
                var result = c.find({instancesOf: desc});
                //In some use cases, only parent component contains instances of ui:tab or subclass of ui:tab
                //need to manually traverse to the top and find them
                var s = c.getSuper();
                if ($A.util.isEmpty(result) && s) {
                    do {
                        result = s.find({instancesOf: desc});
                        s = s.getSuper();
                    } while (s && !s.isInstanceOf(desc) && $A.util.isEmpty(result))
                }
                ret = ret.concat(result);
            }
        }
        return ret;
    },
    /**
     * Render tab component to tabContainer
     * @private
     */
    renderTabBody: function(cmp, tabComponent) {
    	var container = cmp.find("tabContainer").getElement(),
    		docFrag = document.createDocumentFragment();

    	$A.render(tabComponent, docFrag);
		$A.afterRender(tabComponent);
		container.appendChild(docFrag);
     },
     /**
     * Clean up
     * @private
     */
     unrender: function(cmp) {
    	 cmp._tabCollection.destroy();
    	 delete cmp._tabCollection;
     },
     /**
      * Returns an object that wraps the a collection of tabs.
      * @private
      */
     createTabCollection: function() {
         var TabCollection = function(){
             this.tabComponents = [];
             this.tabIds = [];
             this.tabNames = [];
             this.activeIndex = 0;
         };
         TabCollection.prototype = {
             init: function(tabs, tabIds, tabNames, activeIndex) {
                 this.tabComponents = tabs;
                 this.tabIds = tabIds;
                 this.tabNames = tabNames;
                 this.activeIndex = activeIndex;
             },
             getTabIndex: function(option) {
                 var index = -1;
                 if (option.name) {
                     var name = this.tabNames[option.name];
                     if (name) {
                         index = $A.util.arrayIndexOf(this.tabIds, name.tabId);
                     }
                 } else if ($A.util.isComponent(option.tab)) {
                     var gId = option.tab.getGlobalId();
                     if (this.tabComponents[gId]) {
                         index = this.tabComponents[gId].index;
                     }
                 }
                 return index;
             },
             getTab: function(index){
                 var tab = null;
                 if (index >= 0  && index < this.getSize()) {
                     tab = this.tabComponents[this.tabIds[index]];
                 }
                 return tab;
             },
             removeTab: function(index) {
                 var total = this.tabIds.length;
                 if ($A.util.isNumber(index) && index >=0 && index < this.tabIds.length) {
                     var id = this.tabIds.splice(index, 1);
                     var tab = this.tabComponents[id[0]];
                     tab.destroy(true);
                 }
             },
             insertTab: function(index, tab) {
                 if ($A.util.isComponent(tab)) {
                     var id = tab.getGlobalId(),
                         name = tab.get("v.name");

                     if (name) {
                         this.tabNames[name] = {"tabId": id};
                     }
                     this.tabIds.splice(index, 0, id);
                     this.tabComponents[id] = tab;
                     if (tab.get("v.active")) {
                         this.activeIndex = index;
                     }
                 }
             },
             setActiveTabIndex: function(index) {
                 this.activeTabIndex = index;
             },
             getActiveTabIndex: function() {
                 return this.activeIndex;
             },
             getActiveTab: function() {
                 return this.tabIds[this.activeIndex];
             },
             getSize: function() {
                 return this.tabIds.length;
             },
             destroy: function() {
                 var tabs = this.tabComponents;
                 for (var id in tabs) {
                     if (tabs.hasOwnProperty(id)) {
                         tabs[id].destroy(true);
                     }
                 }
                 this.tabIds = null;
                 this.tabComponents = null;
             }
         }
         return new TabCollection();
     }
})
<commit_msg>Fix issue where auradocs source tab not showing up<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * 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.
 */
({
    CONSTANTS: {
    	TAB_DEF : "markup://ui:tab",
    	TAB_ITEM_DEF : "markup://ui:tabItem"
    },
    /**
     * Set tab as active or deactive
     * @param {Component} cmp An instance of ui:tabset componen.
     * @param {Number} index Index position of the tab to activate.
     */
     setActive: function(cmp, option) {
         var active = option.active;
         var index = option.index;
         var tab = option.tab;
         if (typeof active === "undefined") {
             //default to true
             active = true;
         }
         if (!tab) {
             tab = cmp._tabCollection.getTab(index);
         }
         if (tab) {
            // set active tabItem
            var e = cmp.find('tabBar').get('e.setActive');
            e.setParams({"index": index, "active": active}).fire();
            // activate body
            this.setActiveTabBody(cmp, {"index":index, "active": active, "tab": tab});
         }
    },
    /**
     * Add new tab
     * @param {Number} [index] The index of the new tab to insert to.
     * @param {Object} tab The configuration for the new tab. If the "componentDef" is not defined, "ui:tab" is used.
     */
    addTab: function(cmp, index, tab, callback) {
    	var self = this, size = cmp._tabCollection.getSize();
    	if ($A.util.isUndefined(index) || index < 0 || index > size) {
    		index = size;
    	}
    	this.createTabComponent(cmp, tab, function(newTab) {
	    	// insert tab into current tab list
    	    cmp._tabCollection.insertTab(index, newTab);
    		// add tab into tabBar
    	    var active = newTab.get("v.active");
        	var e = cmp.find("tabBar").get("e.addTab");
        	e.setParams({"index": index, "active": active, "tab": self.getTabItemConfig(cmp, newTab)}).fire();
        	if (newTab.get("v.active")) {
        	    this.setActiveTabBody(cmp, {"tab": newTab, "active": true});
        	}
        	if (typeof callback === "function") {
        	    callback({"tab": newTab});
        	}
    	});
    },
    /**
     * Remove tab
     * @param {Component} cmp
     * @param {Integer} index Index position of tab to remove
     */
    removeTab: function(cmp, index) {
        var self = this, e = cmp.find('tabBar').get('e.closeTab');
        var callback = function(succeed) {
            if (succeed) {
                self.removeTabBody(cmp, index);
            }
        }
        e.setParams({"index": index, "callback": callback}).fire();
    },

    /**
     * Returns the active tab
     */
    getActiveTab: function(cmp) {
        return cmp._activeTab;
    },

    /**
     * @private
     */
    getTabIndexFromEvent: function(cmp, evt) {
        var index = evt.getParam("index"), name = evt.getParam("name"), tab = evt.getParam("tab");
       //work around bug where Integer type param passed in as string
        if ($A.util.isString(index)) {
            index = parseInt(index);
        } else if (!$A.util.isNumber(index)) {
            index = cmp._tabCollection.getTabIndex({"name": name, "tab": tab});
        }
        return index;
    },
    /**
     * @private
     */
    setActiveTabBody: function(cmp, option) {
        // set active tab body;
        var tabList = cmp._tabCollection, tab = option.tab, evt,
            activeTab = tabList.getActiveTab();

        if (!tab.isRendered() && option.active) {
            // manually render tab component instead of setting v.body to avoid rerendering of all the tabs
            this.renderTabBody(cmp, tab);
        }
        if (option.active) {
            //deactivate current tabBody
            if (cmp._activeTab && cmp._activeTab.isValid()) {
                evt = cmp._activeTab.get("e.setActive");
                evt.setParams({"active": false}).fire();
                cmp._activeTab = null;
            }
            //fire event to curent tab to update status
            tab.get('e.setActive').setParams({active: true}).fire();
            //save current active tab
            cmp._activeTab = tab;
        } else if (cmp._activeTab === tab){
            //deactivate tab
            tab.get('e.setActive').setParams({active: false}).fire();
            cmp._activeTab = null;
        }
    },
    /**
     * @private
     */
    removeTabBody: function(cmp, index) {
    	cmp._tabCollection.removeTab(index);
    },
    /**
     * Initialize tabs
     * @private
     */
    initTabs: function(cmp) {
        var tabComponents = [], tabIds = [], tabItems = [];
        var tabConfigs = cmp.get("v.tabs");
        cmp._tabCollection = this.createTabCollection();
        if (tabConfigs.length > 0) {
            this.createTabsFromAttribute(cmp, tabConfigs);
        } else {
            //iterate v.body to find instances of ui:tab
            var result = this.getTabsFromBody(cmp);
            cmp._tabCollection.init(result.tabs, result.tabIds, result.tabNames, result.activeIndex);
            cmp.set('v.tabItems', result.tabItemConfigs);
        }
    },

    /**
     * @private
     */
    createTabsFromAttribute: function(cmp, tabConfigs) {
      //construct tabs from pass-in tab objects
        var tabComponents = [], tabIds = [], tabItems = [], tabNames = [], activeIndex = 0,
            lazyRendering = cmp.get("v.lazyRenderTabs"),
            count = tabConfigs.length;

        var callback = function(newTab) {
            var id = newTab.getGlobalId(),
                name = newTab.get("v.name");

            count--;
            tabIds.push(id);
            tabComponents[id] = newTab;
            tabItems.push(this.getTabItemConfig(cmp, newTab));
            if (name) {
                tabNames[name] = {"tabId": id};
            }
            if (count === 0) {
                cmp._tabCollection.init(tabComponents, tabIds, tabNames, activeIndex);
                cmp.set('v.tabItems', tabItems);
                if (!lazyRendering) {
                    cmp.set('v.body', tabComponents);
                }
            }
        }
        for (var i=0; i<tabConfigs.length; i++) {
            this.createTabComponent(cmp, tabConfigs[i], callback);
        }
    },
    /**
     * @private
     */
    getTabsFromBody: function(cmp) {
    	var tabCmps = [], tabs = [], tabIds = [], tabItemConfigs =[], tabNames = [],
    	    //default active tab to first tab
    	    activeTab = 0;

    	// get all instances of ui:tab in the body
    	tabCmps = this.getTabComponents(cmp.get('v.body'));
    	for (var i=0, len=tabCmps.length; i<len; i++) {
    		var tab = tabCmps[i],
    		    id = tab.getGlobalId(),
    		    name = tab.get("v.name");

    		if (tab.get('v.active')) {
    			activeTab = i;
    		}
    		if (name) {
    		    tabNames[name] = {"tabId": id, "index": i};
    		}
    		tabIds.push(id);
    		tabItemConfigs.push(this.getTabItemConfig(cmp, tab));
    		tabs[id] = tab;
    	}

    	return {"tabs": tabs, "tabIds": tabIds, "activeIndex": activeTab, "tabItemConfigs": tabItemConfigs, "tabNames": tabNames};
    },
    /**
     * @private
     */
    createTabComponent: function(cmp, tabConfig, callback, async) {
        var cd, config;
        if (!$A.util.isObject(tabConfig)) {
            return;
        }
        if (tabConfig.componentDef) {
            cd = tabConfig.componentDef;
            delete tabConfig.componentDef;
        } else {
            cd = this.CONSTANTS.TAB_DEF;
        }
        if (!tabConfig.body) {
            tabConfig.body = [];
        }
        config = {"componentDef": cd, attributes: {values: tabConfig}};
        $A.componentService.newComponentAsync(this, callback, config);
    },
    /**
     * @private
     * Get configurations for ui:tabbar to construct tabItems
     * @param {Object} tab ui:tab component
     */
    getTabItemConfig: function(cmp, tab) {
    	var self = this, config={}, values = {},
    		compService = $A.componentService,
    		tabItemDef = this.CONSTANTS.TAB_ITEM_DEF;

    		// Iterate all the attributes ui:tabItem and find the values in ui:tab component
    		var attrDefs = compService.getDef(tabItemDef).getAttributeDefs();
    		attrDefs.each(function(def){
    			var name = def.getDescriptor().getName();
    			//don't want to pass the body to tabItems
    			if (name != "body") {
    			    values[name] = self.findValue(tab, "v." + name);
    			}
    		});
    		values["ariaControlId"] = tab.getGlobalId();
    		config["attributes"] = {"values": values};
    		config["componentDef"] = tabItemDef;

    	return config;
    },
    /**
     * Find the attribute value in the given component
     * @private
     */
    findValue: function(cmp, expression) {
	    var zuper = cmp , value = null;
	    while(zuper){
	        value = zuper.get(expression);
	        if(!$A.util.isEmpty(value)) {
	            return value;
	        }
	        zuper = zuper.getSuper();
	    }
	    return value;
    },
    /**
     * @private
     */
    getTabComponents: function(body) {
        var type = "ui:tab";
        var ret = [];
        for(var i=0;i<body.length;i++) {
            var c = body[i];
            if (c.isInstanceOf("aura:iteration")) {
                ret = ret.concat(this.getTabComponents(c.get('v.realBody')));
            } else {
                var inst = this._getTabComponent(c, type);
                if (inst) {
                    ret.push(inst);
                } else {
                    ret = ret.concat(this.getTabComponents(this._getSuperest(c).get('v.body')));
                }
            }
        }
        return ret;
    },
    _getTabComponent: function(cmp, type) {
        if (cmp.isInstanceOf(type)) {
            return cmp;
        } else {
            var s = cmp.getSuper();
            if (s) {
                return this._getTabComponent(s, type);
            } else {
                return null;
            }
        }
    },
    _getSuperest: function(cmp) {
        var s = cmp.getSuper();
        if (s) {
            var ancestor = this._getSuperest(s);
            if (ancestor) {
                return ancestor;
            }
            return s;
        } else {
            return cmp;
        }
    },
    /**
     * Render tab component to tabContainer
     * @private
     */
    renderTabBody: function(cmp, tabComponent) {
    	var container = cmp.find("tabContainer").getElement(),
    		docFrag = document.createDocumentFragment();

    	$A.render(tabComponent, docFrag);
		$A.afterRender(tabComponent);
		container.appendChild(docFrag);
     },
     /**
     * Clean up
     * @private
     */
     unrender: function(cmp) {
    	 cmp._tabCollection.destroy();
    	 delete cmp._tabCollection;
     },
     /**
      * Returns an object that wraps the a collection of tabs.
      * @private
      */
     createTabCollection: function() {
         var TabCollection = function(){
             this.tabComponents = [];
             this.tabIds = [];
             this.tabNames = [];
             this.activeIndex = 0;
         };
         TabCollection.prototype = {
             init: function(tabs, tabIds, tabNames, activeIndex) {
                 this.tabComponents = tabs;
                 this.tabIds = tabIds;
                 this.tabNames = tabNames;
                 this.activeIndex = activeIndex;
             },
             getTabIndex: function(option) {
                 var index = -1;
                 if (option.name) {
                     var name = this.tabNames[option.name];
                     if (name) {
                         index = $A.util.arrayIndexOf(this.tabIds, name.tabId);
                     }
                 } else if ($A.util.isComponent(option.tab)) {
                     var gId = option.tab.getGlobalId();
                     if (this.tabComponents[gId]) {
                         index = this.tabComponents[gId].index;
                     }
                 }
                 return index;
             },
             getTab: function(index){
                 var tab = null;
                 if (index >= 0  && index < this.getSize()) {
                     tab = this.tabComponents[this.tabIds[index]];
                 }
                 return tab;
             },
             removeTab: function(index) {
                 var total = this.tabIds.length;
                 if ($A.util.isNumber(index) && index >=0 && index < this.tabIds.length) {
                     var id = this.tabIds.splice(index, 1);
                     var tab = this.tabComponents[id[0]];
                     tab.destroy(true);
                 }
             },
             insertTab: function(index, tab) {
                 if ($A.util.isComponent(tab)) {
                     var id = tab.getGlobalId(),
                         name = tab.get("v.name");

                     if (name) {
                         this.tabNames[name] = {"tabId": id};
                     }
                     this.tabIds.splice(index, 0, id);
                     this.tabComponents[id] = tab;
                     if (tab.get("v.active")) {
                         this.activeIndex = index;
                     }
                 }
             },
             setActiveTabIndex: function(index) {
                 this.activeTabIndex = index;
             },
             getActiveTabIndex: function() {
                 return this.activeIndex;
             },
             getActiveTab: function() {
                 return this.tabIds[this.activeIndex];
             },
             getSize: function() {
                 return this.tabIds.length;
             },
             destroy: function() {
                 var tabs = this.tabComponents;
                 for (var id in tabs) {
                     if (tabs.hasOwnProperty(id)) {
                         tabs[id].destroy(true);
                     }
                 }
                 this.tabIds = null;
                 this.tabComponents = null;
             }
         }
         return new TabCollection();
     }
})
<|endoftext|>


<commit_before>$(function () {
    var params = {'data_type': '23andme_names'};

    $.ajax({
        'type': 'GET',
        'url': '/json-data/',
        'data': params,
        'success': function(data) {
            if (data.profiles && data.profiles.length > 0) {
                for (var i = 0; i < data.profiles.length; i++) {
                    var radioElem = $('<input />');
                    radioElem.attr({'type' : 'radio',
                                     'name' : 'profile_id',
                                     'value' : data.profiles[i].id});
                    if (data.profiles.length == 1) {
                        radioElem.attr('checked', true);
                    }
                    var labelElem = $('');
                    labelElem.append(radioElem);
                    labelElem.append(data.profiles[i].first_name + ' ' +
                                      data.profiles[i].last_name);
                    var divElem = $('

');
                    divElem.attr('class', 'radio');
                    divElem.append(labelElem);
                    $("#23andme-list-profiles").append(divElem);
                }
                $("#load-23andme-waiting").hide();
                $("#23andme-complete-submit").css('visibility', 'visible');
            }
        }
    });
});
<commit_msg>Fix JS to use 2-space tabs<commit_after>$(function () {
  var params = {'data_type': '23andme_names'};

  $.ajax({
    'type': 'GET',
    'url': '/json-data/',
    'data': params,
    'success': function(data) {
      if (data.profiles && data.profiles.length > 0) {
        for (var i = 0; i < data.profiles.length; i++) {
          var radioElem = $('<input />');
          radioElem.attr({'type' : 'radio',
                          'name' : 'profile_id',
                          'value' : data.profiles[i].id});
          if (data.profiles.length == 1) {
            radioElem.attr('checked', true);
          }
          var labelElem = $('');
          labelElem.append(radioElem);
          labelElem.append(data.profiles[i].first_name + ' ' +
                           data.profiles[i].last_name);
          var divElem = $('

');
          divElem.attr('class', 'radio');
          divElem.append(labelElem);
          $("#23andme-list-profiles").append(divElem);
        }
        $("#load-23andme-waiting").hide();
        $("#23andme-complete-submit").css('visibility', 'visible');
      }
    }
  });
});
<|endoftext|>