<commit_before>import React from "react";
import PropTypes from "prop-types";
import Helpers from "../victory-util/helpers";
import Collection from "../victory-util/collection";
import { assign } from "lodash";
import CommonProps from "./common-props";
import * as d3Shape from "d3-shape";

export default class Bar extends React.Component {

  static propTypes = {
    ...CommonProps,
    datum: PropTypes.object,
    horizontal: PropTypes.bool,
    padding: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.object
    ]),
    width: PropTypes.number,
    x: PropTypes.number,
    y: PropTypes.number,
    y0: PropTypes.number
  };

  componentWillMount() {
    const { style, path } = this.calculateAttributes(this.props);
    this.style = style;
    this.path = path;
  }

  shouldComponentUpdate(nextProps) {
    const { style, path } = this.calculateAttributes(nextProps);
    const { className, datum, horizontal, x, y, y0 } = this.props;
    if (!Collection.allSetsEqual([
      [className, nextProps.className],
      [x, nextProps.x],
      [y, nextProps.y],
      [y0, nextProps.y0],
      [horizontal, nextProps.horizontal],
      [path, this.path],
      [style, this.style],
      [datum, nextProps.datum]
    ])) {
      this.style = style;
      this.path = path;
      return true;
    }
    return false;
  }

  calculateAttributes(props) {
    const { datum, active, polar } = props;
    const stroke = props.style && props.style.fill || "black";
    const baseStyle = { fill: "black", stroke };
    const style = Helpers.evaluateStyle(assign(baseStyle, props.style), datum, active);
    const width = this.getBarWidth(props, style);
    const path = polar ? this.getPolarBarPath(props, width) : this.getBarPath(props, width);
    return { style, path };
  }

  getPosition(props, width) {
    const size = width / 2;
    const { x, y, y0 } = props;
    return {
      y0: Math.round(y0),
      y1: Math.round(y),
      x0: Math.round(x - size),
      x1: Math.round(x + size)
    };
  }

  getVerticalBarPath(props, width) {
    const { x0, x1, y0, y1 } = this.getPosition(props, width);
    return `M ${x0}, ${y0}
      L ${x0}, ${y1}
      L ${x1}, ${y1}
      L ${x1}, ${y0}
      L ${x0}, ${y0}
      z`;
  }

  getHorizontalBarPath(props, width) {
    const { x0, x1, y0, y1 } = this.getPosition(props, width);
    return `M ${y0}, ${x0}
      L ${y0}, ${x1}
      L ${y1}, ${x1}
      L ${y1}, ${x0}
      L ${y0}, ${x0}
      z`;
  }

  transformAngle(angle) {
    return -1 * angle + (Math.PI / 2);
  }

  getAngularWidth(props, datum, width) {
    const { scale } = props;
    const range = scale.y.range();
    const r = Math.max(...range);
    const angularRange = Math.abs(scale.x.range()[1] - scale.x.range()[0]);
    return (width / (2 * Math.PI * r)) * angularRange;
  }

  getAngle(props, index) {
    const { data, scale } = props;
    const x = data[index]._x1 === undefined ? "_x" : "_x1";
    return scale.x(data[index][x]);
  }

  getStartAngle(props, index) {
    const { data, scale } = props;
    const currentAngle = this.getAngle(props, index);
    const angularRange = Math.abs(scale.x.range()[1] - scale.x.range()[0]);
    const previousAngle = index === 0 ?
      this.getAngle(props, data.length - 1) - (Math.PI * 2) :
      this.getAngle(props, index - 1);
    return index === 0 && angularRange < (2 * Math.PI) ?
      scale.x.range()[0] : (currentAngle + previousAngle) / 2;
  }

  getEndAngle(props, index) {
    const { data, scale } = props;
    const currentAngle = this.getAngle(props, index);
    const angularRange = Math.abs(scale.x.range()[1] - scale.x.range()[0]);
    const lastAngle = scale.x.range()[1] === (2 * Math.PI) ?
      this.getAngle(props, 0) + (Math.PI * 2) : scale.x.range()[1];
    const nextAngle = index === data.length - 1 ?
      this.getAngle(props, 0) + (Math.PI * 2) : this.getAngle(props, index + 1);
    return index === data.length - 1 && angularRange < (2 * Math.PI) ?
      lastAngle : (currentAngle + nextAngle) / 2;
  }

  getVerticalPolarBarPath(props) {
    const { datum, scale, style, index } = props;
    const r1 = scale.y(datum._y0 || 0);
    const r2 = scale.y(datum._y1 !== undefined ? datum._y1 : datum._y);
    console.log(datum.y, r1, r2)
    const currentAngle = scale.x(datum._x1 !== undefined ? datum._x1 : datum._x);
    let start;
    let end;
    if (style.width) {
      const width = this.getAngularWidth(props, datum, style.width);
      start = currentAngle - (width / 2);
      end = currentAngle + (width / 2);
    } else {
      start = this.getStartAngle(props, index);
      end = this.getEndAngle(props, index);
    }
    const path = d3Shape.arc()
      .innerRadius(r1)
      .outerRadius(r2)
      .startAngle(this.transformAngle(start))
      .endAngle(this.transformAngle(end));
    return path();
  }

  getBarPath(props, width) {
    return this.props.horizontal ?
      this.getHorizontalBarPath(props, width) : this.getVerticalBarPath(props, width);
  }

  getPolarBarPath(props) {
    // TODO Radial bars
    return this.getVerticalPolarBarPath(props);
  }

  getBarWidth(props, style) {
    if (style.width) {
      return style.width;
    }
    const { scale, data, horizontal } = props;
    const range = horizontal ? scale.y.range() : scale.x.range();
    const extent = Math.abs(range[1] - range[0]);
    const bars = data.length + 2;
    const barRatio = 0.5;
    // eslint-disable-next-line no-magic-numbers
    const defaultWidth = data.length < 2 ? 8 : (barRatio * extent / bars);
    return Math.max(1, Math.round(defaultWidth));
  }

  // Overridden in victory-core-native
  renderBar(path, style, events) {
    const { role, shapeRendering, className, origin, polar } = this.props;
    const transform = polar && origin ? `translate(${origin.x}, ${origin.y})` : undefined;
    return (
      <path
        d={path}
        transform={transform}
        className={className}
        style={style}
        role={role || "presentation"}
        shapeRendering={shapeRendering || "auto"}
        {...events}
      />
    );
  }

  render() {
    return this.renderBar(this.path, this.style, this.props.events);
  }
}
<commit_msg>clean up<commit_after>import React from "react";
import PropTypes from "prop-types";
import Helpers from "../victory-util/helpers";
import Collection from "../victory-util/collection";
import { assign } from "lodash";
import CommonProps from "./common-props";
import * as d3Shape from "d3-shape";

export default class Bar extends React.Component {

  static propTypes = {
    ...CommonProps,
    datum: PropTypes.object,
    horizontal: PropTypes.bool,
    padding: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.object
    ]),
    width: PropTypes.number,
    x: PropTypes.number,
    y: PropTypes.number,
    y0: PropTypes.number
  };

  componentWillMount() {
    const { style, path } = this.calculateAttributes(this.props);
    this.style = style;
    this.path = path;
  }

  shouldComponentUpdate(nextProps) {
    const { style, path } = this.calculateAttributes(nextProps);
    const { className, datum, horizontal, x, y, y0 } = this.props;
    if (!Collection.allSetsEqual([
      [className, nextProps.className],
      [x, nextProps.x],
      [y, nextProps.y],
      [y0, nextProps.y0],
      [horizontal, nextProps.horizontal],
      [path, this.path],
      [style, this.style],
      [datum, nextProps.datum]
    ])) {
      this.style = style;
      this.path = path;
      return true;
    }
    return false;
  }

  calculateAttributes(props) {
    const { datum, active, polar } = props;
    const stroke = props.style && props.style.fill || "black";
    const baseStyle = { fill: "black", stroke };
    const style = Helpers.evaluateStyle(assign(baseStyle, props.style), datum, active);
    const width = this.getBarWidth(props, style);
    const path = polar ? this.getPolarBarPath(props, width) : this.getBarPath(props, width);
    return { style, path };
  }

  getPosition(props, width) {
    const size = width / 2;
    const { x, y, y0 } = props;
    return {
      y0: Math.round(y0),
      y1: Math.round(y),
      x0: Math.round(x - size),
      x1: Math.round(x + size)
    };
  }

  getVerticalBarPath(props, width) {
    const { x0, x1, y0, y1 } = this.getPosition(props, width);
    return `M ${x0}, ${y0}
      L ${x0}, ${y1}
      L ${x1}, ${y1}
      L ${x1}, ${y0}
      L ${x0}, ${y0}
      z`;
  }

  getHorizontalBarPath(props, width) {
    const { x0, x1, y0, y1 } = this.getPosition(props, width);
    return `M ${y0}, ${x0}
      L ${y0}, ${x1}
      L ${y1}, ${x1}
      L ${y1}, ${x0}
      L ${y0}, ${x0}
      z`;
  }

  transformAngle(angle) {
    return -1 * angle + (Math.PI / 2);
  }

  getAngularWidth(props, width) {
    const { scale } = props;
    const range = scale.y.range();
    const r = Math.max(...range);
    const angularRange = Math.abs(scale.x.range()[1] - scale.x.range()[0]);
    return (width / (2 * Math.PI * r)) * angularRange;
  }

  getAngle(props, index) {
    const { data, scale } = props;
    const x = data[index]._x1 === undefined ? "_x" : "_x1";
    return scale.x(data[index][x]);
  }

  getStartAngle(props, index) {
    const { data, scale } = props;
    const currentAngle = this.getAngle(props, index);
    const angularRange = Math.abs(scale.x.range()[1] - scale.x.range()[0]);
    const previousAngle = index === 0 ?
      this.getAngle(props, data.length - 1) - (Math.PI * 2) :
      this.getAngle(props, index - 1);
    return index === 0 && angularRange < (2 * Math.PI) ?
      scale.x.range()[0] : (currentAngle + previousAngle) / 2;
  }

  getEndAngle(props, index) {
    const { data, scale } = props;
    const currentAngle = this.getAngle(props, index);
    const angularRange = Math.abs(scale.x.range()[1] - scale.x.range()[0]);
    const lastAngle = scale.x.range()[1] === (2 * Math.PI) ?
      this.getAngle(props, 0) + (Math.PI * 2) : scale.x.range()[1];
    const nextAngle = index === data.length - 1 ?
      this.getAngle(props, 0) + (Math.PI * 2) : this.getAngle(props, index + 1);
    return index === data.length - 1 && angularRange < (2 * Math.PI) ?
      lastAngle : (currentAngle + nextAngle) / 2;
  }

  getVerticalPolarBarPath(props) {
    const { datum, scale, style, index } = props;
    const r1 = scale.y(datum._y0 || 0);
    const r2 = scale.y(datum._y1 !== undefined ? datum._y1 : datum._y);
    const currentAngle = scale.x(datum._x1 !== undefined ? datum._x1 : datum._x);
    let start;
    let end;
    if (style.width) {
      const width = this.getAngularWidth(props, style.width);
      start = currentAngle - (width / 2);
      end = currentAngle + (width / 2);
    } else {
      start = this.getStartAngle(props, index);
      end = this.getEndAngle(props, index);
    }
    const path = d3Shape.arc()
      .innerRadius(r1)
      .outerRadius(r2)
      .startAngle(this.transformAngle(start))
      .endAngle(this.transformAngle(end));
    return path();
  }

  getBarPath(props, width) {
    return this.props.horizontal ?
      this.getHorizontalBarPath(props, width) : this.getVerticalBarPath(props, width);
  }

  getPolarBarPath(props) {
    // TODO Radial bars
    return this.getVerticalPolarBarPath(props);
  }

  getBarWidth(props, style) {
    if (style.width) {
      return style.width;
    }
    const { scale, data, horizontal } = props;
    const range = horizontal ? scale.y.range() : scale.x.range();
    const extent = Math.abs(range[1] - range[0]);
    const bars = data.length + 2;
    const barRatio = 0.5;
    // eslint-disable-next-line no-magic-numbers
    const defaultWidth = data.length < 2 ? 8 : (barRatio * extent / bars);
    return Math.max(1, Math.round(defaultWidth));
  }

  // Overridden in victory-core-native
  renderBar(path, style, events) {
    const { role, shapeRendering, className, origin, polar } = this.props;
    const transform = polar && origin ? `translate(${origin.x}, ${origin.y})` : undefined;
    return (
      <path
        d={path}
        transform={transform}
        className={className}
        style={style}
        role={role || "presentation"}
        shapeRendering={shapeRendering || "auto"}
        {...events}
      />
    );
  }

  render() {
    return this.renderBar(this.path, this.style, this.props.events);
  }
}
<|endoftext|>


