<commit_before>var mongo = require('../data/mongodb.js');
var async = require('async');

exports.findLastLog = function(callback) {
	mongo.findLastLog({'ts': -1},function(err,first){
		mongo.findPrevLog(function(err,prev){
			console.log(prev.ts + " - " + first.ts);
			first.RC = first.RC - prev.RC;
			callback(err,first);
		});

	});
};

exports.findPrevLog = function(callback) {
	mongo.findPrevLog(function(err,result){
		callback(err,result);
	});
};

exports.findLast = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

			return	sendJsonResponse(req,res,result);
	});

};

exports.findLastWDWS24 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

		mongo.findWDWSLastFrom(startFrom,function(err,result){

			return	sendJsonResponse(req,res,result);

		});
	});

};

exports.findLastWDWS7 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

		mongo.findWDWSLastFrom(startFrom,function(err,result){

			return	sendJsonResponse(req,res,result);

		});
	});

};

exports.findLastWDWS30 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

		mongo.findWDWSLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastWDWS365 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 365);

		mongo.findWDWSLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastT24 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

		mongo.findTLastFrom(startFrom,function(err,result){

			return	sendJsonResponse(req,res,result);

		});
	});

};

exports.findLastT7 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

		mongo.findTLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastT30 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

		mongo.findTLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastT365 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

		mongo.findTLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastH24 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

	mongo.findHLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastH7 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

	mongo.findHLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastH30 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

	mongo.findHLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastH365 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

	mongo.findHLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastPRESS24 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

	mongo.findPRESSLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastPRESS7 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

	mongo.findPRESSLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastPRESS30 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

	mongo.findPRESSLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastPRESS365 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

	mongo.findPRESSLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastWC24 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

	mongo.findWCLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastWC7 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

	mongo.findWCLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastWC30 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

	mongo.findWCLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastWC365 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

	mongo.findWCLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastRC24 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

	mongo.findRCLastFrom(startFrom,function(err,result){

		recalcRain(result,function(err,data){
		        return	sendJsonResponse(req,res,data);
		        });
		});

	});

};

exports.findLastRC7 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

	mongo.findRCLastFrom(startFrom,function(err,result){

		recalcRain(result,function(err,data){
		        return	sendJsonResponse(req,res,data);
		        });
		});

	});

};

exports.findLastRC30 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

	mongo.findRCLastFrom(startFrom,function(err,result){

		recalcRain(result,function(err,data){
		        return	sendJsonResponse(req,res,data);
		        });
		});

	});

};

exports.findLastRC365 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

	mongo.findRCLastFrom(startFrom,function(err,result){

		recalcRain(result,function(err,data){
		        return	sendJsonResponse(req,res,data);
		        });
		});

	});

};

recalcRain = function(data,callback){
callback(null,data);
/*    var act = 0;
    var first = true;
    var prev = 0;
    var returnData = [];

    var _min = 0;
    var _max = 0;

    async.each(data,function(item,callback){

        if(first == true){
            console.log("first");
            prev = item.RC;
            item.RC = 0;
            first = false;
            callback();
            return;
        }else{
            var tmp = item.RC;
            //console.log("prev" + prev);
            //console.log("item" + item.RC);
            console.log(parseFloat(item.RC) - parseFloat(prev));

            var t = parseFloat(item.RC) - parseFloat(prev);
            prev = item.RC;
            item.RC = t;
            if(t > _max)
                _max = t;

            if(t <= 0){
            callback();
            return;
            }

            prev = tmp;
        }

        delete item.min;
        delete item.max;

        returnData.push(item);

        callback();
    },
    function(err){

        var resultData = [];
            async.each(returnData,function(item,callback){
            item.max = _max;
            item.min = _min;
            resultData.push(item);
            callback();

            }, function(err){
                 callback(null,resultData);
            }

            );

    });*/
};

sendJsonResponse = function(req, res, data) {
    res.charset = 'UTF-8';
    //todo
    data.api_version = 0;
    var os = require("os");
    data.host = os.hostname();

     if (req.query.callback) {
     	res.type("application/json;charset=utf-8");
	res.send(req.query.callback + "(" + JSON.stringify(data) + ")");
     } else {
      	res.json(data);
    }
    return;
};

<commit_msg>fix rain 0<commit_after>var mongo = require('../data/mongodb.js');
var async = require('async');

exports.findLastLog = function(callback) {
	mongo.findLastLog({'ts': -1},function(err,first){
		mongo.findPrevLog(function(err,prev){
			console.log(prev.ts + " - " + first.ts);
			first.RC = first.RC - prev.RC;
			callback(err,first);
		});

	});
};

exports.findPrevLog = function(callback) {
	mongo.findPrevLog(function(err,result){
		callback(err,result);
	});
};

exports.findLast = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

			return	sendJsonResponse(req,res,result);
	});

};

exports.findLastWDWS24 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

		mongo.findWDWSLastFrom(startFrom,function(err,result){

			return	sendJsonResponse(req,res,result);

		});
	});

};

exports.findLastWDWS7 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

		mongo.findWDWSLastFrom(startFrom,function(err,result){

			return	sendJsonResponse(req,res,result);

		});
	});

};

exports.findLastWDWS30 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

		mongo.findWDWSLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastWDWS365 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 365);

		mongo.findWDWSLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastT24 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

		mongo.findTLastFrom(startFrom,function(err,result){

			return	sendJsonResponse(req,res,result);

		});
	});

};

exports.findLastT7 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

		mongo.findTLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastT30 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

		mongo.findTLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastT365 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

		mongo.findTLastFrom(startFrom,function(err,result){
			return	sendJsonResponse(req,res,result);
		});
	});

};

exports.findLastH24 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

	mongo.findHLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastH7 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

	mongo.findHLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastH30 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

	mongo.findHLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastH365 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

	mongo.findHLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastPRESS24 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

	mongo.findPRESSLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastPRESS7 = function(req, res) {
	//retrive last log date
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

	mongo.findPRESSLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastPRESS30 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

	mongo.findPRESSLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastPRESS365 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

	mongo.findPRESSLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastWC24 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

	mongo.findWCLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastWC7 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

	mongo.findWCLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastWC30 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

	mongo.findWCLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastWC365 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

	mongo.findWCLastFrom(startFrom,function(err,result){
		return	sendJsonResponse(req,res,result);
		});

	});

};

exports.findLastRC24 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - 86400000;

	mongo.findRCLastFrom(startFrom,function(err,result){

		recalcRain(result,function(err,data){
		        return	sendJsonResponse(req,res,data);
		        });
		});

	});

};

exports.findLastRC7 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 7);

	mongo.findRCLastFrom(startFrom,function(err,result){

		recalcRain(result,function(err,data){
		        return	sendJsonResponse(req,res,data);
		        });
		});

	});

};

exports.findLastRC30 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30);

	mongo.findRCLastFrom(startFrom,function(err,result){

		recalcRain(result,function(err,data){
		        return	sendJsonResponse(req,res,data);
		        });
		});

	});

};

exports.findLastRC365 = function(req, res) {
	mongo.findLastLog({'ts': -1},function(err,result){

		var startFrom = result.ts.getTime() - (86400000 * 30 * 12);

	mongo.findRCLastFrom(startFrom,function(err,result){

		recalcRain(result,function(err,data){
		        return	sendJsonResponse(req,res,data);
		        });
		});

	});

};

recalcRain = function(data,callback){

    var returnData = [];

    async.each(data,function(item,callback){

        if(!item.RC || parseInt(item.RC) == 0){
            callback();
        }else{
            delete item.min;
            delete item.max;
            returnData.push(item);
            callback();
        }
    },
    function(err){

         callback(null,returnData);

    });

//callback(null,data);
/*    var act = 0;
    var first = true;
    var prev = 0;
    var returnData = [];

    var _min = 0;
    var _max = 0;

    async.each(data,function(item,callback){

        if(first == true){
            console.log("first");
            prev = item.RC;
            item.RC = 0;
            first = false;
            callback();
            return;
        }else{
            var tmp = item.RC;
            //console.log("prev" + prev);
            //console.log("item" + item.RC);
            console.log(parseFloat(item.RC) - parseFloat(prev));

            var t = parseFloat(item.RC) - parseFloat(prev);
            prev = item.RC;
            item.RC = t;
            if(t > _max)
                _max = t;

            if(t <= 0){
            callback();
            return;
            }

            prev = tmp;
        }

        delete item.min;
        delete item.max;

        returnData.push(item);

        callback();
    },
    function(err){

        var resultData = [];
            async.each(returnData,function(item,callback){
            item.max = _max;
            item.min = _min;
            resultData.push(item);
            callback();

            }, function(err){
                 callback(null,resultData);
            }

            );

    });*/
};

sendJsonResponse = function(req, res, data) {
    res.charset = 'UTF-8';
    //todo
    data.api_version = 0;
    var os = require("os");
    data.host = os.hostname();

     if (req.query.callback) {
     	res.type("application/json;charset=utf-8");
	res.send(req.query.callback + "(" + JSON.stringify(data) + ")");
     } else {
      	res.json(data);
    }
    return;
};

<|endoftext|>


<commit_before>/*
 * RevealBase Component For react-reveal
 *
 * Copyright © Roman Nosov 2016, 2017
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */
import React from 'react';
import { string, object, number, bool, func, node, any, oneOfType } from 'prop-types';
import { namespace, ssr, disableSsr, globalHide } from './lib/globals';
import debounce from './lib/debounce';

const
  propTypes = {
    when: bool,
    spy: any,
    effect: string,
    collapse: string,
    duration: number,
    delay: number,
    tag: string,
    className: string,
    style: object,
    props: object,
    step: object,
    force: bool,
    fraction: number,
    onReveal: func,
    children: node.isRequired,
    in: object,
    out: oneOfType([object, bool]),
  },
  defaultProps = {
    duration: 1000,
    delay: 0,
    fraction: 0.2,
    tag: 'div',
    when: true,
  };

