<commit_before>function Croaker(env) {
  var deps = env || {},
    $ = deps.jQuery || jQuery,
    mywindow = deps.window || window,
    MISSING_METRIC_VALUE = -99999,
    maintainabilityIndex,
    cyclomaticComplexity,
    classCoupling,
    depthOfInheritance,
    linesOfCode,
    allDefinitions,
    strains;

  function FatalException(message) {
    return {
      name: 'FatalException',
      message: message
    };
  }

  function NodeEntry(name, attributes, children) {
    return {
      name: name,
      attributes: attributes,
      children: children
    };
  }

  function MetricDefinition(abrev, name) {
    return {
      name:name,
      abbreviation:abrev
    };
  }

  maintainabilityIndex = new MetricDefinition('MI', 'MaintainabilityIndex');
  cyclomaticComplexity = new MetricDefinition('CyC', 'CyclomaticComplexity');
  classCoupling = new MetricDefinition('CC', 'ClassCoupling');
  linesOfCode = new MetricDefinition('LC', 'LinesOfCode');
  depthOfInheritance = new MetricDefinition('DI', 'DepthOfInheritance');

  allDefinitions = [maintainabilityIndex, cyclomaticComplexity, classCoupling, depthOfInheritance, linesOfCode];

  function Parser() {
    var that = {};

    function isNodeValid(node) {
      return node.nodeType === 1 || node.nodeType === 2;
    }

    function parseAttributes(node) {
      var attributes = {}, x;

      for (x = 0; x < node.attributes.length; x++) {
        if(isNodeValid(node.attributes.item(x))) {
          attributes[node.attributes.item(x).name] = node.attributes.item(x).value;
        }
      }

      return attributes;
    }

    function parseChildNodes(processor, node) {
      var children = [], x;

      if (node.hasChildNodes()) {
        for (x = 0; x < node.childNodes.length; x++) {
          if (isNodeValid(node.childNodes.item(x))) {
            children.push(processor(node.childNodes.item(x)));
          }
        }
      }
      return children;
    }

    function processNode(node) {
      return new NodeEntry(node.nodeName, parseAttributes(node), parseChildNodes(processNode, node));
    }

    function validateDoc(doc) {
      if (!doc.documentElement) {
        throw new FatalException('unable to parse xml');
      }

      if (doc.documentElement.innerHTML) {
        throw new FatalException('unable to parse xml');
      }

      if (doc.documentElement.nodeName === 'parsererror') {
        throw new FatalException('unable to parse xml');
      }
    }

    function parse(string) {
      var domparser, xmldoc;

      if (window.DOMParser) {
        try {
        domparser = new DOMParser();
        xmldoc = domparser.parseFromString(string, "text/xml");
        } catch(e) {
          throw new FatalException('unable to parse xml');
        }
      }
      else {
        xmldoc=new ActiveXObject("Microsoft.XMLDOM");
        xmldoc.async=false;
        xmldoc.loadXML(string);
      }

      validateDoc(xmldoc);
      return processNode(xmldoc.documentElement);
    }

    that.parse = parse;
    return that;
  }

  function BaseNamed(name) {
    return {
      name: name
    };
  }

  function Metric(name, value) {
    var that = new BaseNamed(name);

    function getFormattedValue() {
      return (value === -99999) ? '' : value.toString();
    }

    that.value = value;
    that.getFormattedValue = getFormattedValue;

    return that;
  }

  function BaseMetrics (name, metrics) {
    var that = new BaseNamed(name);

    function getFullMetrics() {
      var x, y, results = [], found;

      for (x=0; x < allDefinitions.length; x++) {
        found = false;

        for (y=0; y < metrics.length; y++) {
          if(metrics[y].name === allDefinitions[x].name) {
            results.push(metrics[y]);
            found = true;
          }
        }

        if (found === false) {
          results.push(new Metric(allDefinitions[x].name, MISSING_METRIC_VALUE));
        }
      }

      return results;
    }

    that.metrics = metrics;
    that.getFullMetrics = getFullMetrics;

    return that;
  }

  function Member(name, file, line, metrics) {
    var that = new BaseMetrics(name, metrics);

    that.strain = 'MB';
    that.file = file;
    that.line = line;

    return that;
  }

  function Type (name,members,metrics) {
    var that = new BaseMetrics(name, metrics);

    that.strain = 'TY';
    that.members = members;

    return that;
  }

  function Namespace(name, types, metrics) {
    var that = new BaseMetrics(name, metrics);

    that.strain = 'NS';
    that.types = types;

    return that;
  }

  function Module(name, version, metrics, namespaces) {
    var that = new BaseMetrics(name, metrics);

    that.strain = 'MD';
    that.version = version;
    that.namespaces = namespaces;

    return that;
  }

  function Mapper() {
    var that = {};

    function formMetric(startingNodeChild) {
      var x, val = startingNodeChild.attributes.Value;

      for (x=0; x < val.length; x++) {
        val = val.replace(',','');
      }

      return new Metric(startingNodeChild.attributes.Name,
                        parseInt(val, 10));
    }

    function formMetrics(startingNode, index) {
       var x, metrics = [], metricsNode = startingNode.children[index];

       for (x=0; x < metricsNode.children.length; x++) {
         metrics.push(formMetric(metricsNode.children[x]));
       }

       return metrics;
     }

    function formMember(startingNode) {

      return new Member(startingNode.attributes.Name,
                        startingNode.attributes.File,
                        startingNode.attributes.Line,
                        formMetrics(startingNode, 0)
      );
    }

    function formType(startingNode) {
      var x,  membersNode = startingNode.children[1], membersArray = [];

      for (x=0; x < membersNode.children.length; x++) {
        membersArray.push(formMember(membersNode.children[x]));
      }

      return new Type(startingNode.attributes.Name,
                      membersArray,
                      formMetrics(startingNode, 0)
                 );
    }

    function formNamespace(startingNode) {
      var typesNode = startingNode.children[1], x, typesArray = [];

        for (x=0; x < typesNode.children.length; x++) {
          typesArray.push(formType(typesNode.children[x]));
        }

       return new Namespace(startingNode.attributes.Name,
                            typesArray,
                            formMetrics(startingNode, 0)
       );
    }

    function map(entryNode) {
      var moduleNode = entryNode.children[0].children[0].children[0].children[0],
        namespacesNode = moduleNode.children[1], nsArray = [], x;

        for (x=0; x < namespacesNode.children.length; x++) {
          nsArray.push(formNamespace(namespacesNode.children[x]));
        }

      return new Module(moduleNode.attributes.Name,
                   moduleNode.attributes.AssemblyVersion,
                   formMetrics(moduleNode,0),
                   nsArray
      );
    }

    that.map = map;
    return that;
  }

  function DataLoader(url, callback) {
    function execute() {
      return $.get(url, callback, 'text');
    }

    return {
      execute: execute
    };
  }

  function LocationUrlParser() {
    function validateUrl(url) {
      if (!url || url.length <= 1) {
        throw new FatalException('no path argument provided');
      }
    }

    function parse() {
      var url = mywindow.location.search;
      validateUrl(url);
      return url.substring(1).split('=')[1];
    }

    return {
      parse: parse
    };
  }

  function OrFilter(filterArray) {
    var that = {};

    function filter(element) {
      var x;

      if (filterArray.length === 0) {
        return true;
      }

      for (x=0; x < filterArray.length; x++) {
        if (filterArray[x].filter(element)) {
          return true;
        }
      }
      return false;
    }

    that.filter = filter;

    return that;
  }

  function AndFilter(filters) {
    var that = {};

    function filter(element) {
      var x;

      for (x=0; x < filters.length; x++) {
        if (!filters[x].filter(element)) {
          return false;
        }
      }
      return true;
    }

    that.filter = filter;
    return that;
  }

  function FilteredList(module) {
    var that = {}, filters = [], accepted = [], elements = [], emptyFilter = false,
      x, y, z, temp, actualAccepted = [], nameFilter = [];

    elements.push(module);

    for (x=0; x < module.namespaces.length; x++) {
      temp = module.namespaces[x];
      elements.push(temp);

      for (y=0; y < temp.types.length; y++) {
        elements.push(temp.types[y]);

        for (z=0; z < temp.types[y].members.length; z++) {
          elements.push(temp.types[y].members[z]);
        }
      }
    }

    function addFilter(newFilter) {
      emptyFilter = false;
      filters.push(newFilter);
    }

    function getFilters() {
      return filters;
    }

    function getAccepted() {
      if (emptyFilter) {
        return elements;
      }
      //remove this check ^
      return actualAccepted;
    }

    function clearFilters() {
      filters = [];
      accepted = [];
      actualAccepted = [];
      nameFilter = [];
      emptyFilter = true;
    }

    function applyFilters(filters) {
      var y, andFilter = new AndFilter(filters);

      for (y=0; y < elements.length; y++) {
        if (andFilter.filter(elements[y])) {
          actualAccepted.push(elements[y]);
        }
      }
    }

    that.getAccepted = getAccepted;
    that.applyFilters = applyFilters;
    that.clearFilters = clearFilters;
    that.addFilter = addFilter;
    that.getFilters = getFilters;
    that.applyFilters = applyFilters;

    return that;
  }

  function StrainFilter(lookFor) {
    var that = {};

    function filter(node) {
      return (node.strain === lookFor);
    }

    function isNameFilter() {
      return false;
    }

    that.isNameFilter = isNameFilter;
    that.filter = filter;

    return that;
  }

  function NameFilter(searchFor) {
    var that = {};
    searchFor = searchFor.toLowerCase();

    function filter(compareTo) {
      compareTo = compareTo.name.toLowerCase();
      return (compareTo.indexOf(searchFor) !== -1);
    }

   function isNameFilter() {
      return true;
    }

    that.isNameFilter = isNameFilter;
    that.filter = filter;

    return that;
  }

  return {
    NodeEntry: NodeEntry,
    Parser: Parser,
    Metric: Metric,
    Member: Member,
    Type: Type,
    Namespace: Namespace,
    Module: Module,
    Mapper: Mapper,
    DataLoader: DataLoader,
    LocationUrlParser: LocationUrlParser,
    MISSING_METRIC_VALUE: MISSING_METRIC_VALUE,
    MetricDefinition: MetricDefinition,
    maintainabilityIndex: maintainabilityIndex,
    cyclomaticComplexity: cyclomaticComplexity,
    classCoupling: classCoupling,
    depthOfInheritance: depthOfInheritance,
    linesOfCode: linesOfCode,
    allDefinitions: allDefinitions,
    FilteredList:FilteredList,
    strains: strains,
    StrainFilter: StrainFilter,
    NameFilter: NameFilter,
    AndFilter: AndFilter,
    OrFilter: OrFilter
  };
}