<commit_before>( function( VN ) {

	// TODO : add another implementation since text isn't crisp / sharp because of transformation
	//			create another div for text container
	//			create a SceneText class

	VN.prototype.addTextToScene = function addTextToScene( name, text, info, delay ) {

		var self = this;

		function eventToAdd() {

			// container parallel to floor
			// x & y = 0 ~ 1
			var width = info.width ? info.width : 0;
			var height = info.height ? info.height : 0;
			var pos = self.util.scalePosition(
					{ x : info.x, y : info.y, z : info.z },
					{ x : self.sceneFloorWidth, y : -self.sceneFloorHeight, z : self.sceneFloorHeight }
				);

			var sceneObject = self.objectFactory( "SceneObject", width, height, pos );

			sceneObject.sprite.children[ 0 ].setInnerHTML( text );

			if ( info.size ) {

				sceneObject.sprite.setCSS( "font-size", info.size + "px" );

			}

			if ( info.color ) {

				sceneObject.sprite.setCSS( "color", info.color );

			}

			if ( info.bgColor || info.bgImage ) {

				sceneObject.setBackground( width, height,
					info.bgImage ? self.imgPath + info.bgImage : null,
					info.bgColor ? info.bgColor : null );

			}

			if ( info.fade ) {

				sceneObject.fadeIn( info.fade );

			}

			// To keep track of scene text
			sceneObject.name = name;

			// Add scene object to floor and store in scenes list
			self.sceneFloor.sprite.addChild( sceneObject.sprite );
			self.scenes.object.push( sceneObject );

		}

		this.eventTracker.addEvent( "nowait", eventToAdd, delay );

	};

	VN.prototype.fadeSceneText = function fadeSceneText( name, type, fadeSpeed ) {

		this.fadeSceneObject( name, type, fadeSpeed );

	};

	VN.prototype.moveSceneText = function moveSceneText( name, x, y, z, moveSpeed, delay ) {

		this.moveSceneObject( name, x, y, z, moveSpeed, delay );

	};

	VN.prototype.rotateSceneText = function rotateSceneText( name, axis, angle, speed, loop ) {

		this.rotateSceneObject( name, axis, angle, speed, loop );

	};

	VN.prototype.removeSceneText = function removeSceneText( name ) {

		this.removeSceneObject( name );

	};

} )( window.VisualNovel = window.VisualNovel || {} );<commit_msg>Update scene text module<commit_after>( function( VN ) {

	// TODO : add another implementation since text isn't crisp / sharp because of transformation
	//			create another div for text container
	//			create a SceneText class

	VN.prototype.addTextToScene = function addTextToScene( name, text, info, delay ) {

		var self = this;

		function eventToAdd() {

			// container parallel to floor
			// x & y = 0 ~ 1
			var width = info.width ? info.width : 0;
			var height = info.height ? info.height : 0;
			var pos = self.util.scalePosition(
					{ x : info.x, y : info.y, z : info.z },
					{ x : self.sceneFloorWidth, y : -self.sceneFloorHeight, z : self.sceneFloorHeight }
				);

			var sceneObject = getSceneObjectConstructor( self );

			sceneObject = sceneObject( width, height, pos );

			sceneObject.sprite.children[ 0 ].setInnerHTML( text );

			if ( info.size ) {

				sceneObject.sprite.setCSS( "font-size", info.size + "px" );

			}

			if ( info.color ) {

				sceneObject.sprite.setCSS( "color", info.color );

			}

			if ( info.bgColor || info.bgImage ) {

				sceneObject.setBackground( width, height,
					info.bgImage ? self.imgPath + info.bgImage : null,
					info.bgColor ? info.bgColor : null );

			}

			if ( info.fade ) {

				sceneObject.fadeIn( info.fade );

			}

			// To keep track of scene text
			sceneObject.name = name;

			// Add scene object to floor and store in scenes list
			self.sceneFloor.sprite.addChild( sceneObject.sprite );
			self.scenes.object.push( sceneObject );

		}

		this.eventTracker.addEvent( "nowait", eventToAdd, delay );

	};

	VN.prototype.fadeSceneText = function fadeSceneText( name, type, fadeSpeed ) {

		this.fadeSceneObject( name, type, fadeSpeed );

	};

	VN.prototype.moveSceneText = function moveSceneText( name, x, y, z, moveSpeed, delay ) {

		this.moveSceneObject( name, x, y, z, moveSpeed, delay );

	};

	VN.prototype.rotateSceneText = function rotateSceneText( name, axis, angle, speed, loop ) {

		this.rotateSceneObject( name, axis, angle, speed, loop );

	};

	VN.prototype.removeSceneText = function removeSceneText( name ) {

		this.removeSceneObject( name );

	};

	var getSceneObjectConstructor = function( novel ) {

		var Sprite = novel.sprite;

		/**
		 *	Object : Scene
		 *  States:
		 *		1. sprite
		 *  Behaviors:
		 *		1. Move
		 *		2. Rotate
		 *		3. FadeIn/FadeOut
		 **/
		function SceneObject( width, height, position, transformOrigin, rotate ) {

			if ( this instanceof SceneObject ) {

				// Call the parent constructor
				Sprite.apply( this, arguments );

				// Add states

				this.init( width, height, position, transformOrigin, rotate );

				return this;

			} else {

				return new SceneObject( width, height, position, transformOrigin, rotate );

			}

		}

		// Create a SceneObject.prototype object that inherits from Sprite.prototype
		SceneObject.prototype = Object.create( Sprite.prototype );

		// Set the "constructor" property to refer to SceneObject
		SceneObject.prototype.constructor = SceneObject;

		SceneObject.prototype.init = function init( width, height, position, transformOrigin, rotate ) {

			var pos = {
				x : position.x - 25,
				y : position.z,
				z : position.y
			};
			var trans = {
				x : position.x + ( width / 2 ),
				y : 0
			};

			var sceneObjectContainer = this.createSprite( 50, 50, pos, trans );

			sceneObjectContainer.addClassName( "sceneObjectContainer" );

			pos = {
				x : -( width / 2 ) + 25,
				y : -height,
				z : 0
			};
			trans = {
				x : 25,
				y : 0,
				z : 0
			};
			var rot = {
				x : 90, //+ 20, // refactor
				y : 0,
				z : 0
			};

			var sceneObject = this.createSprite( width, height, pos, trans, rot );
			sceneObject.addClassName( "sceneObject" ).update();

			// Add scene object ( perpendicular to floor )
			// inside container ( parallel to floor )
			// Note: to move object => move container
			//       to rotate object => rotate object
			sceneObjectContainer.addChild( sceneObject );

			this.sprite = sceneObjectContainer;

		};

		SceneObject.prototype.setBackground = function setBackground( width, height, image, color ) {

			// this.sprite => sceneObjectContainer
			var sceneObject = this.sprite.children[ 0 ];

			var bgSize = width && height ? "background-size:" + width + "px " + height + "px;" : "";
			var bgImage = image ? "background-image:url('" + image + "');" : "";
			var bgColor = color ? "background-color:" + color + ";" : "";
			var preSemicolon = bgSize || bgImage || bgColor ? ";" : "";

			sceneObject.style.cssText += preSemicolon + bgSize + bgImage + bgColor;

		};

		SceneObject.prototype.rotate = function rotate( axis, angle, loop, sprite ) {

			// this.sprite => sceneObjectContainer
			var sceneObject = this.sprite.children[ 0 ];

			Sprite.prototype.rotate.call( this, axis, angle, loop, sceneObject );

		};

		SceneObject.prototype.rotateTo = function rotateTo( axis, angle, duration, sprite ) {

			// this.sprite => sceneObjectContainer
			var sceneObject = this.sprite.children[ 0 ];

			Sprite.prototype.rotateTo.call( this, axis, angle, duration, sceneObject );

		};

		getSceneObjectConstructor = function() {

			return SceneObject;

		};

		return SceneObject;

	};

} )( window.VisualNovel = window.VisualNovel || {} );<|endoftext|>


<commit_before>/**
 * Created by leehyeon on 8/9/16.
 */
import { CloudWatch, Config } from 'aws-sdk';
import request from 'request';
import _ from 'lodash';

import BaseModel from './base';
import WatchResult from './watch_result';

const label = 'Watcher';
export class Watcher extends BaseModel {
  static fetchById(id) {
    return super.fetchById(id, label);
  }

  static fetchAll() {
    return super.fetchAll(label);
  }

  insert() {
    if (!this.isValid()) {
      return Promise.reject('Invalid watcher');
    }

    return BaseModel.db()
      .cypher('CREATE (w:Watcher { props }) RETURN id(w), w',
        { props: _.omit(this.serialize(), 'id') })
      .then(resp => {
        const r = resp.body.results[0].data[0].row;
        return _.extend(r[1], { id: r[0] });
      });
  }

  isValid() {
    throw new Error('Not Implemented');
  }

  watch() {
    throw new Error('Not Implemented');
  }
}

export class HttpWatcher extends Watcher {
  constructor(settings, id = undefined) {
    super(_.pick(settings, ['type', 'name', 'url']), id);
  }

  serialize() {
    return _.pick(this, ['type', 'id', 'name', 'url', 'result']);
  }

  isValid() {
    const objFields = Object.keys(this);
    const val = _.reduce(['type', 'name', 'url'], (m, n) => (m & _.includes(objFields, n)), true);

    return val;
  }

  watch() {
    return new Promise((resolve) => {
      request(this.url, (error, response) => {
        if (error || response.statusCode < 200 || response.statusCode > 299) {
          this.result = WatchResult.error({
            description: error.message,
          });
        } else {
          this.result = WatchResult.success({
            description: `Status: ${response.statusCode}`,
          });
        }
        resolve(this.result);
      });
    });
  }
}

export class CloudwatchAlarmWatcher extends Watcher {
  constructor(settings, id = undefined) {
    super(_.pick(settings,
      ['type', 'name', 'awsAccessKeyId', 'awsSecretAccessKey', 'awsRegion', 'alarmName']), id);
  }

  serialize() {
    return _.pick(this,
      ['type', 'id', 'name', 'awsAccessKeyId', 'awsSecretAccessKey', 'awsRegion', 'alarmName']);
  }