class RevealBase extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      legacyMode: false,
      style: props.when || !props.out
        ? {}
        : (props.collapse?{maxHeight: 0,...RevealBase.getStyle(false)}:RevealBase.getStyle(false))
    };
    this.isListener = false;
    this.isAnimated = false;
    this.reveal = this.reveal.bind(this);
    this.revealHandler = debounce(this.reveal, 66);
    //this.concealHandler = debounce(this.conceal.bind(this), 66);
    this.resizeHandler = debounce(this.resize.bind(this), 500);
    this.saveRef = el => this.el = el;
  }

  static getStyle(visible) {
    return { visibility: visible?'visible':'hidden', opacity: visible ? 1 : 0 };
  }

  static getTop(el) {
    while (el.offsetTop === void 0)
      el = el.parentNode;
    let top = el.offsetTop;
    for (;el.offsetParent; top += el.offsetTop)
      el = el.offsetParent;
    return top;
  }

  inViewport() {
    if (!this.el || window.document.hidden) return false;
    const h = this.el.offsetHeight,
          delta = window.pageYOffset - RevealBase.getTop(this.el),
          tail = Math.min(h, window.innerHeight) * ( globalHide ? this.props.fraction : 0 );
    return ( delta > tail - window.innerHeight ) && ( delta < h - tail );
  }

  hide() {
    if (this.props.out)
      this.setState(this.props.collapse
        ?{ style: {maxHeight: 0, transition: `max-height ${this.props.duration}ms`,...RevealBase.getStyle(false),  }}
        :{ style: RevealBase.getStyle(false) });
  }

  resize() {
    if (!this.el) return;
    if ( !this.isAnimated && (this.props.force || this.inViewport()) ) {
      this.isAnimated = true;
      this.setState({ style: RevealBase.getStyle(this.props.when) });
      if (this.props.onReveal && this.props.when)
        window.setTimeout(this.props.onReveal, this.props.delay + this.props.duration);
    }
  }

  log(i, start, end, duration, total) {
    const minv = Math.log(duration);
    const maxv = Math.log(total);
    const scale = (maxv-minv) / (end-start);
    return Math.exp(minv + scale*(i-start));
  }

  animate() {
    this.clean();
    if(this.props.effect)
      this.setState({ legacyMode: true });
    else {
      const inOut = this.props[this.props.when?'in':'out'];
      this.setState({ style: {
        //...RevealBase.getStyle(this.props.when),
        ...RevealBase.getStyle(true),
        //animationName: ( this.props.animation ? this.props.animation : void 0 ),
        animationName: inOut.animation||inOut.make(),
        animationFillMode: 'both',
        animationDuration: `${this.props.duration}ms`,
        animationDelay: `${this.props.delay}ms`,
        ...inOut.style,
      }});
    }
    this.isAnimated = true;
    if (this.props.onReveal && this.props.when)
      window.setTimeout(this.props.onReveal, this.props.delay + this.props.duration);
  }

  clean() {
    if (this.isListener) {
      window.removeEventListener('scroll', this.revealHandler);
      window.removeEventListener('orientationchange', this.revealHandler);
      window.document.removeEventListener('visibilitychange', this.revealHandler);
      window.removeEventListener('resize', this.resizeHandler);
      this.isListener = false;
    }
  }

  componentWillUnmount() {
    this.clean();
    ssr && disableSsr();
  }

  componentWillReceiveProps({ when, spy }) {
    if ( (when !== this.props.when) || (spy !== this.props.spy) ){
      this.setState({ style: {
        maxHeight:(this.props.collapse? 0 : void 0)
      } });
    }
  }

  componentDidUpdate({ when, spy }) {
    if ( (when !== this.props.when ) || (spy !== this.props.spy)) {
      this.isAnimated = false;
      this.props.when?this.reveal():this.conceal();
    }
  }

  listen() {
    if (!this.isListener && !this.props.force ) {
      window.addEventListener('scroll', this.revealHandler);
      window.addEventListener('orientationchange', this.revealHandler);
      window.document.addEventListener("visibilitychange", this.revealHandler);
      window.addEventListener('resize', this.resizeHandler);
      this.isListener = true;
    }
    return this;
  }

  reveal() {
    if (!this.props.when)
      return;
    if ( !this.isAnimated ) {
      this.listen();
      if ( this.props.force || this.inViewport() ) {
        if (this.start) {
          this.hide();
          this.start(this.step);
          return;
        }
        else
          this.animate();
      }
    }
  }

  conceal() {
    if ( !this.isAnimated && this.props.out ) {
      //this.listen(-1);
      if (this.inViewport())
        this.animate();
      else //this.setState({ style: RevealBase.getStyle(true)});
        this.hide();
    }
  }

  componentDidMount() {
    if (!this.el) return;
    if (this.props.step)
      this.props.step.push(this);
    if ( ssr && this.props.out && RevealBase.getTop(this.el) < window.pageYOffset + window.innerHeight ) {
      this.setState({ style: { ...RevealBase.getStyle(true), transition: 'opacity 1000ms' } });
      window.setTimeout(this.reveal, 1000);
    }
    else
      this.reveal();
  }

  //inOut() {
  //  const inOut = this.props[this.props.when?'in':'out'];
  //  if (this.props.effect || !inOut)
  //    return {};
  //  return inOut;
  //}

  render() {
    const { tag: TagName, id, children, style, className } = this.props,
      newClass = `${ this.state.legacyMode ? this.props.effect : ( !this.props.out ? '' : namespace ) }${ className ? ' ' + className : '' }`;
    let newStyle, newChildren= false;
    if (!this.state.legacyMode) {
       newStyle = {...style, ...this.state.style};
      let reverse = false;
      if (this.props.cascade && children && this.state.style.animationName) {
        if (typeof children === 'string') {
          newChildren = children.split("").map( (ch, index) => {ch} );
          reverse = this.props.reverse;
        }
        else
          newChildren = React.Children.toArray(children);
        const count = newChildren.length - 1,
              total =  this.props.duration + (typeof this.props.cascade === 'boolean' ? 1000 : this.props.cascade);
        let i = reverse ? count : 0;
        newChildren = newChildren.map( child =>
          React.cloneElement(child,{style: {...child.props.style, ...this.state.style,
            animationDuration: Math.round(this.log( reverse ? i-- : i++ ,0 ,count, this.props.duration, total)) + 'ms',
          }}));
        newStyle.animationDuration = '0s';
        newStyle.animationName = 'none';
      }
    }
    return <TagName
        id={id}
        {...(this.props.props||void 0)}
        className={newClass}
        style={this.state.legacyMode?style:newStyle}
        children={newChildren||children}
        ref={this.saveRef}
    />;
  }

}

RevealBase.propTypes = propTypes;
RevealBase.defaultProps = defaultProps;
export default RevealBase;
<commit_msg>chrome collapse fix<commit_after>/*
 * RevealBase Component For react-reveal
 *
 * Copyright © Roman Nosov 2016, 2017
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */
import React from 'react';
import { string, object, number, bool, func, node, any, oneOfType } from 'prop-types';
import { namespace, ssr, disableSsr, globalHide } from './lib/globals';
import debounce from './lib/debounce';

const
  propTypes = {
    when: bool,
    spy: any,
    effect: string,
    collapse: string,
    duration: number,
    delay: number,
    tag: string,
    className: string,
    style: object,
    props: object,
    step: object,
    force: bool,
    fraction: number,
    onReveal: func,
    children: node.isRequired,
    in: object,
    out: oneOfType([object, bool]),
  },
  defaultProps = {
    duration: 1000,
    delay: 0,
    fraction: 0.2,
    tag: 'div',
    when: true,
  };