var croaker = new Croaker();<commit_msg>removed add filter functiohn<commit_after>function Croaker(env) {
  var deps = env || {},
    $ = deps.jQuery || jQuery,
    mywindow = deps.window || window,
    MISSING_METRIC_VALUE = -99999,
    maintainabilityIndex,
    cyclomaticComplexity,
    classCoupling,
    depthOfInheritance,
    linesOfCode,
    allDefinitions,
    strains;

  function FatalException(message) {
    return {
      name: 'FatalException',
      message: message
    };
  }

  function NodeEntry(name, attributes, children) {
    return {
      name: name,
      attributes: attributes,
      children: children
    };
  }

  function MetricDefinition(abrev, name) {
    return {
      name:name,
      abbreviation:abrev
    };
  }

  maintainabilityIndex = new MetricDefinition('MI', 'MaintainabilityIndex');
  cyclomaticComplexity = new MetricDefinition('CyC', 'CyclomaticComplexity');
  classCoupling = new MetricDefinition('CC', 'ClassCoupling');
  linesOfCode = new MetricDefinition('LC', 'LinesOfCode');
  depthOfInheritance = new MetricDefinition('DI', 'DepthOfInheritance');

  allDefinitions = [maintainabilityIndex, cyclomaticComplexity, classCoupling, depthOfInheritance, linesOfCode];

  function Parser() {
    var that = {};

    function isNodeValid(node) {
      return node.nodeType === 1 || node.nodeType === 2;
    }

    function parseAttributes(node) {
      var attributes = {}, x;

      for (x = 0; x < node.attributes.length; x++) {
        if(isNodeValid(node.attributes.item(x))) {
          attributes[node.attributes.item(x).name] = node.attributes.item(x).value;
        }
      }

      return attributes;
    }

    function parseChildNodes(processor, node) {
      var children = [], x;

      if (node.hasChildNodes()) {
        for (x = 0; x < node.childNodes.length; x++) {
          if (isNodeValid(node.childNodes.item(x))) {
            children.push(processor(node.childNodes.item(x)));
          }
        }
      }
      return children;
    }

    function processNode(node) {
      return new NodeEntry(node.nodeName, parseAttributes(node), parseChildNodes(processNode, node));
    }

    function validateDoc(doc) {
      if (!doc.documentElement) {
        throw new FatalException('unable to parse xml');
      }

      if (doc.documentElement.innerHTML) {
        throw new FatalException('unable to parse xml');
      }

      if (doc.documentElement.nodeName === 'parsererror') {
        throw new FatalException('unable to parse xml');
      }
    }

    function parse(string) {
      var domparser, xmldoc;

      if (window.DOMParser) {
        try {
        domparser = new DOMParser();
        xmldoc = domparser.parseFromString(string, "text/xml");
        } catch(e) {
          throw new FatalException('unable to parse xml');
        }
      }
      else {
        xmldoc=new ActiveXObject("Microsoft.XMLDOM");
        xmldoc.async=false;
        xmldoc.loadXML(string);
      }

      validateDoc(xmldoc);
      return processNode(xmldoc.documentElement);
    }

    that.parse = parse;
    return that;
  }

  function BaseNamed(name) {
    return {
      name: name
    };
  }

  function Metric(name, value) {
    var that = new BaseNamed(name);

    function getFormattedValue() {
      return (value === -99999) ? '' : value.toString();
    }

    that.value = value;
    that.getFormattedValue = getFormattedValue;

    return that;
  }

  function BaseMetrics (name, metrics) {
    var that = new BaseNamed(name);

    function getFullMetrics() {
      var x, y, results = [], found;

      for (x=0; x < allDefinitions.length; x++) {
        found = false;

        for (y=0; y < metrics.length; y++) {
          if(metrics[y].name === allDefinitions[x].name) {
            results.push(metrics[y]);
            found = true;
          }
        }

        if (found === false) {
          results.push(new Metric(allDefinitions[x].name, MISSING_METRIC_VALUE));
        }
      }

      return results;
    }

    that.metrics = metrics;
    that.getFullMetrics = getFullMetrics;

    return that;
  }

  function Member(name, file, line, metrics) {
    var that = new BaseMetrics(name, metrics);

    that.strain = 'MB';
    that.file = file;
    that.line = line;

    return that;
  }

  function Type (name,members,metrics) {
    var that = new BaseMetrics(name, metrics);

    that.strain = 'TY';
    that.members = members;

    return that;
  }

  function Namespace(name, types, metrics) {
    var that = new BaseMetrics(name, metrics);

    that.strain = 'NS';
    that.types = types;

    return that;
  }

  function Module(name, version, metrics, namespaces) {
    var that = new BaseMetrics(name, metrics);

    that.strain = 'MD';
    that.version = version;
    that.namespaces = namespaces;

    return that;
  }

  function Mapper() {
    var that = {};

    function formMetric(startingNodeChild) {
      var x, val = startingNodeChild.attributes.Value;

      for (x=0; x < val.length; x++) {
        val = val.replace(',','');
      }

      return new Metric(startingNodeChild.attributes.Name,
                        parseInt(val, 10));
    }

    function formMetrics(startingNode, index) {
       var x, metrics = [], metricsNode = startingNode.children[index];

       for (x=0; x < metricsNode.children.length; x++) {
         metrics.push(formMetric(metricsNode.children[x]));
       }

       return metrics;
     }

    function formMember(startingNode) {

      return new Member(startingNode.attributes.Name,
                        startingNode.attributes.File,
                        startingNode.attributes.Line,
                        formMetrics(startingNode, 0)
      );
    }

    function formType(startingNode) {
      var x,  membersNode = startingNode.children[1], membersArray = [];

      for (x=0; x < membersNode.children.length; x++) {
        membersArray.push(formMember(membersNode.children[x]));
      }

      return new Type(startingNode.attributes.Name,
                      membersArray,
                      formMetrics(startingNode, 0)
                 );
    }

    function formNamespace(startingNode) {
      var typesNode = startingNode.children[1], x, typesArray = [];

        for (x=0; x < typesNode.children.length; x++) {
          typesArray.push(formType(typesNode.children[x]));
        }

       return new Namespace(startingNode.attributes.Name,
                            typesArray,
                            formMetrics(startingNode, 0)
       );
    }

    function map(entryNode) {
      var moduleNode = entryNode.children[0].children[0].children[0].children[0],
        namespacesNode = moduleNode.children[1], nsArray = [], x;

        for (x=0; x < namespacesNode.children.length; x++) {
          nsArray.push(formNamespace(namespacesNode.children[x]));
        }

      return new Module(moduleNode.attributes.Name,
                   moduleNode.attributes.AssemblyVersion,
                   formMetrics(moduleNode,0),
                   nsArray
      );
    }

    that.map = map;
    return that;
  }

  function DataLoader(url, callback) {
    function execute() {
      return $.get(url, callback, 'text');
    }

    return {
      execute: execute
    };
  }

  function LocationUrlParser() {
    function validateUrl(url) {
      if (!url || url.length <= 1) {
        throw new FatalException('no path argument provided');
      }
    }

    function parse() {
      var url = mywindow.location.search;
      validateUrl(url);
      return url.substring(1).split('=')[1];
    }

    return {
      parse: parse
    };
  }

  function OrFilter(filterArray) {
    var that = {};

    function filter(element) {
      var x;

      if (filterArray.length === 0) {
        return true;
      }

      for (x=0; x < filterArray.length; x++) {
        if (filterArray[x].filter(element)) {
          return true;
        }
      }
      return false;
    }

    that.filter = filter;

    return that;
  }

  function AndFilter(filters) {
    var that = {};

    function filter(element) {
      var x;

      for (x=0; x < filters.length; x++) {
        if (!filters[x].filter(element)) {
          return false;
        }
      }
      return true;
    }

    that.filter = filter;
    return that;
  }

  function FilteredList(module) {
    var that = {}, filters = [], accepted = [], elements = [], emptyFilter = false,
      x, y, z, temp, actualAccepted = [], nameFilter = [];

    elements.push(module);

    for (x=0; x < module.namespaces.length; x++) {
      temp = module.namespaces[x];
      elements.push(temp);

      for (y=0; y < temp.types.length; y++) {
        elements.push(temp.types[y]);

        for (z=0; z < temp.types[y].members.length; z++) {
          elements.push(temp.types[y].members[z]);
        }
      }
    }

    function getFilters() {
      return filters;
    }

    function getAccepted() {
      return actualAccepted;
    }

    function clearFilters() {
      filters = [];
      accepted = [];
      actualAccepted = [];
      nameFilter = [];
      emptyFilter = true;
    }

    function applyFilters(filters) {
      var y, andFilter = new AndFilter(filters);

      for (y=0; y < elements.length; y++) {
        if (andFilter.filter(elements[y])) {
          actualAccepted.push(elements[y]);
        }
      }
    }

    that.getAccepted = getAccepted;
    that.applyFilters = applyFilters;
    that.clearFilters = clearFilters;
    that.getFilters = getFilters;
    that.applyFilters = applyFilters;

    return that;
  }

  function StrainFilter(lookFor) {
    var that = {};

    function filter(node) {
      return (node.strain === lookFor);
    }

    function isNameFilter() {
      return false;
    }

    that.isNameFilter = isNameFilter;
    that.filter = filter;

    return that;
  }

  function NameFilter(searchFor) {
    var that = {};
    searchFor = searchFor.toLowerCase();

    function filter(compareTo) {
      compareTo = compareTo.name.toLowerCase();
      return (compareTo.indexOf(searchFor) !== -1);
    }

   function isNameFilter() {
      return true;
    }

    that.isNameFilter = isNameFilter;
    that.filter = filter;

    return that;
  }

  return {
    NodeEntry: NodeEntry,
    Parser: Parser,
    Metric: Metric,
    Member: Member,
    Type: Type,
    Namespace: Namespace,
    Module: Module,
    Mapper: Mapper,
    DataLoader: DataLoader,
    LocationUrlParser: LocationUrlParser,
    MISSING_METRIC_VALUE: MISSING_METRIC_VALUE,
    MetricDefinition: MetricDefinition,
    maintainabilityIndex: maintainabilityIndex,
    cyclomaticComplexity: cyclomaticComplexity,
    classCoupling: classCoupling,
    depthOfInheritance: depthOfInheritance,
    linesOfCode: linesOfCode,
    allDefinitions: allDefinitions,
    FilteredList:FilteredList,
    strains: strains,
    StrainFilter: StrainFilter,
    NameFilter: NameFilter,
    AndFilter: AndFilter,
    OrFilter: OrFilter
  };
}