  isValid() {
    const objFields = Object.keys(this);
    const val = _.reduce(['type', 'name', 'awsAccessKeyId',
      'awsSecretAccessKey', 'awsRegion', 'alarmName'],
      (m, n) => (m & _.includes(objFields, n)), true);

    return val;
  }

  watch() {
    return new Promise((resolve) => {
      const config = new Config({
        accessKeyId: this.awsAccessKeyId,
        secretAccessKey: this.awsSecretAccessKey,
        region: this.awsRegion,
      });
      const cloudwatch = new CloudWatch(config);

      cloudwatch.describeAlarms({
        AlarmNames: [
          this.alarmName,
        ],
      }, (err, data) => {
        if (err) {
          this.result = WatchResult.error({
            description: err.message,
          });
        } else {
          const alarm = data.MetricAlarms[0];
          if (!alarm) {
            this.result = WatchResult.error({
              description: 'Alarm not exists.',
            });
          } else if (alarm.StateValue === 'ALARM') {
            this.result = WatchResult.error({
              description: alarm.StateReason,
            });
          } else {
            this.result = WatchResult.success({
              description: alarm.StateReason,
            });
          }
        }
        resolve(this.result);
      });
    });
  }
}

export class DummyWatcher extends Watcher {
  constructor(settings, id = undefined) {
    super(_.pick(settings, ['type', 'name']), id);
    this.result = WatchResult.success();
  }

  serialize() {
    return _.pick(this,
      ['type', 'id', 'name']);
  }

  isValid() {
    const objFields = Object.keys(this);
    const val = _.reduce(['type', 'name'], (m, n) => (m & _.includes(objFields, n)), true);

    return val;
  }

  watch() {
    return this.result;
  }
}

export const watcherTypes = { HttpWatcher, CloudwatchAlarmWatcher, DummyWatcher };
<commit_msg>httpwatcher error handling<commit_after>/**
 * Created by leehyeon on 8/9/16.
 */
import { CloudWatch, Config } from 'aws-sdk';
import request from 'request';
import _ from 'lodash';

import BaseModel from './base';
import WatchResult from './watch_result';

const label = 'Watcher';
export class Watcher extends BaseModel {
  static fetchById(id) {
    return super.fetchById(id, label);
  }

  static fetchAll() {
    return super.fetchAll(label);
  }

  insert() {
    if (!this.isValid()) {
      return Promise.reject('Invalid watcher');
    }

    return BaseModel.db()
      .cypher('CREATE (w:Watcher { props }) RETURN id(w), w',
        { props: _.omit(this.serialize(), 'id') })
      .then(resp => {
        const r = resp.body.results[0].data[0].row;
        return _.extend(r[1], { id: r[0] });
      });
  }

  isValid() {
    throw new Error('Not Implemented');
  }

  watch() {
    throw new Error('Not Implemented');
  }
}

export class HttpWatcher extends Watcher {
  constructor(settings, id = undefined) {
    super(_.pick(settings, ['type', 'name', 'url']), id);
  }

  serialize() {
    return _.pick(this, ['type', 'id', 'name', 'url', 'result']);
  }

  isValid() {
    const objFields = Object.keys(this);
    const val = _.reduce(['type', 'name', 'url'], (m, n) => (m & _.includes(objFields, n)), true);

    return val;
  }

  watch() {
    return new Promise((resolve) => {
      request(this.url, (error, response) => {
        if (error || response.statusCode < 200 || response.statusCode > 299) {
          this.result = WatchResult.error({
            description: error ? error.message : `Status: ${response.statusCode}`,
          });
        } else {
          this.result = WatchResult.success({
            description: `Status: ${response.statusCode}`,
          });
        }
        resolve(this.result);
      });
    });
  }
}

export class CloudwatchAlarmWatcher extends Watcher {
  constructor(settings, id = undefined) {
    super(_.pick(settings,
      ['type', 'name', 'awsAccessKeyId', 'awsSecretAccessKey', 'awsRegion', 'alarmName']), id);
  }

  serialize() {
    return _.pick(this,
      ['type', 'id', 'name', 'awsAccessKeyId', 'awsSecretAccessKey', 'awsRegion', 'alarmName']);
  }

  isValid() {
    const objFields = Object.keys(this);
    const val = _.reduce(['type', 'name', 'awsAccessKeyId',
      'awsSecretAccessKey', 'awsRegion', 'alarmName'],
      (m, n) => (m & _.includes(objFields, n)), true);

    return val;
  }

  watch() {
    return new Promise((resolve) => {
      const config = new Config({
        accessKeyId: this.awsAccessKeyId,
        secretAccessKey: this.awsSecretAccessKey,
        region: this.awsRegion,
      });
      const cloudwatch = new CloudWatch(config);

      cloudwatch.describeAlarms({
        AlarmNames: [
          this.alarmName,
        ],
      }, (err, data) => {
        if (err) {
          this.result = WatchResult.error({
            description: err.message,
          });
        } else {
          const alarm = data.MetricAlarms[0];
          if (!alarm) {
            this.result = WatchResult.error({
              description: 'Alarm not exists.',
            });
          } else if (alarm.StateValue === 'ALARM') {
            this.result = WatchResult.error({
              description: alarm.StateReason,
            });
          } else {
            this.result = WatchResult.success({
              description: alarm.StateReason,
            });
          }
        }
        resolve(this.result);
      });
    });
  }
}

export class DummyWatcher extends Watcher {
  constructor(settings, id = undefined) {
    super(_.pick(settings, ['type', 'name']), id);
    this.result = WatchResult.success();
  }

  serialize() {
    return _.pick(this,
      ['type', 'id', 'name']);
  }

  isValid() {
    const objFields = Object.keys(this);
    const val = _.reduce(['type', 'name'], (m, n) => (m & _.includes(objFields, n)), true);

    return val;
  }

  watch() {
    return this.result;
  }
}

export const watcherTypes = { HttpWatcher, CloudwatchAlarmWatcher, DummyWatcher };
<|endoftext|>


<commit_before>"use strict";
/* jshint undef: true, unused: true */
/* global Applet  */

var MegaUni = {
  stack : []
};

$(function () {

  var show_if = function (raw) {
    var node = $(raw);
    var val  = node.attr('show_if');
    node.removeAttr('show_if');
    node.hide();

    var id = Applet.id(node);
    MegaUni.run(function (data) {
      var ans = Applet.is_true(data, val);
      if (ans === undefined)
        return;

      if ( ans )
        $('#' + id).show();
      else
        $('#' + id).hide();
    });
  }; // === show_if

  var process_node = MegaUni.run_node = function (script) {

    _.each($(script).find('*[show_if]'), show_if);

    ($(script).contents()).insertBefore($(script));
  }; // === process_node

  MegaUni.run = function (func) {
    // === Compile all scripts
    //     before proceding.
    Applet.run(process_node);

    if (_.isFunction(func))
      MegaUni.stack.push(func);
    else if (_.isPlainObject(func)) {
      _.each(MegaUni.stack, function (f) {
        f(func);
      });
    }
  }; // === func

}); // === scope
<commit_msg>Refactoring<commit_after>"use strict";
/* jshint undef: true, unused: true */
/* global Applet  */

var MegaUni = {
  stack : []
};

$(function () {

  var process_node = MegaUni.run_node = function (script) {

    _.each(MegaUni.stack, function (o) {
      if (o.name !== 'attr')
        return;
      _.each($(script).find('*[' + o.attr + ']'), o.func);
    });

    ($(script).contents()).insertBefore($(script));
  }; // === process_node

  MegaUni.run = function (func) {

    // === Compile all scripts:
    Applet.run(process_node);

    if (_.isPlainObject(func))
      _.each(MegaUni.stack, function (f) {
        if (!f.name)
          f(func);
      });

    return MegaUni;

  }; // === func

  var insert = function (pos, name, func) {
    if (_.isFunction(name))
      MegaUni.stack[pos](name);
    else {
      MegaUni.stack[pos]({name: 'attr', attr: name, func: func});
    }

    return MegaUni;
  };

   MegaUni.unshift = function (name, func) {
    return insert('unshift', name, func);
  };

  var push = MegaUni.push = function (name, func) {
    return insert('push', name, func);
  };

  push(
    'show_if',
    function (raw) {
      var node = $(raw);
      var val  = node.attr('show_if');
      node.removeAttr('show_if');
      node.hide();

      var id = Applet.id(node);
      MegaUni.push(function (data) {
        var ans = Applet.is_true(data, val);
        if (ans === undefined)
          return;

        if ( ans )
          $('#' + id).show();
        else
          $('#' + id).hide();
      });
    } // === func
  ); // === show_if

}); // === scope

<|endoftext|>


<commit_before>
angular.module('exampleApp').directive('exampleCard', function(){
   return {
       restrict: 'E',
       replace: true,
       scope:{
           title:'@'
       },
       templateUrl:'/components/directives/examplecard.view.html',
       transclude:true
   }
});

angular.module('exampleApp').directive('rainbowDate', function(){
    return {
        restrict: 'E',
        replace: true,
        scope: {
            date: '=date'
        },
        template: '
' +
            '{{date.getMonth()+1 | numberFixedLen:2}}/' +
            '{{date.getDate()}}/' +
            '{{date.getFullYear()}}' +
            ' ::: ' +
            '{{date.getHours() | numberFixedLen:2}}:' +
            '{{date.getMinutes() | numberFixedLen:2}}:' +
            '{{date.getSeconds() | numberFixedLen:2}}' +
        '
'
    }
});

angular.module('exampleApp').directive('makeGreen', function(){
    return {
        restrict: 'A',
        replace: false,
        priority: 99,
        terminal: true,
        link: function($scope, element, attrs){
            element.css({"color":"green"})
        }
    }
});

angular.module('exampleApp').directive('makeRed', function(){
    return {
        restrict: 'A',
        replace: false,
        priority: 100,
        terminal: true,
        link: function($scope, element, attrs){
            element.css({"color":"red"})
        }
    }
});

angular.module('exampleApp').directive('transcludeBlue', function(){
    return {
        restrict: 'EA',
        priority: 101,
        replace:false,
        scope: {}, //must be isolated, {}, or set to true
        transclude:true,
        template:'

'
    }
});

angular.module('exampleApp').directive('contestExample', function(){
    return {
        restrict: 'E',
        replace: true,
        templateUrl:'/components/directives/clickcontestexample.view.html',
        controllerAs:'contest',
        controller:function($timeout){
            var self = this;
            this.rolling=false;
            this.dice=4;
            this.reroll = function(){
                this.rolling = true;
                $timeout(function(){
                    self.rolling = false;
                    self.dice = this.getRandomArbitrary(1,6);
                }, 1500)
            };

            this.getRandomArbitrary = function(min, max) {
                return Math.random() * (max - min) + min;
            };
        }
    }
});

angular.module('exampleApp').directive('trueScope', function(){
    return{
        restrict: 'E',
        scope:true,
        template:'
' +
        '
This directive has a scope:true property and inherits it\'s scope prototypically as a result
' +
        '
{{controllerProperty}}
' +
        '
'
    };
});

angular.module('exampleApp').directive('noScope', function(){
    return{
        restrict: 'E',
        template:'
' +
        '
This directive does not have a scope property and inherits prototypically as a result
' +
        '
{{controllerProperty}}
' +
        '
'
    };
});

angular.module('exampleApp').directive('isolateScope', function(){
    return{
        restrict: 'E',
        scope:{},
        template:'
' +
            '
This directive sets it\'s scope property and thus does not inherit, the example controller property should not appear below
' +
            '
{{controllerProperty}}
' +
        '
'
    };
});