class RevealBase extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      legacyMode: false,
      style: props.when || !props.out
        ? {}
        : (props.collapse?{maxHeight: 0,...RevealBase.getStyle(false)}:RevealBase.getStyle(false))
    };
    this.isListener = false;
    this.isAnimated = false;
    this.reveal = this.reveal.bind(this);
    this.revealHandler = debounce(this.reveal, 66);
    //this.concealHandler = debounce(this.conceal.bind(this), 66);
    this.resizeHandler = debounce(this.resize.bind(this), 500);
    this.saveRef = el => this.el = el;
  }

  static getStyle(visible) {
    return { visibility: visible?'visible':'hidden', opacity: visible ? 1 : 0 };
  }

  static getTop(el) {
    while (el.offsetTop === void 0)
      el = el.parentNode;
    let top = el.offsetTop;
    for (;el.offsetParent; top += el.offsetTop)
      el = el.offsetParent;
    return top;
  }

  inViewport() {
    if (!this.el || window.document.hidden) return false;
    const h = this.el.offsetHeight,
          delta = window.pageYOffset - RevealBase.getTop(this.el),
          tail = Math.min(h, window.innerHeight) * ( globalHide ? this.props.fraction : 0 );
    return ( delta > tail - window.innerHeight ) && ( delta < h - tail );
  }

  hide() {
    if (this.props.out)
      //this.setState({ style: RevealBase.getStyle(false) });
      this.setState(this.props.collapse
        ?{ style: {maxHeight: 0, transition: `all ${this.props.duration}ms`,opacity: 0}}//...RevealBase.getStyle(false),  }}
        :{ style: RevealBase.getStyle(false) });
  }

  resize() {
    if (!this.el) return;
    if ( !this.isAnimated && (this.props.force || this.inViewport()) ) {
      this.isAnimated = true;
      this.setState({ style: RevealBase.getStyle(this.props.when) });
      if (this.props.onReveal && this.props.when)
        window.setTimeout(this.props.onReveal, this.props.delay + this.props.duration);
    }
  }

  log(i, start, end, duration, total) {
    const minv = Math.log(duration);
    const maxv = Math.log(total);
    const scale = (maxv-minv) / (end-start);
    return Math.exp(minv + scale*(i-start));
  }

  animate() {
    this.clean();
    if(this.props.effect)
      this.setState({ legacyMode: true });
    else {
      const inOut = this.props[this.props.when?'in':'out'];
      this.setState({ style: {
        //...RevealBase.getStyle(this.props.when),
        ...RevealBase.getStyle(true),
        animationName: inOut.animation||inOut.make(),
        animationFillMode: 'both',
        animationDuration: `${this.props.duration}ms`,
        animationDelay: `${this.props.delay}ms`,
        ...inOut.style,
      }});
    }
    this.isAnimated = true;
    if (this.props.onReveal && this.props.when)
      window.setTimeout(this.props.onReveal, this.props.delay + this.props.duration);
  }

  clean() {
    if (this.isListener) {
      window.removeEventListener('scroll', this.revealHandler);
      window.removeEventListener('orientationchange', this.revealHandler);
      window.document.removeEventListener('visibilitychange', this.revealHandler);
      window.removeEventListener('resize', this.resizeHandler);
      this.isListener = false;
    }
  }

  componentWillUnmount() {
    this.clean();
    ssr && disableSsr();
  }

  componentDidUpdate({ when, spy }) {
    if ( (when !== this.props.when ) || (spy !== this.props.spy)) {
      this.isAnimated = false;
      this.props.when?this.reveal():this.conceal();
    }
  }

  listen() {
    if (!this.isListener && !this.props.force ) {
      window.addEventListener('scroll', this.revealHandler);
      window.addEventListener('orientationchange', this.revealHandler);
      window.document.addEventListener("visibilitychange", this.revealHandler);
      window.addEventListener('resize', this.resizeHandler);
      this.isListener = true;
    }
    return this;
  }

  reveal() {
    if (!this.props.when)
      return;
    if ( !this.isAnimated ) {
      this.listen();
      if ( this.props.force || this.inViewport() ) {
        if (this.start) {
          this.hide();
          this.start(this.step);
          return;
        }
        else
          this.animate();
      }
    }
  }

  conceal() {
    if ( !this.isAnimated && this.props.out ) {
      this.animate();
      ////this.listen(-1);
      //if (this.inViewport())
      //  this.animate();
      //else //this.setState({ style: RevealBase.getStyle(true)});
      //  this.hide();
    }
  }

  componentDidMount() {
    if (!this.el) return;
    if (this.props.step)
      this.props.step.push(this);
    if ( ssr && this.props.out && RevealBase.getTop(this.el) < window.pageYOffset + window.innerHeight ) {
      this.setState({ style: { ...RevealBase.getStyle(true), transition: 'opacity 1000ms' } });
      window.setTimeout(this.reveal, 1000);
    }
    else
      this.reveal();
  }

  render() {
    const { tag: TagName, id, children, style, className } = this.props,
      newClass = `${ this.state.legacyMode ? this.props.effect : ( !this.props.out ? '' : namespace ) }${ className ? ' ' + className : '' }`;
    let newStyle, newChildren= false;
    if (!this.state.legacyMode) {
       newStyle = {...style, ...this.state.style};
      let reverse = false;
      if (this.props.cascade && children && this.state.style.animationName) {
        if (typeof children === 'string') {
          newChildren = children.split("").map( (ch, index) => {ch} );
          reverse = this.props.reverse;
        }
        else
          newChildren = React.Children.toArray(children);
        const count = newChildren.length - 1,
              total =  this.props.duration + (typeof this.props.cascade === 'boolean' ? 1000 : this.props.cascade);
        let i = reverse ? count : 0;
        newChildren = newChildren.map( child =>
          React.cloneElement(child,{style: {...child.props.style, ...this.state.style,
            animationDuration: Math.round(this.log( reverse ? i-- : i++ ,0 ,count, this.props.duration, total)) + 'ms',
          }}));
        newStyle.animationDuration = '0s';
        newStyle.animationName = 'none';
      }
    }
    return <TagName
        id={id}
        {...(this.props.props||void 0)}
        className={newClass}
        style={this.state.legacyMode?style:newStyle}
        children={newChildren||children}
        ref={this.saveRef}
    />;
  }

}

RevealBase.propTypes = propTypes;
RevealBase.defaultProps = defaultProps;
export default RevealBase;
<|endoftext|>