var croaker = new Croaker();<|endoftext|>


<commit_before>
biolabsApp.controller('blAddLabController', function ($state, $scope, $resource, $http, settings, ngDialog, $alert, blFlash) {

    var dialog = ngDialog.open({
        template: 'partials/add_lab.html',
        controller: ['$scope', function ($scope) {
            $scope.errors = {};
            $scope.save = function (lab) {
                var LabsResource = $resource(settings.API_ENDPOINT);

                var dataToSave = new LabsResource(lab);
                dataToSave.$save(function (data, headers) {
                        blFlash.setMessage('Thanks for your contribution !');
                        $scope.closeThisDialog();
                    }
                , function(response) {
                        var errors = response['data'];
                        angular.forEach(errors, function(value, key) {
                          $scope.errors[key] = value[0];
                        });
                    });
            };
        }]
    });

    dialog.closePromise.then(function (data) {
        $state.transitionTo('map');
    });

});
<commit_msg>Reinitialising errors each time we are submitting add-lab form<commit_after>
biolabsApp.controller('blAddLabController', function ($state, $scope, $resource, $http, settings, ngDialog, $alert, blFlash) {

    var dialog = ngDialog.open({
        template: 'partials/add_lab.html',
        controller: ['$scope', function ($scope) {
            $scope.errors = {};

            $scope.save = function (lab) {
                var LabsResource = $resource(settings.API_ENDPOINT);

                var dataToSave = new LabsResource(lab);
                dataToSave.$save(function (data, headers) {
                        blFlash.setMessage('Thanks for your contribution !');
                        $scope.closeThisDialog();
                    }
                , function(response) {
                        $scope.errors = {};
                        var serverErrors = response['data'];
                        angular.forEach(serverErrors, function(value, key) {
                          $scope.errors[key] = value[0];
                        });
                    });
            };
        }]
    });

    dialog.closePromise.then(function (data) {
        $state.transitionTo('map');
    });

});
<|endoftext|>


<commit_before>import React from 'react'
import RootSiblings from 'react-native-root-siblings'

import type { SnackItemType } from './type'
import SnackBar from './SnackBar'

export default class SnackBarManager {
  current: SnackItemType
  queue: Array<SnackItemType>

  constructor () {
    this.current = null
    this.queue = []
  }

  _setCurrent = (props: SnackItemType, callback?: Function = () => {}): void => {
    this.current = new RootSiblings(<SnackBar {...props} onAutoDismiss={this.dismiss} />, callback)
  }

  _removeCurrent = (callback?: Function = () => {}): void => {
    if (!this.current) {
      callback()
      return
    }

    this.current.destroy(() => {
      this.current = null
      callback()
    })
  }

  get = () => {
    return {
      current: this.current,
      queue: this.queue
    }
  }

  add = (
    title: string,
    options?: SnackItemType,
    callback?: Function = () => {}
  ): void => {
    const props = { title, ...options }

    if (this.current) {
      this.queue.push(props)
      callback()
      return
    }

    this._setCurrent(props, callback)
  }

  show = (
    title: string,
    options?: SnackItemType,
    callback?: Function = () => {}
  ): void => {
    const props = { title, ...options }

    if (this.current) {
      this.queue.unshift(props)
      callback()
      return
    }

    this._setCurrent(props, callback)
  }

  dismiss = (callback?: Function = () => {}): void => {
    this._removeCurrent(() => {
      if (!this.queue.length) {
        callback()
        return
      }

      const current = this.queue.shift()
      this._setCurrent(current, callback)
    })
  }
}
<commit_msg>#1 Fix race condition of constructing RootSiblings<commit_after>import React from 'react'
import RootSiblings from 'react-native-root-siblings'

import type { SnackItemType } from './type'
import SnackBar from './SnackBar'

export default class SnackBarManager {
  current: SnackItemType
  queue: Array<SnackItemType>

  constructor () {
    this.current = null
    this.queue = []
  }

  _setCurrent = (props: SnackItemType, callback?: Function = () => {}): void => {
    const current = new RootSiblings(<SnackBar {...props} onAutoDismiss={this.dismiss} />, () => {
      this.current = current
      callback()
    })
  }

  _removeCurrent = (callback?: Function = () => {}): void => {
    if (!this.current) {
      callback()
      return
    }

    this.current.destroy(() => {
      this.current = null
      callback()
    })
  }

  get = () => {
    return {
      current: this.current,
      queue: this.queue
    }
  }

  add = (
    title: string,
    options?: SnackItemType,
    callback?: Function = () => {}
  ): void => {
    const props = { title, ...options }

    if (this.current) {
      this.queue.push(props)
      callback()
      return
    }

    this._setCurrent(props, callback)
  }

  show = (
    title: string,
    options?: SnackItemType,
    callback?: Function = () => {}
  ): void => {
    const props = { title, ...options }

    if (this.current) {
      this.queue.unshift(props)
      callback()
      return
    }

    this._setCurrent(props, callback)
  }

  dismiss = (callback?: Function = () => {}): void => {
    this._removeCurrent(() => {
      if (!this.queue.length) {
        callback()
        return
      }

      const current = this.queue.shift()
      this._setCurrent(current, callback)
    })
  }
}
<|endoftext|>


<commit_before>'use strict';

/**
 * All the user authentication in one place.
 *
 * This module allows for users to log(in|out), and get the status of their session.
 * authentication methods.
 *
 * @type {exports}
 */
var bcrypt = require('bcrypt');
var jwt = require('jsonwebtoken');
var util = require('../util/util');
var _ = require('lodash');
var debug = {
  authenticate: require('debug')('formio:authentication:authenticate')
};

module.exports = function(router) {
  var hook = require('../util/hook')(router.formio);

  /**
   * Generate our JWT with the given payload, and pass it to the given callback function.
   *
   * @param payload {Object}
   *   The decoded JWT.
   *
   * @return {String|Boolean}
   *   The JWT from the given payload, or false if the jwt payload is still valid.
   */
  var getToken = function(payload) {
    // Ensure that we do not do multiple re-issues consecutively.
    // Re-issue at the maximum rate of 1/min.
    if (payload.iat) {
      var now = Math.floor(Date.now() / 1000);
      if ((now - payload.iat) < 60) {
        return false;
      }

      delete payload.iat;
      delete payload.exp;
    }

    return jwt.sign(payload, router.formio.config.jwt.secret, {
      expiresIn: router.formio.config.jwt.expireTime * 60
    });
  };

  /**
   * Authenticate a user.
   *
   * @param forms {Mixed}
   *   A single form or an array of forms to authenticate against.
   * @param userField {String}
   *   The user submission field that contains the username.
   * @param passField {String}
   *   The user submission field that contains the password.
   * @param username {String}
   *   The user submission username to login with.
   * @param password {String}
   *   The user submission password to login with.
   * @param next {Function}
   *   The callback function to call after authentication.
   */
  var authenticate = function(forms, userField, passField, username, password, next) {
    // Make sure they have provided a username and password.
    if (!username) {
      return next(new Error('Missing username'));
    }
    if (!password) {
      return next(new Error('Missing password'));
    }

    var query = {deleted: {$eq: null}};

    // Determine the form id for querying.
    if (_.isArray(forms)) {
      query.form = {'$in': _.map(forms, util.idToBson)};
    }
    else if (_.isObject(forms)) {
      query.form = util.idToBson(forms._id);
    }
    else if (_.isString(forms)) {
      query.form = util.idToBson(forms);
    }

    // Look for the user.
    query['data.' + userField] = username;

    // Find the user object.
    router.formio.resources.submission.model.findOne(query, function(err, user) {
      if (err) {
        return next(err);
      }
      if (!user) {
        return next(new Error('Invalid user'));
      }

      // Compare the provided password.
      user = user.toObject();
      bcrypt.compare(password, user.data[passField], function(err, value) {
        if (err) {
          return next(err);
        }
        if (!value) {
          return next(new Error('Incorrect password'));
        }

        // Load the form associated with this user record.
        router.formio.resources.form.model.findOne({
          _id: user.form,
          deleted: {$eq: null}
        }, function(err, form) {
          if (err) {
            return next(err);
          }
          if (!form) {
            return next(new Error('User form not found.'));
          }

          form = form.toObject();

          // Allow anyone to hook and modify the user.
          hook.alter('user', user, function hookUserCallback(err, _user) {
            if (err) {
              // Attempt to fail safely and not update the user reference.
              debug.authenticate(err);
            }
            else {
              // Update the user with the hook results.
              debug.authenticate(user);
              user = _user;
            }

            // Allow anyone to hook and modify the token.
            var token = hook.alter('token', {
              user: {
                _id: user._id
              },
              form: {
                _id: form._id
              }
            }, form);

            // Continue with the token data.
            next(null, {
              user: user,
              token: {
                token: getToken(token),
                decoded: token
              }
            });
          });
        });
      });
    });
  };

  /**
   * Send the current user.
   *
   * @param req
   * @param res
   * @param next
   */
  var currentUser = function(req, res, next) {
    if (!res.token || !req.token) {
      return res.sendStatus(401);
    }

    // Set the headers if they haven't been sent yet.
    if (!res.headersSent) {
      res.setHeader('Access-Control-Expose-Headers', 'x-jwt-token');
      res.setHeader('x-jwt-token', res.token);
    }

    // Duplicate the current request get the users information.
    var url = '/form/:formId/submission/:submissionId';
    var childReq = util.createSubRequest(req);
    if (!childReq) {
      return next('Too many recursive requests.');
    }
    childReq.method = 'GET';
    childReq.skipResource = false;

    // If this request is not directly accessing /current, allow the response to be sent.
    if (req.url !== '/current') {
      childReq.noResponse = true;
    }

    // Update the parameters to use from the decoded token.
    childReq.params = hook.alter('submissionRequestTokenQuery', {
      formId: req.token.form._id,
      submissionId: req.token.user._id
    }, req.token);

    // Execute the resourcejs methods associated with the user submissions.
    router.resourcejs[url].get.call(this, childReq, res, next);
  };

  /**
   * Return the public methods.
   */
  return {
    getToken: getToken,
    authenticate: authenticate,
    currentUser: currentUser,
    logout: function(req, res) {
      res.setHeader('x-jwt-token', '');
      res.sendStatus(200);
    }
  };
};
<commit_msg>Added a much better error message for users without passwords trying to login.<commit_after>'use strict';