angular.module('exampleApp').controller('ScopeExampleController', function($scope){
    $scope.controllerProperty = 'Controller Property';
});

<commit_msg>fixing RNG console error<commit_after>
angular.module('exampleApp').directive('exampleCard', function(){
   return {
       restrict: 'E',
       replace: true,
       scope:{
           title:'@'
       },
       templateUrl:'/components/directives/examplecard.view.html',
       transclude:true
   }
});

angular.module('exampleApp').directive('rainbowDate', function(){
    return {
        restrict: 'E',
        replace: true,
        scope: {
            date: '=date'
        },
        template: '
' +
            '{{date.getMonth()+1 | numberFixedLen:2}}/' +
            '{{date.getDate()}}/' +
            '{{date.getFullYear()}}' +
            ' ::: ' +
            '{{date.getHours() | numberFixedLen:2}}:' +
            '{{date.getMinutes() | numberFixedLen:2}}:' +
            '{{date.getSeconds() | numberFixedLen:2}}' +
        '
'
    }
});

angular.module('exampleApp').directive('makeGreen', function(){
    return {
        restrict: 'A',
        replace: false,
        priority: 99,
        terminal: true,
        link: function($scope, element, attrs){
            element.css({"color":"green"})
        }
    }
});

angular.module('exampleApp').directive('makeRed', function(){
    return {
        restrict: 'A',
        replace: false,
        priority: 100,
        terminal: true,
        link: function($scope, element, attrs){
            element.css({"color":"red"})
        }
    }
});

angular.module('exampleApp').directive('transcludeBlue', function(){
    return {
        restrict: 'EA',
        priority: 101,
        replace:false,
        scope: {}, //must be isolated, {}, or set to true
        transclude:true,
        template:'

'
    }
});

angular.module('exampleApp').directive('contestExample', function(){
    return {
        restrict: 'E',
        replace: true,
        templateUrl:'/components/directives/clickcontestexample.view.html',
        controllerAs:'contest',
        controller:function($timeout){
            var self = this;
            this.rolling=false;
            this.dice=4;
            this.reroll = function(){
                this.rolling = true;
                $timeout(function(){
                    self.rolling = false;
                    self.dice = self.RNG(1,6);
                }, 1500)
            };

            this.RNG = function(min, max) {
                return Math.random() * (max - min) + min;
            };
        }
    }
});

angular.module('exampleApp').directive('trueScope', function(){
    return{
        restrict: 'E',
        scope:true,
        template:'
' +
        '
This directive has a scope:true property and inherits it\'s scope prototypically as a result
' +
        '
{{controllerProperty}}
' +
        '
'
    };
});

angular.module('exampleApp').directive('noScope', function(){
    return{
        restrict: 'E',
        template:'
' +
        '
This directive does not have a scope property and inherits prototypically as a result
' +
        '
{{controllerProperty}}
' +
        '
'
    };
});

angular.module('exampleApp').directive('isolateScope', function(){
    return{
        restrict: 'E',
        scope:{},
        template:'
' +
            '
This directive sets it\'s scope property and thus does not inherit, the example controller property should not appear below
' +
            '
{{controllerProperty}}
' +
        '
'
    };
});

angular.module('exampleApp').controller('ScopeExampleController', function($scope){
    $scope.controllerProperty = 'Controller Property';
});

<|endoftext|>


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

  angular
    .module('fusionSeedApp.components.paginate')
    .directive('paginate', paginate);

  function paginate() {
    'ngInject';
    var directive = {
      restrict: 'EA',
      templateUrl: 'assets/components/paginate/paginate.html',
      controller: Controller,
      controllerAs: 'vm',
      bindToController: true,
      scope: true
    };

    return directive;

  }

  function Controller(Orwell, PaginateService, QueryService) {
    'ngInject';
    var vm = this;
    vm.page = 0;
    vm.totalPages = 0;
    vm.getNormalizedPage = getNormalizedPage;
    vm.getLastPage = getLastPage;
    vm.gotoNextPage = gotoNextPage;
    vm.gotoPreviousPage = gotoPreviousPage;
    vm.showState = 'next';

    activate();

    /////////////

    function activate() {
      var resultsObservable = Orwell.getObservable('queryResults');

      resultsObservable.addObserver(function (data) {
        if (data.hasOwnProperty('response')) {
          vm.page = PaginateService.getCurrentPage();
          vm.totalPages = PaginateService.getTotalPages();
        } else {
          vm.page = 0;
          vm.totalPages = 0;
        }
      });
    }

    function pickPaginatorType(){
      if(vm.page === 0 && vm.totalPages > 1) return 'next';
      if(vm.page === vm.getLastPage() && vm.page > 0) return 'previous';
      if(vm.page !== vm.getLastPage()) return 'both';
    }

    /**
     * Get the page number (normalized for viewers from a 1 base)
     * @return {integer} normalized page number
     */
    function getNormalizedPage() {
      return vm.page + 1;
    }

    /**
     * Get the last page (0 start based)
     * @return {integer} The last page from 0 base.
     */
    function getLastPage() {
      return vm.totalPages - 1;
    }

    /**
     * Updates the query parameters to the next page.
     */
    function gotoNextPage() {
      gotoPage(PaginateService.getCurrentPage() + 1);
    }

    /**
     * Updates the query parameters to the previous page.
     */
    function gotoPreviousPage() {
      gotoPage(PaginateService.getCurrentPage() - 1);
    }

    /**
     * Actually updates the page to go to.
     * @param  {integer} page The page to do to
     */
    function gotoPage(page) {
      if (page < 0) return;
      if (page > PaginateService.getTotalPages()) return;
      if (page === PaginateService.getCurrentPage()) return;
      // This will change the query and cause the interface to make an http call.
      QueryService.setQuery({
        start: PaginateService.pageToStartRow(page)
      });
    }

  }
})();
<commit_msg>fix last commit<commit_after>(function () {
  'use strict';

  angular
    .module('fusionSeedApp.components.paginate')
    .directive('paginate', paginate);

  function paginate() {
    'ngInject';
    var directive = {
      restrict: 'EA',
      templateUrl: 'assets/components/paginate/paginate.html',
      controller: Controller,
      controllerAs: 'vm',
      bindToController: true,
      scope: true
    };

    return directive;

  }

  function Controller(Orwell, PaginateService, QueryService) {
    'ngInject';
    var vm = this;
    vm.page = 0;
    vm.totalPages = 0;
    vm.getNormalizedPage = getNormalizedPage;
    vm.getLastPage = getLastPage;
    vm.gotoNextPage = gotoNextPage;
    vm.gotoPreviousPage = gotoPreviousPage;
    vm.showState = 'next';

    activate();

    /////////////

    function activate() {
      var resultsObservable = Orwell.getObservable('queryResults');

      resultsObservable.addObserver(function (data) {
        if (data.hasOwnProperty('response')) {
          vm.page = PaginateService.getCurrentPage();
          vm.totalPages = PaginateService.getTotalPages();
          vm.showState =  pickPaginatorType();
        } else {
          vm.page = 0;
          vm.totalPages = 0;
        }
      });
    }

    function pickPaginatorType(){
      if(vm.page === 0 && vm.totalPages > 1) return 'next';
      if(vm.page === vm.getLastPage() && vm.page > 0) return 'previous';
      if(vm.page !== vm.getLastPage()) return 'both';
    }

    /**
     * Get the page number (normalized for viewers from a 1 base)
     * @return {integer} normalized page number
     */
    function getNormalizedPage() {
      return vm.page + 1;
    }

    /**
     * Get the last page (0 start based)
     * @return {integer} The last page from 0 base.
     */
    function getLastPage() {
      return vm.totalPages - 1;
    }

    /**
     * Updates the query parameters to the next page.
     */
    function gotoNextPage() {
      gotoPage(PaginateService.getCurrentPage() + 1);
    }

    /**
     * Updates the query parameters to the previous page.
     */
    function gotoPreviousPage() {
      gotoPage(PaginateService.getCurrentPage() - 1);
    }

    /**
     * Actually updates the page to go to.
     * @param  {integer} page The page to do to
     */
    function gotoPage(page) {
      if (page < 0) return;
      if (page > PaginateService.getTotalPages()) return;
      if (page === PaginateService.getCurrentPage()) return;
      // This will change the query and cause the interface to make an http call.
      QueryService.setQuery({
        start: PaginateService.pageToStartRow(page)
      });
    }

  }
})();
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { ReactiveVar } from 'meteor/reactive-var';
import { FlowRouter } from 'meteor/kadira:flow-router';

import { MeetingSeries } from '/imports/meetingseries'
import { UserRoles } from '/imports/userroles'
import { User, userSettings } from '/imports/users'

import { TabItemsConfig } from './tabItems'
import { TabTopicsConfig } from './tabTopics'

let _meetingSeriesID;   // the parent meeting object of this minutes

Template.meetingSeriesDetails.onCreated(function () {
    this.seriesReady = new ReactiveVar();

    this.autorun(() => {
        _meetingSeriesID = FlowRouter.getParam('_id');
        this.showSettingsDialog = FlowRouter.getQueryParam('edit') === 'true';

        let subscriptionHandle = this.subscribe('meetingSeries', _meetingSeriesID);

        this.seriesReady.set(subscriptionHandle.ready());
    });

    this.activeTabTemplate = new ReactiveVar("tabMinutesList");
    this.activeTabId = new ReactiveVar("tab_minutes");
});

Template.meetingSeriesDetails.onRendered(function () {
    if (this.showSettingsDialog) {
        Session.set("meetingSeriesEdit.showUsersPanel", true);
        $('#dlgEditMeetingSeries').modal('show');
    }
});

Template.meetingSeriesDetails.helpers({
    authenticating() {
        const subscriptionReady = Template.instance().seriesReady.get();
        return Meteor.loggingIn() || !subscriptionReady;
    },
    redirectIfNotAllowed() {
        let usrRoles = new UserRoles();
        if (!usrRoles.hasViewRoleFor(_meetingSeriesID)) {
            FlowRouter.go('/');
        }
    },
    meetingSeries: function() {
        return new MeetingSeries(_meetingSeriesID);
    },

    showQuickHelp: function() {
        const user = new User();
        return user.getSetting(userSettings.showQuickHelp.meetingSeries, true);
    },

    minutes: function() {
        let ms = new MeetingSeries(_meetingSeriesID);
        return ms.getAllMinutes();
    },

    isTabActive: function (tabId) {
        return (Template.instance().activeTabId.get() === tabId) ? 'active' : '';
    },

    tab: function() {
        return Template.instance().activeTabTemplate.get();
    },

    tabData: function() {
        let tmpl = Template.instance();
        let tab = tmpl.activeTabTemplate.get();
        let ms = new MeetingSeries(_meetingSeriesID);

        switch (tab) {
            case "tabMinutesList":
                return {
                    minutes: ms.getAllMinutes(),
                    meetingSeriesId: _meetingSeriesID
                };

            case "tabTopics":
            {
                return new TabTopicsConfig(ms.topics, _meetingSeriesID);
            }

            case "tabItems":
            {
                return new TabItemsConfig(ms.topics, _meetingSeriesID);
            }

            default: throw new Meteor.Error('illegal-state', 'Unknown tab: ' + tab);
        }
    },

    isModerator: function () {
        let usrRole = new UserRoles();
        return usrRole.isModeratorOf(_meetingSeriesID);
    }
});

