<commit_before>import React, { Component } from 'react'
import { Alert, Form, FormGroup, FormFeedback, Input } from 'reactstrap'
import { Field, FieldArray, reduxForm } from 'redux-form'
import { Tooltip } from 'reactstrap';
import ButtonConfirmAction from '../ButtonConfirmAction'
import { toSafeInteger, without } from 'lodash'
import { forEach } from 'lodash'

const MIN_PORT = 1
const MAX_PORT = 65535

const validatePortRange = value => {
  const number = toSafeInteger(value)

  if ( number < MIN_PORT || number > MAX_PORT ) {
    return `Invalid port. Must be between ${MIN_PORT} and less than ${MAX_PORT}`
  }
}

const renderInput = ({input, _meta, ...field}) => {
  let _field = without(field, ["meta"])
  return (
    <Input {..._field} {...input} type={field.type} placeholder={field.placeholder} disabled={field.disabled} />
  )
}

const normalizeInt = (value, _previousValue) => {
  return parseInt(value, 10)
}

const normalizeBool = (value, _previousValue) => {
    if(value === ""){
        return false
    }
    return true
}

const InputWithWarnings = props => {
  const { error, touched } = props.meta

  return (
    <FormGroup color={error ? "danger" : ""}>
      {renderInput(props)}
      {touched && error && <FormFeedback>{error}</FormFeedback>}
    </FormGroup>
  )
}

const renderListeners = ({ fields }) => (

    { (fields.length > 0) && Container ports}
    {fields.map((service, i) =>

        <Field name={'listeners['+i+'].port'} component={InputWithWarnings} validate={validatePortRange} type="number" step="1" min={MIN_PORT} max={MAX_PORT} normalize={normalizeInt}/>

            <Field className="form-check-input" name={'listeners['+i+'].protocol'} component={renderInput} type="radio" value="TCP"/> TCP

            <Field className="form-check-input" name={'listeners['+i+'].protocol'} component={renderInput} type="radio" value="UDP"/> UDP

        <button type="button" className="btn btn-secondary btn-sm float-xs-right btn-service-action-right" onClick={() => fields.remove(i)}>

        </button>

    )}

        <button type="button" className="btn btn-secondary btn-sm float-xs-left btn-service-action" onClick={() => fields.push({ protocol: 'TCP' })}>Add container port </button>

  )

const renderSpecsSelect = field => {
  return (
    <select {...field.input} name={field.name} className="form-control">
      <option disabled value="">Choose service spec</option>
      {field.serviceSpecs.map(function (spec) {
        return <option key={spec._id} value={spec._id}>{spec.name}</option>
      })}
    </select>
  )
}

class ProjectServiceForm extends Component {
  constructor(props) {
    super(props);

    this.toggleContainerPort = this.toggleContainerPort.bind(this);
    this.toggleTooltipServiceSettings = this.toggleTooltipServiceSettings.bind(this);
    this.state = {
      tooltipContainerPortOpen: false,
      tooltipServiceSettingsOpen: false
    };
  }

  toggleContainerPort() {
    this.setState({
      tooltipContainerPortOpen: !this.state.tooltipContainerPortOpen
    })
  }

  toggleTooltipServiceSettings() {
    this.setState({
      tooltipServiceSettingsOpen: !this.state.tooltipServiceSettingsOpen
    })
  }

  renderServiceSpecsTip() {
    let { serviceSpecs } = this.props
    let specs_jsx = []

    forEach(serviceSpecs, spec => {
      specs_jsx.push(this.renderQuickSpec(spec))
    })
    return specs_jsx
  }

  renderQuickSpec(spec) {
    return (

{spec.name}

          CPU: {spec.cpuRequest} / {spec.cpuLimit}

          Memory: {spec.memoryRequest} / {spec.memoryLimit}

          Termination: {spec.terminationGracePeriodSeconds}s

    )
  }

  render() {
    const { edit, onCancel, onDelete, handleSubmit, error } = this.props
    return (
        <Form onSubmit={handleSubmit} noValidate>
          { error &&
            <Alert color="danger">{error}</Alert>
          }
          <FormGroup>

                      Name
                      <Field name="name" className="form-control" component={renderInput} disabled={edit} type="text"/>

                        Spec

                        <Field className="form-control" name="specId" serviceSpecs={this.props.serviceSpecs} component={renderSpecsSelect}/>

                      <Tooltip placement="right" isOpen={this.state.tooltipServiceSettingsOpen} target="ToolTipServiceSettings" toggle={this.toggleTooltipServiceSettings}>
                        {this.renderServiceSpecsTip()}
                      </Tooltip>

                      Count
                      <Field name="count" component={renderInput} type="number" step="1" min="0" max="100" normalize={normalizeInt}/>

                  Command
                  <Field name="command" className="form-control" component={renderInput} type="text"/>

                  <Field className="form-check-input" name="oneShot" component={renderInput} type="checkbox" value="false" normalize={normalizeBool} /> One-shot

                    <Tooltip placement="right" isOpen={this.state.tooltipContainerPortOpen} target="ToolTipContainerPort" toggle={this.toggleContainerPort}>
                      If your application is a webserver then add the port that it listens on.
                    </Tooltip>

                  <FieldArray name="listeners" component={renderListeners}/>

                <button type="button" className="btn btn-secondary btn-sm float-xs-right btn-service-action-right" onClick={() => onCancel()}>
                   Cancel
                </button>
                { edit &&
                <ButtonConfirmAction btnLabel="Delete" btnIconClass="fa fa-trash" onConfirm={onDelete} btnClass="btn btn-danger btn-sm float-xs-right btn-service-action-right">
                  Are you sure?
                </ButtonConfirmAction>}
                <button type="submit" className="btn btn-success btn-sm float-xs-right btn-service-action-right">
                   Save
                </button>

          </FormGroup>
        </Form>
    )
  }
}

export default reduxForm({
  enableReinitialize: true,
  destroyOnUnmount: true,
  form: 'projectService'
})(ProjectServiceForm)
<commit_msg>Better to render this tooltip below instead of to the right.<commit_after>import React, { Component } from 'react'
import { Alert, Form, FormGroup, FormFeedback, Input } from 'reactstrap'
import { Field, FieldArray, reduxForm } from 'redux-form'
import { Tooltip } from 'reactstrap';
import ButtonConfirmAction from '../ButtonConfirmAction'
import { toSafeInteger, without } from 'lodash'
import { forEach } from 'lodash'

const MIN_PORT = 1
const MAX_PORT = 65535

const validatePortRange = value => {
  const number = toSafeInteger(value)

  if ( number < MIN_PORT || number > MAX_PORT ) {
    return `Invalid port. Must be between ${MIN_PORT} and less than ${MAX_PORT}`
  }
}

const renderInput = ({input, _meta, ...field}) => {
  let _field = without(field, ["meta"])
  return (
    <Input {..._field} {...input} type={field.type} placeholder={field.placeholder} disabled={field.disabled} />
  )
}

const normalizeInt = (value, _previousValue) => {
  return parseInt(value, 10)
}

const normalizeBool = (value, _previousValue) => {
    if(value === ""){
        return false
    }
    return true
}

const InputWithWarnings = props => {
  const { error, touched } = props.meta

  return (
    <FormGroup color={error ? "danger" : ""}>
      {renderInput(props)}
      {touched && error && <FormFeedback>{error}</FormFeedback>}
    </FormGroup>
  )
}

const renderListeners = ({ fields }) => (

    { (fields.length > 0) && Container ports}
    {fields.map((service, i) =>

        <Field name={'listeners['+i+'].port'} component={InputWithWarnings} validate={validatePortRange} type="number" step="1" min={MIN_PORT} max={MAX_PORT} normalize={normalizeInt}/>

            <Field className="form-check-input" name={'listeners['+i+'].protocol'} component={renderInput} type="radio" value="TCP"/> TCP

            <Field className="form-check-input" name={'listeners['+i+'].protocol'} component={renderInput} type="radio" value="UDP"/> UDP

        <button type="button" className="btn btn-secondary btn-sm float-xs-right btn-service-action-right" onClick={() => fields.remove(i)}>

        </button>

    )}

        <button type="button" className="btn btn-secondary btn-sm float-xs-left btn-service-action" onClick={() => fields.push({ protocol: 'TCP' })}>Add container port </button>

  )

const renderSpecsSelect = field => {
  return (
    <select {...field.input} name={field.name} className="form-control">
      <option disabled value="">Choose service spec</option>
      {field.serviceSpecs.map(function (spec) {
        return <option key={spec._id} value={spec._id}>{spec.name}</option>
      })}
    </select>
  )
}

class ProjectServiceForm extends Component {
  constructor(props) {
    super(props);

    this.toggleContainerPort = this.toggleContainerPort.bind(this);
    this.toggleTooltipServiceSettings = this.toggleTooltipServiceSettings.bind(this);
    this.state = {
      tooltipContainerPortOpen: false,
      tooltipServiceSettingsOpen: false
    };
  }

  toggleContainerPort() {
    this.setState({
      tooltipContainerPortOpen: !this.state.tooltipContainerPortOpen
    })
  }

  toggleTooltipServiceSettings() {
    this.setState({
      tooltipServiceSettingsOpen: !this.state.tooltipServiceSettingsOpen
    })
  }

  renderServiceSpecsTip() {
    let { serviceSpecs } = this.props
    let specs_jsx = []

    forEach(serviceSpecs, spec => {
      specs_jsx.push(this.renderQuickSpec(spec))
    })
    return specs_jsx
  }

  renderQuickSpec(spec) {
    return (

{spec.name}

          CPU: {spec.cpuRequest} / {spec.cpuLimit}

          Memory: {spec.memoryRequest} / {spec.memoryLimit}

          Termination: {spec.terminationGracePeriodSeconds}s

    )
  }

  render() {
    const { edit, onCancel, onDelete, handleSubmit, error } = this.props
    return (
        <Form onSubmit={handleSubmit} noValidate>
          { error &&
            <Alert color="danger">{error}</Alert>
          }
          <FormGroup>

                      Name
                      <Field name="name" className="form-control" component={renderInput} disabled={edit} type="text"/>

                        Spec

                        <Field className="form-control" name="specId" serviceSpecs={this.props.serviceSpecs} component={renderSpecsSelect}/>

                      <Tooltip placement="bottom" isOpen={this.state.tooltipServiceSettingsOpen} target="ToolTipServiceSettings" toggle={this.toggleTooltipServiceSettings}>
                        {this.renderServiceSpecsTip()}
                      </Tooltip>

                      Count
                      <Field name="count" component={renderInput} type="number" step="1" min="0" max="100" normalize={normalizeInt}/>

                  Command
                  <Field name="command" className="form-control" component={renderInput} type="text"/>

                  <Field className="form-check-input" name="oneShot" component={renderInput} type="checkbox" value="false" normalize={normalizeBool} /> One-shot

                    <Tooltip placement="right" isOpen={this.state.tooltipContainerPortOpen} target="ToolTipContainerPort" toggle={this.toggleContainerPort}>
                      If your application is a webserver then add the port that it listens on.
                    </Tooltip>

                  <FieldArray name="listeners" component={renderListeners}/>

                <button type="button" className="btn btn-secondary btn-sm float-xs-right btn-service-action-right" onClick={() => onCancel()}>
                   Cancel
                </button>
                { edit &&
                <ButtonConfirmAction btnLabel="Delete" btnIconClass="fa fa-trash" onConfirm={onDelete} btnClass="btn btn-danger btn-sm float-xs-right btn-service-action-right">
                  Are you sure?
                </ButtonConfirmAction>}
                <button type="submit" className="btn btn-success btn-sm float-xs-right btn-service-action-right">
                   Save
                </button>

          </FormGroup>
        </Form>
    )
  }
}