/**
 * All the user authentication in one place.
 *
 * This module allows for users to log(in|out), and get the status of their session.
 * authentication methods.
 *
 * @type {exports}
 */
var bcrypt = require('bcrypt');
var jwt = require('jsonwebtoken');
var util = require('../util/util');
var _ = require('lodash');
var debug = {
  authenticate: require('debug')('formio:authentication:authenticate')
};

module.exports = function(router) {
  var hook = require('../util/hook')(router.formio);

  /**
   * Generate our JWT with the given payload, and pass it to the given callback function.
   *
   * @param payload {Object}
   *   The decoded JWT.
   *
   * @return {String|Boolean}
   *   The JWT from the given payload, or false if the jwt payload is still valid.
   */
  var getToken = function(payload) {
    // Ensure that we do not do multiple re-issues consecutively.
    // Re-issue at the maximum rate of 1/min.
    if (payload.iat) {
      var now = Math.floor(Date.now() / 1000);
      if ((now - payload.iat) < 60) {
        return false;
      }

      delete payload.iat;
      delete payload.exp;
    }

    return jwt.sign(payload, router.formio.config.jwt.secret, {
      expiresIn: router.formio.config.jwt.expireTime * 60
    });
  };

  /**
   * Authenticate a user.
   *
   * @param forms {Mixed}
   *   A single form or an array of forms to authenticate against.
   * @param userField {String}
   *   The user submission field that contains the username.
   * @param passField {String}
   *   The user submission field that contains the password.
   * @param username {String}
   *   The user submission username to login with.
   * @param password {String}
   *   The user submission password to login with.
   * @param next {Function}
   *   The callback function to call after authentication.
   */
  var authenticate = function(forms, userField, passField, username, password, next) {
    // Make sure they have provided a username and password.
    if (!username) {
      return next(new Error('Missing username'));
    }
    if (!password) {
      return next(new Error('Missing password'));
    }

    var query = {deleted: {$eq: null}};

    // Determine the form id for querying.
    if (_.isArray(forms)) {
      query.form = {'$in': _.map(forms, util.idToBson)};
    }
    else if (_.isObject(forms)) {
      query.form = util.idToBson(forms._id);
    }
    else if (_.isString(forms)) {
      query.form = util.idToBson(forms);
    }

    // Look for the user.
    query['data.' + userField] = username;

    // Find the user object.
    router.formio.resources.submission.model.findOne(query, function(err, user) {
      if (err) {
        return next(err);
      }
      if (!user) {
        return next(new Error('Invalid user'));
      }
      if (!user.data[passField]) {
        return next(new Error('Your account does not have a password. You must reset your password to login.'));
      }

      // Compare the provided password.
      user = user.toObject();
      bcrypt.compare(password, user.data[passField], function(err, value) {
        if (err) {
          return next(err);
        }
        if (!value) {
          return next(new Error('Incorrect password'));
        }

        // Load the form associated with this user record.
        router.formio.resources.form.model.findOne({
          _id: user.form,
          deleted: {$eq: null}
        }, function(err, form) {
          if (err) {
            return next(err);
          }
          if (!form) {
            return next(new Error('User form not found.'));
          }

          form = form.toObject();

          // Allow anyone to hook and modify the user.
          hook.alter('user', user, function hookUserCallback(err, _user) {
            if (err) {
              // Attempt to fail safely and not update the user reference.
              debug.authenticate(err);
            }
            else {
              // Update the user with the hook results.
              debug.authenticate(user);
              user = _user;
            }

            // Allow anyone to hook and modify the token.
            var token = hook.alter('token', {
              user: {
                _id: user._id
              },
              form: {
                _id: form._id
              }
            }, form);

            // Continue with the token data.
            next(null, {
              user: user,
              token: {
                token: getToken(token),
                decoded: token
              }
            });
          });
        });
      });
    });
  };

  /**
   * Send the current user.
   *
   * @param req
   * @param res
   * @param next
   */
  var currentUser = function(req, res, next) {
    if (!res.token || !req.token) {
      return res.sendStatus(401);
    }

    // Set the headers if they haven't been sent yet.
    if (!res.headersSent) {
      res.setHeader('Access-Control-Expose-Headers', 'x-jwt-token');
      res.setHeader('x-jwt-token', res.token);
    }

    // Duplicate the current request get the users information.
    var url = '/form/:formId/submission/:submissionId';
    var childReq = util.createSubRequest(req);
    if (!childReq) {
      return next('Too many recursive requests.');
    }
    childReq.method = 'GET';
    childReq.skipResource = false;

    // If this request is not directly accessing /current, allow the response to be sent.
    if (req.url !== '/current') {
      childReq.noResponse = true;
    }

    // Update the parameters to use from the decoded token.
    childReq.params = hook.alter('submissionRequestTokenQuery', {
      formId: req.token.form._id,
      submissionId: req.token.user._id
    }, req.token);

    // Execute the resourcejs methods associated with the user submissions.
    router.resourcejs[url].get.call(this, childReq, res, next);
  };

  /**
   * Return the public methods.
   */
  return {
    getToken: getToken,
    authenticate: authenticate,
    currentUser: currentUser,
    logout: function(req, res) {
      res.setHeader('x-jwt-token', '');
      res.sendStatus(200);
    }
  };
};
<|endoftext|>


<commit_before>/**
 * Created by GUY on 2015/6/26.
 */

BI.Tab = BI.inherit(BI.Widget, {
    _defaultConfig: function () {
        return BI.extend(BI.Tab.superclass._defaultConfig.apply(this, arguments), {
            baseCls: "bi-tab",
            direction: "top", // top, bottom, left, right, custom
            single: false, // 是不是单页面
            logic: {
                dynamic: false
            },
            showIndex: false,
            tab: false,
            cardCreator: function (v) {
                return BI.createWidget();
            },
            keepAlives: []
        });
    },

    render: function () {
        var self = this, o = this.options;
        if (BI.isObject(o.tab)) {
            this.tab = BI.createWidget(this.options.tab, {type: "bi.button_group"});
            this.tab.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
                self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
            });
        }
        this.cardMap = {};
        this.layout = BI.createWidget({
            type: "bi.card"
        });

        BI.createWidget(BI.extend({
            element: this
        }, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, {
            items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.tab, this.layout)
        }))));

        var listener = new BI.ShowListener({
            eventObj: this.tab,
            cardLayout: this.layout,
            cardCreator: function (v) {
                var card = o.cardCreator.apply(self, arguments);
                self.cardMap[v] = card;
                return card;
            },
            afterCardShow: function (v) {
                self._deleteOtherCards(v);
                self.curr = v;
            }
        });
        listener.on(BI.ShowListener.EVENT_CHANGE, function (value) {
            self.fireEvent(BI.Tab.EVENT_CHANGE, value, self);
        });

        if (BI.isFunction(o.showIndex)) {
            this.__watch(o.showIndex, function (context, newValue) {
                self.setSelect(newValue);
            })
        }
    },

    _deleteOtherCards: function (currCardName) {
        var self = this, o = this.options;
        if (o.single === true) {
            BI.each(this.cardMap, function (name, card) {
                if (name !== (currCardName + "") && self._keepAlive(name) !== true) {
                    self.layout.deleteCardByName(name);
                    delete self.cardMap[name];
                }
            });
        }
    },

    _assertCard: function (v) {
        if (!this.layout.isCardExisted(v)) {
            var card = this.options.cardCreator(v);
            this.cardMap[v] = card;
            this.layout.addCardByName(v, card);
        }
    },

    _keepAlive: function (v) {
        var o = this.options;
        return BI.isFunction(o.keepAlives) ? o.keepAlives(v) : BI.contains(o.keepAlives, v);

    },

    created: function () {
        var o = this.options;
        if (o.showIndex !== false) {
            this.setSelect(o.showIndex);
        }
    },

    setSelect: function (v, action, callback) {
        this.tab && this.tab.setValue(v);
        this._assertCard(v);
        this.layout.showCardByName(v, action, callback);
        this._deleteOtherCards(v);
        if (this.curr !== v) {
            this.curr = v;
        }
    },

    removeTab: function (cardname) {
        var self = this, o = this.options;
        BI.any(this.cardMap, function (name, card) {
            if (BI.isEqual(name, (cardname + ""))) {
                self.layout.deleteCardByName(name);
                delete self.cardMap[name];
                return true;
            }
        });
    },

    isCardExisted: function (cardName) {
        return this.layout.isCardExisted(cardName);
    },

    getSelect: function () {
        return this.curr;
    },

    getSelectedTab: function () {
        return this.layout.getShowingCard();
    },

    getTab: function (v) {
        this._assertCard(v);
        return this.layout.getCardByName(v);
    },

    setValue: function (v) {
        var card = this.layout.getShowingCard();
        if (card) {
            card.setValue(v);
        }
    },

    getValue: function () {
        var card = this.layout.getShowingCard();
        if (card) {
            return card.getValue();
        }
    },

    populate: function () {
        var card = this.layout.getShowingCard();
        if (card) {
            return card.populate && card.populate.apply(card, arguments);
        }
    },

    empty: function () {
        this.layout.deleteAllCard();
        this.cardMap = {};
    },

    destroy: function () {
        this.cardMap = {};
        BI.Tab.superclass.destroy.apply(this, arguments);
    }
});
BI.Tab.EVENT_CHANGE = "EVENT_CHANGE";

BI.shortcut("bi.tab", BI.Tab);
<commit_msg>Pull request #2587: 无jira任务 tab showIndex function<commit_after>/**
 * Created by GUY on 2015/6/26.
 */