Template.meetingSeriesDetails.events({
    "click #btnHideHelp": function () {
        const user = new User();
        user.storeSetting(userSettings.showQuickHelp.meetingSeries, false);
    },
    "click .nav-tabs li": function(event, tmpl) {
        let currentTab = $(event.target).closest("li");

        tmpl.activeTabId.set(currentTab.attr('id'));
        tmpl.activeTabTemplate.set(currentTab.data("template"));
    }
});
<commit_msg>Fix: Meeting Series Editor now opens again after creation of new meeting series<commit_after>import { Meteor } from 'meteor/meteor';
import { ReactiveVar } from 'meteor/reactive-var';
import { FlowRouter } from 'meteor/kadira:flow-router';

import { MeetingSeries } from '/imports/meetingseries'
import { UserRoles } from '/imports/userroles'
import { User, userSettings } from '/imports/users'

import { TabItemsConfig } from './tabItems'
import { TabTopicsConfig } from './tabTopics'

let _meetingSeriesID;   // the parent meeting object of this minutes

Template.meetingSeriesDetails.onCreated(function () {
    this.seriesReady = new ReactiveVar();

    this.autorun(() => {
        _meetingSeriesID = FlowRouter.getParam('_id');
        this.showSettingsDialog = FlowRouter.getQueryParam('edit') === 'true';

        let subscriptionHandle = this.subscribe('meetingSeries', _meetingSeriesID);

        this.seriesReady.set(subscriptionHandle.ready());
    });

    this.activeTabTemplate = new ReactiveVar("tabMinutesList");
    this.activeTabId = new ReactiveVar("tab_minutes");
});

Template.meetingSeriesDetails.onRendered(function () {
    if (this.showSettingsDialog) {
        Session.set("meetingSeriesEdit.showUsersPanel", true);

        // Defer opening the meeting series settings dialog after rendering of the template
        window.setTimeout(function () {
            $('#dlgEditMeetingSeries').modal('show');
        }, 10);
    }
});

Template.meetingSeriesDetails.helpers({
    authenticating() {
        const subscriptionReady = Template.instance().seriesReady.get();
        return Meteor.loggingIn() || !subscriptionReady;
    },
    redirectIfNotAllowed() {
        let usrRoles = new UserRoles();
        if (!usrRoles.hasViewRoleFor(_meetingSeriesID)) {
            FlowRouter.go('/');
        }
    },
    meetingSeries: function() {
        return new MeetingSeries(_meetingSeriesID);
    },

    showQuickHelp: function() {
        const user = new User();
        return user.getSetting(userSettings.showQuickHelp.meetingSeries, true);
    },

    minutes: function() {
        let ms = new MeetingSeries(_meetingSeriesID);
        return ms.getAllMinutes();
    },

    isTabActive: function (tabId) {
        return (Template.instance().activeTabId.get() === tabId) ? 'active' : '';
    },

    tab: function() {
        return Template.instance().activeTabTemplate.get();
    },

    tabData: function() {
        let tmpl = Template.instance();
        let tab = tmpl.activeTabTemplate.get();
        let ms = new MeetingSeries(_meetingSeriesID);

        switch (tab) {
            case "tabMinutesList":
                return {
                    minutes: ms.getAllMinutes(),
                    meetingSeriesId: _meetingSeriesID
                };

            case "tabTopics":
            {
                return new TabTopicsConfig(ms.topics, _meetingSeriesID);
            }

            case "tabItems":
            {
                return new TabItemsConfig(ms.topics, _meetingSeriesID);
            }

            default: throw new Meteor.Error('illegal-state', 'Unknown tab: ' + tab);
        }
    },

    isModerator: function () {
        let usrRole = new UserRoles();
        return usrRole.isModeratorOf(_meetingSeriesID);
    }
});

Template.meetingSeriesDetails.events({
    "click #btnHideHelp": function () {
        const user = new User();
        user.storeSetting(userSettings.showQuickHelp.meetingSeries, false);
    },
    "click .nav-tabs li": function(event, tmpl) {
        let currentTab = $(event.target).closest("li");

        tmpl.activeTabId.set(currentTab.attr('id'));
        tmpl.activeTabTemplate.set(currentTab.data("template"));
    }
});
<|endoftext|>


<commit_before>try {
    // Karma configuration for a local run (the default)
    const createKarmaConfig = require("./karma.base.conf");
    const fs = require("fs");
    const which = require("which");

    // Bring in the launchers directly to detect browsers
    const ChromeHeadlessBrowser = require("karma-chrome-launcher")["launcher:ChromeHeadless"][1];
    const ChromiumHeadlessBrowser = require("karma-chrome-launcher")["launcher:ChromiumHeadless"][1];
    const FirefoxHeadlessBrowser = require("karma-firefox-launcher")["launcher:FirefoxHeadless"][1];
    const EdgeBrowser = require("karma-edge-launcher")["launcher:Edge"][1];
    const SafariBrowser = require("karma-safari-launcher")["launcher:Safari"][1];
    const IEBrowser = require("karma-ie-launcher")["launcher:IE"][1];

    let browsers = [];

    function browserExists(path) {
      // On linux, the browsers just return the command, not a path, so we need to check if it exists.
      if (process.platform === "linux") {
        return !!which.sync(path, { nothrow: true });
      } else {
        return fs.existsSync(path);
      }
    }

    function tryAddBrowser(name, b) {
      var path = b.DEFAULT_CMD[process.platform];
      if (b.ENV_CMD && process.env[b.ENV_CMD]) {
        path = process.env[b.ENV_CMD];
      }
      console.log(`Checking for ${name} at ${path}...`);

      if (path && browserExists(path)) {
        console.log(`Located ${name} at ${path}.`);
        browsers.push(name);
      }
      else {
        console.log(`Unable to locate ${name}. Skipping.`);
      }
    }

    // We use the launchers themselves to figure out if the browser exists. It's a bit sneaky, but it works.
    tryAddBrowser("ChromeHeadlessNoSandbox", new ChromeHeadlessBrowser(() => { }, {}));
    tryAddBrowser("ChromiumHeadless", new ChromiumHeadlessBrowser(() => { }, {}));
    tryAddBrowser("FirefoxHeadless", new FirefoxHeadlessBrowser(0, () => { }, {}));

    // We need to receive an argument from the caller, but globals don't seem to work, so we use an environment variable.
    if (process.env.ASPNETCORE_SIGNALR_TEST_ALL_BROWSERS === "true") {
      tryAddBrowser("Edge", new EdgeBrowser(() => { }, { create() { } }));
      tryAddBrowser("IE", new IEBrowser(() => { }, { create() { } }, {}));
      tryAddBrowser("Safari", new SafariBrowser(() => { }, {}));
    }

    module.exports = createKarmaConfig({
      browsers,
      customLaunchers: {
        ChromeHeadlessNoSandbox: {
          base: 'ChromeHeadless',
          flags: ['--no-sandbox']
        }
      },
    });
} catch (e) {
    console.error(e);
}
<commit_msg>fix chrome headless lag on Win7 (#2890)<commit_after>try {
    // Karma configuration for a local run (the default)
    const createKarmaConfig = require("./karma.base.conf");
    const fs = require("fs");
    const which = require("which");

    // Bring in the launchers directly to detect browsers
    const ChromeHeadlessBrowser = require("karma-chrome-launcher")["launcher:ChromeHeadless"][1];
    const ChromiumHeadlessBrowser = require("karma-chrome-launcher")["launcher:ChromiumHeadless"][1];
    const FirefoxHeadlessBrowser = require("karma-firefox-launcher")["launcher:FirefoxHeadless"][1];
    const EdgeBrowser = require("karma-edge-launcher")["launcher:Edge"][1];
    const SafariBrowser = require("karma-safari-launcher")["launcher:Safari"][1];
    const IEBrowser = require("karma-ie-launcher")["launcher:IE"][1];

    let browsers = [];

    function browserExists(path) {
      // On linux, the browsers just return the command, not a path, so we need to check if it exists.
      if (process.platform === "linux") {
        return !!which.sync(path, { nothrow: true });
      } else {
        return fs.existsSync(path);
      }
    }

    function tryAddBrowser(name, b) {
      var path = b.DEFAULT_CMD[process.platform];
      if (b.ENV_CMD && process.env[b.ENV_CMD]) {
        path = process.env[b.ENV_CMD];
      }
      console.log(`Checking for ${name} at ${path}...`);

      if (path && browserExists(path)) {
        console.log(`Located ${name} at ${path}.`);
        browsers.push(name);
      }
      else {
        console.log(`Unable to locate ${name}. Skipping.`);
      }
    }

    // We use the launchers themselves to figure out if the browser exists. It's a bit sneaky, but it works.
    tryAddBrowser("ChromeHeadlessNoSandbox", new ChromeHeadlessBrowser(() => { }, {}));
    tryAddBrowser("ChromiumHeadless", new ChromiumHeadlessBrowser(() => { }, {}));
    tryAddBrowser("FirefoxHeadless", new FirefoxHeadlessBrowser(0, () => { }, {}));

    // We need to receive an argument from the caller, but globals don't seem to work, so we use an environment variable.
    if (process.env.ASPNETCORE_SIGNALR_TEST_ALL_BROWSERS === "true") {
      tryAddBrowser("Edge", new EdgeBrowser(() => { }, { create() { } }));
      tryAddBrowser("IE", new IEBrowser(() => { }, { create() { } }, {}));
      tryAddBrowser("Safari", new SafariBrowser(() => { }, {}));
    }

    module.exports = createKarmaConfig({
      browsers,
      customLaunchers: {
        ChromeHeadlessNoSandbox: {
          base: 'ChromeHeadless',

          // ChromeHeadless runs about 10x slower on Windows 7 machines without the --proxy switches below. Why? ¯\_(ツ)_/¯
          flags: ["--no-sandbox", "--proxy-server='direct://'", "--proxy-bypass-list=*"]
        }
      },
    });
} catch (e) {
    console.error(e);
}
<|endoftext|>