export default reduxForm({
  enableReinitialize: true,
  destroyOnUnmount: true,
  form: 'projectService'
})(ProjectServiceForm)
<|endoftext|>


<commit_before>function initType(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function String$(x){};//IGNORE
function Character(x){};//IGNORE
function inheritProto(a,b,c,d,e,f,g);//IGNORE
function Exception$(x){};//IGNORE
var Object$,Integral,Numeric,Exponentiable,Scalar,equal,smaller,larger,exports;//IGNORE

function JSNumber(value) { return Number(value); }
initExistingType(JSNumber, Number, 'ceylon.language::JSNumber');
var origNumToString = Number.prototype.toString;
inheritProto(JSNumber, Object$, Scalar, $init$Integral(), Exponentiable);

function Integer(value) { return Number(value); }
initTypeProto(Integer, 'ceylon.language::Integer', Object$, Scalar,
        $init$Integral(), Exponentiable, Binary);

function Float(value) {
    var that = new Number(value);
    that.float$ = true;
    return that;
}
initTypeProto(Float, 'ceylon.language::Float', Object$, Scalar, Exponentiable);

var JSNum$proto = Number.prototype;
JSNum$proto.getT$all = function() {
    return (this.float$ ? Float : Integer).$$.T$all;
}
JSNum$proto.getT$name = function() {
    return (this.float$ ? Float : Integer).$$.T$name;
}
JSNum$proto.toString = origNumToString;
defineAttr(JSNum$proto, 'string', function(){ return String$(this.toString()); });
JSNum$proto.plus = function(other) {
    return (this.float$||other.float$) ? Float(this+other) : (this+other);
}
JSNum$proto.minus = function(other) {
    return (this.float$||other.float$) ? Float(this-other) : (this-other);
}
JSNum$proto.times = function(other) {
    return (this.float$||other.float$) ? Float(this*other) : (this*other);
}
JSNum$proto.divided = function(other) {
    if (this.float$||other.float$) { return Float(this/other); }
    if (other == 0) {
        throw Exception(String$("Division by Zero"));
    }
    return (this/other)|0;
}
JSNum$proto.remainder = function(other) { return this%other; }
JSNum$proto.power = function(exp) {
    if (this.float$||exp.float$) { return Float(Math.pow(this, exp)); }
    if (exp<0 && this!=1 && this!=-1) {
        throw Exception(String$("Negative exponent"));
    }
    return Math.pow(this, exp)|0;
}
defineAttr(JSNum$proto, 'negativeValue', function() {
    return this.float$ ? Float(-this) : -this;
});
defineAttr(JSNum$proto, 'positiveValue', function() {
    return this.float$ ? this : this.valueOf();
});
JSNum$proto.equals = function(other) { return other==this.valueOf(); }
JSNum$proto.compare = function(other) {
    var value = this.valueOf();
    return value==other ? equal : (value<other ? smaller:larger);
}
defineAttr(JSNum$proto, '$float', function(){ return Float(this.valueOf()); });
defineAttr(JSNum$proto, 'integer', function(){ return this|0; });
defineAttr(JSNum$proto, 'integerValue', function(){ return this|0; });
defineAttr(JSNum$proto, 'character', function(){ return Character(this.valueOf()); });
defineAttr(JSNum$proto, 'successor', function(){ return this+1; });
defineAttr(JSNum$proto, 'predecessor', function(){ return this-1; });
defineAttr(JSNum$proto, 'unit', function(){ return this == 1; });
defineAttr(JSNum$proto, 'zero', function(){ return this == 0; });
defineAttr(JSNum$proto, 'fractionalPart', function() {
    if (!this.float$) { return 0; }
    return Float(this - (this>=0 ? Math.floor(this) : Math.ceil(this)));
});
defineAttr(JSNum$proto, 'wholePart', function() {
    if (!this.float$) { return this.valueOf(); }
    return Float(this>=0 ? Math.floor(this) : Math.ceil(this));
});
defineAttr(JSNum$proto, 'sign', function(){ return this > 0 ? 1 : this < 0 ? -1 : 0; });
defineAttr(JSNum$proto, 'hash', function() {
    return this.float$ ? String$(this.toPrecision()).hash : this.valueOf();
});
JSNum$proto.distanceFrom = function(other) {
    return (this.float$ ? this.wholePart : this) - other;
}
//Binary interface
defineAttr(JSNum$proto, 'not', function(){ return ~this; });
JSNum$proto.leftLogicalShift = function(i) { return this << i; }
JSNum$proto.rightLogicalShift = function(i) { return this >> i; }
JSNum$proto.rightArithmeticShift = function(i) { return this >>> i; }
JSNum$proto.and = function(x) { return this & x; }
JSNum$proto.or = function(x) { return this | x; }
JSNum$proto.xor = function(x) { return this ^ x; }
JSNum$proto.get = function(idx) {
    var mask = 1 << idx;
    return (this & mask) != 0 ? $true : $false;
}
JSNum$proto.set = function(idx,bit) {
    if (bit === undefined) { bit = $true; }
        var mask = idx > 1 ? 1 << idx : 1;
    return (bit === $true) ? this | mask : this & ~mask;
}
JSNum$proto.flip = function(idx) {
    var mask = 1 << idx;
    return this ^ mask;
}
JSNum$proto.clear = function(index) {
    return this.set(index, false);
}
defineAttr(JSNum$proto, 'size', function(){ return 53; });
defineAttr(JSNum$proto, 'magnitude', function(){ return Math.abs(this); });

function $parseInteger(s) {
    //xkcd.com/208/
    if (s.match(/^[+-]?\d+(_\d+)*[kMGPT]?$/g) === null) {
        return null;
    }
    s = s.replace(/_/g, "");
    var mag = null;
    if (s.match(/[kMGTP]$/g) !== null) {
        mag = s[s.length-1];
        s = s.slice(0,-1);
    }
    var i = parseInt(s);
    if (s[0]=='+') s = s.substring(1);
    if (s[0]=='-') {
        while (s[1]=='0') s='-'+s.substring(2);
    } else {
        while (s[0]=='0') s=s.substring(1);
    }
    if (i.toString()!==s) return null;
    var factor=1;
    switch(mag) {
        case 'P':factor*=1000;
        case 'T':factor*=1000;
        case 'G':factor*=1000;
        case 'M':factor*=1000;
        case 'k':factor*=1000;
    }
    return isNaN(i) ? null : i*factor;
}
function $parseFloat(s) { return Float(parseFloat(s)); }

defineAttr(JSNum$proto, 'undefined', function(){ return isNaN(this); });
defineAttr(JSNum$proto, 'finite', function(){ return this!=Infinity && this!=-Infinity && !isNaN(this); });
defineAttr(JSNum$proto, 'infinite', function(){ return this==Infinity || this==-Infinity; });
defineAttr(JSNum$proto, 'strictlyPositive', function(){ return this>0 || (this==0 && (1/this==Infinity)); });
defineAttr(JSNum$proto, 'strictlyNegative', function() { return this<0 || (this==0 && (1/this==-Infinity)); });

var $infinity = Float(Infinity);
function getInfinity() { return $infinity; }
//function getNegativeInfinity() { return Float(-Infinity); }

exports.Integer=Integer;
exports.Float=Float;
exports.getInfinity=getInfinity;
exports.parseInteger=$parseInteger;
exports.parseFloat=$parseFloat;
<commit_msg>fix #224 float truncation overflow<commit_after>function initType(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function String$(x){};//IGNORE
function Character(x){};//IGNORE
function inheritProto(a,b,c,d,e,f,g);//IGNORE
function Exception$(x){};//IGNORE
var Object$,Integral,Numeric,Exponentiable,Scalar,equal,smaller,larger,exports;//IGNORE

var toInt = function(float) {
    return (float >= 0) ? Math.floor(float) : Math.ceil(float);
}

function JSNumber(value) { return Number(value); }
initExistingType(JSNumber, Number, 'ceylon.language::JSNumber');
var origNumToString = Number.prototype.toString;
inheritProto(JSNumber, Object$, Scalar, $init$Integral(), Exponentiable);

function Integer(value) { return Number(value); }
initTypeProto(Integer, 'ceylon.language::Integer', Object$, Scalar,
        $init$Integral(), Exponentiable, Binary);

function Float(value) {
    var that = new Number(value);
    that.float$ = true;
    return that;
}
initTypeProto(Float, 'ceylon.language::Float', Object$, Scalar, Exponentiable);

var JSNum$proto = Number.prototype;
JSNum$proto.getT$all = function() {
    return (this.float$ ? Float : Integer).$$.T$all;
}
JSNum$proto.getT$name = function() {
    return (this.float$ ? Float : Integer).$$.T$name;
}
JSNum$proto.toString = origNumToString;
defineAttr(JSNum$proto, 'string', function(){ return String$(this.toString()); });
JSNum$proto.plus = function(other) {
    return (this.float$||other.float$) ? Float(this+other) : (this+other);
}
JSNum$proto.minus = function(other) {
    return (this.float$||other.float$) ? Float(this-other) : (this-other);
}
JSNum$proto.times = function(other) {
    return (this.float$||other.float$) ? Float(this*other) : (this*other);
}
JSNum$proto.divided = function(other) {
    if (this.float$||other.float$) { return Float(this/other); }
    if (other == 0) {
        throw Exception(String$("Division by Zero"));
    }
    return toInt(this/other);
}
JSNum$proto.remainder = function(other) { return this%other; }
JSNum$proto.power = function(exp) {
    if (this.float$||exp.float$) { return Float(Math.pow(this, exp)); }
    if (exp<0 && this!=1 && this!=-1) {
        throw Exception(String$("Negative exponent"));
    }
    return toInt(Math.pow(this, exp));
}
defineAttr(JSNum$proto, 'negativeValue', function() {
    return this.float$ ? Float(-this) : -this;
});
defineAttr(JSNum$proto, 'positiveValue', function() {
    return this.float$ ? this : this.valueOf();
});
JSNum$proto.equals = function(other) { return other==this.valueOf(); }
JSNum$proto.compare = function(other) {
    var value = this.valueOf();
    return value==other ? equal : (value<other ? smaller:larger);
}
defineAttr(JSNum$proto, '$float', function(){ return Float(this.valueOf()); });
defineAttr(JSNum$proto, 'integer', function(){ return toInt(this); });
defineAttr(JSNum$proto, 'integerValue', function(){ return toInt(this); });
defineAttr(JSNum$proto, 'character', function(){ return Character(this.valueOf()); });
defineAttr(JSNum$proto, 'successor', function(){ return this+1; });
defineAttr(JSNum$proto, 'predecessor', function(){ return this-1; });
defineAttr(JSNum$proto, 'unit', function(){ return this == 1; });
defineAttr(JSNum$proto, 'zero', function(){ return this == 0; });
defineAttr(JSNum$proto, 'fractionalPart', function() {
    if (!this.float$) { return 0; }
    return Float(this - (this>=0 ? Math.floor(this) : Math.ceil(this)));
});
defineAttr(JSNum$proto, 'wholePart', function() {
    if (!this.float$) { return this.valueOf(); }
    return Float(this>=0 ? Math.floor(this) : Math.ceil(this));
});
defineAttr(JSNum$proto, 'sign', function(){ return this > 0 ? 1 : this < 0 ? -1 : 0; });
defineAttr(JSNum$proto, 'hash', function() {
    return this.float$ ? String$(this.toPrecision()).hash : this.valueOf();
});
JSNum$proto.distanceFrom = function(other) {
    return (this.float$ ? this.wholePart : this) - other;
}
//Binary interface
defineAttr(JSNum$proto, 'not', function(){ return ~this; });
JSNum$proto.leftLogicalShift = function(i) { return this << i; }
JSNum$proto.rightLogicalShift = function(i) { return this >> i; }
JSNum$proto.rightArithmeticShift = function(i) { return this >>> i; }
JSNum$proto.and = function(x) { return this & x; }
JSNum$proto.or = function(x) { return this | x; }
JSNum$proto.xor = function(x) { return this ^ x; }
JSNum$proto.get = function(idx) {
    var mask = 1 << idx;
    return (this & mask) != 0 ? $true : $false;
}
JSNum$proto.set = function(idx,bit) {
    if (bit === undefined) { bit = $true; }
        var mask = idx > 1 ? 1 << idx : 1;
    return (bit === $true) ? this | mask : this & ~mask;
}
JSNum$proto.flip = function(idx) {
    var mask = 1 << idx;
    return this ^ mask;
}
JSNum$proto.clear = function(index) {
    return this.set(index, false);
}
defineAttr(JSNum$proto, 'size', function(){ return 53; });
defineAttr(JSNum$proto, 'magnitude', function(){ return Math.abs(this); });

function $parseInteger(s) {
    //xkcd.com/208/
    if (s.match(/^[+-]?\d+(_\d+)*[kMGPT]?$/g) === null) {
        return null;
    }
    s = s.replace(/_/g, "");
    var mag = null;
    if (s.match(/[kMGTP]$/g) !== null) {
        mag = s[s.length-1];
        s = s.slice(0,-1);
    }
    var i = parseInt(s);
    if (s[0]=='+') s = s.substring(1);
    if (s[0]=='-') {
        while (s[1]=='0') s='-'+s.substring(2);
    } else {
        while (s[0]=='0') s=s.substring(1);
    }
    if (i.toString()!==s) return null;
    var factor=1;
    switch(mag) {
        case 'P':factor*=1000;
        case 'T':factor*=1000;
        case 'G':factor*=1000;
        case 'M':factor*=1000;
        case 'k':factor*=1000;
    }
    return isNaN(i) ? null : i*factor;
}
function $parseFloat(s) { return Float(parseFloat(s)); }

defineAttr(JSNum$proto, 'undefined', function(){ return isNaN(this); });
defineAttr(JSNum$proto, 'finite', function(){ return this!=Infinity && this!=-Infinity && !isNaN(this); });
defineAttr(JSNum$proto, 'infinite', function(){ return this==Infinity || this==-Infinity; });
defineAttr(JSNum$proto, 'strictlyPositive', function(){ return this>0 || (this==0 && (1/this==Infinity)); });
defineAttr(JSNum$proto, 'strictlyNegative', function() { return this<0 || (this==0 && (1/this==-Infinity)); });

var $infinity = Float(Infinity);
function getInfinity() { return $infinity; }
//function getNegativeInfinity() { return Float(-Infinity); }

exports.Integer=Integer;
exports.Float=Float;
exports.getInfinity=getInfinity;
exports.parseInteger=$parseInteger;
exports.parseFloat=$parseFloat;
<|endoftext|>


<commit_before>import React from 'react'

export default props => (
  <style>{`
    * {
      -webkit-overflow-scrolling: touch;
    }
    html,body,#root {
      height:100%;
      margin:0;
    }
    a,button,div,img,input,form,h1,h2,h3,h4,h5,h6,h7,nav,label,li,ol,p,span,svg,ul {
      box-sizing: border-box;
      position: relative;
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-orient: vertical;
      -webkit-box-direction: normal;
          -ms-flex-direction: column;
              flex-direction: column;
      -webkit-box-align: stretch;
          -ms-flex-align: stretch;
              align-items: stretch;
      -ms-flex-negative: 0;
          flex-shrink: 0;
      margin: 0;
      padding: 0;
      outline: 0;
    }
    button::-moz-focus-inner {
      border: 0;
      margin: 0;
      padding: 0;
    }
  `}</style>
)
<commit_msg>fix: reset button and a on style<commit_after>import React from 'react'

export default props => (
  <style>{`
    * {
      -webkit-overflow-scrolling: touch;
    }
    html,body,#root {
      height:100%;
      margin:0;
    }
    a,button,div,img,input,form,h1,h2,h3,h4,h5,h6,h7,nav,label,li,ol,p,span,svg,ul {
      box-sizing: border-box;
      position: relative;
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-orient: vertical;
      -webkit-box-direction: normal;
          -ms-flex-direction: column;
              flex-direction: column;
      -webkit-box-align: stretch;
          -ms-flex-align: stretch;
              align-items: stretch;
      -ms-flex-negative: 0;
          flex-shrink: 0;
      margin: 0;
      padding: 0;
      outline: 0;
    }
    button,a {
      background-color: transparent;
      border: 0;
      margin: 0;
      padding: 0;
      white-space: normal;
      line-height: inherit;
      text-align: left;
      font-family: inherit;
      font-size: inherit;
    }
    button::-moz-focus-inner {
      border: 0;
      margin: 0;
      padding: 0;
    }
  `}</style>
)
<|endoftext|>


<commit_before>var
	fs = require("fs"),
	path = require("path"),
	walker = require("walker"),
	jsp = require("uglify-js").parser,
	pro = require("uglify-js").uglify
	;

options = function(args) {
	var opts = {};
	for (var i=2; i<args.length; i++) {
		var arg = args[i];
		if (arg[0] == "-") {
			var o = arg.slice(1);
			opts[o] = {enyo: 1, output: 1, alias: 1}[o] ? args[++i] : true;
		} else {
			opts.source = arg;
		}
	}
	w(opts);
	w("");
	return opts;
};

function printUsage() {
	w("Enyo 2.0 Minifier");
	w("Flags:")
	w("-no-alias:", "Don't use path macros");
	w("-alias ALIAS:", "Give paths a macroized alias");
	w("-enyo ENYOPATH:", "Path to enyo loader (enyo/enyo.js)");
	w("-output PATH/NAME:", "name of output file, prepend folder paths to change output directory");
	w("-h, -?, -help:", "Show this message");
}

// make a relative path from source to target
function makeRelPath(inSource, inTarget) {
	// node 0.5 has this nice thing, 0.4 does not
	if (path.relative) {
		return path.relative(inSource, inTarget);
	}
	var s,t;
	s = pathSplit(path.resolve(inSource));
	t = pathSplit(path.resolve(inTarget));
	while (s.length && s[0] === t[0]){
		s.shift();
		t.shift();
	}
	for(var i = 0, l = s.length; i < l; i++) {
		t.unshift("..");
	}
	return path.join.apply(null, t);
}

// properly split path based on platform
function pathSplit(inPath) {
	var sep = process.platform == "win32" ? "\\" : "/";
	return inPath.split(sep);
}

buildPathBlock = function(loader) {
	var p$ = [];
	for (var i=0, p; p=loader.packages[i]; i++) {
		if (p.name.indexOf("-") == -1) {
			p$.push(p.name + ': "' + p.folder + '"');
		}
	}
	var p = p$.join(', ');
	return !p ? "" : "\n// minifier: path aliases\n\nenyo.path.addPaths({" + p + "});\n";
};

concatCss = function(loader) {
	w("");
	var blob = "";
	for (var i=0, s; s=loader.sheets[i]; i++) {
		w(s);
		var code = fs.readFileSync(s, "utf8");
		// fix url paths
		code = code.replace(/url\([^)]*\)/g, function(inMatch) {
			// find the url path, ignore quotes in url string
			var urlPath = inMatch.replace(/["']/g, "").slice(4, -1);
			// skip data urls
			if (/^data:/.test(urlPath)) {
				return "url(" + urlPath + ")";
			}
			// get absolute path to referenced asset
			var normalizedUrlPath = path.join(s, "..", urlPath);
			// Make relative asset path to built css
			var relPath = makeRelPath(path.dirname(opt.output || "build"), normalizedUrlPath);
			if (process.platform == "win32") {
				relPath = pathSplit(relPath).join("/");
			}
			return "url(" + relPath + ")";
		});
		blob += "\n/* " + s + " */\n\n" + code + "\n";
	}
	return blob;
};

concatJs = function(loader) {
	w("");
	var blob = "";
	for (var i=0, m; m=loader.modules[i]; i++) {
		if (!opt["no-alias"] && !opt.alias) {
			w("* inserting path aliases");
			blob += buildPathBlock(loader);
			opt["no-alias"] = true;
		}
		w(m.path);
		blob += "\n// " + m.rawPath + "\n\n" + compressJsFile(m.path) + "\n";
		if (opt.alias == m.rawPath) {
			w("* inserting path aliases");
			blob += buildPathBlock(loader);
		}
	}
	return blob;
};

compress = function(inCode) {
	var ast = jsp.parse(inCode); // parse code and get the initial AST
	ast = pro.ast_mangle(ast); // get a new AST with mangled names
	ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
	return pro.gen_code(ast, {indent_level:0, beautify: !opt.aggro, ascii_only:true}); // compressed code here
};

compressJsFile = function(inPath) {
	var code = fs.readFileSync(inPath, "utf8");
	return compress(code);
};

finish = function(loader) {
	//w(loader.packages);
	//w('');
	//
	var output = opt.output || "build";
	var outfolder = path.dirname(output);
	if (outfolder != ".") {
		fs.mkdirSync(outfolder);
	}
	//
	var css = concatCss(loader);
	if (css.length) {
		w("");
		fs.writeFileSync(output + ".css", css, "utf8");
	}
	//
	var js = concatJs(loader);
	/*
	if (css.length) {
		js += "\n// " + "minifier: load css" + "\n\n";
		js += 'enyo.machine.sheet("' + output + '.css");\n';
	}
	*/
	if (js.length) {
		w("");
		fs.writeFileSync(output + ".js", js, "utf8");
	}
	//
	w("");
	w("done.");
	w("");
};

w = console.log;

opt = options(process.argv);
w("");

if (opt.help || opt.h || opt["?"]) {
	printUsage();
	process.exit();
}

walker.init(opt.enyo);
walker.walk(opt.source, finish);
<commit_msg>Added path.existsSync check before building the output directory to prevent build errors that will abort the minify<commit_after>var
	fs = require("fs"),
	path = require("path"),
	walker = require("walker"),
	jsp = require("uglify-js").parser,
	pro = require("uglify-js").uglify
	;

options = function(args) {
	var opts = {};
	for (var i=2; i<args.length; i++) {
		var arg = args[i];
		if (arg[0] == "-") {
			var o = arg.slice(1);
			opts[o] = {enyo: 1, output: 1, alias: 1}[o] ? args[++i] : true;
		} else {
			opts.source = arg;
		}
	}
	w(opts);
	w("");
	return opts;
};

function printUsage() {
	w("Enyo 2.0 Minifier");
	w("Flags:")
	w("-no-alias:", "Don't use path macros");
	w("-alias ALIAS:", "Give paths a macroized alias");
	w("-enyo ENYOPATH:", "Path to enyo loader (enyo/enyo.js)");
	w("-output PATH/NAME:", "name of output file, prepend folder paths to change output directory");
	w("-h, -?, -help:", "Show this message");
}

// make a relative path from source to target
function makeRelPath(inSource, inTarget) {
	// node 0.5 has this nice thing, 0.4 does not
	if (path.relative) {
		return path.relative(inSource, inTarget);
	}
	var s,t;
	s = pathSplit(path.resolve(inSource));
	t = pathSplit(path.resolve(inTarget));
	while (s.length && s[0] === t[0]){
		s.shift();
		t.shift();
	}
	for(var i = 0, l = s.length; i < l; i++) {
		t.unshift("..");
	}
	return path.join.apply(null, t);
}

// properly split path based on platform
function pathSplit(inPath) {
	var sep = process.platform == "win32" ? "\\" : "/";
	return inPath.split(sep);
}

buildPathBlock = function(loader) {
	var p$ = [];
	for (var i=0, p; p=loader.packages[i]; i++) {
		if (p.name.indexOf("-") == -1) {
			p$.push(p.name + ': "' + p.folder + '"');
		}
	}
	var p = p$.join(', ');
	return !p ? "" : "\n// minifier: path aliases\n\nenyo.path.addPaths({" + p + "});\n";
};

concatCss = function(loader) {
	w("");
	var blob = "";
	for (var i=0, s; s=loader.sheets[i]; i++) {
		w(s);
		var code = fs.readFileSync(s, "utf8");
		// fix url paths
		code = code.replace(/url\([^)]*\)/g, function(inMatch) {
			// find the url path, ignore quotes in url string
			var urlPath = inMatch.replace(/["']/g, "").slice(4, -1);
			// skip data urls
			if (/^data:/.test(urlPath)) {
				return "url(" + urlPath + ")";
			}
			// get absolute path to referenced asset
			var normalizedUrlPath = path.join(s, "..", urlPath);
			// Make relative asset path to built css
			var relPath = makeRelPath(path.dirname(opt.output || "build"), normalizedUrlPath);
			if (process.platform == "win32") {
				relPath = pathSplit(relPath).join("/");
			}
			return "url(" + relPath + ")";
		});
		blob += "\n/* " + s + " */\n\n" + code + "\n";
	}
	return blob;
};

concatJs = function(loader) {
	w("");
	var blob = "";
	for (var i=0, m; m=loader.modules[i]; i++) {
		if (!opt["no-alias"] && !opt.alias) {
			w("* inserting path aliases");
			blob += buildPathBlock(loader);
			opt["no-alias"] = true;
		}
		w(m.path);
		blob += "\n// " + m.rawPath + "\n\n" + compressJsFile(m.path) + "\n";
		if (opt.alias == m.rawPath) {
			w("* inserting path aliases");
			blob += buildPathBlock(loader);
		}
	}
	return blob;
};

compress = function(inCode) {
	var ast = jsp.parse(inCode); // parse code and get the initial AST
	ast = pro.ast_mangle(ast); // get a new AST with mangled names
	ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
	return pro.gen_code(ast, {indent_level:0, beautify: !opt.aggro, ascii_only:true}); // compressed code here
};

compressJsFile = function(inPath) {
	var code = fs.readFileSync(inPath, "utf8");
	return compress(code);
};

finish = function(loader) {
	//w(loader.packages);
	//w('');
	//
	var output = opt.output || "build";
	var outfolder = path.dirname(output);
	if (outfolder != "." && !path.existsSync(outfolder)) {
		fs.mkdirSync(outfolder);
	}
	//
	var css = concatCss(loader);
	if (css.length) {
		w("");
		fs.writeFileSync(output + ".css", css, "utf8");
	}
	//
	var js = concatJs(loader);
	/*
	if (css.length) {
		js += "\n// " + "minifier: load css" + "\n\n";
		js += 'enyo.machine.sheet("' + output + '.css");\n';
	}
	*/
	if (js.length) {
		w("");
		fs.writeFileSync(output + ".js", js, "utf8");
	}
	//
	w("");
	w("done.");
	w("");
};

w = console.log;

opt = options(process.argv);
w("");

if (opt.help || opt.h || opt["?"]) {
	printUsage();
	process.exit();
}

walker.init(opt.enyo);
walker.walk(opt.source, finish);
<|endoftext|>


<commit_before>;(function() {
	/*
	 * Alloy JavaScript Library v@VERSION@
	 * http://alloy.liferay.com/
	 *
	 * Copyright (c) 2010 Liferay Inc.
	 * http://alloy.liferay.com/LICENSE.txt
	 *
	 * Nate Cavanaugh (nathan.cavanaugh@liferay.com)
	 * Eduardo Lundgren (eduardo.lundgren@liferay.com)
	 *
	 * Attribution/Third-party licenses
	 * http://alloy.liferay.com/ATTRIBUTION.txt
	 *
	 * Date: @DATE@
	 * Revision: @REVISION@
	 */

	YUI.AUI_config = YUI.AUI_config || {};

	var defaults = YUI.AUI_config;

	YUI.prototype.ready = function() {
		var instance = this;

		var slice = Array.prototype.slice;
		var args = slice.call(arguments, 0), index = args.length - 1;

		var fn = args[index];

		var modules = slice.call(arguments, 0, index);

		modules.push('event');

		modules.push(
			function(instance) {
				var args = arguments;

				instance.on(
					'domready',
					function() {
						fn.apply(this, args);
					}
				);
			}
		);

		instance.use.apply(instance, modules);
	};

	var ALLOY;

	if (typeof A != 'undefined') {
		ALLOY = A;
	}
	else {
		ALLOY = YUI(defaults);
	}

	var guidExtensions = function(A) {
		A.Env._guidp = ['aui', A.version, A.Env._yidx].join('_').replace(/\./g, '_');
	};

	guidExtensions(ALLOY);

	var originalConfig = ALLOY.config;

	ALLOY.config = ALLOY.merge(originalConfig, YUI.AUI_config);

	YUI.AUI = function(o) {
		var instance = this;

		if (o || instance instanceof AUI) {
			var args = ALLOY.Array(arguments);

			args.unshift(ALLOY.config);

			var newInstance = YUI.apply(ALLOY.config.win, args);

			AUI._uaExtensions(newInstance);
			AUI._guidExtensions(newInstance);

			return newInstance;
		}

		return ALLOY;
	};

	var AUI = YUI.AUI;

	AUI._guidExtensions = guidExtensions;

	window.AUI = AUI;

	var UA = ALLOY.UA;

	ALLOY.mix(AUI, YUI, true, null, 2);

	ALLOY.mix(
		AUI,
		{
			__version: '@VERSION',

			defaults: defaults,

			html5shiv: function(frag) {
				var instance = this;
				var doc = frag || document;

				if (UA.ie && doc && doc.createElement) {
					var elements = AUI.HTML5_ELEMENTS, length = elements.length;

					while (length--) {
						doc.createElement(elements[length]);
					}
				}

				return frag;
			},

			setDefaults: function(defaults) {
				var instance = this;

				ALLOY.mix(AUI.defaults, defaults, true, null, 0, true);
				ALLOY.mix(ALLOY.config, defaults, true, null, 0, true);
			},

			HTML5_ELEMENTS: 'abbr,article,aside,audio,canvas,command,datalist,details,figure,figcaption,footer,header,hgroup,keygen,mark,meter,nav,output,progress,section,source,summary,time,video'.split(',')
		},
		true
	);

	/*
	* HTML5 Compatability for IE
	*/

	AUI.html5shiv();

	/*
		UA extensions
	*/

	(function() {
		var REGEX_VERSION_DOT = /\./g;

		var parseVersionNumber = function(str) {
			var count = 0;

			return parseFloat(
				str.replace(
					REGEX_VERSION_DOT,
					function() {
						return (count++ == 1) ? '' : '.';
					}
				)
			);
		};

		var DEFAULTS_VERSION = ['0','0'];

		var getVersion = function(regex, userAgent) {
			var version = (userAgent.match(regex) || DEFAULTS_VERSION)[1];

			return parseVersionNumber(version);
		};

		var MAP_OS_SELECTORS = {
			windows: 'win',
			macintosh: 'mac'
		};

		var BROWSERS = [
			'ie',
			'opera',
			'chrome',
			'aol',
			'camino',
			'firefox',
			'flock',
			'mozilla',
			'netscape',
			'icab',
			'konqueror',
			'safari'
		];

		AUI._uaExtensions = function(A) {
			var nav = navigator;

			var userAgent = nav.userAgent;

			var UA = A.UA;
			var OS = UA.os;

			var UAX = {
				aol: 0,

				camino: 0,
				firefox: 0,
				flock: 0,
				mozilla: 0,
				netscape: 0,

				icab: 0,
				konqueror: 0,

				safari: 0,

				browser: 0,

				win: OS == 'windows',
				mac: OS == 'macintosh',
				rhino: OS == 'rhino',

				agent: userAgent
			};

			if (UA.ie) {
				UAX.aol = getVersion(/America Online Browser ([^\s]*);/, userAgent);
			}
			else if (UA.gecko) {
				UAX.netscape = getVersion(/(Netscape|Navigator)\/([^\s]*)/, userAgent);
				UAX.flock = getVersion(/Flock\/([^\s]*)/, userAgent);
				UAX.camino = getVersion(/Camino\/([^\s]*)/, userAgent);
				UAX.firefox = getVersion(/Firefox\/([^\s]*)/, userAgent);
			}
			else if (UA.webkit) {
				UAX.safari = getVersion(/Version\/([^\s]*) Safari/, userAgent);
			}
			else {
				UAX.icab = getVersion(/iCab(?:\/|\s)?([^\s]*)/, userAgent);
				UAX.konqueror = getVersion(/Konqueror\/([^\s]*)/, userAgent);
			}

			if (!UAX.win && !UAX.mac) {
				var linux = /Linux/.test(userAgent);
				var sun = /Solaris|SunOS/.test(userAgent);

				if (linux) {
					UA.os = 'linux';
					UAX.linux = linux;
				}
				else if (sun) {
					UA.os = 'sun';
					UAX.sun = sun;
				}
			}

			A.mix(UA, UAX);

			var browserList = [];
			var versionMajor = 0;

			var browser;
			var version;
			var uaVersionMajor;
			var uaVersionMinor;

			var versionObj = {
				string: '',
				major: versionMajor
			};

			var i = BROWSERS.length;

			while (i--) {
				browser = BROWSERS[i];
				version = UA[browser];

				if (version > 0) {
					versionMajor = parseInt(version, 10);
					uaVersionMajor = browser + versionMajor;

					uaVersionMinor = (browser + version);

					if (String(version).indexOf('.') > -1) {
						uaVersionMinor = uaVersionMinor.replace(/\.(\d).*/, '-$1');
					}
					else {
						uaVersionMinor += '-0';
					}

					browserList.push(browser, uaVersionMajor, uaVersionMinor);

					versionObj.string = browser + '';
					versionObj.major = versionMajor;
				}
			}

			UA.version = versionObj;

			UA.renderer = '';

			var CONFIG = A.config,
				DOC = CONFIG.doc;

			var documentElement = DOC.documentElement;

			UA.dir = documentElement.getAttribute('dir') || 'ltr';

			if (UA.ie) {
				UA.renderer = 'trident';
			}
			else if (UA.gecko) {
				UA.renderer = 'gecko';
			}
			else if (UA.webkit) {
				UA.renderer = 'webkit';
			}
			else if (UA.opera) {
				UA.renderer = 'presto';
			}

			A.UA = UA;

			/*
			* Browser selectors
			*/

			var selectors = [
				UA.renderer,
				UA.dir,
				'js'
			].concat(browserList);

			var osSelector = MAP_OS_SELECTORS[UA.os] || UA.os;

			selectors.push(osSelector);

			if (UA.mobile) {
				selectors.push('mobile');
			}

			if (UA.secure) {
				selectors.push('secure');
			}

			if ('ontouchstart' in DOC) {
				selectors.push('touch');
			}

			UA.selectors = selectors.join(' ');

			// The methods in this if block only run once across all instances
			if (!documentElement._yuid) {
				documentElement.className += ' ' + UA.selectors;

				var vml,
					svg;

				vml = !(svg = !!(CONFIG.win.SVGAngle || DOC.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1')));

				if (vml) {
					var div = DOC.createElement('div');
					var behaviorObj;

					div.innerHTML = '<v:shape adj="1"/>';

					behaviorObj = div.firstChild;

					behaviorObj.style.behavior = 'url(#default#VML)';

					if (!(behaviorObj && typeof behaviorObj.adj == 'object')) {
						vml = false;
					}

					div = null;
				}

				AUI._VML = vml;
				AUI._SVG = svg;

				A.stamp(documentElement);
			}

			UA.vml = AUI._VML;
			UA.svg = AUI._SVG;
		};
	})();

	AUI._uaExtensions(ALLOY);

	/*
	* Disable background image flickering in IE6
	*/

	if (UA.ie && UA.version.major <= 6) {
		try {
			document.execCommand('BackgroundImageCache', false, true);
		}
		catch (e) {
		}
	}
})();<commit_msg>AUI-341 - Need to add this to the UA object as well<commit_after>;(function() {
	/*
	 * Alloy JavaScript Library v@VERSION@
	 * http://alloy.liferay.com/
	 *
	 * Copyright (c) 2010 Liferay Inc.
	 * http://alloy.liferay.com/LICENSE.txt
	 *
	 * Nate Cavanaugh (nathan.cavanaugh@liferay.com)
	 * Eduardo Lundgren (eduardo.lundgren@liferay.com)
	 *
	 * Attribution/Third-party licenses
	 * http://alloy.liferay.com/ATTRIBUTION.txt
	 *
	 * Date: @DATE@
	 * Revision: @REVISION@
	 */

	YUI.AUI_config = YUI.AUI_config || {};

	var defaults = YUI.AUI_config;

	YUI.prototype.ready = function() {
		var instance = this;

		var slice = Array.prototype.slice;
		var args = slice.call(arguments, 0), index = args.length - 1;

		var fn = args[index];

		var modules = slice.call(arguments, 0, index);

		modules.push('event');

		modules.push(
			function(instance) {
				var args = arguments;

				instance.on(
					'domready',
					function() {
						fn.apply(this, args);
					}
				);
			}
		);

		instance.use.apply(instance, modules);
	};

	var ALLOY;

	if (typeof A != 'undefined') {
		ALLOY = A;
	}
	else {
		ALLOY = YUI(defaults);
	}

	var guidExtensions = function(A) {
		A.Env._guidp = ['aui', A.version, A.Env._yidx].join('_').replace(/\./g, '_');
	};

	guidExtensions(ALLOY);

	var originalConfig = ALLOY.config;

	ALLOY.config = ALLOY.merge(originalConfig, YUI.AUI_config);

	YUI.AUI = function(o) {
		var instance = this;

		if (o || instance instanceof AUI) {
			var args = ALLOY.Array(arguments);

			args.unshift(ALLOY.config);

			var newInstance = YUI.apply(ALLOY.config.win, args);

			AUI._uaExtensions(newInstance);
			AUI._guidExtensions(newInstance);

			return newInstance;
		}

		return ALLOY;
	};

	var AUI = YUI.AUI;

	AUI._guidExtensions = guidExtensions;

	window.AUI = AUI;

	var UA = ALLOY.UA;

	ALLOY.mix(AUI, YUI, true, null, 2);

	ALLOY.mix(
		AUI,
		{
			__version: '@VERSION',

			defaults: defaults,

			html5shiv: function(frag) {
				var instance = this;
				var doc = frag || document;

				if (UA.ie && doc && doc.createElement) {
					var elements = AUI.HTML5_ELEMENTS, length = elements.length;

					while (length--) {
						doc.createElement(elements[length]);
					}
				}

				return frag;
			},

			setDefaults: function(defaults) {
				var instance = this;

				ALLOY.mix(AUI.defaults, defaults, true, null, 0, true);
				ALLOY.mix(ALLOY.config, defaults, true, null, 0, true);
			},

			HTML5_ELEMENTS: 'abbr,article,aside,audio,canvas,command,datalist,details,figure,figcaption,footer,header,hgroup,keygen,mark,meter,nav,output,progress,section,source,summary,time,video'.split(',')
		},
		true
	);

	/*
	* HTML5 Compatability for IE
	*/

	AUI.html5shiv();

	/*
		UA extensions
	*/

	(function() {
		var REGEX_VERSION_DOT = /\./g;

		var parseVersionNumber = function(str) {
			var count = 0;

			return parseFloat(
				str.replace(
					REGEX_VERSION_DOT,
					function() {
						return (count++ == 1) ? '' : '.';
					}
				)
			);
		};

		var DEFAULTS_VERSION = ['0','0'];

		var getVersion = function(regex, userAgent) {
			var version = (userAgent.match(regex) || DEFAULTS_VERSION)[1];

			return parseVersionNumber(version);
		};

		var MAP_OS_SELECTORS = {
			windows: 'win',
			macintosh: 'mac'
		};

		var BROWSERS = [
			'ie',
			'opera',
			'chrome',
			'aol',
			'camino',
			'firefox',
			'flock',
			'mozilla',
			'netscape',
			'icab',
			'konqueror',
			'safari'
		];

		AUI._uaExtensions = function(A) {
			var nav = navigator;

			var userAgent = nav.userAgent;

			var UA = A.UA;
			var OS = UA.os;

			var UAX = {
				aol: 0,

				camino: 0,
				firefox: 0,
				flock: 0,
				mozilla: 0,
				netscape: 0,

				icab: 0,
				konqueror: 0,

				safari: 0,

				browser: 0,

				win: OS == 'windows',
				mac: OS == 'macintosh',
				rhino: OS == 'rhino',

				agent: userAgent
			};

			if (UA.ie) {
				UAX.aol = getVersion(/America Online Browser ([^\s]*);/, userAgent);
			}
			else if (UA.gecko) {
				UAX.netscape = getVersion(/(Netscape|Navigator)\/([^\s]*)/, userAgent);
				UAX.flock = getVersion(/Flock\/([^\s]*)/, userAgent);
				UAX.camino = getVersion(/Camino\/([^\s]*)/, userAgent);
				UAX.firefox = getVersion(/Firefox\/([^\s]*)/, userAgent);
			}
			else if (UA.webkit) {
				UAX.safari = getVersion(/Version\/([^\s]*) Safari/, userAgent);
			}
			else {
				UAX.icab = getVersion(/iCab(?:\/|\s)?([^\s]*)/, userAgent);
				UAX.konqueror = getVersion(/Konqueror\/([^\s]*)/, userAgent);
			}

			if (!UAX.win && !UAX.mac) {
				var linux = /Linux/.test(userAgent);
				var sun = /Solaris|SunOS/.test(userAgent);

				if (linux) {
					UA.os = 'linux';
					UAX.linux = linux;
				}
				else if (sun) {
					UA.os = 'sun';
					UAX.sun = sun;
				}
			}

			var CONFIG = A.config,
				DOC = CONFIG.doc;

			UAX.touch = ('ontouchstart' in DOC);

			A.mix(UA, UAX);

			var browserList = [];
			var versionMajor = 0;

			var browser;
			var version;
			var uaVersionMajor;
			var uaVersionMinor;

			var versionObj = {
				string: '',
				major: versionMajor
			};

			var i = BROWSERS.length;

			while (i--) {
				browser = BROWSERS[i];
				version = UA[browser];

				if (version > 0) {
					versionMajor = parseInt(version, 10);
					uaVersionMajor = browser + versionMajor;

					uaVersionMinor = (browser + version);

					if (String(version).indexOf('.') > -1) {
						uaVersionMinor = uaVersionMinor.replace(/\.(\d).*/, '-$1');
					}
					else {
						uaVersionMinor += '-0';
					}

					browserList.push(browser, uaVersionMajor, uaVersionMinor);

					versionObj.string = browser + '';
					versionObj.major = versionMajor;
				}
			}

			UA.version = versionObj;

			UA.renderer = '';

			var documentElement = DOC.documentElement;

			UA.dir = documentElement.getAttribute('dir') || 'ltr';

			if (UA.ie) {
				UA.renderer = 'trident';
			}
			else if (UA.gecko) {
				UA.renderer = 'gecko';
			}
			else if (UA.webkit) {
				UA.renderer = 'webkit';
			}
			else if (UA.opera) {
				UA.renderer = 'presto';
			}

			A.UA = UA;

			/*
			* Browser selectors
			*/

			var selectors = [
				UA.renderer,
				UA.dir,
				'js'
			].concat(browserList);

			var osSelector = MAP_OS_SELECTORS[UA.os] || UA.os;

			selectors.push(osSelector);

			if (UA.mobile) {
				selectors.push('mobile');
			}

			if (UA.secure) {
				selectors.push('secure');
			}

			if (UA.touch) {
				selectors.push('touch');
			}

			UA.selectors = selectors.join(' ');

			// The methods in this if block only run once across all instances
			if (!documentElement._yuid) {
				documentElement.className += ' ' + UA.selectors;

				var vml,
					svg;

				vml = !(svg = !!(CONFIG.win.SVGAngle || DOC.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1')));

				if (vml) {
					var div = DOC.createElement('div');
					var behaviorObj;

					div.innerHTML = '<v:shape adj="1"/>';

					behaviorObj = div.firstChild;

					behaviorObj.style.behavior = 'url(#default#VML)';

					if (!(behaviorObj && typeof behaviorObj.adj == 'object')) {
						vml = false;
					}

					div = null;
				}

				AUI._VML = vml;
				AUI._SVG = svg;

				A.stamp(documentElement);
			}

			UA.vml = AUI._VML;
			UA.svg = AUI._SVG;
		};
	})();

	AUI._uaExtensions(ALLOY);

	/*
	* Disable background image flickering in IE6
	*/

	if (UA.ie && UA.version.major <= 6) {
		try {
			document.execCommand('BackgroundImageCache', false, true);
		}
		catch (e) {
		}
	}
})();<|endoftext|>


<commit_before>var SteamUser = require('../index.js');
var Steam = require('steam');
var SteamID = require('steamid');
var ByteBuffer = require('bytebuffer');

// name is optional
SteamUser.prototype.setPersona = function(state, name) {
	this._send(Steam.EMsg.ClientChangeStatus, {
		"persona_state": state,
		"player_name": name
	});
};

SteamUser.prototype.addFriend = function(steamID) {
	if(typeof steamID === 'string') {
		steamID = new SteamID(steamID);
	}

	this._send(Steam.EMsg.ClientAddFriend, {"steamid_to_add": steamID.getSteamID64()});
};

SteamUser.prototype.removeFriend = function(steamID) {
	if(typeof steamID === 'string') {
		steamID = new SteamID(steamID);
	}

	this._send(Steam.EMsg.ClientRemoveFriend, {"friendid": steamID.getSteamID64()});
};

SteamUser.prototype.blockUser = function(steamID, block, callback) {
	if(typeof steamID === 'string') {
		steamID = new SteamID(steamID);
	}

	var buffer = new ByteBuffer(17, ByteBuffer.LITTLE_ENDIAN);
	buffer.writeUint64(this.steamID.getSteamID64());
	buffer.writeUint64(steamID.getSteamID64());
	buffer.writeUint8(block ? 1 : 0);

	this._send(Steam.EMsg.ClientSetIgnoreFriend, buffer.flip(), function(body) {
		if(!callback) {
			return; // ignore
		}

		body.readUint64(); // unknown
		callback(body.readUint32());
	});
};

SteamUser.prototype.getPersonas = function(steamids, callback) {
	var Flags = Steam.EClientPersonaStateFlag;
	var flags = Flags.Status|Flags.PlayerName|Flags.QueryPort|Flags.SourceID|Flags.Presence|
		Flags.Metadata|Flags.LastSeen|Flags.ClanInfo|Flags.GameExtraInfo|Flags.GameDataBlob|
		Flags.ClanTag|Flags.Facebook;

	var ids = steamids.map(function(id) {
		if(typeof id === 'string') {
			return (new SteamID(id)).getSteamID64();
		}

		return id.toString();
	});

	this._send(Steam.EMsg.ClientRequestFriendData, {
		"friends": ids,
		"persona_state_requested": flags
	});

	if(callback) {
		var output = {};

		var self = this;
		ids.forEach(function(id) {
			self.once('user#' + id, receive);
		});

		function receive(sid, user) {
			var sid64 = sid.getSteamID64();
			output[sid64] = user;

			var index = ids.indexOf(sid64);
			if(index != -1) {
				ids.splice(index, 1);
			}

			if(ids.length === 0) {
				callback(output);
			}
		}
	}
};

SteamUser.prototype.getSteamLevels = function(steamids, callback) {
	var accountids = steamids.map(function(steamID) {
		if(typeof steamID === 'string') {
			return (new SteamID(steamID)).accountid;
		} else {
			return steamID.accountid;
		}
	});

	this._send(Steam.EMsg.ClientFSGetFriendsSteamLevels, {"accountids": accountids}, function(body) {
		var output = {};

		var sid = new SteamID();
		sid.universe = SteamID.Universe.PUBLIC;
		sid.type = SteamID.Type.INDIVIDUAL;
		sid.instance = SteamID.Instance.DESKTOP;

		(body.friends || []).forEach(function(user) {
			sid.accountid = user.accountid;
			output[sid.getSteamID64()] = user.level;
		});

		callback(output);
	});
};

// Handlers

SteamUser.prototype._handlers[Steam.EMsg.ClientPersonaState] = function(body) {
	var self = this;
	body.friends.forEach(function(user) {
		var sid = new SteamID(user.friendid.toString());
		var sid64 = sid.getSteamID64();
		delete user.friendid;

		if(!self.users[sid64]) {
			self.users[sid64] = user;
			processUser(self.users[sid64]);
		}

		self.emit('user', sid, user);
		self.emit('user#' + sid64, sid, user);

		for(var i in user) {
			if(user.hasOwnProperty(i) && user[i] !== null) {
				self.users[sid][i] = user[i];
			}
		}

		processUser(user);
	});
};

SteamUser.prototype._handlers[Steam.EMsg.ClientClanState] = function(body) {
	var sid = new SteamID(body.steamid_clan.toString());
	var sid64 = sid.getSteamID64();
	delete body.steamid_clan;

	if(!this.groups[sid64]) {
		this.groups[sid64] = body;
	}

	this.emit('group', sid, body);
	this.emit('group#' + sid64, sid, body);

	for(var i in body) {
		if(body.hasOwnProperty(i) && body[i] !== null) {
			this.groups[sid64][i] = body[i];
		}
	}

	var self = this;
	(body.events || []).forEach(function(event) {
		if(!event.just_posted) {
			return;
		}

		self.emit('groupEvent', sid, event.headline, new Date(event.event_time * 1000), event.gid.toString(), event.game_id.toNumber());
		self.emit('groupEvent#' + sid64, sid, event.headline, new Date(event.event_time * 1000), event.gid.toString(), event.game_id.toNumber());
	});

	(body.announcements || []).forEach(function(announcement) {
		if(!announcement.just_posted) {
			return;
		}

		self.emit('groupAnnouncement', sid, announcement.headline, announcement.gid.toString());
		self.emit('groupAnnouncement#' + sid64, sid, announcement.headline, announcement.gid.toString());
	});
};

SteamUser.prototype._handlers[Steam.EMsg.ClientFriendsList] = function(body) {
	var self = this;
	(body.friends || []).forEach(function(relationship) {
		var sid = new SteamID(relationship.ulfriendid.toString());
		var key = sid.type == SteamID.Type.CLAN ? 'myGroups' : 'myFriends';

		if(body.bincremental) {
			// This isn't an initial download of the friends list, something changed
			self.emit(key == 'myGroups' ? 'groupRelationship' : 'friendRelationship', sid, relationship.efriendrelationship);
		}

		if(relationship.efriendrelationship == Steam.EFriendRelationship.None) {
			delete self[key][sid.getSteamID64()];
		} else {
			self[key][sid.getSteamID64()] = relationship.efriendrelationship;
		}
	});

	if(!body.bincremental) {
		this.emit('friendsList');
		this.emit('groupList');
	}
};

function processUser(user) {
	if(typeof user.gameid === 'object' && user.gameid !== null) {
		user.gameid = user.gameid.toNumber();
	}

	if(typeof user.last_logoff === 'number') {
		user.last_logoff = new Date(user.last_logoff * 1000);
	}

	if(typeof user.last_logon === 'number') {
		user.last_logon = new Date(user.last_logon * 1000);
	}
}
<commit_msg>Include known data that wasn't received in user and group events<commit_after>var SteamUser = require('../index.js');
var Steam = require('steam');
var SteamID = require('steamid');
var ByteBuffer = require('bytebuffer');

// name is optional
SteamUser.prototype.setPersona = function(state, name) {
	this._send(Steam.EMsg.ClientChangeStatus, {
		"persona_state": state,
		"player_name": name
	});
};

SteamUser.prototype.addFriend = function(steamID) {
	if(typeof steamID === 'string') {
		steamID = new SteamID(steamID);
	}

	this._send(Steam.EMsg.ClientAddFriend, {"steamid_to_add": steamID.getSteamID64()});
};

SteamUser.prototype.removeFriend = function(steamID) {
	if(typeof steamID === 'string') {
		steamID = new SteamID(steamID);
	}

	this._send(Steam.EMsg.ClientRemoveFriend, {"friendid": steamID.getSteamID64()});
};

SteamUser.prototype.blockUser = function(steamID, block, callback) {
	if(typeof steamID === 'string') {
		steamID = new SteamID(steamID);
	}

	var buffer = new ByteBuffer(17, ByteBuffer.LITTLE_ENDIAN);
	buffer.writeUint64(this.steamID.getSteamID64());
	buffer.writeUint64(steamID.getSteamID64());
	buffer.writeUint8(block ? 1 : 0);

	this._send(Steam.EMsg.ClientSetIgnoreFriend, buffer.flip(), function(body) {
		if(!callback) {
			return; // ignore
		}

		body.readUint64(); // unknown
		callback(body.readUint32());
	});
};

SteamUser.prototype.getPersonas = function(steamids, callback) {
	var Flags = Steam.EClientPersonaStateFlag;
	var flags = Flags.Status|Flags.PlayerName|Flags.QueryPort|Flags.SourceID|Flags.Presence|
		Flags.Metadata|Flags.LastSeen|Flags.ClanInfo|Flags.GameExtraInfo|Flags.GameDataBlob|
		Flags.ClanTag|Flags.Facebook;

	var ids = steamids.map(function(id) {
		if(typeof id === 'string') {
			return (new SteamID(id)).getSteamID64();
		}

		return id.toString();
	});

	this._send(Steam.EMsg.ClientRequestFriendData, {
		"friends": ids,
		"persona_state_requested": flags
	});

	if(callback) {
		var output = {};

		var self = this;
		ids.forEach(function(id) {
			self.once('user#' + id, receive);
		});

		function receive(sid, user) {
			var sid64 = sid.getSteamID64();
			output[sid64] = user;

			var index = ids.indexOf(sid64);
			if(index != -1) {
				ids.splice(index, 1);
			}

			if(ids.length === 0) {
				callback(output);
			}
		}
	}
};

SteamUser.prototype.getSteamLevels = function(steamids, callback) {
	var accountids = steamids.map(function(steamID) {
		if(typeof steamID === 'string') {
			return (new SteamID(steamID)).accountid;
		} else {
			return steamID.accountid;
		}
	});

	this._send(Steam.EMsg.ClientFSGetFriendsSteamLevels, {"accountids": accountids}, function(body) {
		var output = {};

		var sid = new SteamID();
		sid.universe = SteamID.Universe.PUBLIC;
		sid.type = SteamID.Type.INDIVIDUAL;
		sid.instance = SteamID.Instance.DESKTOP;

		(body.friends || []).forEach(function(user) {
			sid.accountid = user.accountid;
			output[sid.getSteamID64()] = user.level;
		});

		callback(output);
	});
};

// Handlers

SteamUser.prototype._handlers[Steam.EMsg.ClientPersonaState] = function(body) {
	var self = this;
	body.friends.forEach(function(user) {
		var sid = new SteamID(user.friendid.toString());
		var sid64 = sid.getSteamID64();
		delete user.friendid;

		var i;
		if(!self.users[sid64]) {
			self.users[sid64] = user;
			processUser(self.users[sid64]);
		} else {
			// Replace unknown data in the received object with already-known data
			for(i in self.users[sid64]) {
				if(self.users[sid64].hasOwnProperty(i) && user.hasOwnProperty(i) && user[i] === null) {
					user[i] = self.users[sid64][i];
				}
			}
		}

		self.emit('user', sid, user);
		self.emit('user#' + sid64, sid, user);

		for(i in user) {
			if(user.hasOwnProperty(i) && user[i] !== null) {
				self.users[sid][i] = user[i];
			}
		}

		processUser(user);
	});
};

SteamUser.prototype._handlers[Steam.EMsg.ClientClanState] = function(body) {
	var sid = new SteamID(body.steamid_clan.toString());
	var sid64 = sid.getSteamID64();
	delete body.steamid_clan;

	var i;
	if(!this.groups[sid64]) {
		this.groups[sid64] = body;
	} else {
		// Replace unknown data in the received object with already-known data
		for(i in this.groups[sid64]) {
			if(this.groups[sid64].hasOwnProperty(i) && body.hasOwnProperty(i) && body[i] === null) {
				body[i] = this.groups[sid64][i];
			}
		}
	}

	this.emit('group', sid, body);
	this.emit('group#' + sid64, sid, body);

	for(i in body) {
		if(body.hasOwnProperty(i) && body[i] !== null) {
			this.groups[sid64][i] = body[i];
		}
	}

	var self = this;
	(body.events || []).forEach(function(event) {
		if(!event.just_posted) {
			return;
		}

		self.emit('groupEvent', sid, event.headline, new Date(event.event_time * 1000), event.gid.toString(), event.game_id.toNumber());
		self.emit('groupEvent#' + sid64, sid, event.headline, new Date(event.event_time * 1000), event.gid.toString(), event.game_id.toNumber());
	});

	(body.announcements || []).forEach(function(announcement) {
		if(!announcement.just_posted) {
			return;
		}

		self.emit('groupAnnouncement', sid, announcement.headline, announcement.gid.toString());
		self.emit('groupAnnouncement#' + sid64, sid, announcement.headline, announcement.gid.toString());
	});
};

SteamUser.prototype._handlers[Steam.EMsg.ClientFriendsList] = function(body) {
	var self = this;
	(body.friends || []).forEach(function(relationship) {
		var sid = new SteamID(relationship.ulfriendid.toString());
		var key = sid.type == SteamID.Type.CLAN ? 'myGroups' : 'myFriends';

		if(body.bincremental) {
			// This isn't an initial download of the friends list, something changed
			self.emit(key == 'myGroups' ? 'groupRelationship' : 'friendRelationship', sid, relationship.efriendrelationship);
		}

		if(relationship.efriendrelationship == Steam.EFriendRelationship.None) {
			delete self[key][sid.getSteamID64()];
		} else {
			self[key][sid.getSteamID64()] = relationship.efriendrelationship;
		}
	});

	if(!body.bincremental) {
		this.emit('friendsList');
		this.emit('groupList');
	}
};

function processUser(user) {
	if(typeof user.gameid === 'object' && user.gameid !== null) {
		user.gameid = user.gameid.toNumber();
	}

	if(typeof user.last_logoff === 'number') {
		user.last_logoff = new Date(user.last_logoff * 1000);
	}

	if(typeof user.last_logon === 'number') {
		user.last_logon = new Date(user.last_logon * 1000);
	}
}
<|endoftext|>


<commit_before>import { createSlice } from "@reduxjs/toolkit";

const defaultFilter = { action: "mark as read", "action on": "match",
                        type: "simple match", pattern: "" };

const editSlice = createSlice({
  name: "feeds",
  initialState: { isOpen: false,
                  isLoading: false,
                  objType: "", // feed, category
                  objId: null,
                  job: "", // edit, add
                  loadedObj: {},
                  editedKeys: [],
  },
  reducers: {
    openPanel: (state, action) => ({
      ...state, isOpen: true,
      isLoading: !!action.payload.isLoading,
      objType: action.payload.objType,
      objId: action.payload.objId,
      job: action.payload.job ? action.payload.job : action.payload.objId ? "edit" : "add",
    }),
    closePanel: (state, action) => ({
      ...state, isOpen: false,
      objType: "", objId: null, job: "",
      loadedObj: {},
      editedKeys: [],
    }),
    editLoadedObj: (state, action) => ({
      ...state,
      editedKeys: [ ...state.editedKeys, action.payload.key ],
      loadedObj: { ...state.loadedObj,
                   [action.payload.key]: action.payload.value }
    }),
    loadedObjToEdit: (state, action) => {
      if (state.objId !== action.payload.data.id && !action.payload.noIdCheck ) {
        // not the object that was asked for last, ignoring
        return state;
      }
      const loadedObj = { ...action.payload.data };
      if (loadedObj.filters) {
        loadedObj.filters = loadedObj.filters.map((filter, i) => (
          { id: `f${i}`, ...filter }
        ));
      }
      return { ...state, isOpen: true, isLoading: false,
               editedKeys: [], loadedObj,
               job: action.payload.job ? action.payload.job: state.job };
    },
    requestedBuildedFeed: (state, action) => ({ ...state, isLoading: true }),
    addFilter: (state, action) => {
      const filters = [ ...state.loadedObj.filters,
                        { ...defaultFilter,
                          id: `f${state.loadedObj.filters.length + 1}` }];
      return { ...state,
               editedKeys: [ ...state.editedKeys, "filters"],
               loadedObj: { ...state.loadedObj, filters },
      };
    },
    moveUpFilter: (state, action) => {
      const filters = [ ...state.loadedObj.filters.slice(0, action.payload - 1),
                        state.loadedObj.filters[action.payload],
                        state.loadedObj.filters[action.payload - 1],
                        ...state.loadedObj.filters.slice(action.payload + 1)];
      return { ...state,
               editedKeys: [ ...state.editedKeys, "filters"],
               loadedObj: { ...state.loadedObj, filters },
      };
    },
    moveDownFilter(state, action) {
      const filters = [ ...state.loadedObj.filters.slice(0, action.payload),
                        state.loadedObj.filters[action.payload + 1],
                        state.loadedObj.filters[action.payload],
                        ...state.loadedObj.filters.slice(action.payload + 2)];
      return { ...state,
               editedKeys: [ ...state.editedKeys, "filters"],
               loadedObj: { ...state.loadedObj, filters },
      };
    },
    editFilter: (state, action) => {
      state.loadedObj.filters[action.payload.index][action.payload.key] = action.payload.value;
      if (state.editedKeys.indexOf("filters") === -1) {
        state.editedKeys.push("filters");
      }
      return state;
    },
    removeFilter: (state, action) => ({
      ...state,
      editedKeys: [ ...state.editedKeys, "filters"],
      loadedObj: { ...state.loadedObj,
      filters: [ ...state.loadedObj.filters.slice(0, action.payload),
                 ...state.loadedObj.filters.slice(action.payload + 1)] },
    }),
  },
});

export const { openPanel, closePanel,
               requestedBuildedFeed,
               editLoadedObj, loadedObjToEdit,
               addFilter, moveUpFilter, moveDownFilter, editFilter, removeFilter,
} = editSlice.actions;
export default editSlice.reducer;
<commit_msg>UI: fixing adding filter on new feeds<commit_after>import { createSlice } from "@reduxjs/toolkit";

const defaultFilter = { action: "mark as read", "action on": "match",
                        type: "simple match", pattern: "" };

const editSlice = createSlice({
  name: "feeds",
  initialState: { isOpen: false,
                  isLoading: false,
                  objType: "", // feed, category
                  objId: null,
                  job: "", // edit, add
                  loadedObj: {},
                  editedKeys: [],
  },
  reducers: {
    openPanel: (state, action) => ({
      ...state, isOpen: true,
      isLoading: !!action.payload.isLoading,
      objType: action.payload.objType,
      objId: action.payload.objId,
      job: action.payload.job ? action.payload.job : action.payload.objId ? "edit" : "add",
    }),
    closePanel: (state, action) => ({
      ...state, isOpen: false,
      objType: "", objId: null, job: "",
      loadedObj: {},
      editedKeys: [],
    }),
    editLoadedObj: (state, action) => ({
      ...state,
      editedKeys: [ ...state.editedKeys, action.payload.key ],
      loadedObj: { ...state.loadedObj,
                   [action.payload.key]: action.payload.value }
    }),
    loadedObjToEdit: (state, action) => {
      if (state.objId !== action.payload.data.id && !action.payload.noIdCheck ) {
        // not the object that was asked for last, ignoring
        return state;
      }
      const loadedObj = { ...action.payload.data };
      if (loadedObj.filters) {
        loadedObj.filters = loadedObj.filters.map((filter, i) => (
          { id: `f${i}`, ...filter }
        ));
      }
      return { ...state, isOpen: true, isLoading: false,
               editedKeys: [], loadedObj,
               job: action.payload.job ? action.payload.job: state.job };
    },
    requestedBuildedFeed: (state, action) => ({ ...state, isLoading: true }),
    addFilter: (state, action) => {
      let filters = state.loadedObj.filters;
      if (filters) {
        filters = [ ...filters,
                    { ...defaultFilter, id: `f${filters.length + 1}` }];
      } else {
        filters = [ { ...defaultFilter, id: "f1" } ];
      }
      return { ...state,
               editedKeys: [ ...state.editedKeys, "filters"],
               loadedObj: { ...state.loadedObj, filters },
      };
    },
    moveUpFilter: (state, action) => {
      const filters = [ ...state.loadedObj.filters.slice(0, action.payload - 1),
                        state.loadedObj.filters[action.payload],
                        state.loadedObj.filters[action.payload - 1],
                        ...state.loadedObj.filters.slice(action.payload + 1)];
      return { ...state,
               editedKeys: [ ...state.editedKeys, "filters"],
               loadedObj: { ...state.loadedObj, filters },
      };
    },
    moveDownFilter(state, action) {
      const filters = [ ...state.loadedObj.filters.slice(0, action.payload),
                        state.loadedObj.filters[action.payload + 1],
                        state.loadedObj.filters[action.payload],
                        ...state.loadedObj.filters.slice(action.payload + 2)];
      return { ...state,
               editedKeys: [ ...state.editedKeys, "filters"],
               loadedObj: { ...state.loadedObj, filters },
      };
    },
    editFilter: (state, action) => {
      state.loadedObj.filters[action.payload.index][action.payload.key] = action.payload.value;
      if (state.editedKeys.indexOf("filters") === -1) {
        state.editedKeys.push("filters");
      }
      return state;
    },
    removeFilter: (state, action) => ({
      ...state,
      editedKeys: [ ...state.editedKeys, "filters"],
      loadedObj: { ...state.loadedObj,
      filters: [ ...state.loadedObj.filters.slice(0, action.payload),
                 ...state.loadedObj.filters.slice(action.payload + 1)] },
    }),
  },
});

export const { openPanel, closePanel,
               requestedBuildedFeed,
               editLoadedObj, loadedObjToEdit,
               addFilter, moveUpFilter, moveDownFilter, editFilter, removeFilter,
} = editSlice.actions;
export default editSlice.reducer;
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor'

Meteor.methods({

	"parser.check" (QMLTesto) {

		if(checkQML(QMLTesto) != null)
			return true;
		else
			return false;

		//questa funzione ritorna true o false controllando sia sintassi QML che la coerenza delle risposte.
		//la sintassi QML generale viene controllata effettivamente da checkText() mentre checkAnswer fa due lavori, chiama
		// checkText() e poi fa il controllo delle risposte.
		// checkText quindi è una funzione secondaria, la funzione principale è checkAnswer(), ma mi sa che devo cambiare i nomi
		// per rendere la cosa più intuitiva
	}

});

//DEFINIZIONE ESPRESSIONI REGOLARI PER I QUATTRO TIPI DI DOMANDE:
// VF = DOMANDA VERO FALSO
// MU = RISPOSTA MULTIPLA (CON UNA SOLA RISPOSTA ESATTA)
// MX = RISPOSTA MULTIPLA (CON PIÙ RISPOSTE ESATTE)
// AS = DOMANDA ASSOCIAZIONE

var VF = /^[\s]*<question>\{(VF|vf|Vf|vF)\}[\s]*[aA][sS][kK]{(.*)[}][\s]*\{(V|v|f|F)\}[\s]*<\/question>[\s]*$/;
var MU = /^[\s]*<question>\{(MU)\}[\s]*[aA][sS][kK]{([^\{]*)}[\s]*((\{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*){2,})<\/question>[\s]*$/;
var MX = /^[\s]*<question>\{(MU)\}[\s]*[aA][sS][kK]{([^\{]*)}[\s]*((\{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*){2,})<\/question>[\s]*$/
var AS = /^[\s]*<question>\{(AS)\}[\s]*[aA][sS][kK]{(.*\s)}((([abAB])->([a-zA-Z0-9])[\s]*(\S{1,}.*)[\s]*){2,})<\/question>[\s]*$/;
var OD = /^[\s]*<question>\{(OD)\}[\s]*[aA][sS][kK]{([^\{]*)}[\s]*((\{(\d[\s]*)\}[\s]*(\S{1,}.*)[\s]*){2,})<\/question>[\s]*$/;

var str; // stringa in cui viene memorizzato il testo di input compilato dall'utente
var m; // array in cui viene memorizzata la domanda scomposta secondo l'espressione regolare definita
// per capire il funzionamento della funzione exec() e quindi la variabile m risultante, basta guardare questo sito:
// https://regex101.com/ dove metti l'espressione regolare e il testo che vuoi controllare e vedi come viene suddiviso il testo.
// l'array m quindi contiene tutti i gruppi definiti dalle parentesi tonde delle espressioni regolari

function checkText(testo)
{
	// AR è l'array che contiene le espressioni regolari definite globalmente fuori dalla funzione
    var AR = [VF, MU, AS, MX, OD];
    var match = false;
    // questo ciclo controlla tramite il metodo exec() se il testo matcha
    // con una delle espressioni regolari definite dell'array AR
    for (var i = 0; i < AR.length && !match; i++)
    {
        if ((m = AR[i].exec(testo)) !== null)
        {
            match = true;
            if (m.index === AR[i].lastIndex)
                AR[i].lastIndex++;
        }
    }
    return match;
}

//controlla il tipo della domanda e in base a quello chiama le funzioni seguenti per controllare se c'è almeno una risposta giusta

export default function checkQML(testo)
{
    var question;
    //in pratica prima di fare il controllo sulla coerenza delle risposte controlla che
    //la sintassi QML sia giusta. Questo è necessario in quanto con le sole espressioni regolari non
    //riesco a fare controlli ulteriori sulle risposte (cioè se per esempio una domanda a risposta multipla a più risposte giuste ha
    // almeno due risposte giuste e non una come la risposta multipla singola)
    if(checkText(testo))
    {
        switch (m[1])
        {
            case "VF":

                question = {
                  type: m[1],
                  text: m[2],
                  ans: checkVF()
                };
                break;

            case "MU":
                var answer = getRightAns();
                if(answer.length == 1)
                {
                    question = {
                        type: m[1],
                        text: m[2],
                        ans: checkM(),
                        rightAns: getRightAnsObj('MU') //answer
                    };
                }
               // else     window.alert("errore in checkQML");
                break;

            case "MX":
                question = {
                    type: m[1],
                    text: m[2],
                    ans: checkM(),
                    rightAns: getRightAnsObj('MX')
                    };
                break;

            case "AS":
				debugger;
                question = {
                  type: m[1],
                  text: m[2],
                  ans: checkAS(),
				  rightAns: getRightAnsObj('AS') //DA FARE restituisce oggetto: {idA:"idB", idA:"idB"}
                };
                break;
			case "OD":
                question = {
                    type: m[1],
                    text: m[2],
                    ans: checkM(),
                    rightAns: getRightAnsObj('OD')  //DA FARE restituisce oggetto: {1:"id1", 2:"id2"}
                    };
                break;

        }
    }
    // la variabile question sarà un elemento con dei campi dipendenti dal tipo di domanda,
    // nello switch precedente si capisce che tipo di elemento viene ritornato
    if(question)
        return question;
    else
        return null;
}

function checkVF()
{
    switch(m[3])
    {
        case ("V"):
        case ("v"):
            return true;

        case ("F"):
        case ("f"):
            return false;
        default:
			return "errore in checkVF";
    }
}

function checkAS()
{
    var A = [],
        B = [];

    var re = /([abAB])->([a-zA-Z0-9])[\s]*(\S{1,}.*)/;
    var s;

    var lines = m[3].split('\n');
    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
            if (s.index === re.lastIndex)
                re.lastIndex++;

        var element = [
            s[1],
            s[2],
            s[3]
        ];

        switch(element[0])
        {
            case ('A'):
                A.push(element);
                break;
            case ('B'):
                B.push(element);
                break;
                }
    }

    var groups = [A, B];
    return groups;
}

function checkM()
{debugger;
    var re = /{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*/;
    var s;

    var lines = m[3].split('\n');

    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
		{
            if (s.index === re.lastIndex)
			{ re.lastIndex++; }

			lines[i] = {text: s[2], id: i };

		}

    }
    return lines;

}

function checkMX(){
debugger;
    var re = /{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*/;
    var s;

    var lines = m[3].split('\n');

    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
        {
            if (s.index === re.lastIndex)
			{ re.lastIndex++; }

			lines[i] = {text: s[2], id: i };

		}
    }
    return lines;
}

function getRightAns()
{

    var re = /\{X[\s]*\}([\s]*\S{1,}.*[\s]*)/;
    var s;

    var lines = m[3].split('\n');

    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    var rAns = [];
    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
        {
            if (s.index === re.lastIndex)
                re.lastIndex++;
            rAns.push(s[1]);
        }

    }

    return rAns;
}

function getRightAnsObj(ztipo)
{

    var re = /{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*/;
    var s;

    var lines = m[3].split('\n');

    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    var rAns={} ;// = [];
    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
        {
            if (s.index === re.lastIndex)
                re.lastIndex++;
           // rAns.push(s[1]);
			if(s[1] == 'X')
			{ 	if(ztipo === 'MU') { return i;} //se siamo su una domanda di tipo MU si esce solo con l'indice la risposta giusta.
				rAns[i] = true;
			}else rAns[i] = false;
        }

    }

    return rAns;
}<commit_msg>Il parser è tutto rotto, mamma compramene un altro<commit_after>import { Meteor } from 'meteor/meteor'

Meteor.methods({

	"parser.check" (QMLTesto) {

		if(checkQML(QMLTesto) != null)
			return true;
		else
			return false;

		//questa funzione ritorna true o false controllando sia sintassi QML che la coerenza delle risposte.
		//la sintassi QML generale viene controllata effettivamente da checkText() mentre checkAnswer fa due lavori, chiama
		// checkText() e poi fa il controllo delle risposte.
		// checkText quindi è una funzione secondaria, la funzione principale è checkAnswer(), ma mi sa che devo cambiare i nomi
		// per rendere la cosa più intuitiva
	}

});

//DEFINIZIONE ESPRESSIONI REGOLARI PER I QUATTRO TIPI DI DOMANDE:
// VF = DOMANDA VERO FALSO
// MU = RISPOSTA MULTIPLA (CON UNA SOLA RISPOSTA ESATTA)
// MX = RISPOSTA MULTIPLA (CON PIÙ RISPOSTE ESATTE)
// AS = DOMANDA ASSOCIAZIONE

var VF = /^[\s]*<question>\{(VF|vf|Vf|vF)\}[\s]*[aA][sS][kK]{(.*)[}][\s]*\{(V|v|f|F)\}[\s]*<\/question>[\s]*$/;
var MU = /^[\s]*<question>\{(MU)\}[\s]*[aA][sS][kK]{([^\{]*)}[\s]*((\{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*){2,})<\/question>[\s]*$/;
var MX = /^[\s]*<question>\{(MU)\}[\s]*[aA][sS][kK]{([^\{]*)}[\s]*((\{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*){2,})<\/question>[\s]*$/
var AS = /^[\s]*<question>\{(AS)\}[\s]*[aA][sS][kK]{(.*\s)}((([abAB])->([a-zA-Z0-9])[\s]*(\S{1,}.*)[\s]*){2,})<\/question>[\s]*$/;
var OD = /^[\s]*<question>\{(OD)\}[\s]*[aA][sS][kK]{([^\{]*)}[\s]*((\{(\d[\s]*)\}[\s]*(\S{1,}.*)[\s]*){2,})<\/question>[\s]*$/;

var str; // stringa in cui viene memorizzato il testo di input compilato dall'utente
var m; // array in cui viene memorizzata la domanda scomposta secondo l'espressione regolare definita
// per capire il funzionamento della funzione exec() e quindi la variabile m risultante, basta guardare questo sito:
// https://regex101.com/ dove metti l'espressione regolare e il testo che vuoi controllare e vedi come viene suddiviso il testo.
// l'array m quindi contiene tutti i gruppi definiti dalle parentesi tonde delle espressioni regolari

function checkText(testo)
{
	// AR è l'array che contiene le espressioni regolari definite globalmente fuori dalla funzione
    var AR = [VF, MU, AS, MX, OD];
    var match = false;
    // questo ciclo controlla tramite il metodo exec() se il testo matcha
    // con una delle espressioni regolari definite dell'array AR
    for (var i = 0; i < AR.length && !match; i++)
    {
        if ((m = AR[i].exec(testo)) !== null)
        {
            match = true;
            if (m.index === AR[i].lastIndex)
                AR[i].lastIndex++;
        }
    }
    return match;
}

//controlla il tipo della domanda e in base a quello chiama le funzioni seguenti per controllare se c'è almeno una risposta giusta

export default function checkQML(testo)
{
    var question;
    //in pratica prima di fare il controllo sulla coerenza delle risposte controlla che
    //la sintassi QML sia giusta. Questo è necessario in quanto con le sole espressioni regolari non
    //riesco a fare controlli ulteriori sulle risposte (cioè se per esempio una domanda a risposta multipla a più risposte giuste ha
    // almeno due risposte giuste e non una come la risposta multipla singola)
    if(checkText(testo))
    {
        switch (m[1])
        {
            case "VF":

                question = {
                  type: m[1],
                  text: m[2],
                  ans: checkVF()
                };
                break;

            case "MU":
                var answer = getRightAns();
                if(answer.length == 1)
                {
                    question = {
                        type: m[1],
                        text: m[2],
                        ans: checkM(),
                        rightAns: getRightAnsObj('MU') //answer
                    };
                }
                break;

            case "MX":
                question = {
                    type: m[1],
                    text: m[2],
                    ans: checkM(),
                    rightAns: getRightAnsObj('MX')
                };
                break;

            case "AS":
				debugger;
                question = {
                  type: m[1],
                  text: m[2],
                  ans: checkAS(),
				  rightAns: getRightAnsObj('AS') //DA FARE restituisce oggetto: {idA:"idB", idA:"idB"}
                };
                break;

			case "OD":
                question = {
                    type: m[1],
                    text: m[2],
                    ans: checkM(),
                    rightAns: getRightAnsObj('OD')  //DA FARE restituisce oggetto: {1:"id1", 2:"id2"}
                };
                break;

        }
    }
    // la variabile question sarà un elemento con dei campi dipendenti dal tipo di domanda,
    // nello switch precedente si capisce che tipo di elemento viene ritornato
    if(question)
        return question;
    else
        return null;
}

function checkVF()
{
    switch(m[3])
    {
        case ("V"):
        case ("v"):
            return true;

        case ("F"):
        case ("f"):
            return false;
        default:
			return "errore in checkVF";
    }
}

function checkAS()
{
    var A = [],
        B = [];

    var re = /([abAB])->([a-zA-Z0-9])[\s]*(\S{1,}.*)/;
    var s;

    var lines = m[3].split('\n');
    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
            if (s.index === re.lastIndex)
                re.lastIndex++;

        var element = [
            s[1],
            s[2],
            s[3]
        ];

        switch(element[0])
        {
            case ('A'):
                A.push(element);
                break;
            case ('B'):
                B.push(element);
                break;
                }
    }

    var groups = [A, B];
    return groups;
}

function checkM()
{debugger;
    var re = /{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*/;
    var s;

    var lines = m[3].split('\n');

    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
		{
            if (s.index === re.lastIndex)
			{ re.lastIndex++; }

			lines[i] = {text: s[2], id: i };

		}

    }
    return lines;

}

function checkMX(){
debugger;
    var re = /{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*/;
    var s;

    var lines = m[3].split('\n');

    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
        {
            if (s.index === re.lastIndex)
			{ re.lastIndex++; }

			lines[i] = {text: s[2], id: i };

		}
    }
    return lines;
}

function getRightAns()
{

    var re = /\{X[\s]*\}([\s]*\S{1,}.*[\s]*)/;
    var s;

    var lines = m[3].split('\n');

    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    var rAns = [];
    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
        {
            if (s.index === re.lastIndex)
                re.lastIndex++;
            rAns.push(s[1]);
        }

    }

    return rAns;
}

function getRightAnsObj(ztipo)
{

    var re = /{(X?[\s]*)\}[\s]*(\S{1,}.*)[\s]*/;
    var s;

    var lines = m[3].split('\n');

    var j = 0;
    for (var i = 0; i < lines.length; i++) {
        if(lines[i] == null)
            j = i;
    }
    lines.pop(j);

    var rAns={} ;// = [];
    for (var i = 0; i < lines.length; i++)
    {
        if ((s = re.exec(lines[i])) !== null)
        {
            if (s.index === re.lastIndex)
                re.lastIndex++;
           // rAns.push(s[1]);
			if(s[1] == 'X')
			{ 	if(ztipo === 'MU') { return i;} //se siamo su una domanda di tipo MU si esce solo con l'indice la risposta giusta.
				rAns[i] = true;
			}else rAns[i] = false;
        }

    }

    return rAns;
}
<|endoftext|>