<commit_before>'use strict';
;(function($, window, document, undefined) {
    // Variables only created once.

    // Name of the plugin
    var validate = 'validate',

    defaults = {
        rules: {},
        validationError: 'validationError',
        debug: true,
        onchange: false,
        valid: false,
        onsubmit: true,
        onchangeElements: ['select', 'checkbox'],
        onkeyupElements: ['text', 'textarea'],
        errorList: [], //list of elements with validation failures.
        errorMap: {},
        errorMessage: $('')
    };

    // create the validate class
    function Validate( form, options) {
        this.$form = $(form);

        this.options = $.extend( {}, defaults, options);

        this._defaults = defaults;
        this._name = validate;

        return this;
    }

    // Prototype the validate class
    // This contains all the methods that can be called by all instances of the class.
    Validate.prototype = {
        // the init function will need to check the validity of all required elements.
        validation: function() {
            var $this = this;
            var form = this.$form;
            this.options.errorList = [];

            //loop through all elements
            $.each(this.options.rules, function(element, value) {
                var element = $(form.find('#' + element));

                $this.checkValidity(element);
                $this.updateErrorList(element);
            });
        },

        // Validate a single element
        checkValidity: function(element) {
            var $this = this;

            $.each(element.data('rules'), function(ruleType, details) {
                var value = $this.elementValue(element);
                element.data('rules')[ruleType].valid = $this.validateRule(ruleType, value);
            });

            $this.updateErrorList(element);
            $this.displayErrors(element);
        },

        // validate a single rule for the given element.
        validateRule: function(ruleType, value) {
            switch(ruleType){
                case 'required':
                    return this.methods.required(value);
                break;

                case 'number':
                    return this.methods.number(value);
                break;
                default:
                    return false;
            }
        },

        //If an elements rule is valid == false then it should be added to the errorMap.
        updateErrorList: function(element) {
            var failure = false;

            $.each(element.data('rules'), function(ruleType, details) {
                if(!element.data('rules')[ruleType].valid) {
                    failure = true;
                }
            });

            var errorList = this.options.errorList;

            if(failure) {
                errorList.push(element.prop('id'));
            }
            else{
                var index = errorList.indexOf(element.prop('id'));
                if(index > 0) {
                    errorList.splice(index, 1);
                }
            }
        },

        // Display errors for all failed fields.
        // take into account select2 inputs.
        displayErrors: function(element) {
            var $this = this;
            var selector = element.prop('id');
            var errorEnabled = false;
            var formatElement = element;

            if ($(element).prop('tagName').toLowerCase() === 'select' && (element.prev('div').hasClass('select2-container'))) {
                formatElement = $(element.prev('div'));
            }

            $this.reset(formatElement);

            if ($.inArray(selector, this.options.errorList) >= 0) {
                $.each(element.data('rules'), function(ruleType, details) {

                    if (!details.valid && !errorEnabled) {
                        var errorMessage = $this.options.errorMessage;

                        formatElement.parent().append((errorMessage).append(details.message));
                        formatElement.css('border', '2px solid #b94a48');

                        errorEnabled = true;
                    }
                });
            }
        },

        // Reset the error details against a given element.
        // since the error element is currently displayed at the same level as the input
        // the parent element is used to find the #errorMessage element for removal.
        reset: function(element) {
            element.parent().find('#errorMessage').remove();
            this.options.errorMessage = $('');
            element.attr('style', '');
        },

        // If any error remain form is still invalid.
        formValid: function() {
            return this.options.errorList.length === 0;
        },

        // Set the rule for all valid inputs.
        setuprules: function() {
            var $this = this;
            // will need to check the elements that are in the options and bind change events to them.
            $.each(this.options.rules, function(input, rules){
                var form = $this.$form;
                var input = $(form.find('#' + input));
                var inputType = $this.inputtype(input);

                if (!$this.validinputtype(input)){
                    console.log(inputType + ' is not a valid form element, please alter your configuration.');
                    $this.removeRule(input.prop('id'));
                    return;
                }
                // Apply rules to the input.
                input.data('rules', $this.setrules(rules));
                $this.seteventhandler(input, inputType);
            });

            // Setup event handler for on submit
            if (this.options.onsubmit === true) {
                $this.seteventhandler(this.$form, 'submit');
            }
        },

        // Build the rules for an element setting validity at false.
        setrules: function(rules) {
            var validationRules = {};

            $.each(rules, function(element, value) {

                validationRules[element] = {
                            'message': value,
                            'valid'  : false
                         };
            });

            return validationRules;
        },

        // Delete the rules for a given input (usually this will be to ignore invalid element assignments
        // when the plugin is instatntiated)
        removeRule: function(input) {
            delete this.options.rules[input];
        },

        // Based on the input type set the event handlers.
        seteventhandler: function(input, inputType) {
            var $this = this;
            // set event types based on the element type.
            if ($.inArray(inputType, this.options.onchangeElements) === 0) {
                input.on(
                    'change',
                    function() {
                        $this.onchange(input);
                    });
            }

            if ($.inArray(inputType, this.options.onkeyupElements) === 0) {
                input.on(
                    'keyup blur',
                    function() {
                        $this.onkeyup(input);
                    });
            }

            if (inputType === 'submit'){
                input.on(
                    'submit',
                    function( event ) {
                        $this.onsubmit(event);
                    });
            }
        },

        // The onsubmit event
        onsubmit:function(event) {
            //If debug mode set then never submit the form.
            if (this.options.debug) {
                event.preventDefault();
            }

            this.validation();
            // If the form is not valid do not submit.

            if(!this.formValid()){
                event.preventDefault();
                return false;
            }

        },

        // The onkeyup event
        onkeyup: function(element) {
            this.checkValidity(element);
        },

        // The onchange event
        onchange: function(element) {
            this.checkValidity(element);
        },

        // Check if the element is a valid input type for a form.
        validinputtype: function(element) {
            return element.is('select, input, textarea');
        },

        // Return the input type as a string.
        inputtype: function(element) {
            var type = '';

            type = $(element).prop('tagName').toLowerCase();

            // If an input, get the input type.
            if (type === 'input'){
                return $(element).prop('type');
            }

            return type;
        },

        // Return the value of the given form element.
        elementValue: function(element) {
            var val,
            $element = $( element ),
            type = element.type;

            if ( type === 'radio' || type === 'checkbox' ) {
                return $( 'input[name="' + element.name + '"]:checked' ).val();
            }

            val = $element.val();

            if ( typeof val === 'string' ) {
                return val.replace(/\r/g, '' );
            }

            return val;
        },

        // Methods to check inputs value is correct.
        methods: {
            required: function(value) {
                return $.trim( value ).length > 0;
            },

            number: function(value) {
                return /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
            }
        }
    };

    // A really lightweight plugin wrapper around the constructor,
    // preventing multiple instantiations.
    $.fn[validate] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, 'validate')) {
                var validate = $.data(this, 'validate', new Validate( this, options));
            }
            validate.setuprules();
        });
    };

}) ( jQuery, window, document );<commit_msg>added extra validation check for email, minLength, maxLength and rangeLength. <commit_after>;(function($, window, document, undefined) {
    // Variables only created once.

    // Name of the plugin
    var validate = "validate",

    defaults = {
        rules: {},
        validationError: "validationError",
        debug: true,
        onchange: false,
        valid: false,
        onsubmit: true,
        onchangeElements: ['select', 'checkbox'],
        onkeyupElements: ['text', 'textarea'],
        errorList: [], //list of elements with validation failures.
        errorMap: {},
        errorMessage: $("")
    };

    // create the validate class
    function Validate( form, options) {
        this.$form = $(form);

        this.options = $.extend( {}, defaults, options);

        this._defaults = defaults;
        this._name = validate;

        return this;
    }

    // Prototype the validate class
    // This contains all the methods that can be called by all instances of the class.
    Validate.prototype = {

        // the init function will need to check the validity of all required elements.
        validation: function() {
            var $this = this;
            var form = this.$form;
            this.options.errorList = [];

            //loop through all elements
            $.each(this.options.rules, function(element, value) {
                var element = $(form.find("#" + element));

                $this.checkValidity(element);
                $this.updateErrorList(element);
            });
        },

        // Validate a single element
        checkValidity: function(element) {
            var $this = this;

            $.each(element.data("rules"), function(ruleType, details) {
                var value = $this.elementValue(element);
                element.data("rules")[ruleType].valid = $this.validateRule(ruleType, value, element);
            });

            $this.updateErrorList(element);
            $this.displayErrors(element);
        },

        // validate a single rule for the given element.
        validateRule: function(ruleType, value, element) {
            var parameter = this.options.rules[element.prop("id")][ruleType]
            return this.methods[ruleType](value, element, parameter);
        },

        //If an elements rule is valid == false then it should be added to the errorMap.
        updateErrorList: function(element) {
            var $this = this;
            var failure = false;

            $.each(element.data("rules"), function(ruleType, details) {
                if(!element.data("rules")[ruleType].valid) {
                    failure = true;
                }
            });

            var errorList = this.options.errorList;

            if(failure) {
                errorList.push(element.prop("id"));
            }
            else{
                var index = errorList.indexOf(element.prop("id"));
                if(index > 0) {
                    errorList.splice(index, 1);
                }
            }
        },

        // Display errors for all failed fields.
        // take into account select2 inputs.
        displayErrors: function(element) {
            var $this = this;
            var selector = element.prop("id");
            var errorEnabled = false;
            var formatElement = element;

            if ($(element).prop('tagName').toLowerCase() === 'select' && (element.prev('div').hasClass('select2-container'))) {
                formatElement = $(element.prev('div'));
            }

            $this.reset(formatElement);

            if ($.inArray(selector, this.options.errorList) >= 0) {
                $.each(element.data("rules"), function(ruleType, details) {

                    if (!details.valid && !errorEnabled) {
                        var errorMessage = $this.options.errorMessage;

                        formatElement.parent().append((errorMessage).append(details.message));
                        formatElement.css("border", "2px solid #b94a48");

                        errorEnabled = true;
                    }
                })
            }
        },

        // Reset the error details against a given element.
        // since the error element is currently displayed at the same level as the input
        // the parent element is used to find the #errorMessage element for removal.
        reset: function(element) {
            element.parent().find("#errorMessage").remove();
            this.options.errorMessage = $("");
            element.attr("style", "");
        },

        // If any error remain form is still invalid.
        formValid: function() {
            return this.options.errorList.length === 0;
        },

        // Set the rule for all valid inputs.
        setuprules: function() {
            var $this = this;
            // will need to check the elements that are in the options and bind change events to them.
            $.each(this.options.rules, function(input, rules){
                var form = $this.$form;
                var input = $(form.find("#" + input));
                var inputType = $this.inputtype(input);

                if (!$this.validinputtype(input)){
                    console.log(inputType + " is not a valid form element, please alter your configuration.");
                    $this.removeRule(input.prop("id"));
                    return;
                }
                // Apply rules to the input.
                input.data("rules", $this.setrules(rules));
                $this.seteventhandler(input, inputType);
            });

            // Setup event handler for on submit
            if (this.options.onsubmit === true) {
                $this.seteventhandler(this.$form, "submit");
            }
        },

        // Build the rules for an element setting validity at false.
        setrules: function(rules) {
            var validationRules = {};

            $.each(rules, function(element, value) {

                validationRules[element] = {
                            'message': value,
                            'valid'  : false
                         }
            });

            return validationRules;
        },

        // Delete the rules for a given input (usually this will be to ignore invalid element assignments
        // when the plugin is instatntiated)
        removeRule: function(input) {
            delete this.options.rules[input];
        },

        // Based on the input type set the event handlers.
        seteventhandler: function(input, inputType) {
            var $this = this;
            // set event types based on the element type.
            if ($.inArray(inputType, this.options.onchangeElements) === 0) {
                input.on(
                    "change",
                    function() {
                        $this.onchange(input)
                    });
            }

            if ($.inArray(inputType, this.options.onkeyupElements) === 0) {
                input.on(
                    "keyup blur",
                    function() {
                        $this.onkeyup(input)
                    });
            }

            if (inputType === 'submit'){
                input.on(
                    "submit",
                    function( event ) {
                        $this.onsubmit(event, input)
                    });
            }
        },

        // The onsubmit event
        onsubmit:function(event, element) {
            //If debug mode set then never submit the form.
            if (this.options.debug) {
                event.preventDefault();
            }

            this.validation();
            // If the form is not valid do not submit.

            if(!this.formValid()){
                event.preventDefault();
                return false;
            }
        },

        // The onkeyup event
        onkeyup: function(element) {
            this.checkValidity(element);
        },

        // The onchange event
        onchange: function(element) {
            this.checkValidity(element);
        },

        // Check if the element is a valid input type for a form.
        validinputtype: function(element) {
            return element.is("select, input, textarea");
        },

        // Return the input type as a string.
        inputtype: function(element) {
            var type = "";

            type = $(element).prop('tagName').toLowerCase();

            // If an input, get the input type.
            if (type === "input"){
                return $(element).prop("type");
            }

            return type;
        },

        // Return the value of the given form element.
        elementValue: function(element) {
            var val,
            $element = $( element ),
            type = element.type;

            if ( type === "radio" || type === "checkbox" ) {
                return $( "input[name='" + element.name + "']:checked" ).val();
            }

            val = $element.val();

            if ( typeof val === "string" ) {
                return val.replace(/\r/g, "" );
            }

            return val;
        },

        // Methods to check inputs value is correct.
        methods: {
            required: function(value) {
                return $.trim( value ).length > 0;
            },

            number: function(value) {
                return /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
            },

            email: function(value) {
                // From http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
                return /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test( value );
            },

            maxLength: function(value, element, parameter) {
                element.data("rules").maxLength.message = "must be less than " + parameter + " characters long, currently " + value.length;
                return value.length <= parameter;
            },

            minLength: function(value, element, parameter) {
                element.data("rules").minLength.message = "must be more than " + parameter + " characters long, currently " + value.length;
                return value.length >= parameter;
            },

            rangeLength: function(value, element, parameter) {
                element.data("rules").rangeLength.message = "must be between " + parameter[ 0 ] + " and " + parameter[ 1 ] + " characters long, currently " + value.length;
                return value.length >= parameter[ 0 ] && value.length <= parameter[ 1 ];
            }
        }
    };

    // A really lightweight plugin wrapper around the constructor,
    // preventing multiple instantiations.
    $.fn[validate] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, "validate")) {
                var validate = $.data(this, "validate", new Validate( this, options));
            }
            validate.setuprules();
        });
    };

}) ( jQuery, window, document );<|endoftext|>


<commit_before>/*!
 * Funnel Chart v0.0.1
 * https://github.com/promotably/funnel-chart
 *
 * Copyright 2015 Promotably LLC
 * Released under the MIT license
 */