BI.Tab = BI.inherit(BI.Widget, {
    _defaultConfig: function () {
        return BI.extend(BI.Tab.superclass._defaultConfig.apply(this, arguments), {
            baseCls: "bi-tab",
            direction: "top", // top, bottom, left, right, custom
            single: false, // 是不是单页面
            logic: {
                dynamic: false
            },
            showIndex: false,
            tab: false,
            cardCreator: function (v) {
                return BI.createWidget();
            },
            keepAlives: []
        });
    },

    render: function () {
        var self = this, o = this.options;
        if (BI.isObject(o.tab)) {
            this.tab = BI.createWidget(this.options.tab, { type: "bi.button_group" });
            this.tab.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
                self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
            });
        }
        this.cardMap = {};
        this.layout = BI.createWidget({
            type: "bi.card"
        });

        BI.createWidget(BI.extend({
            element: this
        }, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, {
            items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.tab, this.layout)
        }))));

        var listener = new BI.ShowListener({
            eventObj: this.tab,
            cardLayout: this.layout,
            cardCreator: function (v) {
                var card = o.cardCreator.apply(self, arguments);
                self.cardMap[v] = card;

                return card;
            },
            afterCardShow: function (v) {
                self._deleteOtherCards(v);
                self.curr = v;
            }
        });
        listener.on(BI.ShowListener.EVENT_CHANGE, function (value) {
            self.fireEvent(BI.Tab.EVENT_CHANGE, value, self);
        });
    },

    _deleteOtherCards: function (currCardName) {
        var self = this, o = this.options;
        if (o.single === true) {
            BI.each(this.cardMap, function (name, card) {
                if (name !== (currCardName + "") && self._keepAlive(name) !== true) {
                    self.layout.deleteCardByName(name);
                    delete self.cardMap[name];
                }
            });
        }
    },

    _assertCard: function (v) {
        if (!this.layout.isCardExisted(v)) {
            var card = this.options.cardCreator(v);
            this.cardMap[v] = card;
            this.layout.addCardByName(v, card);
        }
    },

    _keepAlive: function (v) {
        var o = this.options;

        return BI.isFunction(o.keepAlives) ? o.keepAlives(v) : BI.contains(o.keepAlives, v);
    },

    created: function () {
        var self = this, o = this.options;
        if (o.showIndex !== false) {
            if (BI.isFunction(o.showIndex)) {
                var v = this.__watch(o.showIndex, function (context, newValue) {
                    self.setSelect(newValue);
                });
                this.setSelect(v);
            } else {
                this.setSelect(o.showIndex);
            }
        }
    },

    setSelect: function (v, action, callback) {
        this.tab && this.tab.setValue(v);
        this._assertCard(v);
        this.layout.showCardByName(v, action, callback);
        this._deleteOtherCards(v);
        if (this.curr !== v) {
            this.curr = v;
        }
    },

    removeTab: function (cardname) {
        var self = this, o = this.options;
        BI.any(this.cardMap, function (name, card) {
            if (BI.isEqual(name, (cardname + ""))) {
                self.layout.deleteCardByName(name);
                delete self.cardMap[name];

                return true;
            }
        });
    },

    isCardExisted: function (cardName) {
        return this.layout.isCardExisted(cardName);
    },

    getSelect: function () {
        return this.curr;
    },

    getSelectedTab: function () {
        return this.layout.getShowingCard();
    },

    getTab: function (v) {
        this._assertCard(v);

return this.layout.getCardByName(v);
    },

    setValue: function (v) {
        var card = this.layout.getShowingCard();
        if (card) {
            card.setValue(v);
        }
    },

    getValue: function () {
        var card = this.layout.getShowingCard();
        if (card) {
            return card.getValue();
        }
    },

    populate: function () {
        var card = this.layout.getShowingCard();
        if (card) {
            return card.populate && card.populate.apply(card, arguments);
        }
    },

    empty: function () {
        this.layout.deleteAllCard();
        this.cardMap = {};
    },

    destroy: function () {
        this.cardMap = {};
        BI.Tab.superclass.destroy.apply(this, arguments);
    }
});
BI.Tab.EVENT_CHANGE = "EVENT_CHANGE";

BI.shortcut("bi.tab", BI.Tab);
<|endoftext|>


<commit_before>/* @flow */

import * as React from 'react';
import PropTypes from 'prop-types';
import {
  Animated,
  PanResponder,
  StyleSheet,
  View,
  Platform,
} from 'react-native';
import { PagerRendererPropType } from './TabViewPropTypes';
import type { PagerRendererProps } from './TabViewTypeDefinitions';

type GestureEvent = {
  nativeEvent: {
    changedTouches: Array<*>,
    identifier: number,
    locationX: number,
    locationY: number,
    pageX: number,
    pageY: number,
    target: number,
    timestamp: number,
    touches: Array<*>,
  },
};

type GestureState = {
  stateID: number,
  moveX: number,
  moveY: number,
  x0: number,
  y0: number,
  dx: number,
  dy: number,
  vx: number,
  vy: number,
  numberActiveTouches: number,
};

type Props<T> = PagerRendererProps<T> & {
  swipeDistanceThreshold?: number,
  swipeVelocityThreshold?: number,
};

const DEAD_ZONE = 12;

const DefaultTransitionSpec = {
  timing: Animated.spring,
  tension: 300,
  friction: 35,
};

export default class TabViewPagerPan<T: *> extends React.Component<Props<T>> {
  static propTypes = {
    ...PagerRendererPropType,
    swipeDistanceThreshold: PropTypes.number,
    swipeVelocityThreshold: PropTypes.number,
  };

  static defaultProps = {
    canJumpToTab: () => true,
    initialLayout: {
      height: 0,
      width: 0,
    },
  };

  componentDidUpdate(prevProps: Props<T>) {
    this._currentIndex = this.props.navigationState.index;

    if (
      prevProps.navigationState.routes !== this.props.navigationState.routes ||
      prevProps.layout.width !== this.props.layout.width
    ) {
      this._transitionTo(this.props.navigationState.index, false);
    } else if (
      prevProps.navigationState.index !== this.props.navigationState.index
    ) {
      this._transitionTo(this.props.navigationState.index);
    }
  }

  _currentIndex = this.props.navigationState.index;
  _pendingIndex: ?number;

  _isMovingHorizontally = (evt: GestureEvent, gestureState: GestureState) => {
    return (
      Math.abs(gestureState.dx) > Math.abs(gestureState.dy * 2) &&
      Math.abs(gestureState.vx) > Math.abs(gestureState.vy * 2)
    );
  };

  _canMoveScreen = (evt: GestureEvent, gestureState: GestureState) => {
    if (this.props.swipeEnabled === false) {
      return false;
    }

    const { navigationState: { routes } } = this.props;

    return (
      this._isMovingHorizontally(evt, gestureState) &&
      ((gestureState.dx >= DEAD_ZONE && this._currentIndex > 0) ||
        (gestureState.dx <= -DEAD_ZONE &&
          this._currentIndex < routes.length - 1))
    );
  };

  _startGesture = () => {
    this.props.onSwipeStart && this.props.onSwipeStart();
    this.props.panX.stopAnimation();
  };

  _respondToGesture = (evt: GestureEvent, gestureState: GestureState) => {
    const { navigationState: { routes, index } } = this.props;

    if (
      // swiping left
      (gestureState.dx > 0 && index <= 0) ||
      // swiping right
      (gestureState.dx < 0 && index >= routes.length - 1)
    ) {
      return;
    }

    this.props.panX.setValue(gestureState.dx);
  };

  _finishGesture = (evt: GestureEvent, gestureState: GestureState) => {
    const {
      navigationState,
      layout,
      swipeDistanceThreshold = layout.width / 1.75,
    } = this.props;

    let { swipeVelocityThreshold = 0.15 } = this.props;

    this.props.onSwipeEnd && this.props.onSwipeEnd();

    if (Platform.OS === 'android') {
      // on Android, velocity is way lower due to timestamp being in nanosecond
      // normalize it to have the same velocity on both iOS and Android
      swipeVelocityThreshold /= 1000000;
    }

    const currentIndex =
      typeof this._pendingIndex === 'number'
        ? this._pendingIndex
        : this._currentIndex;

    let nextIndex = currentIndex;

    if (
      Math.abs(gestureState.dx) > Math.abs(gestureState.dy) &&
      Math.abs(gestureState.vx) > Math.abs(gestureState.vy) &&
      (Math.abs(gestureState.dx) > swipeDistanceThreshold ||
        Math.abs(gestureState.vx) > swipeVelocityThreshold)
    ) {
      nextIndex = Math.round(
        Math.min(
          Math.max(
            0,
            currentIndex - gestureState.dx / Math.abs(gestureState.dx)
          ),
          navigationState.routes.length - 1
        )
      );

      this._currentIndex = nextIndex;
    }

    if (
      !isFinite(nextIndex) ||
      !this.props.canJumpToTab(this.props.navigationState.routes[nextIndex])
    ) {
      nextIndex = currentIndex;
    }

    this._transitionTo(nextIndex);
  };

  _transitionTo = (index: number, animated: boolean = true) => {
    const offset = -index * this.props.layout.width;

    if (this.props.animationEnabled === false || animated === false) {
      this.props.panX.setValue(0);
      this.props.offsetX.setValue(offset);
      return;
    }

    const { timing, ...transitionConfig } = DefaultTransitionSpec;

    Animated.parallel([
      timing(this.props.panX, {
        ...transitionConfig,
        toValue: 0,
      }),
      timing(this.props.offsetX, {
        ...transitionConfig,
        toValue: offset,
      }),
    ]).start(({ finished }) => {
      if (finished) {
        const route = this.props.navigationState.routes[index];
        this.props.jumpTo(route.key);
        this.props.onAnimationEnd && this.props.onAnimationEnd();
        this._pendingIndex = null;
      }
    });

    this._pendingIndex = index;
  };

  _panResponder = PanResponder.create({
    onMoveShouldSetPanResponder: this._canMoveScreen,
    onMoveShouldSetPanResponderCapture: this._canMoveScreen,
    onPanResponderGrant: this._startGesture,
    onPanResponderMove: this._respondToGesture,
    onPanResponderTerminate: this._finishGesture,
    onPanResponderRelease: this._finishGesture,
    onPanResponderTerminationRequest: () => true,
  });