<commit_before>define(["backbone", "js/models/location", "js/collections/course_grader"],
    function(Backbone, Location, CourseGraderCollection) {

var CourseGradingPolicy = Backbone.Model.extend({
    defaults : {
        graders : null,  // CourseGraderCollection
        grade_cutoffs : null,  // CourseGradeCutoff model
        grace_period : null, // either null or { hours: n, minutes: m, ...}
        minimum_grade_credit : null // either null or percentage
    },
    parse: function(attributes) {
        if (attributes['graders']) {
            var graderCollection;
            // interesting race condition: if {parse:true} when newing, then parse called before .attributes created
            if (this.attributes && this.has('graders')) {
                graderCollection = this.get('graders');
                graderCollection.reset(attributes.graders, {parse:true});
            }
            else {
                graderCollection = new CourseGraderCollection(attributes.graders, {parse:true});
            }
            attributes.graders = graderCollection;
        }
        // If grace period is unset or equal to 00:00 on the server,
        // it's received as null
        if (attributes['grace_period'] === null) {
            attributes.grace_period = {
                hours: 0,
                minutes: 0
            }
        }
        // If minimum_grade_credit is unset or equal to 0 on the server,
        // it's received as 0
        if (attributes.minimum_grade_credit === null) {
            attributes.minimum_grade_credit = 0;
        }
        return attributes;
    },
    gracePeriodToDate : function() {
        var newDate = new Date();
        if (this.has('grace_period') && this.get('grace_period')['hours'])
            newDate.setHours(this.get('grace_period')['hours']);
        else newDate.setHours(0);
        if (this.has('grace_period') && this.get('grace_period')['minutes'])
            newDate.setMinutes(this.get('grace_period')['minutes']);
        else newDate.setMinutes(0);
        if (this.has('grace_period') && this.get('grace_period')['seconds'])
            newDate.setSeconds(this.get('grace_period')['seconds']);
        else newDate.setSeconds(0);

        return newDate;
    },
    parseGracePeriod : function(grace_period) {
        // Enforce hours:minutes format
        if(!/^\d{2,3}:\d{2}$/.test(grace_period)) {
            return null;
        }
        var pieces = grace_period.split(/:/);
        return {
            hours: parseInt(pieces[0], 10),
            minutes: parseInt(pieces[1], 10)
        }
    },
    parseMinimumGradeCredit : function(minimum_grade_credit) {
        // get the value of minimum grade credit value in percentage
        if (isNaN(minimum_grade_credit)) {
            return 0;
        }
        return parseInt(minimum_grade_credit);
    },
    validate : function(attrs) {
        if(_.has(attrs, 'grace_period')) {
            if(attrs['grace_period'] === null) {
                return {
                    'grace_period': gettext('Grace period must be specified in HH:MM format.')
                }
            }
        }
        if(this.get('is_credit_course') && _.has(attrs, 'minimum_grade_credit')) {
            var minimum_grade_cutoff = _.values(attrs.grade_cutoffs).pop();
            if(isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null || attrs.minimum_grade_credit < minimum_grade_cutoff) {
                return {
                    'minimum_grade_credit': interpolate(
                        gettext('Not able to set passing grade to less than %(minimum_grade_cutoff)s%.'),
                        {minimum_grade_cutoff: minimum_grade_cutoff * 100},
                        true
                    )
                };
            }
        }
    }
});

return CourseGradingPolicy;
}); // end define()
<commit_msg>Fixing minimum grade value error ECOM-2109<commit_after>define(["backbone", "js/models/location", "js/collections/course_grader"],
    function(Backbone, Location, CourseGraderCollection) {

var CourseGradingPolicy = Backbone.Model.extend({
    defaults : {
        graders : null,  // CourseGraderCollection
        grade_cutoffs : null,  // CourseGradeCutoff model
        grace_period : null, // either null or { hours: n, minutes: m, ...}
        minimum_grade_credit : null // either null or percentage
    },
    parse: function(attributes) {
        if (attributes['graders']) {
            var graderCollection;
            // interesting race condition: if {parse:true} when newing, then parse called before .attributes created
            if (this.attributes && this.has('graders')) {
                graderCollection = this.get('graders');
                graderCollection.reset(attributes.graders, {parse:true});
            }
            else {
                graderCollection = new CourseGraderCollection(attributes.graders, {parse:true});
            }
            attributes.graders = graderCollection;
        }
        // If grace period is unset or equal to 00:00 on the server,
        // it's received as null
        if (attributes['grace_period'] === null) {
            attributes.grace_period = {
                hours: 0,
                minutes: 0
            }
        }
        // If minimum_grade_credit is unset or equal to 0 on the server,
        // it's received as 0
        if (attributes.minimum_grade_credit === null) {
            attributes.minimum_grade_credit = 0;
        }
        return attributes;
    },
    gracePeriodToDate : function() {
        var newDate = new Date();
        if (this.has('grace_period') && this.get('grace_period')['hours'])
            newDate.setHours(this.get('grace_period')['hours']);
        else newDate.setHours(0);
        if (this.has('grace_period') && this.get('grace_period')['minutes'])
            newDate.setMinutes(this.get('grace_period')['minutes']);
        else newDate.setMinutes(0);
        if (this.has('grace_period') && this.get('grace_period')['seconds'])
            newDate.setSeconds(this.get('grace_period')['seconds']);
        else newDate.setSeconds(0);

        return newDate;
    },
    parseGracePeriod : function(grace_period) {
        // Enforce hours:minutes format
        if(!/^\d{2,3}:\d{2}$/.test(grace_period)) {
            return null;
        }
        var pieces = grace_period.split(/:/);
        return {
            hours: parseInt(pieces[0], 10),
            minutes: parseInt(pieces[1], 10)
        }
    },
    parseMinimumGradeCredit : function(minimum_grade_credit) {
        // get the value of minimum grade credit value in percentage
        if (isNaN(minimum_grade_credit)) {
            return 0;
        }
        return parseInt(minimum_grade_credit);
    },
    validate : function(attrs) {
        if(_.has(attrs, 'grace_period')) {
            if(attrs['grace_period'] === null) {
                return {
                    'grace_period': gettext('Grace period must be specified in HH:MM format.')
                }
            }
        }
        if(this.get('is_credit_course') && _.has(attrs, 'minimum_grade_credit')) {
            // Getting minimum grade cutoff value
            var minimum_grade_cutoff = _.min(_.values(attrs.grade_cutoffs));
            if(isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null || attrs.minimum_grade_credit < minimum_grade_cutoff) {
                return {
                    'minimum_grade_credit': interpolate(
                        gettext('Not able to set passing grade to less than %(minimum_grade_cutoff)s%.'),
                        {minimum_grade_cutoff: minimum_grade_cutoff * 100},
                        true
                    )
                };
            }
        }
    }
});

return CourseGradingPolicy;
}); // end define()
<|endoftext|>