(function (root, factory) {
  if(typeof define === 'function' && define.amd) {
    define(factory);
  }
  else if(typeof module === 'object' && module.exports) {
    module.exports = factory();
  }
  else {
    root.FunnelChart = factory();
  }
}(this, function() {

  function extend(out) {
    out = out || {};

    for (var i = 1; i < arguments.length; i++) {
      if (!arguments[i])
        continue;

      for (var key in arguments[i]) {
        if (arguments[i].hasOwnProperty(key))
          out[key] = arguments[i][key];
      }
    }

    return out;
  }

  // canvas arg can be an ID string or HTMLElement
  function FunnelChart(canvas, settings) {
    // Allows FunnelChart to be instantiated without use of "new"
    if (!(this instanceof FunnelChart))
      return new FunnelChart(canvas, settings);

    // Ensure canvas is an HTMLElement
    this.canvas = (typeof canvas === 'string') ?
      document.getElementById(canvas) : canvas;

    // TODO: Check settings.values exists
    if(!settings.values || !settings.values.length)
      throw('A values setting must be provided');

    // Extend default settings
    this.settings = extend(this.settings, settings);

    // Init!
    this.initialize();
  }

  FunnelChart.prototype = extend(FunnelChart.prototype, {

    settings: {

      // Boolean - Whether to display % change between sections
      displayPercentageChange: true,

      // Number - The number of decimal places that should be displayed for %
      // change values
      pPrecision: 1,

      // String - The color of the horizontal label lines (if labels are shown)
      labelLineColor: '#eee',

      // String or Array - The font color(s) of the labels.
      labelFontColor: '#657274',

      // String or Array - The color(s) of the funnel sections.
      sectionColor: '#0498b3',

      // String or Array - The color(s) of the funnel percentage sections.
      pSectionColor: '#bfd1d4',

      // String - The font for labels and values
      font: 'Helvetica Neue',

      // Number - The maximum font size in pixels (px) for labels and values.
      // This will always be used where possible unless the height of the
      // funnel sections is too small to permit it, in which case the font size
      // will be automatically reduced to fit
      maxFontSize: 13,

      // String - The font weight for labels and values
      fontWeight: '300',

      // String or Array - The font color(s) for funnel sections
      sectionFontColor: '#fff',

      // String or Array - The font color(s) for % change sections
      pSectionFontColor: '#657274',

      // Number - The height of the % change sections compared to the main
      // funnel sections. This is a percent value.
      pSectionHeightPercent: 100,

      // Number - The percentage of the full canvas width that should be
      // reserved for display of labels (if provided). The funnel will expand
      // to fit the remainder.
      labelWidthPercent: 30,

      // Number - The percentage width difference between the top and the
      // bottom of the funnel.
      funnelReductionPercent: 40,

      // Number - The space between the right hand edge of the funnel and the
      // label text in pixels.
      labelOffset: 10
    },

    initialize: function() {
      this.calculateDimensions();
      this.draw();
    },

    calculateDimensions: function() {
      var settings = this.settings,
          labelWidth, sectionTotalHeight;

      // Width and height of canvas
      this.width = this.canvas.offsetWidth;
      this.height = canvas.offsetHeight;

      // Width allocated to labels
      labelWidth = this.hasLabels() ? this.width * (settings.labelWidthPercent / 100) : 0;
      this.labelMaxWidth = labelWidth - settings.labelOffset;

      // Start and end width of funnel
      this.startWidth = this.width - labelWidth;
      this.endWidth = this.startWidth * (settings.funnelReductionPercent / 100);

      // Section heights
      if(settings.displayPercentageChange) {
        sectionTotalHeight = (this.height / (settings.values.length - 0.5));
        this.pSectionHeight = (sectionTotalHeight / (settings.pSectionHeightPercent + 100)) * settings.pSectionHeightPercent;
        this.sectionHeight = sectionTotalHeight - this.pSectionHeight - 1;
        this.pSectionHeight = this.pSectionHeight - 1;
      }
      else {
        sectionTotalHeight = (this.height / settings.values.length);
        this.sectionHeight = sectionTotalHeight - 1;
        this.pSectionHeight = 0;
      }
    },

    draw: function() {
      var canvas = this.canvas,
          settings = this.settings;

      if (canvas.getContext) {
        var ctx = canvas.getContext('2d'),
            maxAvailFontSize = ((settings.displayPercentageChange) ? this.pSectionHeight : this.sectionHeight) - 2;

        // Reduce font size if necessary
        if(settings.maxFontSize >= maxAvailFontSize)
          settings.maxFontSize = maxAvailFontSize;

        // Configure font styling
        ctx.font = settings.fontWeight + ' ' + settings.maxFontSize + 'px ' + settings.font;

        // Draw labels if we have any
        if(this.hasLabels()) this.drawLabels(ctx);

        // Draw funnel clipping area with white background
        this.drawClippingArea(ctx, settings);
        ctx.fillStyle = '#fff';
        ctx.fill();
        ctx.clip();

        // Draw funnel sections
        this.drawSections(ctx);

        // Tidy up funnel outline
        this.drawClippingArea(ctx, settings);
        ctx.lineWidth = 2;
        ctx.strokeStyle = '#fff';
        ctx.stroke();
      }
    },

    drawLabels: function(ctx) {
      var settings = this.settings,
          i, yPos;

      ctx.strokeStyle = settings.labelLineColor;
      ctx.lineWidth = 1;

      for(i = 0; i < settings.values.length; i++) {
        yPos = this.calculateYPos(i);

        ctx.fillStyle = this.sequentialValue(settings.labelFontColor, i);
        ctx.fillText(
          settings.labels[i] || '',
          this.startWidth + settings.labelOffset,
          yPos + (this.sectionHeight / 2) + (settings.maxFontSize / 2) - 2,
          this.labelMaxWidth
        );

        if(i > 0) {
          ctx.beginPath();
          ctx.moveTo(i, yPos);
          ctx.lineTo(this.width, yPos);
          ctx.stroke();
        }

        if(i < (settings.values.length - 1) && settings.displayPercentageChange){
          ctx.beginPath();
          ctx.moveTo(i, yPos + this.sectionHeight);
          ctx.lineTo(this.width, yPos + this.sectionHeight);
          ctx.stroke();
        }

      }
    },

    drawClippingArea: function(ctx, settings) {
      var inset = (this.startWidth - this.endWidth) / 2;
      var height = (settings.values.length * this.sectionHeight) +
                     ((settings.values.length - 1) * this.pSectionHeight) +
                     (settings.values.length + 1);

      ctx.beginPath();
      ctx.moveTo(0,0);
      ctx.lineTo(this.startWidth,0);
      ctx.quadraticCurveTo(
        (this.startWidth - inset),
        (height / 3),
        (this.startWidth - inset),
        height
      );
      ctx.lineTo(inset,height);
      ctx.quadraticCurveTo(inset, (height / 3), 0, 0);
    },

    drawSections: function(ctx) {
      var settings = this.settings,
          i, yPos;

      ctx.textAlign = 'center';

      for(i = 0; i < settings.values.length; i++) {
        yPos = this.calculateYPos(i);

        ctx.fillStyle = this.sequentialValue(settings.sectionColor, i);
        ctx.fillRect(0, yPos, this.startWidth, this.sectionHeight);
        ctx.fillStyle = this.sequentialValue(settings.sectionFontColor, i);
        ctx.fillText(
          settings.values[i],
          this.startWidth / 2,
          yPos + (this.sectionHeight / 2) + (settings.maxFontSize / 2) - 2
        );

        if(i < (settings.values.length - 1) && settings.displayPercentageChange) {
          ctx.fillStyle = this.sequentialValue(settings.pSectionColor, i);
          ctx.fillRect(
            0,
            (yPos + this.sectionHeight + 1),
            this.startWidth,
            this.pSectionHeight
          );

          ctx.fillStyle = this.sequentialValue(settings.pSectionFontColor, i);
          ctx.fillText(
            ((settings.values[i + 1] / settings.values[i]) * 100).toFixed(settings.pPrecision) + '%',
            this.startWidth / 2,
            yPos + this.sectionHeight + (this.pSectionHeight / 2) + (settings.maxFontSize / 2) - 1
          );
        }
      }
    },

    hasLabels: function() {
      return this.settings.labels && !!this.settings.labels.length;
    },

    calculateYPos: function(i) {
      var sectionHeight = this.sectionHeight + 1;

      if(this.settings.displayPercentageChange)
        sectionHeight += this.pSectionHeight + 1;

      return (i === 0) ? 0 : (sectionHeight * i);
    },

    sequentialValue: function(arr, i) {
      if(typeof arr === 'string') return arr;
      return arr[i % arr.length];
    }

  });

  return FunnelChart;

}));
<commit_msg>Fix bad ref to canvas element<commit_after>/*!
 * Funnel Chart v0.0.1
 * https://github.com/promotably/funnel-chart
 *
 * Copyright 2015 Promotably LLC
 * Released under the MIT license
 */