  render() {
    const { panX, offsetX, navigationState, layout, children } = this.props;
    const { width } = layout;
    const { routes } = navigationState;
    const maxTranslate = width * (routes.length - 1);
    const translateX = Animated.add(panX, offsetX).interpolate({
      inputRange: [-maxTranslate, 0],
      outputRange: [-maxTranslate, 0],
      extrapolate: 'clamp',
    });

    return (
      <Animated.View
        style={[
          styles.sheet,
          width
            ? {
                width: routes.length * width,
                transform: [{ translateX }],
              }
            : null,
        ]}
        {...this._panResponder.panHandlers}
      >
        {React.Children.map(children, (child, i) => (
          <View
            key={navigationState.routes[i].key}
            testID={navigationState.routes[i].testID}
            style={
              width
                ? { width }
                : i === navigationState.index ? StyleSheet.absoluteFill : null
            }
          >
            {i === navigationState.index || width ? child : null}
          </View>
        ))}
      </Animated.View>
    );
  }
}

const styles = StyleSheet.create({
  sheet: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'stretch',
  },
});
<commit_msg>fix: RTL support for TabViewPagerPan (#497)<commit_after>/* @flow */

import * as React from 'react';
import PropTypes from 'prop-types';
import {
  Animated,
  I18nManager,
  PanResponder,
  StyleSheet,
  View,
  Platform,
} from 'react-native';
import { PagerRendererPropType } from './TabViewPropTypes';
import type { PagerRendererProps } from './TabViewTypeDefinitions';

type GestureEvent = {
  nativeEvent: {
    changedTouches: Array<*>,
    identifier: number,
    locationX: number,
    locationY: number,
    pageX: number,
    pageY: number,
    target: number,
    timestamp: number,
    touches: Array<*>,
  },
};

type GestureState = {
  stateID: number,
  moveX: number,
  moveY: number,
  x0: number,
  y0: number,
  dx: number,
  dy: number,
  vx: number,
  vy: number,
  numberActiveTouches: number,
};

type Props<T> = PagerRendererProps<T> & {
  swipeDistanceThreshold?: number,
  swipeVelocityThreshold?: number,
};

const DEAD_ZONE = 12;

const DefaultTransitionSpec = {
  timing: Animated.spring,
  tension: 300,
  friction: 35,
};

export default class TabViewPagerPan<T: *> extends React.Component<Props<T>> {
  static propTypes = {
    ...PagerRendererPropType,
    swipeDistanceThreshold: PropTypes.number,
    swipeVelocityThreshold: PropTypes.number,
  };

  static defaultProps = {
    canJumpToTab: () => true,
    initialLayout: {
      height: 0,
      width: 0,
    },
  };

  componentDidUpdate(prevProps: Props<T>) {
    this._currentIndex = this.props.navigationState.index;

    if (
      prevProps.navigationState.routes !== this.props.navigationState.routes ||
      prevProps.layout.width !== this.props.layout.width
    ) {
      this._transitionTo(this.props.navigationState.index, false);
    } else if (
      prevProps.navigationState.index !== this.props.navigationState.index
    ) {
      this._transitionTo(this.props.navigationState.index);
    }
  }

  _currentIndex = this.props.navigationState.index;
  _pendingIndex: ?number;

  _isMovingHorizontally = (evt: GestureEvent, gestureState: GestureState) => {
    return (
      Math.abs(gestureState.dx) > Math.abs(gestureState.dy * 2) &&
      Math.abs(gestureState.vx) > Math.abs(gestureState.vy * 2)
    );
  };

  _canMoveScreen = (evt: GestureEvent, gestureState: GestureState) => {
    if (this.props.swipeEnabled === false) {
      return false;
    }

    const { navigationState: { routes } } = this.props;

    return (
      this._isMovingHorizontally(evt, gestureState) &&
      ((gestureState.dx >= DEAD_ZONE && this._currentIndex > 0) ||
        (gestureState.dx <= -DEAD_ZONE &&
          this._currentIndex < routes.length - 1))
    );
  };

  _startGesture = () => {
    this.props.onSwipeStart && this.props.onSwipeStart();
    this.props.panX.stopAnimation();
  };

  _respondToGesture = (evt: GestureEvent, gestureState: GestureState) => {
    const { navigationState: { routes, index } } = this.props;

    if (
      // swiping left
      (gestureState.dx > 0 && index <= 0) ||
      // swiping right
      (gestureState.dx < 0 && index >= routes.length - 1)
    ) {
      return;
    }

    this.props.panX.setValue(gestureState.dx);
  };

  _finishGesture = (evt: GestureEvent, gestureState: GestureState) => {
    const {
      navigationState,
      layout,
      swipeDistanceThreshold = layout.width / 1.75,
    } = this.props;

    let { swipeVelocityThreshold = 0.15 } = this.props;

    this.props.onSwipeEnd && this.props.onSwipeEnd();

    if (Platform.OS === 'android') {
      // on Android, velocity is way lower due to timestamp being in nanosecond
      // normalize it to have the same velocity on both iOS and Android
      swipeVelocityThreshold /= 1000000;
    }

    const currentIndex =
      typeof this._pendingIndex === 'number'
        ? this._pendingIndex
        : this._currentIndex;

    let nextIndex = currentIndex;

    if (
      Math.abs(gestureState.dx) > Math.abs(gestureState.dy) &&
      Math.abs(gestureState.vx) > Math.abs(gestureState.vy) &&
      (Math.abs(gestureState.dx) > swipeDistanceThreshold ||
        Math.abs(gestureState.vx) > swipeVelocityThreshold)
    ) {
      nextIndex = Math.round(
        Math.min(
          Math.max(
            0,
            currentIndex - gestureState.dx / Math.abs(gestureState.dx)
          ),
          navigationState.routes.length - 1
        )
      );

      this._currentIndex = nextIndex;
    }

    if (
      !isFinite(nextIndex) ||
      !this.props.canJumpToTab(this.props.navigationState.routes[nextIndex])
    ) {
      nextIndex = currentIndex;
    }

    this._transitionTo(nextIndex);
  };

  _transitionTo = (index: number, animated: boolean = true) => {
    const offset = -index * this.props.layout.width;

    if (this.props.animationEnabled === false || animated === false) {
      this.props.panX.setValue(0);
      this.props.offsetX.setValue(offset);
      return;
    }

    const { timing, ...transitionConfig } = DefaultTransitionSpec;

    Animated.parallel([
      timing(this.props.panX, {
        ...transitionConfig,
        toValue: 0,
      }),
      timing(this.props.offsetX, {
        ...transitionConfig,
        toValue: offset,
      }),
    ]).start(({ finished }) => {
      if (finished) {
        const route = this.props.navigationState.routes[index];
        this.props.jumpTo(route.key);
        this.props.onAnimationEnd && this.props.onAnimationEnd();
        this._pendingIndex = null;
      }
    });

    this._pendingIndex = index;
  };

  _panResponder = PanResponder.create({
    onMoveShouldSetPanResponder: this._canMoveScreen,
    onMoveShouldSetPanResponderCapture: this._canMoveScreen,
    onPanResponderGrant: this._startGesture,
    onPanResponderMove: this._respondToGesture,
    onPanResponderTerminate: this._finishGesture,
    onPanResponderRelease: this._finishGesture,
    onPanResponderTerminationRequest: () => true,
  });

  render() {
    const { panX, offsetX, navigationState, layout, children } = this.props;
    const { width } = layout;
    const { routes } = navigationState;
    const maxTranslate = width * (routes.length - 1);
    const translateX = Animated.multiply(
      Animated.add(panX, offsetX).interpolate({
        inputRange: [-maxTranslate, 0],
        outputRange: [-maxTranslate, 0],
        extrapolate: 'clamp',
      }),
      I18nManager.isRTL ? -1 : 1
    );

    return (
      <Animated.View
        style={[
          styles.sheet,
          width
            ? {
                width: routes.length * width,
                transform: [{ translateX }],
              }
            : null,
        ]}
        {...this._panResponder.panHandlers}
      >
        {React.Children.map(children, (child, i) => (
          <View
            key={navigationState.routes[i].key}
            testID={navigationState.routes[i].testID}
            style={
              width
                ? { width }
                : i === navigationState.index ? StyleSheet.absoluteFill : null
            }
          >
            {i === navigationState.index || width ? child : null}
          </View>
        ))}
      </Animated.View>
    );
  }
}

const styles = StyleSheet.create({
  sheet: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'stretch',
  },
});
<|endoftext|>


<commit_before>/* eslint-disable class-methods-use-this */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
  Keyboard,
  Platform,
  Animated,
  ViewPropTypes,
  PanResponder
} from 'react-native';
import { connectStyle } from 'native-base-shoutem-theme';

import mapPropsToStyleNames from '../utils/mapPropsToStyleNames';
import { PLATFORM } from '../theme/variables/commonColor';

import { Text } from './Text';
import { Button } from './Button';
import { Toast } from './Toast';

const POSITION = {
  ABSOLUTE: 'absolute',
  BOTTOM: 'bottom',
  TOP: 'top'
};

class ToastContainer extends Component {
  static toastInstance;
  static show({ ...config }) {
    this.toastInstance._root.showToast({ config });
  }
  static hide() {
    if (this.toastInstance._root.getModalState()) {
      this.toastInstance._root.closeToast('functionCall');
    }
  }
  constructor(props) {
    super(props);

    this.state = {
      fadeAnim: new Animated.Value(0),
      keyboardHeight: 0,
      isKeyboardVisible: false,
      modalVisible: false
    };

    this.keyboardDidHide = this.keyboardDidHide.bind(this);
    this.keyboardDidShow = this.keyboardDidShow.bind(this);

    this._panResponder = PanResponder.create({
      onMoveShouldSetPanResponderCapture: () => true,
      onPanResponderRelease: (evt, gestureState) => {
        if (gestureState.moveX > gestureState.x0) {
          console.log('RIGHT');
          this.closeToast('user');
        }
        if (gestureState.moveX < gestureState.x0) {
          console.log('LEFT');
          this.closeToast('user');
        }
      }
    });
  }