<commit_before>/* globals Clipboard */
(function (angular, undefined) {
    'use strict';
    // module: hq.list_exports

    /* This module is for helping fetching and showing a list of exports,
     * and activating bulk export download, as well as single export download.
      * */

    var list_exports = angular.module('hq.list_exports', [
        'ngResource',
        'ngRoute',
        'ng.django.rmi',
        'ngMessages'
    ]);

    list_exports.config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    }]);

    var exportsControllers = {};
    exportsControllers.ListExportsController = function (
        $scope, djangoRMI, bulk_download_url, legacy_bulk_download_url, $rootScope
    ) {
        /**
         * This controller fetches a list of saved exports from
         * subclasses of BaseExportListView.
         *
         * It also generates a list of exports selected for bulk exports.
         */
        var self = {};
        $scope._ = _;  // allow use of underscore.js within the template
        $scope.hasLoaded = false;
        $scope.exports = [];
        $scope.exportsListError = null;
        $scope.bulk_download_url = bulk_download_url;
        $scope.legacy_bulk_download_url = legacy_bulk_download_url;

        self._numTries = 0;
        self._getExportsList = function () {
            // The method below lives in the subclasses of
            // BaseExportListView.
            djangoRMI.get_exports_list({})
                .success(function (data) {
                    if (data.success) {
                        $scope.exports = data.exports;
                    } else {
                        $scope.exportsListError = data.error;
                    }
                    $scope.hasLoaded = true;
                })
                .error(function () {
                    // Retry in case the connection was flaky.
                    if (self._numTries > 3) {
                        $scope.hasLoaded = true;
                        $scope.exportsListError = 'default';
                        return;
                    }
                    self._numTries ++;
                    self._getExportsList();
                });
        };
        self._getExportsList();

        // For Bulk Export
        $scope.showBulkExportDownload = false;
        $scope.bulkExportList = '[]';

        $scope.updateBulkStatus = function () {
            var selectedExports = _.filter($scope.exports, function (exp) {
                return !!exp.addedToBulk;
            });
            $scope.showBulkExportDownload = !_.isEmpty(selectedExports);
            $scope.bulkExportList = JSON.stringify(selectedExports);
            var input = $('input[name="export_list"]');
            input.val(JSON.stringify(selectedExports));

            var useLegacyBulkExportUrl = _.every(selectedExports, function (e) {
                return e.isLegacy;
            });
            var currentUrl = useLegacyBulkExportUrl ? $scope.legacy_bulk_download_url : $scope.bulk_download_url;
            input.closest("form").attr("action", currentUrl);
        };
        $scope.downloadRequested = function($event) {
            var $btn = $($event.target);
            $btn.addClass('disabled');
            $btn.text(gettext('Download Requested'));
        };
        $scope.copyLinkRequested = function($event, export_) {
            export_.showLink = true;
            var clipboard = new Clipboard($event.target, {
                target: function (trigger) {
                    return trigger.nextElementSibling;
                },
            });
            clipboard.onClick($event);
            clipboard.destroy();
        };
        $scope.selectAll = function () {
            _.each($scope.exports, function (exp) {
                exp.addedToBulk = true;
            });
            $scope.updateBulkStatus();
        };
        $scope.selectNone = function () {
            _.each($scope.exports, function (exp) {
                exp.addedToBulk = false;
            });
            $scope.updateBulkStatus();
        };
        $scope.sendExportAnalytics = function() {
            analytics.workflow("Clicked Export button");
        };
        $scope.updateEmailedExportData = function (component, exp) {
            $('#modalRefreshExportConfirm-' + exp.id + '-' + (component.groupId ? component.groupId : '')).modal('hide');
            component.updatingData = true;
            djangoRMI.update_emailed_export_data({
                'component': component,
                'export': exp
            })
                .success(function (data) {
                    if (data.success) {
                        var exportType = _(exp.exportType).capitalize();
                        analytics.usage("Update Saved Export", exportType, "Saved");
                        component.updatingData = false;
                        component.updatedDataTriggered = true;
                    }
                });
        };
        $scope.setFilterModalExport = function (export_) {
            // The filterModalExport is used as context for the FeedFilterFormController
            $rootScope.filterModalExport = export_;
        };
        $scope.isLocationSafeForUser = function(export_) {
            return (!export_.emailedExport) || export_.emailedExport.isLocationSafeForUser;
        };
    };
    exportsControllers.FeedFilterFormController = function (
        $scope, $rootScope, djangoRMI, filterFormElements, filterFormModalElement
    ) {
        var self = {};
        $scope._ = _;   // make underscore.js available
        $scope.formData = {};
        $scope.modelType = null;  // "form" or "case" - corresponding to the type of export selected.
        // A list a location names. The export will be restricted to these locations.
        $scope.locationRestrictions = [];
        $scope.isSubmittingForm = false;
        $scope.hasFormSubmitError = false;
        $scope.formSubmitErrorMessage = null;
        $scope.dateRegex = '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]';
        self.nonPristineExportFilters = {};
        $scope.formElement = filterFormElements;

        $rootScope.$watch("filterModalExport", function (newSelectedExport) {
            if (newSelectedExport) {
                if (!(newSelectedExport.id in self.nonPristineExportFilters)) {
                    // Mark the form as pristine if we are editing filters of a different export than before
                    self.nonPristineExportFilters[newSelectedExport.id] = true;
                    $scope.feedFiltersForm.$setPristine();

                }

                $scope.formData = newSelectedExport.emailedExport.filters;
                $scope.locationRestrictions = newSelectedExport.emailedExport.locationRestrictions;
                $scope.modelType = newSelectedExport.exportType;
                // select2s require programmatic update
                $scope.formElement.emwf_case_filter().select2("data", newSelectedExport.emailedExport.filters.emwf_case_filter);
                $scope.formElement.emwf_form_filter().select2("data", newSelectedExport.emailedExport.filters.emwf_form_filter);
            }
        });

        $scope.$watch("formData.date_range", function(newDateRange) {
            if (!newDateRange) {
                $scope.formData.date_range = "last7";
            } else {
                self._clearSubmitError();
            }
        });

        $scope.commitFilters = function () {
            var export_ = $rootScope.filterModalExport;
            $scope.isSubmittingForm = true;

            // Put the data from the select2 into the formData object
            if ($scope.modelType === 'form') {
                $scope.formData.emwf_form_filter = $scope.formElement.emwf_form_filter().select2("data");
                $scope.formData.emwf_case_filter = null;
            }
            if ($scope.modelType === 'case') {
                $scope.formData.emwf_case_filter = $scope.formElement.emwf_case_filter().select2("data");
                $scope.formData.emwf_form_filter = null;
            }

            djangoRMI.commit_filters({
                export: export_,
                form_data: $scope.formData,
            }).success(function (data) {
                $scope.isSubmittingForm = false;
                if (data.success) {
                    self._clearSubmitError();
                    export_.emailedExport.filters = $scope.formData;
                    export_.emailedExport.updatingData = false;
                    export_.emailedExport.updatedDataTriggered = true;
                    filterFormModalElement().modal('hide');
                } else {
                    self._handleSubmitError(data);
                }
            }).error(function (data) {
                $scope.isSubmittingForm = false;
                self._handleSubmitError(data);
            });
        };

        self._handleSubmitError = function(data) {
            $scope.hasFormSubmitError = true;
            $scope.formSubmitErrorMessage = data.error;
        };
        self._clearSubmitError = function() {
            $scope.hasFormSubmitError = false;
            $scope.formSubmitErrorMessage = null;
        };
    };

    list_exports.controller(exportsControllers);

}(window.angular));
<commit_msg>Use early return statement to eliminate a level of indentation<commit_after>/* globals Clipboard */
(function (angular, undefined) {
    'use strict';
    // module: hq.list_exports

    /* This module is for helping fetching and showing a list of exports,
     * and activating bulk export download, as well as single export download.
      * */

    var list_exports = angular.module('hq.list_exports', [
        'ngResource',
        'ngRoute',
        'ng.django.rmi',
        'ngMessages'
    ]);

    list_exports.config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    }]);

    var exportsControllers = {};
    exportsControllers.ListExportsController = function (
        $scope, djangoRMI, bulk_download_url, legacy_bulk_download_url, $rootScope
    ) {
        /**
         * This controller fetches a list of saved exports from
         * subclasses of BaseExportListView.
         *
         * It also generates a list of exports selected for bulk exports.
         */
        var self = {};
        $scope._ = _;  // allow use of underscore.js within the template
        $scope.hasLoaded = false;
        $scope.exports = [];
        $scope.exportsListError = null;
        $scope.bulk_download_url = bulk_download_url;
        $scope.legacy_bulk_download_url = legacy_bulk_download_url;

        self._numTries = 0;
        self._getExportsList = function () {
            // The method below lives in the subclasses of
            // BaseExportListView.
            djangoRMI.get_exports_list({})
                .success(function (data) {
                    if (data.success) {
                        $scope.exports = data.exports;
                    } else {
                        $scope.exportsListError = data.error;
                    }
                    $scope.hasLoaded = true;
                })
                .error(function () {
                    // Retry in case the connection was flaky.
                    if (self._numTries > 3) {
                        $scope.hasLoaded = true;
                        $scope.exportsListError = 'default';
                        return;
                    }
                    self._numTries ++;
                    self._getExportsList();
                });
        };
        self._getExportsList();

        // For Bulk Export
        $scope.showBulkExportDownload = false;
        $scope.bulkExportList = '[]';

        $scope.updateBulkStatus = function () {
            var selectedExports = _.filter($scope.exports, function (exp) {
                return !!exp.addedToBulk;
            });
            $scope.showBulkExportDownload = !_.isEmpty(selectedExports);
            $scope.bulkExportList = JSON.stringify(selectedExports);
            var input = $('input[name="export_list"]');
            input.val(JSON.stringify(selectedExports));

            var useLegacyBulkExportUrl = _.every(selectedExports, function (e) {
                return e.isLegacy;
            });
            var currentUrl = useLegacyBulkExportUrl ? $scope.legacy_bulk_download_url : $scope.bulk_download_url;
            input.closest("form").attr("action", currentUrl);
        };
        $scope.downloadRequested = function($event) {
            var $btn = $($event.target);
            $btn.addClass('disabled');
            $btn.text(gettext('Download Requested'));
        };
        $scope.copyLinkRequested = function($event, export_) {
            export_.showLink = true;
            var clipboard = new Clipboard($event.target, {
                target: function (trigger) {
                    return trigger.nextElementSibling;
                },
            });
            clipboard.onClick($event);
            clipboard.destroy();
        };
        $scope.selectAll = function () {
            _.each($scope.exports, function (exp) {
                exp.addedToBulk = true;
            });
            $scope.updateBulkStatus();
        };
        $scope.selectNone = function () {
            _.each($scope.exports, function (exp) {
                exp.addedToBulk = false;
            });
            $scope.updateBulkStatus();
        };
        $scope.sendExportAnalytics = function() {
            analytics.workflow("Clicked Export button");
        };
        $scope.updateEmailedExportData = function (component, exp) {
            $('#modalRefreshExportConfirm-' + exp.id + '-' + (component.groupId ? component.groupId : '')).modal('hide');
            component.updatingData = true;
            djangoRMI.update_emailed_export_data({
                'component': component,
                'export': exp
            })
                .success(function (data) {
                    if (data.success) {
                        var exportType = _(exp.exportType).capitalize();
                        analytics.usage("Update Saved Export", exportType, "Saved");
                        component.updatingData = false;
                        component.updatedDataTriggered = true;
                    }
                });
        };
        $scope.setFilterModalExport = function (export_) {
            // The filterModalExport is used as context for the FeedFilterFormController
            $rootScope.filterModalExport = export_;
        };
        $scope.isLocationSafeForUser = function(export_) {
            return (!export_.emailedExport) || export_.emailedExport.isLocationSafeForUser;
        };
    };
    exportsControllers.FeedFilterFormController = function (
        $scope, $rootScope, djangoRMI, filterFormElements, filterFormModalElement
    ) {
        var self = {};
        $scope._ = _;   // make underscore.js available
        $scope.formData = {};
        $scope.modelType = null;  // "form" or "case" - corresponding to the type of export selected.
        // A list a location names. The export will be restricted to these locations.
        $scope.locationRestrictions = [];
        $scope.isSubmittingForm = false;
        $scope.hasFormSubmitError = false;
        $scope.formSubmitErrorMessage = null;
        $scope.dateRegex = '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]';
        self.nonPristineExportFilters = {};
        $scope.formElement = filterFormElements;

        $rootScope.$watch("filterModalExport", function (newSelectedExport) {
            if (!newSelectedExport) {
                return;
            }
            if (!(newSelectedExport.id in self.nonPristineExportFilters)) {
                // Mark the form as pristine if we are editing filters of a different export than before
                self.nonPristineExportFilters[newSelectedExport.id] = true;
                $scope.feedFiltersForm.$setPristine();

            }

            $scope.formData = newSelectedExport.emailedExport.filters;
            $scope.locationRestrictions = newSelectedExport.emailedExport.locationRestrictions;
            $scope.modelType = newSelectedExport.exportType;
            // select2s require programmatic update
            $scope.formElement.emwf_case_filter().select2("data", newSelectedExport.emailedExport.filters.emwf_case_filter);
            $scope.formElement.emwf_form_filter().select2("data", newSelectedExport.emailedExport.filters.emwf_form_filter);
        });

        $scope.$watch("formData.date_range", function(newDateRange) {
            if (!newDateRange) {
                $scope.formData.date_range = "last7";
            } else {
                self._clearSubmitError();
            }
        });

        $scope.commitFilters = function () {
            var export_ = $rootScope.filterModalExport;
            $scope.isSubmittingForm = true;

            // Put the data from the select2 into the formData object
            if ($scope.modelType === 'form') {
                $scope.formData.emwf_form_filter = $scope.formElement.emwf_form_filter().select2("data");
                $scope.formData.emwf_case_filter = null;
            }
            if ($scope.modelType === 'case') {
                $scope.formData.emwf_case_filter = $scope.formElement.emwf_case_filter().select2("data");
                $scope.formData.emwf_form_filter = null;
            }

            djangoRMI.commit_filters({
                export: export_,
                form_data: $scope.formData,
            }).success(function (data) {
                $scope.isSubmittingForm = false;
                if (data.success) {
                    self._clearSubmitError();
                    export_.emailedExport.filters = $scope.formData;
                    export_.emailedExport.updatingData = false;
                    export_.emailedExport.updatedDataTriggered = true;
                    filterFormModalElement().modal('hide');
                } else {
                    self._handleSubmitError(data);
                }
            }).error(function (data) {
                $scope.isSubmittingForm = false;
                self._handleSubmitError(data);
            });
        };

        self._handleSubmitError = function(data) {
            $scope.hasFormSubmitError = true;
            $scope.formSubmitErrorMessage = data.error;
        };
        self._clearSubmitError = function() {
            $scope.hasFormSubmitError = false;
            $scope.formSubmitErrorMessage = null;
        };
    };

    list_exports.controller(exportsControllers);

}(window.angular));
<|endoftext|>


<commit_before>import { default as React, Component } from "react";

import { render, setCacheStrategy, Promise } from "../src";
import { useDefaultCacheStrategy } from "../src/sequence/cache";