(function (root, factory) {
  if(typeof define === 'function' && define.amd) {
    define(factory);
  }
  else if(typeof module === 'object' && module.exports) {
    module.exports = factory();
  }
  else {
    root.FunnelChart = factory();
  }
}(this, function() {

  function extend(out) {
    out = out || {};

    for (var i = 1; i < arguments.length; i++) {
      if (!arguments[i])
        continue;

      for (var key in arguments[i]) {
        if (arguments[i].hasOwnProperty(key))
          out[key] = arguments[i][key];
      }
    }

    return out;
  }

  // canvas arg can be an ID string or HTMLElement
  function FunnelChart(canvas, settings) {
    // Allows FunnelChart to be instantiated without use of "new"
    if (!(this instanceof FunnelChart))
      return new FunnelChart(canvas, settings);

    // Ensure canvas is an HTMLElement
    this.canvas = (typeof canvas === 'string') ?
      document.getElementById(canvas) : canvas;

    // TODO: Check settings.values exists
    if(!settings.values || !settings.values.length)
      throw('A values setting must be provided');

    // Extend default settings
    this.settings = extend(this.settings, settings);

    // Init!
    this.initialize();
  }

  FunnelChart.prototype = extend(FunnelChart.prototype, {

    settings: {

      // Boolean - Whether to display % change between sections
      displayPercentageChange: true,

      // Number - The number of decimal places that should be displayed for %
      // change values
      pPrecision: 1,

      // String - The color of the horizontal label lines (if labels are shown)
      labelLineColor: '#eee',

      // String or Array - The font color(s) of the labels.
      labelFontColor: '#657274',

      // String or Array - The color(s) of the funnel sections.
      sectionColor: '#0498b3',

      // String or Array - The color(s) of the funnel percentage sections.
      pSectionColor: '#bfd1d4',

      // String - The font for labels and values
      font: 'Helvetica Neue',

      // Number - The maximum font size in pixels (px) for labels and values.
      // This will always be used where possible unless the height of the
      // funnel sections is too small to permit it, in which case the font size
      // will be automatically reduced to fit
      maxFontSize: 13,

      // String - The font weight for labels and values
      fontWeight: '300',

      // String or Array - The font color(s) for funnel sections
      sectionFontColor: '#fff',

      // String or Array - The font color(s) for % change sections
      pSectionFontColor: '#657274',

      // Number - The height of the % change sections compared to the main
      // funnel sections. This is a percent value.
      pSectionHeightPercent: 100,

      // Number - The percentage of the full canvas width that should be
      // reserved for display of labels (if provided). The funnel will expand
      // to fit the remainder.
      labelWidthPercent: 30,

      // Number - The percentage width difference between the top and the
      // bottom of the funnel.
      funnelReductionPercent: 40,

      // Number - The space between the right hand edge of the funnel and the
      // label text in pixels.
      labelOffset: 10
    },

    initialize: function() {
      this.calculateDimensions();
      this.draw();
    },

    calculateDimensions: function() {
      var settings = this.settings,
          labelWidth, sectionTotalHeight;

      // Width and height of canvas
      this.width = this.canvas.offsetWidth;
      this.height = this.canvas.offsetHeight;

      // Width allocated to labels
      labelWidth = this.hasLabels() ? this.width * (settings.labelWidthPercent / 100) : 0;
      this.labelMaxWidth = labelWidth - settings.labelOffset;

      // Start and end width of funnel
      this.startWidth = this.width - labelWidth;
      this.endWidth = this.startWidth * (settings.funnelReductionPercent / 100);

      // Section heights
      if(settings.displayPercentageChange) {
        sectionTotalHeight = (this.height / (settings.values.length - 0.5));
        this.pSectionHeight = (sectionTotalHeight / (settings.pSectionHeightPercent + 100)) * settings.pSectionHeightPercent;
        this.sectionHeight = sectionTotalHeight - this.pSectionHeight - 1;
        this.pSectionHeight = this.pSectionHeight - 1;
      }
      else {
        sectionTotalHeight = (this.height / settings.values.length);
        this.sectionHeight = sectionTotalHeight - 1;
        this.pSectionHeight = 0;
      }
    },

    draw: function() {
      var canvas = this.canvas,
          settings = this.settings;

      if (canvas.getContext) {
        var ctx = canvas.getContext('2d'),
            maxAvailFontSize = ((settings.displayPercentageChange) ? this.pSectionHeight : this.sectionHeight) - 2;

        // Reduce font size if necessary
        if(settings.maxFontSize >= maxAvailFontSize)
          settings.maxFontSize = maxAvailFontSize;

        // Configure font styling
        ctx.font = settings.fontWeight + ' ' + settings.maxFontSize + 'px ' + settings.font;

        // Draw labels if we have any
        if(this.hasLabels()) this.drawLabels(ctx);

        // Draw funnel clipping area with white background
        this.drawClippingArea(ctx, settings);
        ctx.fillStyle = '#fff';
        ctx.fill();
        ctx.clip();

        // Draw funnel sections
        this.drawSections(ctx);

        // Tidy up funnel outline
        this.drawClippingArea(ctx, settings);
        ctx.lineWidth = 2;
        ctx.strokeStyle = '#fff';
        ctx.stroke();
      }
    },

    drawLabels: function(ctx) {
      var settings = this.settings,
          i, yPos;

      ctx.strokeStyle = settings.labelLineColor;
      ctx.lineWidth = 1;

      for(i = 0; i < settings.values.length; i++) {
        yPos = this.calculateYPos(i);

        ctx.fillStyle = this.sequentialValue(settings.labelFontColor, i);
        ctx.fillText(
          settings.labels[i] || '',
          this.startWidth + settings.labelOffset,
          yPos + (this.sectionHeight / 2) + (settings.maxFontSize / 2) - 2,
          this.labelMaxWidth
        );

        if(i > 0) {
          ctx.beginPath();
          ctx.moveTo(i, yPos);
          ctx.lineTo(this.width, yPos);
          ctx.stroke();
        }

        if(i < (settings.values.length - 1) && settings.displayPercentageChange){
          ctx.beginPath();
          ctx.moveTo(i, yPos + this.sectionHeight);
          ctx.lineTo(this.width, yPos + this.sectionHeight);
          ctx.stroke();
        }

      }
    },

    drawClippingArea: function(ctx, settings) {
      var inset = (this.startWidth - this.endWidth) / 2;
      var height = (settings.values.length * this.sectionHeight) +
                     ((settings.values.length - 1) * this.pSectionHeight) +
                     (settings.values.length + 1);

      ctx.beginPath();
      ctx.moveTo(0,0);
      ctx.lineTo(this.startWidth,0);
      ctx.quadraticCurveTo(
        (this.startWidth - inset),
        (height / 3),
        (this.startWidth - inset),
        height
      );
      ctx.lineTo(inset,height);
      ctx.quadraticCurveTo(inset, (height / 3), 0, 0);
    },

    drawSections: function(ctx) {
      var settings = this.settings,
          i, yPos;

      ctx.textAlign = 'center';

      for(i = 0; i < settings.values.length; i++) {
        yPos = this.calculateYPos(i);

        ctx.fillStyle = this.sequentialValue(settings.sectionColor, i);
        ctx.fillRect(0, yPos, this.startWidth, this.sectionHeight);
        ctx.fillStyle = this.sequentialValue(settings.sectionFontColor, i);
        ctx.fillText(
          settings.values[i],
          this.startWidth / 2,
          yPos + (this.sectionHeight / 2) + (settings.maxFontSize / 2) - 2
        );

        if(i < (settings.values.length - 1) && settings.displayPercentageChange) {
          ctx.fillStyle = this.sequentialValue(settings.pSectionColor, i);
          ctx.fillRect(
            0,
            (yPos + this.sectionHeight + 1),
            this.startWidth,
            this.pSectionHeight
          );

          ctx.fillStyle = this.sequentialValue(settings.pSectionFontColor, i);
          ctx.fillText(
            ((settings.values[i + 1] / settings.values[i]) * 100).toFixed(settings.pPrecision) + '%',
            this.startWidth / 2,
            yPos + this.sectionHeight + (this.pSectionHeight / 2) + (settings.maxFontSize / 2) - 1
          );
        }
      }
    },

    hasLabels: function() {
      return this.settings.labels && !!this.settings.labels.length;
    },

    calculateYPos: function(i) {
      var sectionHeight = this.sectionHeight + 1;

      if(this.settings.displayPercentageChange)
        sectionHeight += this.pSectionHeight + 1;

      return (i === 0) ? 0 : (sectionHeight * i);
    },

    sequentialValue: function(arr, i) {
      if(typeof arr === 'string') return arr;
      return arr[i % arr.length];
    }

  });

  return FunnelChart;

}));
<|endoftext|>