  componentDidMount() {
    Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);
    Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);
  }

  getToastStyle() {
    return {
      position: POSITION.ABSOLUTE,
      opacity: this.state.fadeAnim,
      width: '100%',
      elevation: 9,
      paddingHorizontal: Platform.OS === PLATFORM.IOS ? 20 : 0,
      top: this.state.position === POSITION.TOP ? 30 : undefined,
      bottom:
        this.state.position === POSITION.BOTTOM ? this.getTop() : undefined
    };
  }

  getTop() {
    if (Platform.OS === PLATFORM.IOS) {
      if (this.state.isKeyboardVisible) {
        return this.state.keyboardHeight;
      }
      return 30;
    }
    return 0;
  }

  getButtonText(buttonText) {
    if (buttonText) {
      if (buttonText.trim().length === 0) {
        return undefined;
      }
      return buttonText;
    }
    return undefined;
  }
  getModalState() {
    return this.state.modalVisible;
  }

  keyboardDidHide() {
    this.setState({
      keyboardHeight: 0,
      isKeyboardVisible: false
    });
  }

  keyboardDidShow(e) {
    this.setState({
      keyboardHeight: e.endCoordinates.height,
      isKeyboardVisible: true
    });
  }

  showToast({ config }) {
    this.setState({
      modalVisible: true,
      text: config.text,
      buttonText: this.getButtonText(config.buttonText),
      type: config.type,
      position: config.position ? config.position : POSITION.BOTTOM,
      supportedOrientations: config.supportedOrientations,
      style: config.style,
      buttonTextStyle: config.buttonTextStyle,
      buttonStyle: config.buttonStyle,
      textStyle: config.textStyle,
      onClose: config.onClose
    });
    // If we have a toast already open, cut off its close timeout so that it won't affect *this* toast.
    if (this.closeTimeout) {
      clearTimeout(this.closeTimeout);
    }
    // Set the toast to close after the duration.
    if (config.duration !== 0) {
      const duration = config.duration > 0 ? config.duration : 1500;
      this.closeTimeout = setTimeout(
        this.closeToast.bind(this, 'timeout'),
        duration
      );
    }
    // Fade the toast in now.
    Animated.timing(this.state.fadeAnim, {
      toValue: 1,
      duration: 200
    }).start();
  }
  closeModal(reason) {
    this.setState({
      modalVisible: false
    });
    const { onClose } = this.state;
    if (onClose && typeof onClose === 'function') {
      onClose(reason);
    }
  }
  closeToast(reason) {
    clearTimeout(this.closeTimeout);
    Animated.timing(this.state.fadeAnim, {
      toValue: 0,
      duration: 200
    }).start(this.closeModal.bind(this, reason));
  }

  render() {
    if (this.state.modalVisible) {
      return (
        <Animated.View
          style={this.getToastStyle()}
          {...this._panResponder.panHandlers}
        >
          <Toast
            style={this.state.style}
            danger={this.state.type === 'danger'}
            success={this.state.type === 'success'}
            warning={this.state.type === 'warning'}
          >
            <Text style={this.state.textStyle}>{this.state.text}</Text>
            {this.state.buttonText && (
              <Button
                style={this.state.buttonStyle}
                onPress={() => this.closeToast('user')}
              >
                <Text style={this.state.buttonTextStyle}>
                  {this.state.buttonText}
                </Text>
              </Button>
            )}
          </Toast>
        </Animated.View>
      );
    }
    return null;
  }
}

ToastContainer.propTypes = {
  ...ViewPropTypes,
  style: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.number,
    PropTypes.array
  ])
};

const StyledToastContainer = connectStyle(
  'NativeBase.ToastContainer',
  {},
  mapPropsToStyleNames
)(ToastContainer);

export { StyledToastContainer as ToastContainer };
<commit_msg>Moved to toast<commit_after>/* eslint-disable class-methods-use-this */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
  Keyboard,
  Platform,
  Animated,
  ViewPropTypes,
  PanResponder
} from 'react-native';
import { connectStyle } from 'native-base-shoutem-theme';

import mapPropsToStyleNames from '../utils/mapPropsToStyleNames';
import { PLATFORM } from '../theme/variables/commonColor';

import { Text } from './Text';
import { Button } from './Button';
import { Toast } from './Toast';

const POSITION = {
  ABSOLUTE: 'absolute',
  BOTTOM: 'bottom',
  TOP: 'top'
};

class ToastContainer extends Component {
  static toastInstance;
  static show({ ...config }) {
    this.toastInstance._root.showToast({ config });
  }
  static hide() {
    if (this.toastInstance._root.getModalState()) {
      this.toastInstance._root.closeToast('functionCall');
    }
  }
  constructor(props) {
    super(props);

    this.state = {
      fadeAnim: new Animated.Value(0),
      keyboardHeight: 0,
      isKeyboardVisible: false,
      modalVisible: false
    };

    this.keyboardDidHide = this.keyboardDidHide.bind(this);
    this.keyboardDidShow = this.keyboardDidShow.bind(this);

    this._panResponder = PanResponder.create({
      onMoveShouldSetPanResponderCapture: () => true,
      onPanResponderRelease: (evt, gestureState) => {
        if (gestureState.moveX > gestureState.x0) {
          console.log('RIGHT');
          this.closeToast('user');
        }
        if (gestureState.moveX < gestureState.x0) {
          console.log('LEFT');
          this.closeToast('user');
        }
      }
    });
  }

  componentDidMount() {
    Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);
    Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);
  }

  getToastStyle() {
    return {
      position: POSITION.ABSOLUTE,
      opacity: this.state.fadeAnim,
      width: '100%',
      elevation: 9,
      paddingHorizontal: Platform.OS === PLATFORM.IOS ? 20 : 0,
      top: this.state.position === POSITION.TOP ? 30 : undefined,
      bottom:
        this.state.position === POSITION.BOTTOM ? this.getTop() : undefined
    };
  }

  getTop() {
    if (Platform.OS === PLATFORM.IOS) {
      if (this.state.isKeyboardVisible) {
        return this.state.keyboardHeight;
      }
      return 30;
    }
    return 0;
  }

  getButtonText(buttonText) {
    if (buttonText) {
      if (buttonText.trim().length === 0) {
        return undefined;
      }
      return buttonText;
    }
    return undefined;
  }
  getModalState() {
    return this.state.modalVisible;
  }

  keyboardDidHide() {
    this.setState({
      keyboardHeight: 0,
      isKeyboardVisible: false
    });
  }

  keyboardDidShow(e) {
    this.setState({
      keyboardHeight: e.endCoordinates.height,
      isKeyboardVisible: true
    });
  }

  showToast({ config }) {
    this.setState({
      modalVisible: true,
      text: config.text,
      buttonText: this.getButtonText(config.buttonText),
      type: config.type,
      position: config.position ? config.position : POSITION.BOTTOM,
      supportedOrientations: config.supportedOrientations,
      style: config.style,
      buttonTextStyle: config.buttonTextStyle,
      buttonStyle: config.buttonStyle,
      textStyle: config.textStyle,
      onClose: config.onClose
    });
    // If we have a toast already open, cut off its close timeout so that it won't affect *this* toast.
    if (this.closeTimeout) {
      clearTimeout(this.closeTimeout);
    }
    // Set the toast to close after the duration.
    if (config.duration !== 0) {
      const duration = config.duration > 0 ? config.duration : 1500;
      this.closeTimeout = setTimeout(
        this.closeToast.bind(this, 'timeout'),
        duration
      );
    }
    // Fade the toast in now.
    Animated.timing(this.state.fadeAnim, {
      toValue: 1,
      duration: 200
    }).start();
  }
  closeModal(reason) {
    this.setState({
      modalVisible: false
    });
    const { onClose } = this.state;
    if (onClose && typeof onClose === 'function') {
      onClose(reason);
    }
  }
  closeToast(reason) {
    clearTimeout(this.closeTimeout);
    Animated.timing(this.state.fadeAnim, {
      toValue: 0,
      duration: 200
    }).start(this.closeModal.bind(this, reason));
  }

  render() {
    if (this.state.modalVisible) {
      return (
        <Animated.View style={this.getToastStyle()}>
          <Toast
            {...this._panResponder.panHandlers}
            style={this.state.style}
            danger={this.state.type === 'danger'}
            success={this.state.type === 'success'}
            warning={this.state.type === 'warning'}
          >
            <Text style={this.state.textStyle}>{this.state.text}</Text>
            {this.state.buttonText && (
              <Button
                style={this.state.buttonStyle}
                onPress={() => this.closeToast('user')}
              >
                <Text style={this.state.buttonTextStyle}>
                  {this.state.buttonText}
                </Text>
              </Button>
            )}
          </Toast>
        </Animated.View>
      );
    }
    return null;
  }
}

ToastContainer.propTypes = {
  ...ViewPropTypes,
  style: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.number,
    PropTypes.array
  ])
};

const StyledToastContainer = connectStyle(
  'NativeBase.ToastContainer',
  {},
  mapPropsToStyleNames
)(ToastContainer);

export { StyledToastContainer as ToastContainer };
<|endoftext|>


<commit_before>import React, { useState, useEffect } from 'react'
import {
    Card,
    CardActions,
    CardContent,
    Button,
    TextField,
    Grid,
    Typography,
} from '@material-ui/core';
import DateFnsUtils from '@date-io/date-fns';
import {
    MuiPickersUtilsProvider,
    KeyboardDatePicker,
} from '@material-ui/pickers';
import LocationAutocompleteInput from "../Utilities/LocationAutocompleteInput"
import PreferenceForm from "../Utilities/PreferenceForm"

export default class TripSettingFormPopover extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isValidated: false,
            tripSetting: this.props.tripSetting
        };
        this.handleValidation = this.handleValidation.bind(this);
        this.handleDataChange = this.handleDataChange.bind(this);
        this.handleSave = this.handleSave.bind(this);
    }

    handleValidation(isValidated) {
        if (this.state.isValidated !== isValidated) {
            this.setState({ isValidated: isValidated });
        }
    }

    handleDataChange(newTripSetting) {
        this.setState({ tripSetting: newTripSetting });
    }

    handleSave() {
        // Doesn't save data if improper input --> doesn't close popover which shows error
        if (!this.state.isValidated) {
            return;
        }
        else {
            this.props.onEditTripSetting(this.state.tripSetting);
            this.props.onClose();
        }
    }

    render() {
        return (
            <Card id="add-form-container" style={{ height: "350px" }}>
                <CardContent>
                    <EditTripSetting
                        tripSetting={this.props.tripSetting}
                        onValidation={this.handleValidation}
                        onDataChange={this.handleDataChange}
                    />
                </CardContent>
                <CardActions>
                    <Button onClick={this.props.onClose} size="small">Cancel</Button>
                    <Button onClick={this.handleSave} size="small">Save</Button>
                </CardActions>
            </Card>
        )
    }
}