const runAllTests = () => {
  describe("for stateful components", () => {
    const staticDivKey = `div:static:${Math.random()}`;
    const staticChildKey = `child:static:${Math.random()}`;

    class Child extends Component {
      render () {
        const cacheKey = this.props.cacheChild ? staticDivKey : null;
        return (

{this.props.val}

        );
      }
    }

    class Parent extends Component {
      render () {
        const cacheKey = this.props.cacheParent ? staticChildKey : null;
        return (
          <Child
            cacheKey={cacheKey}
            {...this.props}
          />
        );
      }
    }

    it("returns cached HTML for
", () => {
      return Promise.resolve()
        .then(() => render(<Parent val="first" cacheChild />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(() => render(<Parent val="second" cacheChild />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(html => {
          expect(html).to.equal("
first
");
        });
    });

    it("returns cached HTML for <Child>", () => {
      return Promise.resolve()
        .then(() => render(<Parent val="first" cacheParent />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(() => render(<Parent val="second" cacheParent />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(html => {
          expect(html).to.equal("
first
");
        });
    });
  });

  describe("for stateless functional components", () => {
    const staticDivKey = `div:static:${Math.random()}`;
    const staticChildKey = `child:static:${Math.random()}`;

    const Child = props => {
      const cacheKey = props.cacheChild ? staticDivKey : null;
      return (

{props.val}

      );
    };

    const Parent = props => {
      const cacheKey = props.cacheParent ? staticChildKey : null;
      return (
        <Child
          cacheKey={cacheKey}
          {...props}
        />
      );
    };

    it("returns cached HTML for
", () => {
      return Promise.resolve()
        .then(() => render(<Parent val="first" cacheChild />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(() => render(<Parent val="second" cacheChild />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(html => {
          expect(html).to.equal("
first
");
        });
    });

    it("returns cached HTML for <Child>", () => {
      return Promise.resolve()
        .then(() => render(<Parent val="first" cacheParent />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(() => render(<Parent val="second" cacheParent />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(html => {
          expect(html).to.equal("
first
");
        });
    });
  });
};

describe("naive caching", () => {
  runAllTests();
});

describe("async caching", () => {
  beforeEach(() => {
    const asyncCache = Object.create(null);

    setCacheStrategy({
      get: key => Promise.resolve(asyncCache[key] && JSON.parse(asyncCache[key]) || null),
      set: (key, val) => {
        asyncCache[key] = JSON.stringify(val);
        return Promise.resolve();
      }
    });
  });

  afterEach(() => {
    useDefaultCacheStrategy();
  });

  runAllTests();
});
<commit_msg>Update cache tests to not rely on global side effects.<commit_after>import { default as React, Component } from "react";

import { render, setCacheStrategy, Promise } from "../src";
import { useDefaultCacheStrategy } from "../src/sequence/cache";

const getParentKey = () => `div:static:${Math.random()}`;
const getChildKey = () => `child:static:${Math.random()}`;

const runAllTests = () => {
  describe("for stateful components", () => {
    class Child extends Component {
      render () {
        return (

{this.props.val}

        );
      }
    }

    class Parent extends Component {
      render () {
        return (
          <Child
            cacheKey={this.props.parentKey}
            {...this.props}
          />
        );
      }
    }

    it("returns cached HTML for
", () => {
      const childKey = getChildKey();
      return Promise.resolve()
        .then(() => render(<Parent val="firstA" childKey={childKey} />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(() => render(<Parent val="secondA" childKey={childKey} />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(html => {
          expect(html).to.equal("
firstA
");
        });
    });

    it("returns cached HTML for <Child>", () => {
      const parentKey = getParentKey();
      return Promise.resolve()
        .then(() => render(<Parent val="firstB" parentKey={parentKey} />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(() => render(<Parent val="secondB" parentKey={parentKey} />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(html => {
          expect(html).to.equal("
firstB
");
        });
    });
  });

  describe("for stateless functional components", () => {
    const Child = props => {
      return (

{props.val}

      );
    };

    const Parent = props => {
      return (
        <Child
          cacheKey={props.parentKey}
          {...props}
        />
      );
    };

    it("returns cached HTML for
", () => {
      const childKey = getChildKey();
      return Promise.resolve()
        .then(() => render(<Parent val="firstC" childKey={childKey} />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(() => render(<Parent val="secondC" childKey={childKey} />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(html => {
          expect(html).to.equal("
firstC
");
        });
    });

    it("returns cached HTML for <Child>", () => {
      const parentKey = getParentKey();
      return Promise.resolve()
        .then(() => render(<Parent val="firstD" parentKey={parentKey} />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(() => render(<Parent val="secondD" parentKey={parentKey} />)
          .includeDataReactAttrs(false)
          .toPromise()
        )
        .then(html => {
          expect(html).to.equal("
firstD
");
        });
    });
  });
};

describe("naive caching", () => {
  runAllTests();
});

describe("async caching", () => {
  beforeEach(() => {
    const asyncCache = Object.create(null);

    setCacheStrategy({
      get: key => Promise.resolve(asyncCache[key] && JSON.parse(asyncCache[key]) || null),
      set: (key, val) => {
        asyncCache[key] = JSON.stringify(val);
        return Promise.resolve();
      }
    });
  });

  afterEach(() => {
    useDefaultCacheStrategy();
  });

  runAllTests();
});
<|endoftext|>


<commit_before>/* global window */
import ApolloClient from 'apollo-client';
import { withClientState } from 'apollo-link-state';
import { from } from 'apollo-link';
import getGraphqlFragments from './getGraphqlFragments';
import buildNetworkComponents from './buildNetworkComponents';
import buildCache from './buildCache';
import Config from 'lib/Config';

const buildClient = async (baseUrl) => {
    const graphQLConfig = Config.getSection('SilverStripe\\Admin\\LeftAndMain').graphql;
    const cachedTypenames = graphQLConfig && graphQLConfig.cachedTypenames;
    let fragmentData;
    try {
      fragmentData = await getGraphqlFragments(baseUrl, cachedTypenames);
    } catch (e) {
        fragmentData = null;
    }
    const cache = buildCache(fragmentData);
    const components = buildNetworkComponents(baseUrl);
    const stateLink = withClientState({
      cache,
      resolvers: {}
    });
    const link = from([stateLink, ...components]);
    return new ApolloClient({ cache, link });
};

export default buildClient;
<commit_msg>Add comment for graphql fragment<commit_after>/* global window */
import ApolloClient from 'apollo-client';
import { withClientState } from 'apollo-link-state';
import { from } from 'apollo-link';
import getGraphqlFragments from './getGraphqlFragments';
import buildNetworkComponents from './buildNetworkComponents';
import buildCache from './buildCache';
import Config from 'lib/Config';

const buildClient = async (baseUrl) => {
    const graphQLConfig = Config.getSection('SilverStripe\\Admin\\LeftAndMain').graphql;
    const cachedTypenames = graphQLConfig && graphQLConfig.cachedTypenames;
    let fragmentData;
    // GraphQL may not return what we want (e.g. if schema is empty, so fail gracefully)
    try {
      fragmentData = await getGraphqlFragments(baseUrl, cachedTypenames);
    } catch (e) {
        fragmentData = null;
    }
    const cache = buildCache(fragmentData);
    const components = buildNetworkComponents(baseUrl);
    const stateLink = withClientState({
      cache,
      resolvers: {}
    });
    const link = from([stateLink, ...components]);
    return new ApolloClient({ cache, link });
};

export default buildClient;
<|endoftext|>


<commit_before>(function(window, angular, undefined) {

  'use strict';

  var controllers = angular.module('clubadm.controllers', []);

  /**
   * Контроллер главной страницы. Перенаправляет пользователя на последний
   * доступный сезон.
   */
  controllers.controller('HomeController', [
    '$state', 'SeasonService',
    function($state, SeasonService) {
      SeasonService.getLatest().then(function(response) {
        $state.go('season.welcome', {
          year: response.data.year
        });
      });
    }]);

  /**
   * Промежуточный контроллер, который загружает информацию о сезоне.
   */
  controllers.controller('SeasonController', [
    '$scope', '$state', '$stateParams', 'SeasonService',
    function($scope, $state, $stateParams, SeasonService) {
      SeasonService.getByYear($stateParams.year).then(function(response) {
        $scope.season = response.data;
      }, function(response) {
        $state.go('home');
      });
    }]);

  /**
   * Контроллер страницы с предложением принять участие в акции.
   */
  controllers.controller('WelcomeController', [
    '$state', '$stateParams', 'UserService',
    function($state, $stateParams, UserService) {
      if (UserService.isUserLoggedIn()) {
        $state.go('season.profile', $stateParams);
      }
    }]);

  /**
   * Контроллер личной страницы участника.
   */
  controllers.controller('ProfileController', [
    '$scope', '$state', '$stateParams', 'UserService', 'SeasonService',
    function($scope, $state, $stateParams, UserService, SeasonService) {
      if (!UserService.isUserLoggedIn()) {
        $state.go('season.welcome', $stateParams);
      }

      SeasonService.getMemberByYear($stateParams.year).then(function(response) {
        $scope.member = response.data;
        $scope.form = angular.copy(response.data);

        // Начинаем грузить чат только если загрузился профиль.
        SeasonService.getMails($stateParams.year).then(function(response) {
          $scope.chat = response.data;
        });
      }, function(response) {
        $scope.form = {};
      });

      /**
       * Написать письмо.
       */
      $scope.sendMail = function(receptient) {
        var year = $scope.season.year;
        if (receptient == 'giftee') {
          var message = $scope.chat.giftee_message;
          $scope.chat.giftee_message = '';
        } else {
          var message = $scope.chat.santa_message;
          $scope.chat.santa_message = '';
        }
        SeasonService.sendMail(year, message, receptient).then(function(response) {
          $scope.chat = response.data;
        });
      };

      /**
       * Отправить подарок.
       */
      $scope.sendGift = function() {
        SeasonService.sendGift($scope.season.year).then(function(response) {
          $scope.member = response.data;
          $scope.season.sent++;
        });
      };

      /**
       * Получить подарок.
       */
      $scope.receiveGift = function() {
        SeasonService.receiveGift($scope.season.year).then(function(response) {
          $scope.member = response.data;
          $scope.season.received++;
        });
      };

      /**
       * Записаться в участники.
       */
      $scope.signUp = function() {
        console.log($scope.form);
        console.log($scope);
        SeasonService.signUp($scope.season.year, $scope.form).then(function(response) {
          $scope.member = response.data;
          $scope.season.members++;
        });
      };

      /**
       * Отказаться от участия.
       */
      $scope.signOut = function() {
        SeasonService.signOut($scope.season.year).then(function() {
          $scope.member = null;
          $scope.season.members--;
        });
      };
    }]);

})(window, window.angular);
<commit_msg>controllers.js: fix #2<commit_after>(function(window, angular, undefined) {

  'use strict';

  var controllers = angular.module('clubadm.controllers', []);

  /**
   * Контроллер главной страницы. Перенаправляет пользователя на последний
   * доступный сезон.
   */
  controllers.controller('HomeController', [
    '$state', 'SeasonService',
    function($state, SeasonService) {
      SeasonService.getLatest().then(function(response) {
        $state.go('season.welcome', {
          year: response.data.year
        });
      });
    }]);

  /**
   * Промежуточный контроллер, который загружает информацию о сезоне.
   */
  controllers.controller('SeasonController', [
    '$scope', '$state', '$stateParams', 'SeasonService',
    function($scope, $state, $stateParams, SeasonService) {
      SeasonService.getByYear($stateParams.year).then(function(response) {
        $scope.season = response.data;
      }, function(response) {
        $state.go('home');
      });
    }]);

  /**
   * Контроллер страницы с предложением принять участие в акции.
   */
  controllers.controller('WelcomeController', [
    '$state', '$stateParams', 'UserService',
    function($state, $stateParams, UserService) {
      if (UserService.isUserLoggedIn()) {
        $state.go('season.profile', $stateParams);
      }
    }]);

  /**
   * Контроллер личной страницы участника.
   */
  controllers.controller('ProfileController', [
    '$scope', '$state', '$stateParams', 'UserService', 'SeasonService',
    function($scope, $state, $stateParams, UserService, SeasonService) {
      if (!UserService.isUserLoggedIn()) {
        $state.go('season.welcome', $stateParams);
      }

      SeasonService.getMemberByYear($stateParams.year).then(function(response) {
        $scope.member = response.data;
        $scope.form = angular.copy(response.data);

        // Начинаем грузить чат только если загрузился профиль.
        SeasonService.getMails($stateParams.year).then(function(response) {
          $scope.chat = response.data;
        });
      }, function(response) {
        $scope.form = {};
      });

      /**
       * Написать письмо.
       */
      $scope.sendMail = function(receptient) {
        var year = $scope.season.year;
        if (receptient == 'giftee') {
          var message = $scope.chat.giftee_message;
          $scope.chat.giftee_message = '';
        } else {
          var message = $scope.chat.santa_message;
          $scope.chat.santa_message = '';
        }
        SeasonService.sendMail(year, message, receptient).then(function(response) {
          $scope.chat = response.data;
        });
      };

      /**
       * Отправить подарок.
       */
      $scope.sendGift = function() {
        SeasonService.sendGift($scope.season.year).then(function(response) {
          $scope.member = response.data;
          $scope.season.sent++;
        });
      };

      /**
       * Получить подарок.
       */
      $scope.receiveGift = function() {
        SeasonService.receiveGift($scope.season.year).then(function(response) {
          $scope.member = response.data;
          $scope.season.received++;
        });
      };

      /**
       * Записаться в участники.
       */
      $scope.signUp = function() {
        SeasonService.signUp($scope.season.year, $scope.form).then(function(response) {
          $scope.member = response.data;
          $scope.season.members++;
        }, function(response) {
          alert(response.data);
        });
      };

      /**
       * Отказаться от участия.
       */
      $scope.signOut = function() {
        SeasonService.signOut($scope.season.year).then(function() {
          $scope.member = null;
          $scope.season.members--;
        });
      };
    }]);

})(window, window.angular);
<|endoftext|>