<commit_before>{{#all}}
describe('{{name}}', function(){
  beforeEach(function(){
    navigateTo('index.html#{{name}}');
  });
  // {{raw.file}}:{{raw.line}}
{{{scenario}}}
});
{{/all}}<commit_msg>fixing docs scenario runner template<commit_after>{{#all}}
describe('{{name}}', function(){
  beforeEach(function(){
    browser().navigateTo('index.html#{{name}}');
  });
  // {{raw.file}}:{{raw.line}}
{{{scenario}}}
});
{{/all}}
<|endoftext|>


<commit_before>export class Router {
	_scopedAction = null
	_scopedPrefix = ''

	app = null
	bindings = { }
	patterns = { }

	constructor(app) {
		this.app = app
	}

	group(action, callback) {
		this._scopedAction = Object.assign({ }, action)

		if(this._scopedAction.prefix) {
			this._scopedPrefix = this._scopedAction.prefix
			delete this._scopedAction.prefix
		} else {
			this._scopedPrefix = ''
		}

		callback()

		this._scopedAction = null
		this._scopedPrefix = ''
	}

	all(path, action) {
		console.log('Don’t use `all` routes. Offender: %s', path)
		return this.app.all(this._scopedPrefix + path, this._makeAction(action))
	}

	get(path, action, extra) {
		return this._add('get', path, action, extra)
	}

	post(path, action, extra) {
		return this._add('post', path, action, extra)
	}

	put(path, action, extra) {
		return this._add('put', path, action, extra)
	}

	patch(path, action, extra) {
		return this._add('patch', path, action, extra)
	}

	delete(path, action, extra) {
		return this._add('delete', path, action, extra)
	}

	_add(method, path, action, extra) {
		const handler = this._makeAction(action)

		// WARNING: Prone to failure if ExpressJS changes this logic
		this.app.lazyrouter()

		const handlers = [ handler ]

		if(typeof action.use !== 'undefined') {
			if(Array.isArray(action.use)) {
				action.use = {
					before: action.use
				}
			}

			if(typeof action.use === 'object') {
				if(Array.isArray(action.use.before)) {
					handlers.unshift(...action.use.before)
				} else if(Array.isArray(action.use.before)) {
					handlers.push(...action.use.after)
				}
			}
		}

		const compiledPath = (this._scopedPrefix + path).replace(/:([a-z0-0_\-\.]+)/g, (param, name) => {
			const pattern = this.patterns[name]

			if(typeof pattern === 'undefined') {
				return param
			} else {
				return param + '(' + pattern + ')'
			}
		})

		let route = this.app._router.route(compiledPath)
		route = route[method](...handlers)
		route.extra = extra || {}

		return route
	}

	_makeAction(action) {
		if(typeof action === 'function') {
			return action
		}

		if(typeof action === 'string') {
			action = { method: action }
		}

		action = Object.assign({ }, this._scopedAction, action)
		const method = action.controller[action.method]
		const controller = action.controller

		return (...args) => {
			const result = method.apply(controller, args)

			if(result && typeof result === 'object' && typeof result.catch === 'function') {
				return result.catch(args[2])
			} else {
				return result
			}
		}
	}

	bind(name, resolver, extra) {
		this.bindings[name] = { resolver }

		if(extra) {
			this.bindings[name].extra = extra
		}

		this.app.param(name, (req, res, next, value) => {
			resolver(value, newValue => {
				req.params[name] = newValue
				next()
			}, err => {
				next(err)
			}, req, res)
		})
	}

	pattern(name, pattern) {
		this.patterns[name] = pattern
	}

}
<commit_msg>Renamed route.extra to route.context<commit_after>export class Router {
	_scopedAction = null
	_scopedPrefix = ''

	app = null
	bindings = { }
	patterns = { }

	constructor(app) {
		this.app = app
	}

	group(action, callback) {
		this._scopedAction = Object.assign({ }, action)

		if(this._scopedAction.prefix) {
			this._scopedPrefix = this._scopedAction.prefix
			delete this._scopedAction.prefix
		} else {
			this._scopedPrefix = ''
		}

		callback()

		this._scopedAction = null
		this._scopedPrefix = ''
	}

	all(path, action) {
		console.log('Don’t use `all` routes. Offender: %s', path)
		return this.app.all(this._scopedPrefix + path, this._makeAction(action))
	}

	get(path, action, context) {
		return this._add('get', path, action, context)
	}

	post(path, action, context) {
		return this._add('post', path, action, context)
	}

	put(path, action, context) {
		return this._add('put', path, action, context)
	}

	patch(path, action, context) {
		return this._add('patch', path, action, context)
	}

	delete(path, action, context) {
		return this._add('delete', path, action, context)
	}

	_add(method, path, action, context) {
		const handler = this._makeAction(action)

		// WARNING: Prone to failure if ExpressJS changes this logic
		this.app.lazyrouter()

		const handlers = [ handler ]

		if(typeof action.use !== 'undefined') {
			if(Array.isArray(action.use)) {
				action.use = {
					before: action.use
				}
			}

			if(typeof action.use === 'object') {
				if(Array.isArray(action.use.before)) {
					handlers.unshift(...action.use.before)
				} else if(Array.isArray(action.use.before)) {
					handlers.push(...action.use.after)
				}
			}
		}

		const compiledPath = (this._scopedPrefix + path).replace(/:([a-z0-0_\-\.]+)/g, (param, name) => {
			const pattern = this.patterns[name]

			if(typeof pattern === 'undefined') {
				return param
			} else {
				return param + '(' + pattern + ')'
			}
		})

		let route = this.app._router.route(compiledPath)
		route = route[method](...handlers)
		route.context = context || {}

		return route
	}

	_makeAction(action) {
		if(typeof action === 'function') {
			return action
		}

		if(typeof action === 'string') {
			action = { method: action }
		}

		action = Object.assign({ }, this._scopedAction, action)
		const method = action.controller[action.method]
		const controller = action.controller

		return (...args) => {
			const result = method.apply(controller, args)

			if(result && typeof result === 'object' && typeof result.catch === 'function') {
				return result.catch(args[2])
			} else {
				return result
			}
		}
	}

	bind(name, resolver, context) {
		this.bindings[name] = { resolver }

		if(!context.isNil) {
			this.bindings[name].context = context
		}

		this.app.param(name, (req, res, next, value) => {
			resolver(value, newValue => {
				req.params[name] = newValue
				next()
			}, err => {
				next(err)
			}, req, res)
		})
	}

	pattern(name, pattern) {
		this.patterns[name] = pattern
	}

}
<|endoftext|>


<commit_before>import Resource from 'ember-api-store/models/resource';
import { inject as service } from '@ember/service';
import {  get, computed } from '@ember/object';
import { hash } from 'rsvp';
import C from 'ui/utils/constants';
import moment from 'moment';

export default Resource.extend({
  growl:        service(),
  intl:  service(),

  globalStore:  service(),
  modalService: service('modal'),

  type:         'notifier',
  init(...args) {
    this._super(...args);
  },

  displayNameAndType: computed('displayName', 'notifierType', function() {
    const upperCaseType = (get(this, 'notifierType') || '').replace(/^\S/, (s) => {
      return s.toUpperCase();
    })

    return `${ get(this, 'displayName') } (${ upperCaseType })`
  }),

  notifierTableLabel: computed('slackConfig', 'pagerdutyConfig', 'emailConfig', 'webhookConfig', function() {
    const sc = get(this, 'slackConfig');
    const pc = get(this, 'pagerdutyConfig');
    const ec = get(this, 'smtpConfig');
    const wc = get(this, 'webhookConfig');

    if (sc) {
      return C.NOTIFIER_TABLE_LABEL.SLACK;
    }
    if (pc) {
      return C.NOTIFIER_TABLE_LABEL.PAGERDUTY;
    }
    if (ec) {
      return C.NOTIFIER_TABLE_LABEL.SMTP;
    }
    if (wc) {
      return C.NOTIFIER_TABLE_LABEL.WEBHOOK;
    }

    return C.NOTIFIER_TABLE_LABEL.DEFAULT;
  }),

  notifierType: function() {
    const sc = this.get('slackConfig');
    const pc = this.get('pagerdutyConfig');
    const ec = this.get('smtpConfig');
    const wc = this.get('webhookConfig');

    if (sc) {
      return 'slack';
    }
    if (pc) {
      return 'pagerduty';
    }
    if (ec) {
      return 'email';
    }
    if (wc) {
      return 'webhook';
    }

    return null;
  }.property('slackConfig', 'pagerdutyConfig', 'emailConfig', 'webhookConfig'),

  notifierValue: function() {
    const sc = this.get('slackConfig');
    const pc = this.get('pagerdutyConfig');
    const ec = this.get('smtpConfig');
    const wc = this.get('webhookConfig');

    if (sc) {
      return get(sc, 'defaultRecipient');
    }
    if (pc) {
      return get(pc, 'serviceKey');
    }
    if (ec) {
      return get(ec, 'defaultRecipient');
    }
    if (wc) {
      return get(wc, 'url');
    }

    return '';
  }.property('slackConfig', 'pagerdutyConfig', 'emailConfig', 'webhookConfig'),

  displayCreated: function() {
    const d = get(this, 'created');

    return moment(d).fromNow();
  }.property('created'),

  notifierLabel: function() {
    const sc = this.get('slackConfig');
    const pc = this.get('pagerdutyConfig');
    const ec = this.get('smtpConfig');
    const wc = this.get('webhookConfig');

    if (sc) {
      return 'Channel';
    }
    if (pc) {
      return 'Service Key';
    }
    if (ec) {
      return 'Address';
    }
    if (wc) {
      return 'URL';
    }

    return 'Notifier';
  }.property('slackConfig', 'pagerdutyConfig', 'emailConfig', 'webhookConfig'),
  findAlerts() {
    const globalStore = get(this, 'globalStore');
    const clusterId = get(this, 'clusterId');
    const clusterAlerts = globalStore.findAll('clusterAlertRule', { filter: { clusterId } });
    const projectAlerts = globalStore.findAll('projectAlertRule');

    return hash({
      clusterAlerts,
      projectAlerts,
    }).then(({
      clusterAlerts,
      projectAlerts,
    }) => {
      const alerts = [
        ...clusterAlerts.content,
        ...projectAlerts.content,
      ].filter((alert) => {
        const recipients = get(alert, 'recipients');

        if (!recipients || recipients.length === 0) {
          return false;
        }

        return recipients.some((recipient) => recipient.notifierId === get(this, 'id'));
      });

      return alerts;
    });
  },
  delete() {
    const self = this;
    const sup = self._super;

    return this.findAlerts().then((alerts) => {
      if (alerts.length) {
        const alertNames = alerts.map((alert) => get(alert, 'displayName')).join(',');

        get(this, 'growl')
          .error(get(this, 'intl')
            .t('notifierPage.deleteErrorMessage', {
              displayName: get(this, 'displayName'),
              alertNames
            }));
      } else {
        sup.apply(self, arguments);
      }
    });
  },
  actions: {
    edit() {
      this.get('modalService').toggleModal('notifier/modal-new-edit', {
        closeWithOutsideClick: false,
        currentType:           get(this, 'notifierType'),
        model:                 this,
        mode:                  'edit',
      });
    },

    clone() {
      const nue = this.clone();

      nue.set('id', null);
      nue.set('name', null);
      this.get('modalService').toggleModal('notifier/modal-new-edit', {
        closeWithOutsideClick: false,
        currentType:           get(this, 'notifierType'),
        model:                 nue,
        mode:                  'clone',
      });
    },
  },

});
<commit_msg>Notifier can be deleted when an alert group use https://github.com/rancher/rancher/issues/17103<commit_after>import Resource from 'ember-api-store/models/resource';
import { inject as service } from '@ember/service';
import {  get, computed } from '@ember/object';
import { hash } from 'rsvp';
import C from 'ui/utils/constants';
import moment from 'moment';

export default Resource.extend({
  growl:        service(),
  intl:  service(),

  globalStore:  service(),
  modalService: service('modal'),

  type:         'notifier',
  init(...args) {
    this._super(...args);
  },

  displayNameAndType: computed('displayName', 'notifierType', function() {
    const upperCaseType = (get(this, 'notifierType') || '').replace(/^\S/, (s) => {
      return s.toUpperCase();
    })

    return `${ get(this, 'displayName') } (${ upperCaseType })`
  }),

  notifierTableLabel: computed('slackConfig', 'pagerdutyConfig', 'emailConfig', 'webhookConfig', function() {
    const sc = get(this, 'slackConfig');
    const pc = get(this, 'pagerdutyConfig');
    const ec = get(this, 'smtpConfig');
    const wc = get(this, 'webhookConfig');

    if (sc) {
      return C.NOTIFIER_TABLE_LABEL.SLACK;
    }
    if (pc) {
      return C.NOTIFIER_TABLE_LABEL.PAGERDUTY;
    }
    if (ec) {
      return C.NOTIFIER_TABLE_LABEL.SMTP;
    }
    if (wc) {
      return C.NOTIFIER_TABLE_LABEL.WEBHOOK;
    }

    return C.NOTIFIER_TABLE_LABEL.DEFAULT;
  }),

  notifierType: function() {
    const sc = this.get('slackConfig');
    const pc = this.get('pagerdutyConfig');
    const ec = this.get('smtpConfig');
    const wc = this.get('webhookConfig');

    if (sc) {
      return 'slack';
    }
    if (pc) {
      return 'pagerduty';
    }
    if (ec) {
      return 'email';
    }
    if (wc) {
      return 'webhook';
    }

    return null;
  }.property('slackConfig', 'pagerdutyConfig', 'emailConfig', 'webhookConfig'),

  notifierValue: function() {
    const sc = this.get('slackConfig');
    const pc = this.get('pagerdutyConfig');
    const ec = this.get('smtpConfig');
    const wc = this.get('webhookConfig');

    if (sc) {
      return get(sc, 'defaultRecipient');
    }
    if (pc) {
      return get(pc, 'serviceKey');
    }
    if (ec) {
      return get(ec, 'defaultRecipient');
    }
    if (wc) {
      return get(wc, 'url');
    }

    return '';
  }.property('slackConfig', 'pagerdutyConfig', 'emailConfig', 'webhookConfig'),

  displayCreated: function() {
    const d = get(this, 'created');

    return moment(d).fromNow();
  }.property('created'),

  notifierLabel: function() {
    const sc = this.get('slackConfig');
    const pc = this.get('pagerdutyConfig');
    const ec = this.get('smtpConfig');
    const wc = this.get('webhookConfig');

    if (sc) {
      return 'Channel';
    }
    if (pc) {
      return 'Service Key';
    }
    if (ec) {
      return 'Address';
    }
    if (wc) {
      return 'URL';
    }

    return 'Notifier';
  }.property('slackConfig', 'pagerdutyConfig', 'emailConfig', 'webhookConfig'),
  findAlerts() {
    const globalStore = get(this, 'globalStore');
    const clusterId = get(this, 'clusterId');
    const clusterAlertGroups = globalStore.findAll('clusterAlertGroup', { filter: { clusterId } });
    const projectAlertGroups = globalStore.findAll('projectAlertGroup');

    return hash({
      clusterAlertGroups,
      projectAlertGroups,
    }).then(({
      clusterAlertGroups,
      projectAlertGroups,
    }) => {
      const alerts = [
        ...clusterAlertGroups.content,
        ...projectAlertGroups.content,
      ].filter((alert) => {
        const recipients = get(alert, 'recipients');

        if (!recipients || recipients.length === 0) {
          return false;
        }

        return recipients.some((recipient) => recipient.notifierId === get(this, 'id'));
      });

      return alerts;
    });
  },
  delete() {
    const self = this;
    const sup = self._super;

    return this.findAlerts().then((alerts) => {
      if (alerts.length) {
        const alertNames = alerts.map((alert) => get(alert, 'displayName')).join(',');

        get(this, 'growl')
          .error(get(this, 'intl')
            .t('notifierPage.deleteErrorMessage', {
              displayName: get(this, 'displayName'),
              alertNames
            }));
      } else {
        sup.apply(self, arguments);
      }
    });
  },
  actions: {
    edit() {
      this.get('modalService').toggleModal('notifier/modal-new-edit', {
        closeWithOutsideClick: false,
        currentType:           get(this, 'notifierType'),
        model:                 this,
        mode:                  'edit',
      });
    },

    clone() {
      const nue = this.clone();

      nue.set('id', null);
      nue.set('name', null);
      this.get('modalService').toggleModal('notifier/modal-new-edit', {
        closeWithOutsideClick: false,
        currentType:           get(this, 'notifierType'),
        model:                 nue,
        mode:                  'clone',
      });
    },
  },

});
<|endoftext|>


<commit_before>const stringHash = require('../StringHash')

module.exports = (hash = stringHash) => {
  const UPPER_LOAD_LIMIT = 0.75
  const LOWER_LOAD_LIMIT = 0.25

  let size = 0
  let dimension = 2
  let table = new Array(dimension)

  return {
    get size() {
      return size
    },
    set,
    has,
    find,
    remove
  }

  /**
   * Save `value` in hash table with `key`.
   *
   * Performance: O(1)
   * @param {string|number} key
   * @param {*} value
   */
  function set(key, value) {
    const index = indexOf(key)
    if (table[index] && table[index].key === key) {
      table[index].value = value
    } else {
      table[index] = { key, value }
      size++
      resizeIfNeeded()
    }
  }

  /**
   * Check if given key is present in hash table
   *
   * Performance: O(1)
   * @param {string|number} key
   * @returns {boolean}
   */
  function has(key) {
    const index = indexOf(key)

    return table[index] !== undefined
  }

  /**
   * Retrieve value for given key.
   *
   * Performance: O(1)
   * @param {string|number} key
   * @returns {*}
   */
  function find(key) {
    const index = indexOf(key)

    return table[index] === undefined ? undefined : table[index].value
  }

  /**
   * Delete entry for given key.
   *
   * Performance: O(1)
   * @param {string|number} key
   */
  function remove(key) {
    let index = indexOf(key)
    if (table[index] === undefined) return

    let next = index
    while (table[next] !== undefined) {
      let naturalNext = hash(table[next].key) % dimension
      if (
        (next > index && (naturalNext <= index || naturalNext > next)) ||
        (next < index && (naturalNext <= index || naturalNext > next))
      ) {
        table[index] = table[next]
        index = next
      }
      next = (next + 1) % dimension
    }
    table[index] = undefined
    size--
    resizeIfNeeded()
  }

  /**
   * Get position in hash table for given key.
   *
   * @param {string|number} key
   * @returns {number}
   */
  function indexOf(key) {
    if (typeof key !== 'string' && typeof key !== 'number') {
      throw TypeError('Key must be a string or a number.')
    }

    let index = hash(key) % dimension
    while (table[index] !== undefined) {
      if (table[index].key === key) {
        return index
      }
      index = (index + 1) % dimension
    }

    return index
  }

  /**
   * Increase or decrease underlying table when load factor goes up or down.
   */
  function resizeIfNeeded() {
    if (loadFactor() >= UPPER_LOAD_LIMIT) {
      dimension = dimension * 2
    } else if (loadFactor() < LOWER_LOAD_LIMIT) {
      dimension = dimension / 2
    } else {
      return
    }

    const resized = new Array(dimension)
    for (let i = 0; i < table.length; i++) {
      if (table[i] !== undefined) {
        let index = hash(table[i].key) % dimension
        while (resized[index] !== undefined) {
          index = (index + 1) % dimension
        }
        resized[index] = table[i]
      }
    }

    table = resized
  }

  function loadFactor() {
    return size / dimension
  }
}
<commit_msg>Refactor find<commit_after>const stringHash = require('../StringHash')

module.exports = (hash = stringHash) => {
  const UPPER_LOAD_LIMIT = 0.75
  const LOWER_LOAD_LIMIT = 0.25

  let size = 0
  let dimension = 2
  let table = new Array(dimension)

  return {
    get size() {
      return size
    },
    set,
    has,
    find,
    remove
  }

  /**
   * Save `value` in hash table with `key`.
   *
   * Performance: O(1)
   * @param {string|number} key
   * @param {*} value
   */
  function set(key, value) {
    const index = indexOf(key)
    if (table[index] && table[index].key === key) {
      table[index].value = value
    } else {
      table[index] = { key, value }
      size++
      resizeIfNeeded()
    }
  }

  /**
   * Check if given key is present in hash table
   *
   * Performance: O(1)
   * @param {string|number} key
   * @returns {boolean}
   */
  function has(key) {
    const index = indexOf(key)

    return table[index] !== undefined
  }

  /**
   * Retrieve value for given key.
   *
   * Performance: O(1)
   * @param {string|number} key
   * @returns {*}
   */
  function find(key) {
    const index = indexOf(key)

    return table[index] && table[index].value
  }

  /**
   * Delete entry for given key.
   *
   * Performance: O(1)
   * @param {string|number} key
   */
  function remove(key) {
    let index = indexOf(key)
    if (table[index] === undefined) return

    let next = index
    while (table[next] !== undefined) {
      let naturalNext = hash(table[next].key) % dimension
      if (
        (next > index && (naturalNext <= index || naturalNext > next)) ||
        (next < index && (naturalNext <= index || naturalNext > next))
      ) {
        table[index] = table[next]
        index = next
      }
      next = (next + 1) % dimension
    }
    table[index] = undefined
    size--
    resizeIfNeeded()
  }

  /**
   * Get position in hash table for given key.
   *
   * @param {string|number} key
   * @returns {number}
   */
  function indexOf(key) {
    if (typeof key !== 'string' && typeof key !== 'number') {
      throw TypeError('Key must be a string or a number.')
    }

    let index = hash(key) % dimension
    while (table[index] !== undefined) {
      if (table[index].key === key) {
        return index
      }
      index = (index + 1) % dimension
    }

    return index
  }

  /**
   * Increase or decrease underlying table when load factor goes up or down.
   */
  function resizeIfNeeded() {
    if (loadFactor() >= UPPER_LOAD_LIMIT) {
      dimension = dimension * 2
    } else if (loadFactor() < LOWER_LOAD_LIMIT) {
      dimension = dimension / 2
    } else {
      return
    }

    const resized = new Array(dimension)
    for (let i = 0; i < table.length; i++) {
      if (table[i] !== undefined) {
        let index = hash(table[i].key) % dimension
        while (resized[index] !== undefined) {
          index = (index + 1) % dimension
        }
        resized[index] = table[i]
      }
    }

    table = resized
  }

  function loadFactor() {
    return size / dimension
  }
}
<|endoftext|>


<commit_before>/**
 * Function that returns default values.
 * Used because Object.assign does a shallow instead of a deep copy.
 * Using [].push will add to the base array, so a require will alter
 * the base array output.
 */
'use strict';

const path = require('path');
const srcPath = path.join(__dirname, '/../src');
const dfltPort = 8000;

/**
 * Get the default modules object for webpack
 * @return {Object}
 */
function getDefaultModules() {
  return {
    preLoaders: [
      {
        test: /\.(js|jsx)$/,
        include: srcPath,
        loader: 'eslint-loader'
      }
    ],
    loaders: [
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
      },
      {
        test: /\.sass/,
        loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax'
      },
      {
        test: /\.scss/,
        loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded'
      },
      {
        test: /\.less/,
        loader: 'style-loader!css-loader!less-loader'
      },
      {
        test: /\.styl/,
        loader: 'style-loader!css-loader!stylus-loader'
      },
      {
        test: /\.(png|jpg|gif|woff|woff2)$/,
        loader: 'url-loader?limit=8192'
      },
      {
        test: /\.(mp4|ogg|svg)$/,
        loader: 'file-loader'
      }
    ]
  };
}

module.exports = {
  srcPath: srcPath,
  publicPath: '/assets/',
  port: dfltPort,
  getDefaultModules: getDefaultModules
};
<commit_msg>添加json-loader支持json文件的加载<commit_after>/**
 * Function that returns default values.
 * Used because Object.assign does a shallow instead of a deep copy.
 * Using [].push will add to the base array, so a require will alter
 * the base array output.
 */
'use strict';

const path = require('path');
const srcPath = path.join(__dirname, '/../src');
const dfltPort = 8000;

/**
 * Get the default modules object for webpack
 * @return {Object}
 */
function getDefaultModules() {
  return {
    preLoaders: [
      {
        test: /\.(js|jsx)$/,
        include: srcPath,
        loader: 'eslint-loader'
      }
    ],
    loaders: [
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
      },
      {
        test: /\.sass/,
        loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax'
      },
      {
        test: /\.scss/,
        loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded'
      },
      {
        test: /\.less/,
        loader: 'style-loader!css-loader!less-loader'
      },
      {
        test: /\.styl/,
        loader: 'style-loader!css-loader!stylus-loader'
      },
      {
        test: /\.(png|jpg|gif|woff|woff2)$/,
        loader: 'url-loader?limit=8192'
      },
      {
        test: /\.(mp4|ogg|svg)$/,
        loader: 'file-loader'
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      }
    ]
  };
}

module.exports = {
  srcPath: srcPath,
  publicPath: '/assets/',
  port: dfltPort,
  getDefaultModules: getDefaultModules
};
<|endoftext|>