function EditTripSetting(props) {
    // Sets values to previous values if editing, otherwise blank slate
    const [title, setTitle] = useState(props.tripSetting.title);
    const [destination, setDestination] = useState(props.tripSetting.destination);
    const [startDate, setStartDate] = useState(props.tripSetting.startDate);
    const [endDate, setEndDate] = useState(props.tripSetting.endDate);
    const [description, setDescription] = useState(props.tripSetting.description);
    const [userPref, setUserPref] = useState(props.tripSetting.userPref);

    const handleTitleChange = (event) => {
        setTitle(event.target.value);
    }

    const handleDestinationChange = (location) => {
        setDestination(location);
    }

    const handleStartDateChange = (newStartDate) => {
        if (newStartDate > endDate) {
            setEndDate(newStartDate);
        }
        setStartDate(newStartDate);

    }

    const handleEndDateChange = (newEndDate) => {
        if (startDate > newEndDate) {
            setStartDate(newEndDate);
        }
        setEndDate(newEndDate);
    }

    const handleDescriptionChange = (event) => {
        setDescription(event.target.value);
    }

    const handleUserPrefChange = (pref) => {
        setUserPref(pref);
    }

    useEffect(() => {
        props.onDataChange({
            title: title,
            destination: destination,
            startDate: startDate,
            endDate: endDate,
            description: description,
            userPref: userPref
        })
        // notifies form if necessary inputs are present
        props.onValidation(!(!destination || (title === "")))
    }, [destination, startDate, endDate, description, userPref])

    return (

            <Grid container direction="column">
                <Grid>
                    <Typography variant={"h4"} gutterBottom>New Trip</Typography>
                </Grid>
                <Grid item container direction="row" justify="space-between">
                    <TextField
                        error={title === ""}
                        helperText={(title === "") ? "Cannot leave field blank" : null}
                        id="title"
                        label={"Title"}
                        defaultValue={title}
                        onChange={handleTitleChange}
                    />
                </Grid>
                <Grid item container direction="row" justify="space-between"></Grid>
                <LocationAutocompleteInput
                    onLocationSelected={handleDestinationChange}
                    error={!destination}
                    helperText={!destination ? "Cannot leave field blank, list your destinations, and separate them using comma" : null}
                    text={destination ? destination.address : ""}
                    type="other"
                />
            </Grid>
            <Grid item container direction="row" justify="space-between">
                <MuiPickersUtilsProvider utils={DateFnsUtils}>
                    <KeyboardDatePicker
                        variant="inline"
                        format="MM/dd/yyyy"
                        margin="normal"
                        id="startDate"
                        label="Date Start"
                        value={startDate}
                        onChange={handleStartDateChange}
                    />
                    <KeyboardDatePicker
                        variant="inline"
                        format="MM/dd/yyyy"
                        margin="normal"
                        id="endDate"
                        label="Date End"
                        value={endDate}
                        onChange={handleEndDateChange}
                    />
                </MuiPickersUtilsProvider>
            </Grid>
            <Grid item>
                <TextField
                    id="description"
                    label={"Add Description"}
                    defaultValue={description}
                    fullWidth
                    multiline
                    onChange={handleDescriptionChange}
                />
            </Grid>
            <PreferenceForm pref={userPref} onChange={handleUserPrefChange} />

    )
}

<commit_msg>fix sizing of trip settings popover<commit_after>import React, { useState, useEffect } from 'react'
import {
    Card,
    CardActions,
    CardContent,
    Button,
    TextField,
    Grid,
    Typography,
    Box
} from '@material-ui/core';
import DateFnsUtils from '@date-io/date-fns';
import {
    MuiPickersUtilsProvider,
    KeyboardDatePicker,
} from '@material-ui/pickers';
import LocationAutocompleteInput from "../Utilities/LocationAutocompleteInput"
import PreferenceForm from "../Utilities/PreferenceForm"

export default class TripSettingFormPopover extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isValidated: false,
            tripSetting: this.props.tripSetting
        };
        this.handleValidation = this.handleValidation.bind(this);
        this.handleDataChange = this.handleDataChange.bind(this);
        this.handleSave = this.handleSave.bind(this);
    }

    handleValidation(isValidated) {
        if (this.state.isValidated !== isValidated) {
            this.setState({ isValidated: isValidated });
        }
    }

    handleDataChange(newTripSetting) {
        this.setState({ tripSetting: newTripSetting });
    }

    handleSave() {
        // Doesn't save data if improper input --> doesn't close popover which shows error
        if (!this.state.isValidated) {
            return;
        }
        else {
            this.props.onEditTripSetting(this.state.tripSetting);
            this.props.onClose();
        }
    }

    render() {
        return (
            <Card>
                <Box width={600}>
                    <CardContent>
                        <EditTripSetting
                            tripSetting={this.props.tripSetting}
                            onValidation={this.handleValidation}
                            onDataChange={this.handleDataChange}
                        />
                    </CardContent>
                    <CardActions>
                        <Button onClick={this.props.onClose} size="small">Cancel</Button>
                        <Button onClick={this.handleSave} size="small">Save</Button>
                    </CardActions>
                </Box>
            </Card>
        )
    }
}

function EditTripSetting(props) {
    // Sets values to previous values if editing, otherwise blank slate
    const [title, setTitle] = useState(props.tripSetting.title);
    const [destination, setDestination] = useState(props.tripSetting.destination);
    const [startDate, setStartDate] = useState(props.tripSetting.startDate);
    const [endDate, setEndDate] = useState(props.tripSetting.endDate);
    const [description, setDescription] = useState(props.tripSetting.description);
    const [userPref, setUserPref] = useState(props.tripSetting.userPref);

    const handleTitleChange = (event) => {
        setTitle(event.target.value);
    }

    const handleDestinationChange = (location) => {
        setDestination(location);
    }

    const handleStartDateChange = (newStartDate) => {
        if (newStartDate > endDate) {
            setEndDate(newStartDate);
        }
        setStartDate(newStartDate);

    }

    const handleEndDateChange = (newEndDate) => {
        if (startDate > newEndDate) {
            setStartDate(newEndDate);
        }
        setEndDate(newEndDate);
    }

    const handleDescriptionChange = (event) => {
        setDescription(event.target.value);
    }

    const handleUserPrefChange = (pref) => {
        setUserPref(pref);
    }

    useEffect(() => {
        props.onDataChange({
            title: title,
            destination: destination,
            startDate: startDate,
            endDate: endDate,
            description: description,
            userPref: userPref
        })
        // notifies form if necessary inputs are present
        props.onValidation(!(!destination || (title === "")))
    }, [destination, startDate, endDate, description, userPref])

    return (

            <Grid container direction="column">
                <Grid>
                    <Typography variant={"h4"} gutterBottom>New Trip</Typography>
                </Grid>
                <Grid item container direction="row" justify="space-between">
                    <TextField
                        error={title === ""}
                        helperText={(title === "") ? "Cannot leave field blank" : null}
                        id="title"
                        label={"Title"}
                        defaultValue={title}
                        onChange={handleTitleChange}
                    />
                </Grid>
                <Grid item container direction="row" justify="space-between"></Grid>
                <LocationAutocompleteInput
                    onLocationSelected={handleDestinationChange}
                    error={!destination}
                    helperText={!destination ? "Cannot leave field blank, list your destinations, and separate them using comma" : null}
                    text={destination ? destination.address : ""}
                    type="other"
                />
            </Grid>
            <Grid item container direction="row" justify="space-between">
                <MuiPickersUtilsProvider utils={DateFnsUtils}>
                    <KeyboardDatePicker
                        variant="inline"
                        format="MM/dd/yyyy"
                        margin="normal"
                        id="startDate"
                        label="Date Start"
                        value={startDate}
                        onChange={handleStartDateChange}
                    />
                    <KeyboardDatePicker
                        variant="inline"
                        format="MM/dd/yyyy"
                        margin="normal"
                        id="endDate"
                        label="Date End"
                        value={endDate}
                        onChange={handleEndDateChange}
                    />
                </MuiPickersUtilsProvider>
            </Grid>
            <Grid item>
                <TextField
                    id="description"
                    label={"Add Description"}
                    defaultValue={description}
                    fullWidth
                    multiline
                    onChange={handleDescriptionChange}
                />
            </Grid>
            <PreferenceForm pref={userPref} onChange={handleUserPrefChange} />

    )
}

<|endoftext|>


<commit_before>import ENSManager from './ens-manager-dapp/TheENSManagerLayout.vue';
import MakerDAO from './makerdao/MakerDAO';
import Aave from './aave-dapp/Aave';
import Ambrpay from './AmbrpayDapp/Ambrpay';
import UnstoppableDomain from './unstoppable-domains/UnstoppableDomain';
import Dapps from '@/modules/dapps-center/ModuleDappsCenter';

export default [
  {
    path: '',
    name: 'Dapps',
    component: Dapps
  },
  {
    path: 'ens-manager',
    name: 'ENSManager',
    component: ENSManager
  },
  {
    path: 'maker-dao',
    name: 'MakerDAO',
    component: MakerDAO
  },
  {
    path: 'aave',
    name: 'Aave',
    component: Aave
  },
  {
    path: 'ambrpay',
    name: 'Ambrpay',
    component: Ambrpay
  },
  {
    path: 'unstoppable-domain',
    name: 'UnstoppableDomain',
    component: UnstoppableDomain
  }
];
<commit_msg>fix ambrpay route<commit_after>import ENSManager from './ens-manager-dapp/TheENSManagerLayout.vue';
import MakerDAO from './makerdao/MakerDAO';
import Aave from './aave-dapp/Aave';
import Ambrpay from './ambrpay-dapp/TheAmbrpayLayout';
import UnstoppableDomain from './unstoppable-domains/UnstoppableDomain';
import Dapps from '@/modules/dapps-center/ModuleDappsCenter';

export default [
  {
    path: '',
    name: 'Dapps',
    component: Dapps
  },
  {
    path: 'ens-manager',
    name: 'ENSManager',
    component: ENSManager
  },
  {
    path: 'maker-dao',
    name: 'MakerDAO',
    component: MakerDAO
  },
  {
    path: 'aave',
    name: 'Aave',
    component: Aave
  },
  {
    path: 'ambrpay',
    name: 'Ambrpay',
    component: Ambrpay
  },
  {
    path: 'unstoppable-domain',
    name: 'UnstoppableDomain',
    component: UnstoppableDomain
  }
];
<|endoftext|>