<commit_before>/**
 * DraggableGroupElement is a mixin class used to create a group element to
 * contain draggable elements, which are items that can be clicked and dragged by a mouse.
 * The class is used with OO.ui.DraggableElement.
 *
 * @abstract
 * @class
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {jQuery} [$group] Container node, assigned to #$group, omit to use a generated `<div>`
 * @cfg {string} [orientation] Item orientation, 'horizontal' or 'vertical'. Defaults to 'vertical'
 */
OO.ui.DraggableGroupElement = function OoUiDraggableGroupElement( config ) {
	// Configuration initialization
	config = config || {};

	// Parent constructor
	OO.ui.GroupElement.call( this, config );

	// Properties
	this.orientation = config.orientation || 'vertical';
	this.dragItem = null;
	this.itemDragOver = null;
	this.itemKeys = {};
	this.sideInsertion = '';

	// Events
	this.aggregate( {
		dragstart: 'itemDragStart',
		dragend: 'itemDragEnd',
		drop: 'itemDrop'
	} );
	this.connect( this, {
		itemDragStart: 'onItemDragStart',
		itemDrop: 'onItemDrop',
		itemDragEnd: 'onItemDragEnd'
	} );
	this.$element.on( {
		dragover: $.proxy( this.onDragOver, this ),
		dragleave: $.proxy( this.onDragLeave, this )
	} );

	// Initialize
	if ( Array.isArray( config.items ) ) {
		this.addItems( config.items );
	}
	this.$placeholder = $( '<div>' )
		.addClass( 'oo-ui-draggableGroupElement-placeholder' );
	this.$element
		.addClass( 'oo-ui-draggableGroupElement' )
		.append( this.$status )
		.toggleClass( 'oo-ui-draggableGroupElement-horizontal', this.orientation === 'horizontal' )
		.prepend( this.$placeholder );
};

/* Setup */
OO.mixinClass( OO.ui.DraggableGroupElement, OO.ui.GroupElement );

/* Events */

/**
 * @event reorder
 * @param {OO.ui.DraggableElement} item Reordered item
 * @param {number} [newIndex] New index for the item
 */

/* Methods */

/**
 * Respond to item drag start event
 * @param {OO.ui.DraggableElement} item Dragged item
 */
OO.ui.DraggableGroupElement.prototype.onItemDragStart = function ( item ) {
	var i, len;

	// Map the index of each object
	for ( i = 0, len = this.items.length; i < len; i++ ) {
		this.items[ i ].setIndex( i );
	}

	if ( this.orientation === 'horizontal' ) {
		// Set the height of the indicator
		this.$placeholder.css( {
			height: item.$element.outerHeight(),
			width: 2
		} );
	} else {
		// Set the width of the indicator
		this.$placeholder.css( {
			height: 2,
			width: item.$element.outerWidth()
		} );
	}
	this.setDragItem( item );
};

/**
 * Respond to item drag end event
 */
OO.ui.DraggableGroupElement.prototype.onItemDragEnd = function () {
	this.unsetDragItem();
	return false;
};

/**
 * Handle drop event and switch the order of the items accordingly
 * @param {OO.ui.DraggableElement} item Dropped item
 * @fires reorder
 */
OO.ui.DraggableGroupElement.prototype.onItemDrop = function ( item ) {
	var toIndex = item.getIndex();
	// Check if the dropped item is from the current group
	// TODO: Figure out a way to configure a list of legally droppable
	// elements even if they are not yet in the list
	if ( this.getDragItem() ) {
		// If the insertion point is 'after', the insertion index
		// is shifted to the right (or to the left in RTL, hence 'after')
		if ( this.sideInsertion === 'after' ) {
			toIndex++;
		}
		// Emit change event
		this.emit( 'reorder', this.getDragItem(), toIndex );
	}
	this.unsetDragItem();
	// Return false to prevent propogation
	return false;
};

/**
 * Handle dragleave event.
 */
OO.ui.DraggableGroupElement.prototype.onDragLeave = function () {
	// This means the item was dragged outside the widget
	this.$placeholder
		.css( 'left', 0 )
		.addClass( 'oo-ui-element-hidden' );
};

/**
 * Respond to dragover event
 * @param {jQuery.Event} event Event details
 */
OO.ui.DraggableGroupElement.prototype.onDragOver = function ( e ) {
	var dragOverObj, $optionWidget, itemOffset, itemMidpoint, itemBoundingRect,
		itemSize, cssOutput, dragPosition, itemIndex, itemPosition,
		clientX = e.originalEvent.clientX,
		clientY = e.originalEvent.clientY;

	// Get the OptionWidget item we are dragging over
	dragOverObj = this.getElementDocument().elementFromPoint( clientX, clientY );
	$optionWidget = $( dragOverObj ).closest( '.oo-ui-draggableElement' );
	if ( $optionWidget[ 0 ] ) {
		itemOffset = $optionWidget.offset();
		itemBoundingRect = $optionWidget[ 0 ].getBoundingClientRect();
		itemPosition = $optionWidget.position();
		itemIndex = $optionWidget.data( 'index' );
	}

	if (
		itemOffset &&
		this.isDragging() &&
		itemIndex !== this.getDragItem().getIndex()
	) {
		if ( this.orientation === 'horizontal' ) {
			// Calculate where the mouse is relative to the item width
			itemSize = itemBoundingRect.width;
			itemMidpoint = itemBoundingRect.left + itemSize / 2;
			dragPosition = clientX;
			// Which side of the item we hover over will dictate
			// where the placeholder will appear, on the left or
			// on the right
			cssOutput = {
				left: dragPosition < itemMidpoint ? itemPosition.left : itemPosition.left + itemSize,
				top: itemPosition.top
			};
		} else {
			// Calculate where the mouse is relative to the item height
			itemSize = itemBoundingRect.height;
			itemMidpoint = itemBoundingRect.top + itemSize / 2;
			dragPosition = clientY;
			// Which side of the item we hover over will dictate
			// where the placeholder will appear, on the top or
			// on the bottom
			cssOutput = {
				top: dragPosition < itemMidpoint ? itemPosition.top : itemPosition.top + itemSize,
				left: itemPosition.left
			};
		}
		// Store whether we are before or after an item to rearrange
		// For horizontal layout, we need to account for RTL, as this is flipped
		if (  this.orientation === 'horizontal' && this.$element.css( 'direction' ) === 'rtl' ) {
			this.sideInsertion = dragPosition < itemMidpoint ? 'after' : 'before';
		} else {
			this.sideInsertion = dragPosition < itemMidpoint ? 'before' : 'after';
		}
		// Add drop indicator between objects
		this.$placeholder
			.css( cssOutput )
			.removeClass( 'oo-ui-element-hidden' );
	} else {
		// This means the item was dragged outside the widget
		this.$placeholder
			.css( 'left', 0 )
			.addClass( 'oo-ui-element-hidden' );
	}
	// Prevent default
	e.preventDefault();
};

/**
 * Set a dragged item
 * @param {OO.ui.DraggableElement} item Dragged item
 */
OO.ui.DraggableGroupElement.prototype.setDragItem = function ( item ) {
	this.dragItem = item;
};

/**
 * Unset the current dragged item
 */
OO.ui.DraggableGroupElement.prototype.unsetDragItem = function () {
	this.dragItem = null;
	this.itemDragOver = null;
	this.$placeholder.addClass( 'oo-ui-element-hidden' );
	this.sideInsertion = '';
};

/**
 * Get the current dragged item
 * @return {OO.ui.DraggableElement|null} item Dragged item or null if no item is dragged
 */
OO.ui.DraggableGroupElement.prototype.getDragItem = function () {
	return this.dragItem;
};

/**
 * Check if there's an item being dragged.
 * @return {Boolean} Item is being dragged
 */
OO.ui.DraggableGroupElement.prototype.isDragging = function () {
	return this.getDragItem() !== null;
};
<commit_msg>DraggableGroupElement: Clarify description and mark private methods<commit_after>/**
 * DraggableGroupElement is a mixin class used to create a group element to
 * contain draggable elements, which are items that can be clicked and dragged by a mouse.
 * The class is used with OO.ui.DraggableElement.
 *
 * @abstract
 * @class
 * @mixins OO.ui.GroupElement
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {string} [orientation] Item orientation: 'horizontal' or 'vertical'. The orientation
 *  should match the layout of the items. Items displayed in a single row
 *  or in several rows should use horizontal orientation. The vertical orientation should only be
 *  used when the items are displayed in a single column. Defaults to 'vertical'
 */
OO.ui.DraggableGroupElement = function OoUiDraggableGroupElement( config ) {
	// Configuration initialization
	config = config || {};

	// Parent constructor
	OO.ui.GroupElement.call( this, config );

	// Properties
	this.orientation = config.orientation || 'vertical';
	this.dragItem = null;
	this.itemDragOver = null;
	this.itemKeys = {};
	this.sideInsertion = '';

	// Events
	this.aggregate( {
		dragstart: 'itemDragStart',
		dragend: 'itemDragEnd',
		drop: 'itemDrop'
	} );
	this.connect( this, {
		itemDragStart: 'onItemDragStart',
		itemDrop: 'onItemDrop',
		itemDragEnd: 'onItemDragEnd'
	} );
	this.$element.on( {
		dragover: $.proxy( this.onDragOver, this ),
		dragleave: $.proxy( this.onDragLeave, this )
	} );

	// Initialize
	if ( Array.isArray( config.items ) ) {
		this.addItems( config.items );
	}
	this.$placeholder = $( '<div>' )
		.addClass( 'oo-ui-draggableGroupElement-placeholder' );
	this.$element
		.addClass( 'oo-ui-draggableGroupElement' )
		.append( this.$status )
		.toggleClass( 'oo-ui-draggableGroupElement-horizontal', this.orientation === 'horizontal' )
		.prepend( this.$placeholder );
};

/* Setup */
OO.mixinClass( OO.ui.DraggableGroupElement, OO.ui.GroupElement );

/* Events */

/**
 * A 'reorder' event is emitted when the order of items in the group changes.
 *
 * @event reorder
 * @param {OO.ui.DraggableElement} item Reordered item
 * @param {number} [newIndex] New index for the item
 */

/* Methods */

/**
 * Respond to item drag start event
 *
 * @private
 * @param {OO.ui.DraggableElement} item Dragged item
 */
OO.ui.DraggableGroupElement.prototype.onItemDragStart = function ( item ) {
	var i, len;

	// Map the index of each object
	for ( i = 0, len = this.items.length; i < len; i++ ) {
		this.items[ i ].setIndex( i );
	}

	if ( this.orientation === 'horizontal' ) {
		// Set the height of the indicator
		this.$placeholder.css( {
			height: item.$element.outerHeight(),
			width: 2
		} );
	} else {
		// Set the width of the indicator
		this.$placeholder.css( {
			height: 2,
			width: item.$element.outerWidth()
		} );
	}
	this.setDragItem( item );
};

/**
 * Respond to item drag end event
 *
 * @private
 */
OO.ui.DraggableGroupElement.prototype.onItemDragEnd = function () {
	this.unsetDragItem();
	return false;
};

/**
 * Handle drop event and switch the order of the items accordingly
 *
 * @private
 * @param {OO.ui.DraggableElement} item Dropped item
 * @fires reorder
 */
OO.ui.DraggableGroupElement.prototype.onItemDrop = function ( item ) {
	var toIndex = item.getIndex();
	// Check if the dropped item is from the current group
	// TODO: Figure out a way to configure a list of legally droppable
	// elements even if they are not yet in the list
	if ( this.getDragItem() ) {
		// If the insertion point is 'after', the insertion index
		// is shifted to the right (or to the left in RTL, hence 'after')
		if ( this.sideInsertion === 'after' ) {
			toIndex++;
		}
		// Emit change event
		this.emit( 'reorder', this.getDragItem(), toIndex );
	}
	this.unsetDragItem();
	// Return false to prevent propogation
	return false;
};

/**
 * Handle dragleave event.
 *
 * @private
 */
OO.ui.DraggableGroupElement.prototype.onDragLeave = function () {
	// This means the item was dragged outside the widget
	this.$placeholder
		.css( 'left', 0 )
		.addClass( 'oo-ui-element-hidden' );
};

/**
 * Respond to dragover event
 *
 * @private
 * @param {jQuery.Event} event Event details
 */
OO.ui.DraggableGroupElement.prototype.onDragOver = function ( e ) {
	var dragOverObj, $optionWidget, itemOffset, itemMidpoint, itemBoundingRect,
		itemSize, cssOutput, dragPosition, itemIndex, itemPosition,
		clientX = e.originalEvent.clientX,
		clientY = e.originalEvent.clientY;

	// Get the OptionWidget item we are dragging over
	dragOverObj = this.getElementDocument().elementFromPoint( clientX, clientY );
	$optionWidget = $( dragOverObj ).closest( '.oo-ui-draggableElement' );
	if ( $optionWidget[ 0 ] ) {
		itemOffset = $optionWidget.offset();
		itemBoundingRect = $optionWidget[ 0 ].getBoundingClientRect();
		itemPosition = $optionWidget.position();
		itemIndex = $optionWidget.data( 'index' );
	}

	if (
		itemOffset &&
		this.isDragging() &&
		itemIndex !== this.getDragItem().getIndex()
	) {
		if ( this.orientation === 'horizontal' ) {
			// Calculate where the mouse is relative to the item width
			itemSize = itemBoundingRect.width;
			itemMidpoint = itemBoundingRect.left + itemSize / 2;
			dragPosition = clientX;
			// Which side of the item we hover over will dictate
			// where the placeholder will appear, on the left or
			// on the right
			cssOutput = {
				left: dragPosition < itemMidpoint ? itemPosition.left : itemPosition.left + itemSize,
				top: itemPosition.top
			};
		} else {
			// Calculate where the mouse is relative to the item height
			itemSize = itemBoundingRect.height;
			itemMidpoint = itemBoundingRect.top + itemSize / 2;
			dragPosition = clientY;
			// Which side of the item we hover over will dictate
			// where the placeholder will appear, on the top or
			// on the bottom
			cssOutput = {
				top: dragPosition < itemMidpoint ? itemPosition.top : itemPosition.top + itemSize,
				left: itemPosition.left
			};
		}
		// Store whether we are before or after an item to rearrange
		// For horizontal layout, we need to account for RTL, as this is flipped
		if (  this.orientation === 'horizontal' && this.$element.css( 'direction' ) === 'rtl' ) {
			this.sideInsertion = dragPosition < itemMidpoint ? 'after' : 'before';
		} else {
			this.sideInsertion = dragPosition < itemMidpoint ? 'before' : 'after';
		}
		// Add drop indicator between objects
		this.$placeholder
			.css( cssOutput )
			.removeClass( 'oo-ui-element-hidden' );
	} else {
		// This means the item was dragged outside the widget
		this.$placeholder
			.css( 'left', 0 )
			.addClass( 'oo-ui-element-hidden' );
	}
	// Prevent default
	e.preventDefault();
};

/**
 * Set a dragged item
 *
 * @param {OO.ui.DraggableElement} item Dragged item
 */
OO.ui.DraggableGroupElement.prototype.setDragItem = function ( item ) {
	this.dragItem = item;
};

/**
 * Unset the current dragged item
 */
OO.ui.DraggableGroupElement.prototype.unsetDragItem = function () {
	this.dragItem = null;
	this.itemDragOver = null;
	this.$placeholder.addClass( 'oo-ui-element-hidden' );
	this.sideInsertion = '';
};

/**
 * Get the item that is currently being dragged.
 *
 * @return {OO.ui.DraggableElement|null} The currently dragged item, or `null` if no item is being dragged
 */
OO.ui.DraggableGroupElement.prototype.getDragItem = function () {
	return this.dragItem;
};

/**
 * Check if an item in the group is currently being dragged.
 *
 * @return {Boolean} Item is being dragged
 */
OO.ui.DraggableGroupElement.prototype.isDragging = function () {
	return this.getDragItem() !== null;
};
<|endoftext|>


<commit_before>"use strict";

var abi = require("augur-abi");
var clone = require("clone");
var RPCError = require("../errors/rpc-error");
var errors = require("../errors/codes");
var constants = require("../constants");

/**
 * Package a transaction payload so that it can be sent to the network.
 * @param {Object} payload Static API data.
 * @return {Object} Packaged transaction.
 */
var packageRequest = function (payload) {
  var tx, numParams, j, k, packaged, arrayLen;
  tx = clone(payload);
  if (tx.params === undefined || tx.params === null) {
    tx.params = [];
  } else if (tx.params.constructor !== Array) {
    tx.params = [tx.params];
  }
  numParams = tx.params.length;
  if (numParams) {
    if (tx.signature && tx.signature.length !== numParams) {
      throw new RPCError(errors.PARAMETER_NUMBER_ERROR);
    }
    for (j = 0; j < numParams; ++j) {
      if (tx.params[j] !== undefined && tx.params[j] !== null && tx.signature[j]) {
        if (tx.params[j].constructor === Number) {
          tx.params[j] = abi.prefix_hex(tx.params[j].toString(16));
        }
        if (tx.signature[j] === "int256") {
          tx.params[j] = abi.unfork(tx.params[j], true);
        } else if (tx.signature[j] === "int256[]" &&
          tx.params[j].constructor === Array && tx.params[j].length) {
          for (k = 0, arrayLen = tx.params[j].length; k < arrayLen; ++k) {
            tx.params[j][k] = abi.unfork(tx.params[j][k], true);
          }
        }
      }
    }
  }
  if (tx.to) tx.to = abi.format_address(tx.to);
  if (tx.from) tx.from = abi.format_address(tx.from);
  packaged = {
    from: tx.from,
    to: tx.to,
    data: abi.encode(tx),
    gas: tx.gas ? abi.hex(tx.gas) : constants.DEFAULT_GAS
  };
  if (tx.gasPrice) packaged.gasPrice = abi.hex(tx.gasPrice);
  if (tx.timeout) packaged.timeout = abi.hex(tx.timeout);
  if (tx.value) packaged.value = abi.hex(tx.value);
  if (tx.returns) packaged.returns = tx.returns;
  if (tx.nonce) packaged.nonce = tx.nonce;
  return packaged;
};

module.exports = packageRequest;
<commit_msg>Removed packaged.timeout from packageRequest<commit_after>"use strict";

var abi = require("augur-abi");
var clone = require("clone");
var RPCError = require("../errors/rpc-error");
var errors = require("../errors/codes");
var constants = require("../constants");

/**
 * Package a transaction payload so that it can be sent to the network.
 * @param {Object} payload Static API data.
 * @return {Object} Packaged transaction.
 */
var packageRequest = function (payload) {
  var tx, numParams, j, k, packaged, arrayLen;
  tx = clone(payload);
  if (tx.params === undefined || tx.params === null) {
    tx.params = [];
  } else if (tx.params.constructor !== Array) {
    tx.params = [tx.params];
  }
  numParams = tx.params.length;
  if (numParams) {
    if (tx.signature && tx.signature.length !== numParams) {
      throw new RPCError(errors.PARAMETER_NUMBER_ERROR);
    }
    for (j = 0; j < numParams; ++j) {
      if (tx.params[j] !== undefined && tx.params[j] !== null && tx.signature[j]) {
        if (tx.params[j].constructor === Number) {
          tx.params[j] = abi.prefix_hex(tx.params[j].toString(16));
        }
        if (tx.signature[j] === "int256") {
          tx.params[j] = abi.unfork(tx.params[j], true);
        } else if (tx.signature[j] === "int256[]" &&
          tx.params[j].constructor === Array && tx.params[j].length) {
          for (k = 0, arrayLen = tx.params[j].length; k < arrayLen; ++k) {
            tx.params[j][k] = abi.unfork(tx.params[j][k], true);
          }
        }
      }
    }
  }
  if (tx.to) tx.to = abi.format_address(tx.to);
  if (tx.from) tx.from = abi.format_address(tx.from);
  packaged = {
    from: tx.from,
    to: tx.to,
    data: abi.encode(tx),
    gas: tx.gas ? abi.hex(tx.gas) : constants.DEFAULT_GAS
  };
  if (tx.gasPrice) packaged.gasPrice = abi.hex(tx.gasPrice);
  if (tx.value) packaged.value = abi.hex(tx.value);
  if (tx.returns) packaged.returns = tx.returns;
  if (tx.nonce) packaged.nonce = tx.nonce;
  return packaged;
};

module.exports = packageRequest;
<|endoftext|>


<commit_before>/**
 * Developer: Stepan Burguchev
 * Date: 10/13/2014
 * Copyright: 2009-2016 Comindware®
 *       All Rights Reserved
 * Published under the MIT license
 */

"use strict";

import { Handlebars } from 'lib';
import template from './templates/booleanEditor.hbs';
import BaseItemEditorView from './base/BaseItemEditorView';
import formRepository from '../formRepository';

const defaultOptions = {
    displayText: ''
};

const classes = {
    CHECKED: 'editor_checked',
    UNDEFINED: 'editor_check_undefined'
};

/**
 * @name BooleanEditorView
 * @memberof module:core.form.editors
 * @class A simple Checkbox editor. Supported data type: Boolean.
 * @extends module:core.form.editors.base.BaseEditorView
 * @param {Object} options Options object. All the properties of {@link module:core.form.editors.base.BaseEditorView BaseEditorView} class are also supported.
 * @param {String} [options.displayText] Text to the right of the checkbox. Click on text triggers the checkbox.
 * @param {String} [options.displayHtml] HTML content to the right of the checkbox. Click on it triggers the checkbox.
 * @param {String} [options.title] Title attribute for the editor.
 * */
formRepository.editors.Boolean = BaseItemEditorView.extend(/** @lends module:core.form.editors.BooleanEditorView.prototype */{
    initialize: function (options) {
        if (options.schema) {
            _.extend(this.options, defaultOptions, _.pick(options.schema, _.keys(defaultOptions)));
        } else {
            _.extend(this.options, defaultOptions, _.pick(options || {}, _.keys(defaultOptions)));
        }
    },

    ui: {
        toggleButton: '.js-toggle-button',
        displayText: '.js-display-text'
    },

    focusElement: null,

    events: {
        'click @ui.toggleButton': '__toggle',
        'click @ui.displayText': '__toggle'
    },

    className: 'editor editor_checkbox',

    attributes() {
        return {
            title: this.options.title || null,
            tabindex: '0'
        }
    },

    template: Handlebars.compile(template),

    templateHelpers: function () {
        return {
            displayText: this.options.displayText,
            displayHtml: this.options.displayHtml
        };
    },

    __toggle: function () {
        if (!this.getEnabled() || this.getReadonly()) {
            return false;
        }
        this.setValue(!this.getValue());
        this.__triggerChange();
        return false;
    },

    onRender: function () {
        if (this.getValue()) {
            this.$el.addClass(classes.CHECKED);
        }
    },

    setValue: function (value) {
        this.value = value;
        if (this.value) {
            this.$el.addClass(classes.CHECKED);
            this.$el.removeClass(classes.UNDEFINED);
        } else if (this.value === false) {
            this.$el.removeClass(classes.UNDEFINED);
            this.$el.removeClass(classes.CHECKED);
        } else {
            this.$el.removeClass(classes.CHECKED);
            this.$el.addClass(classes.UNDEFINED);
        }
    },

    isEmptyValue: function () {
        return !_.isBoolean(this.getValue());
    }
}, {
    classes
});

export default formRepository.editors.Boolean;
<commit_msg>[Bolean editor] update state<commit_after>/**
 * Developer: Stepan Burguchev
 * Date: 10/13/2014
 * Copyright: 2009-2016 Comindware®
 *       All Rights Reserved
 * Published under the MIT license
 */

"use strict";

import { Handlebars } from 'lib';
import template from './templates/booleanEditor.hbs';
import BaseItemEditorView from './base/BaseItemEditorView';
import formRepository from '../formRepository';

const defaultOptions = {
    displayText: ''
};

const classes = {
    CHECKED: 'editor_checked',
    UNDEFINED: 'editor_check_undefined'
};

/**
 * @name BooleanEditorView
 * @memberof module:core.form.editors
 * @class A simple Checkbox editor. Supported data type: Boolean.
 * @extends module:core.form.editors.base.BaseEditorView
 * @param {Object} options Options object. All the properties of {@link module:core.form.editors.base.BaseEditorView BaseEditorView} class are also supported.
 * @param {String} [options.displayText] Text to the right of the checkbox. Click on text triggers the checkbox.
 * @param {String} [options.displayHtml] HTML content to the right of the checkbox. Click on it triggers the checkbox.
 * @param {String} [options.title] Title attribute for the editor.
 * */
formRepository.editors.Boolean = BaseItemEditorView.extend(/** @lends module:core.form.editors.BooleanEditorView.prototype */{
    initialize: function (options) {
        if (options.schema) {
            _.extend(this.options, defaultOptions, _.pick(options.schema, _.keys(defaultOptions)));
        } else {
            _.extend(this.options, defaultOptions, _.pick(options || {}, _.keys(defaultOptions)));
        }
    },

    ui: {
        toggleButton: '.js-toggle-button',
        displayText: '.js-display-text'
    },

    focusElement: null,

    events: {
        'click @ui.toggleButton': '__toggle',
        'click @ui.displayText': '__toggle'
    },

    className: 'editor editor_checkbox',

    attributes() {
        return {
            title: this.options.title || null,
            tabindex: '0'
        }
    },

    template: Handlebars.compile(template),

    templateHelpers: function () {
        return {
            displayText: this.options.displayText,
            displayHtml: this.options.displayHtml
        };
    },

    __toggle: function () {
        if (!this.getEnabled() || this.getReadonly()) {
            return false;
        }
        this.setValue(!this.getValue());
        this.__triggerChange();
        return false;
    },

    onRender: function () {
        this.__updateState();
    },

    setValue: function (value) {
        if (this.value === value) {
            return;
        }
        this.value = value;
        this.__updateState();
    },

    isEmptyValue: function () {
        return !_.isBoolean(this.getValue());
    },

    __updateState(value) {
        if (this.value) {
            this.$el.addClass(classes.CHECKED);
            this.$el.removeClass(classes.UNDEFINED);
        } else if (this.value === false) {
            this.$el.removeClass(classes.UNDEFINED);
            this.$el.removeClass(classes.CHECKED);
        } else {
            this.$el.removeClass(classes.CHECKED);
            this.$el.addClass(classes.UNDEFINED);
        }
    }
}, {
    classes
});

export default formRepository.editors.Boolean;
<|endoftext|>


<commit_before>pc.extend(pc, function () {
    /**
     * @name pc.Component
     * @description Base constructor for a Component
     * @class Components are used to attach functionality on a {@link pc.Entity}. Components
     * can receive update events each frame, and expose properties to the PlayCanvas Editor.
     * @param {pc.ComponentSystem} system The ComponentSystem used to create this Component
     * @param {pc.Entity} entity The Entity that this Component is attached to
     * @property {Boolean} enabled Enables or disables the component.
     */
    var Component = function (system, entity) {
        this.system = system;
        this.entity = entity;

        pc.events.attach(this);

        this.on("set", function (name, oldValue, newValue) {
            this.fire("set_" + name, name, oldValue, newValue);
        });

        this.on('set_enabled', this.onSetEnabled, this);
    };

    Component._buildAccessors = function (prototype, schema) {
        // Create getter/setter pairs for each property defined in the schema
        schema.forEach(function (prop) {
            Object.defineProperty(prototype, prop, {
                get: function () {
                    return this.data[prop];
                },
                set: function (value) {
                    var data = this.data;
                    var oldValue = data[prop];
                    data[prop] = value;
                    this.fire('set', prop, oldValue, value);
                },
                configurable: true
            });
        });
    };

    Component.prototype = {
        /**
         * @private
         * @readonly
         * @name pc.Component#data
         * @type pc.ComponentData
         * @description Access the {@link pc.ComponentData} directly. Usually you should
         * access the data properties via the individual properties as modifying this data
         * directly will not fire 'set' events.
         */
        get data() {
            var record = this.system.store[this.entity._guid];
            if (record) {
                return record.data;
            } else {
                return null;
            }
        },

        onSetEnabled: function (name, oldValue, newValue) {
            if (oldValue !== newValue) {
                if (this.entity.enabled) {
                    if (newValue) {
                        this.onEnable();
                    } else {
                        this.onDisable();
                    }
                }
            }
        },

        onEnable: function () { },

        onDisable: function () { },

        onPostStateChange: function() { }
    };

    return {
        Component: Component
    };
}());
<commit_msg>Keeping old buildAccessors logic as a fallback<commit_after>pc.extend(pc, function () {
    /**
     * @name pc.Component
     * @description Base constructor for a Component
     * @class Components are used to attach functionality on a {@link pc.Entity}. Components
     * can receive update events each frame, and expose properties to the PlayCanvas Editor.
     * @param {pc.ComponentSystem} system The ComponentSystem used to create this Component
     * @param {pc.Entity} entity The Entity that this Component is attached to
     * @property {Boolean} enabled Enables or disables the component.
     */
    var Component = function (system, entity) {
        this.system = system;
        this.entity = entity;

        pc.events.attach(this);

        if (this.system.schema && !this._accessorsBuilt) {
            this.buildAccessors(this.system.schema);
        }

        this.on("set", function (name, oldValue, newValue) {
            this.fire("set_" + name, name, oldValue, newValue);
        });

        this.on('set_enabled', this.onSetEnabled, this);
    };

    Component._buildAccessors = function (prototype, schema) {
        // Create getter/setter pairs for each property defined in the schema
        schema.forEach(function (prop) {
            Object.defineProperty(prototype, prop, {
                get: function () {
                    return this.data[prop];
                },
                set: function (value) {
                    var data = this.data;
                    var oldValue = data[prop];
                    data[prop] = value;
                    this.fire('set', prop, oldValue, value);
                },
                configurable: true
            });
        });

        prototype._accessorsBuilt = true;
    };

    Component.prototype = {
        /**
         * @private
         * @readonly
         * @name pc.Component#data
         * @type pc.ComponentData
         * @description Access the {@link pc.ComponentData} directly. Usually you should
         * access the data properties via the individual properties as modifying this data
         * directly will not fire 'set' events.
         */
        get data() {
            var record = this.system.store[this.entity._guid];
            if (record) {
                return record.data;
            } else {
                return null;
            }
        },

        buildAccessors: function (schema) {
            var self = this;

            // Create getter/setter pairs for each property defined in the schema
            schema.forEach(function (prop) {
                Object.defineProperty(self, prop, {
                    get: function () {
                        return self.data[prop];
                    },
                    set: function (value) {
                        var data = self.data;
                        var oldValue = data[prop];
                        data[prop] = value;
                        self.fire('set', prop, oldValue, value);
                    },
                    configurable: true
                });
            });
        },

        onSetEnabled: function (name, oldValue, newValue) {
            if (oldValue !== newValue) {
                if (this.entity.enabled) {
                    if (newValue) {
                        this.onEnable();
                    } else {
                        this.onDisable();
                    }
                }
            }
        },

        onEnable: function () { },

        onDisable: function () { },

        onPostStateChange: function() { }
    };

    return {
        Component: Component
    };
}());
<|endoftext|>


<commit_before>// Manages showing and hiding pop-ups
define(['ash', 'core/ExceptionHandler', 'game/GameGlobals', 'game/GlobalSignals'],
function (Ash, ExceptionHandler, GameGlobals, GlobalSignals) {
    var UIPopupManager = Ash.Class.extend({

        popupQueue: null,
        hiddenQueue: null,

        constructor: function () {
            this.popupQueue = [];
            this.hiddenQueue = [];

            GlobalSignals.add(this, GlobalSignals.windowResizedSignal, this.onWindowResized);
            GlobalSignals.add(this, GlobalSignals.popupResizedSignal, this.onPopupResized);
        },

        showPopup: function (title, msg, okButtonLabel, cancelButtonLabel, resultVO, okCallback, cancelCallback) {
            if (GameGlobals.gameState.uiStatus.isHidden) {
                this.hiddenQueue.push({title: title, msg: msg, okButtonLabel: okButtonLabel, cancelButtonLabel: cancelButtonLabel, resultVO: resultVO, okCallback: okCallback, cancelCallback: cancelCallback });
                return;
            }

            if (this.hasOpenPopup()) {
                this.popupQueue.push({title: title, msg: msg, okButtonLabel: okButtonLabel, cancelButtonLabel: cancelButtonLabel, resultVO: resultVO, okCallback: okCallback, cancelCallback: cancelCallback });
                return;
            }

            // use the same popup container for all popups
            var popUpManager = this;
            var popup = $("#common-popup");
            if ($(popup).parent().hasClass("popup-overlay")) $(popup).unwrap();

            // text
            GameGlobals.uiFunctions.toggle("#common-popup-input-container", false);
            $("#common-popup h3").text(title);
            $("#common-popup p#common-popup-desc").html(msg);

            // results and rewards
            var hasResult = resultVO && typeof resultVO !== 'undefined';
            GameGlobals.uiFunctions.toggle("#info-results", hasResult);
            $("#info-results").empty();
            if (hasResult) {
                var rewardDiv = GameGlobals.playerActionResultsHelper.getRewardDiv(resultVO, false);
                $("#info-results").append(rewardDiv);
                GameGlobals.uiFunctions.generateCallouts("#reward-div");
            }

            // buttons and callbacks
            var $defaultButton = null;
            $("#common-popup .buttonbox").empty();
            $("#common-popup .buttonbox").append("<button id='info-ok' class='action'>" + okButtonLabel + "</button>");
            $("#info-ok").attr("action", hasResult ? "accept_inventory" : null);
            $("#info-ok").toggleClass("inventory-selection-ok", hasResult);
            $("#info-ok").toggleClass("action", hasResult);
            $("#info-ok").click(ExceptionHandler.wrapClick(function (e) {
                popUpManager.closePopup("common-popup");
                if (okCallback) okCallback(false);
            }));
            $defaultButton = $("#info-ok");

            var showTakeAll = hasResult && resultVO.hasSelectable();
            if (showTakeAll) {
                $("#common-popup .buttonbox").append("<button id='confirmation-takeall' class='action' action='take_all'>Take all</button>");
                $("#confirmation-takeall").click(ExceptionHandler.wrapClick(function (e) {
                    popUpManager.closePopup("common-popup");
                    if (okCallback) okCallback(true);
                }));
                $defaultButton = $("#confirmation-takeall");
            }

            if (cancelButtonLabel) {
                $("#common-popup .buttonbox").append("<button id='confirmation-cancel'>" + cancelButtonLabel + "</button>");
                $("#confirmation-cancel").click(ExceptionHandler.wrapClick(function (e) {
                    popUpManager.closePopup("common-popup");
                    if (cancelCallback) cancelCallback();
                }));
            }

            // overlay
            $("#common-popup").wrap("

");
            GameGlobals.uiFunctions.toggle(".popup-overlay", true);
            popUpManager.repositionPopups();
            GlobalSignals.popupOpenedSignal.dispatch("common-popup");
            $("#common-popup").slideDown(150, popUpManager.repositionPopups);

            GameGlobals.uiFunctions.generateButtonOverlays("#common-popup .buttonbox");
            GameGlobals.uiFunctions.generateCallouts("#common-popup .buttonbox");

            if ($defaultButton) {
                $defaultButton.focus()
            }

            // pause the game while a popup is open
            GameGlobals.gameState.isPaused = this.hasOpenPopup();
        },

        closePopup: function (id) {
            var popupManager = this;
            if (popupManager.popupQueue.length === 0) {
                GlobalSignals.popupClosingSignal.dispatch(id);
                $("#" + id).data("fading", true);
                $("#" + id).slideUp(100, function () {
                    GameGlobals.uiFunctions.toggle(".popup-overlay", false);
                    $("#" + id).unwrap();
                    $("#" + id).data("fading", false);
                    $("#" + id + "p#common-popup-desc");
                    GlobalSignals.popupClosedSignal.dispatch(id);
                    popupManager.showQueuedPopup();
                    GameGlobals.gameState.isPaused = popupManager.hasOpenPopup();
                });
            } else {
                $("#" + id).data("fading", false);
                GameGlobals.uiFunctions.toggle("#" + id, false);
                GlobalSignals.popupClosedSignal.dispatch(id);
                popupManager.showQueuedPopup();
                GameGlobals.gameState.isPaused = popupManager.hasOpenPopup();
            }
        },

        repositionPopups: function () {
            var winh = $(window).height();
            var winw = $(window).width();
            var padding = 20;
            $.each($(".popup"), function () {
                var popuph = $(this).height();
                var popupw = $(this).width();
                $(this).css("top", Math.max(0, (winh - popuph) / 2 - padding));
                $(this).css("left", (winw - popupw) / 2);
            });
        },

        closeHidden: function (ok) {
            if (this.hiddenQueue.length > 0) {
                var hidden = this.hiddenQueue.pop();
                if (ok) {
                    if (hidden.okCallback) hidden.okCallback();
                } else {
                    if (hidden.cancelCallback) hidden.cancelCallback();
                }
            }
        },

        closeAllPopups: function () {
            this.popupQueue = [];
            var popupManager = this;
            $.each($(".popup:visible"), function () {
                popupManager.closePopup($(this).attr("id"));
            });
        },

        showQueuedPopup: function () {
            if (this.popupQueue.length > 0) {
                var queued = this.popupQueue.pop();
                this.showPopup(queued.title, queued.msg, queued.okButtonLabel, queued.cancelButtonLabel, queued.resultVO, queued.okCallback, queued.cancelCallback);
            }
        },

        hasOpenPopup: function () {
            return $(".popup:visible").length > 0;
        },

        onWindowResized: function () {
            this.repositionPopups();
        },

        onPopupResized: function () {
            this.repositionPopups();
        },

    });

    return UIPopupManager;
});
<commit_msg>[analytics] track popup views<commit_after>// Manages showing and hiding pop-ups
define(['ash', 'core/ExceptionHandler', 'game/GameGlobals', 'game/GlobalSignals'],
function (Ash, ExceptionHandler, GameGlobals, GlobalSignals) {
    var UIPopupManager = Ash.Class.extend({

        popupQueue: null,
        hiddenQueue: null,

        constructor: function () {
            this.popupQueue = [];
            this.hiddenQueue = [];

            GlobalSignals.add(this, GlobalSignals.windowResizedSignal, this.onWindowResized);
            GlobalSignals.add(this, GlobalSignals.popupResizedSignal, this.onPopupResized);
        },

        showPopup: function (title, msg, okButtonLabel, cancelButtonLabel, resultVO, okCallback, cancelCallback) {
            if (GameGlobals.gameState.uiStatus.isHidden) {
                this.hiddenQueue.push({title: title, msg: msg, okButtonLabel: okButtonLabel, cancelButtonLabel: cancelButtonLabel, resultVO: resultVO, okCallback: okCallback, cancelCallback: cancelCallback });
                return;
            }

            if (this.hasOpenPopup()) {
                this.popupQueue.push({title: title, msg: msg, okButtonLabel: okButtonLabel, cancelButtonLabel: cancelButtonLabel, resultVO: resultVO, okCallback: okCallback, cancelCallback: cancelCallback });
                return;
            }

            // use the same popup container for all popups
            var popUpManager = this;
            var popup = $("#common-popup");
            if ($(popup).parent().hasClass("popup-overlay")) $(popup).unwrap();

            // text
            GameGlobals.uiFunctions.toggle("#common-popup-input-container", false);
            $("#common-popup h3").text(title);
            $("#common-popup p#common-popup-desc").html(msg);

            // results and rewards
            var hasResult = resultVO && typeof resultVO !== 'undefined';
            GameGlobals.uiFunctions.toggle("#info-results", hasResult);
            $("#info-results").empty();
            if (hasResult) {
                var rewardDiv = GameGlobals.playerActionResultsHelper.getRewardDiv(resultVO, false);
                $("#info-results").append(rewardDiv);
                GameGlobals.uiFunctions.generateCallouts("#reward-div");
            }

            // buttons and callbacks
            var $defaultButton = null;
            $("#common-popup .buttonbox").empty();
            $("#common-popup .buttonbox").append("<button id='info-ok' class='action'>" + okButtonLabel + "</button>");
            $("#info-ok").attr("action", hasResult ? "accept_inventory" : null);
            $("#info-ok").toggleClass("inventory-selection-ok", hasResult);
            $("#info-ok").toggleClass("action", hasResult);
            $("#info-ok").click(ExceptionHandler.wrapClick(function (e) {
                popUpManager.closePopup("common-popup");
                if (okCallback) okCallback(false);
            }));
            $defaultButton = $("#info-ok");

            var showTakeAll = hasResult && resultVO.hasSelectable();
            if (showTakeAll) {
                $("#common-popup .buttonbox").append("<button id='confirmation-takeall' class='action' action='take_all'>Take all</button>");
                $("#confirmation-takeall").click(ExceptionHandler.wrapClick(function (e) {
                    popUpManager.closePopup("common-popup");
                    if (okCallback) okCallback(true);
                }));
                $defaultButton = $("#confirmation-takeall");
            }

            if (cancelButtonLabel) {
                $("#common-popup .buttonbox").append("<button id='confirmation-cancel'>" + cancelButtonLabel + "</button>");
                $("#confirmation-cancel").click(ExceptionHandler.wrapClick(function (e) {
                    popUpManager.closePopup("common-popup");
                    if (cancelCallback) cancelCallback();
                }));
            }

            // overlay
            $("#common-popup").wrap("

");
            GameGlobals.uiFunctions.toggle(".popup-overlay", true);
            popUpManager.repositionPopups();
            GlobalSignals.popupOpenedSignal.dispatch("common-popup");
            $("#common-popup").slideDown(150, popUpManager.repositionPopups);

            gtag('event', 'screen_view', {
                'screen_name': "popup-common"
            });

            GameGlobals.uiFunctions.generateButtonOverlays("#common-popup .buttonbox");
            GameGlobals.uiFunctions.generateCallouts("#common-popup .buttonbox");

            if ($defaultButton) {
                $defaultButton.focus()
            }

            // pause the game while a popup is open
            GameGlobals.gameState.isPaused = this.hasOpenPopup();
        },

        closePopup: function (id) {
            var popupManager = this;
            if (popupManager.popupQueue.length === 0) {
                GlobalSignals.popupClosingSignal.dispatch(id);
                $("#" + id).data("fading", true);
                $("#" + id).slideUp(100, function () {
                    GameGlobals.uiFunctions.toggle(".popup-overlay", false);
                    $("#" + id).unwrap();
                    $("#" + id).data("fading", false);
                    $("#" + id + "p#common-popup-desc");
                    GlobalSignals.popupClosedSignal.dispatch(id);
                    popupManager.showQueuedPopup();
                    GameGlobals.gameState.isPaused = popupManager.hasOpenPopup();
                });
            } else {
                $("#" + id).data("fading", false);
                GameGlobals.uiFunctions.toggle("#" + id, false);
                GlobalSignals.popupClosedSignal.dispatch(id);
                popupManager.showQueuedPopup();
                GameGlobals.gameState.isPaused = popupManager.hasOpenPopup();
            }
        },

        repositionPopups: function () {
            var winh = $(window).height();
            var winw = $(window).width();
            var padding = 20;
            $.each($(".popup"), function () {
                var popuph = $(this).height();
                var popupw = $(this).width();
                $(this).css("top", Math.max(0, (winh - popuph) / 2 - padding));
                $(this).css("left", (winw - popupw) / 2);
            });
        },

        closeHidden: function (ok) {
            if (this.hiddenQueue.length > 0) {
                var hidden = this.hiddenQueue.pop();
                if (ok) {
                    if (hidden.okCallback) hidden.okCallback();
                } else {
                    if (hidden.cancelCallback) hidden.cancelCallback();
                }
            }
        },

        closeAllPopups: function () {
            this.popupQueue = [];
            var popupManager = this;
            $.each($(".popup:visible"), function () {
                popupManager.closePopup($(this).attr("id"));
            });
        },

        showQueuedPopup: function () {
            if (this.popupQueue.length > 0) {
                var queued = this.popupQueue.pop();
                this.showPopup(queued.title, queued.msg, queued.okButtonLabel, queued.cancelButtonLabel, queued.resultVO, queued.okCallback, queued.cancelCallback);
            }
        },

        hasOpenPopup: function () {
            return $(".popup:visible").length > 0;
        },

        onWindowResized: function () {
            this.repositionPopups();
        },

        onPopupResized: function () {
            this.repositionPopups();
        },

    });

    return UIPopupManager;
});
<|endoftext|>


<commit_before>define([
	'goo/entities/systems/System',
	'goo/renderer/Material',
	'goo/renderer/shaders/ShaderLib',
	'goo/shapes/ShapeCreator',
	'goo/debug/components/MarkerComponent',
	'goo/renderer/Renderer'],
	/** @lends */
	function (
		System,
		Material,
		ShaderLib,
		ShapeCreator,
		MarkerComponent,
		Renderer
	) {
	"use strict";

	/**
	 * @class Processes all entities with a marker component
	 */
	function MarkerSystem(goo) {
		System.call(this, 'MarkerSystem', ['MarkerComponent']);

		this.material = Material.createMaterial(ShaderLib.simpleColored, '');
		this.material.depthState.enabled = false;
		this.material.shader.uniforms.color = [0.0, 1.0, 0.0];
		//this.material.wireframe = true;

		this.goo = goo;
		this.renderer = this.goo.renderer;

		this.entities = [];

		// drawing needs to be performed AFTER the render system completes its execution
		this.goo.callbacks.push(function() {
			for (var i = 0; i < this.entities.length; i++) {
				var entity = this.entities[i];
				if(entity.hasComponent('MarkerComponent')) {
					var transform = entity.transformComponent.worldTransform;

					var renderableMarker = {
						meshData: entity.markerComponent.meshData,
						materials: [this.material],
						transform: transform
					};

					this.goo.renderer.render(renderableMarker, Renderer.mainCamera, [], null, false);
				}
			}
		}.bind(this));
	}

	MarkerSystem.prototype = Object.create(System.prototype);

	MarkerSystem.prototype.process = function (entities) {
		this.entities = entities;
	};

	return MarkerSystem;
});<commit_msg>Fixed transform for marker meshes<commit_after>define([
	'goo/entities/systems/System',
	'goo/renderer/Material',
	'goo/renderer/shaders/ShaderLib',
	'goo/shapes/ShapeCreator',
	'goo/debug/components/MarkerComponent',
	'goo/renderer/Renderer',
	'goo/math/Transform'
],
	/** @lends */
	function (
		System,
		Material,
		ShaderLib,
		ShapeCreator,
		MarkerComponent,
		Renderer,
		Transform
	) {
	'use strict';

	/**
	 * @class Processes all entities with a marker component
	 */
	function MarkerSystem(goo) {
		System.call(this, 'MarkerSystem', ['MarkerComponent']);

		this.material = Material.createMaterial(ShaderLib.simpleColored, '');
		this.material.depthState.enabled = false;
		this.material.shader.uniforms.color = [0.0, 1.0, 0.0];

		this.goo = goo;
		this.renderer = this.goo.renderer;

		this.entities = [];

		// drawing needs to be performed AFTER the render system completes its execution
		this.goo.callbacks.push(function() {
			for (var i = 0; i < this.entities.length; i++) {
				var entity = this.entities[i];
				if(entity.hasComponent('MarkerComponent')) {
					var transform = new Transform();
					transform.copy(entity.transformComponent.worldTransform);
					transform.setRotationXYZ(0, 0, 0);
					transform.scale.setd(1, 1, 1);
					transform.update();

					var renderableMarker = {
						meshData: entity.markerComponent.meshData,
						materials: [this.material],
						transform: transform
					};

					this.goo.renderer.render(renderableMarker, Renderer.mainCamera, [], null, false);
				}
			}
		}.bind(this));
	}

	MarkerSystem.prototype = Object.create(System.prototype);

	MarkerSystem.prototype.process = function (entities) {
		this.entities = entities;
	};

	return MarkerSystem;
});<|endoftext|>


<commit_before>'use strict';

import BaseStore from 'fluxible/addons/BaseStore';
import api from '../services/api';

class ReleaseStore extends BaseStore {
    constructor (dispatcher) {
        super(dispatcher);
        this.release;
    }

    handleGetRelease (payload) {
        switch (payload) {
            case 'LATEST':
                this.fetchLatest();
                break;
            default:
                this.fetchCatNo(payload);
                break;
        }
    }

    fetchLatest() {
        let url = 'http://api.archaichorizon.com/releases/latest.json';
        this.latest ? this.setRelease(catNo) : api(this, url, 'latest');
    }

    fetchCatNo(catNo) {
        catNo = catNo.toUpperCase();
        let url = 'http://api.archaichorizon.com/releases/' + catNo + '.json';
        this[catNo] ? this.setRelease(catNo) : api(this, url, catNo);
    }

    setRelease (release) {
        console.warn('already fetched ' + release)
        this.release = this[release];
    }

    setState (release, key) {
        this[key] = release;
        this.release = release;
        this.emitChange();
    }

    getState () {
        return this.release;
    }

    getLatest () {
        return this.latest;
    }

    dehydrate () {
        return this.getState();
    }

    rehydrate (state) {
        this.release = getRelease.release();
    }

}

ReleaseStore.storeName = 'ReleaseStore';
ReleaseStore.handlers = {
    'GET_RELEASE': 'handleGetRelease'
};

export default ReleaseStore;
<commit_msg>fix undefined var<commit_after>'use strict';

import BaseStore from 'fluxible/addons/BaseStore';
import api from '../services/api';

class ReleaseStore extends BaseStore {
    constructor (dispatcher) {
        super(dispatcher);
        this.release;
    }

    handleGetRelease (payload) {
        switch (payload) {
            case 'LATEST':
                this.fetchLatest();
                break;
            default:
                this.fetchCatNo(payload);
                break;
        }
    }

    fetchLatest() {
        let url = 'http://api.archaichorizon.com/releases/latest.json';
        this.latest ? this.setRelease('latest') : api(this, url, 'latest');
    }

    fetchCatNo(catNo) {
        catNo = catNo.toUpperCase();
        let url = 'http://api.archaichorizon.com/releases/' + catNo + '.json';
        this[catNo] ? this.setRelease(catNo) : api(this, url, catNo);
    }

    setRelease (release) {
        console.warn('already fetched ' + release)
        this.release = this[release];
    }

    setState (release, key) {
        this[key] = release;
        this.release = release;
        this.emitChange();
    }

    getState () {
        return this.release;
    }

    getLatest () {
        return this.latest;
    }

    dehydrate () {
        return this.getState();
    }

    rehydrate (state) {
        this.release = getRelease.release();
    }

}

ReleaseStore.storeName = 'ReleaseStore';
ReleaseStore.handlers = {
    'GET_RELEASE': 'handleGetRelease'
};

export default ReleaseStore;
<|endoftext|>


<commit_before>define(function(require) {
	var MyModel = require("models/model")
		,MediaView = require("app/media/media_constructor")
		,pubsub = require("utils/pubsub")
		,_ = require("underscore")
		,is_touch = require("utils/is_touch")
		,settings = require("app/task/settings");

	var Model = MyModel.extend({
		initialize: function(){
			// set trial in the model
			if (this.collection.trial) {
				this.trial = this.collection.trial;
			}

			// set model handle
			this.attributes.data = this.attributes.data || {}; // make sure we have a data object
			this.attributes.data.handle = this.attributes.data.handle || this.attributes.handle; // set the handle in the data object
			this.handle =  this.attributes.data.handle; // set the handle in the stimulus object

			// pick the correct media according to if this is a touch device
			var mediaSource = is_touch && this.get('touchMedia') ? this.get('touchMedia') : this.get('media');

			// take the media source and build it into a full fledged view
			this.media = new MediaView(mediaSource,this);

		},

		// Default values for all of the attributes
		defaults: {
			size: {height: 'auto', width: 'auto'},
			css:{}
		},

		// activate stimulus listeners (maybe these shoud sit in one of the trial modules? call with apply)
		// ----------------------------------------------------------------------------------------------------------

		activate: function(){
			var self = this;
			var stimHandle = this.handle;
			this.timeStack = this.timeStack || [];
			this.pubsubStack = this.pubsubStack || [];

			// subscribe to start action
			// -------------------------
			pubsub.subscribe('stim:start', self.pubsubStack, function(handle){
				if (!_.include([stimHandle,'All'], handle)) {
					// make sure this publication is aimed at us
					return false;
				}

				// present the stimulus
				self.media.show();
			});

			// subscribe to set attribute action
			// ---------------------------------

			pubsub.subscribe('stim:setAttr', self.pubsubStack, function(handle,setter){
				if (!_.include([stimHandle,'All'], handle)) {
					// make sure this publication is aimed at us
					return false;
				}

				// if this is a function let it do whatever it wants with this model, otherwise simply call set.
				if (_.isFunction(setter)) {
					setter.apply(self);
				} else {
					var data = self.get('data') || {};
					data = _.extend(data, setter);
					self.set('data', data);
				}
			});

			// subscribe to stop stimulus action
			// ---------------------------------
			pubsub.subscribe('stim:stop', self.pubsubStack, function(handle){
				if (!_.include([stimHandle,'All'], handle)) {
					// make sure this publication is aimed at us
					return false;
				}

				// hide the stimulus
				self.media.hide();
			});
		},

		disable: function(){
			// hide the stimulus
			this.media.hide();

			// make sure the stacks exist
			this.timeStack = this.timeStack || [];
			this.pubsubStack = this.pubsubStack || [];

			_.each(this.pubsubStack, function(handle) {
				pubsub.unsubscribe(handle);
			});

			// empty stacks
			this.timeStack = [];
			this.pubsubStack = [];
		},

		name: function(){
			var attr = this.attributes;
			if (attr.data.alias) {return attr.data.alias;} // if we have an alias ues it
			if (attr.inherit && attr.inherit.set) {return attr.inherit.set;} // otherwise try using the set we inherited from
			if (attr.handle) {return attr.handle;} // otherwise use handle
			return false; // we're out of options here
		},

		mediaName: function(){
			var media = this.media.options;
			var fullpath = settings.logger && settings.logger.fullpath; // should we use the full path or just the file name
			if (media.alias) {return media.alias;} // if we have an alias ues it
			for (var prop in media) {
				if (prop != 'inherit') {
					if (_.contains(['image','template'],prop)) {
                        return fullpath ? media[prop] : media[prop].replace(/^.*[\\\/]/, '');
					}
				}
			}
		}

	});

	// Returns the Model class
	return Model;

});<commit_msg>fix(stimulus): stimulus.name returns Anonymous Stimulus instead of false<commit_after>define(function(require) {
	var MyModel = require("models/model")
		,MediaView = require("app/media/media_constructor")
		,pubsub = require("utils/pubsub")
		,_ = require("underscore")
		,is_touch = require("utils/is_touch")
		,settings = require("app/task/settings");

	var Model = MyModel.extend({
		initialize: function(){
			// set trial in the model
			if (this.collection.trial) {
				this.trial = this.collection.trial;
			}

			// set model handle
			this.attributes.data = this.attributes.data || {}; // make sure we have a data object
			this.attributes.data.handle = this.attributes.data.handle || this.attributes.handle; // set the handle in the data object
			this.handle =  this.attributes.data.handle; // set the handle in the stimulus object

			// pick the correct media according to if this is a touch device
			var mediaSource = is_touch && this.get('touchMedia') ? this.get('touchMedia') : this.get('media');

			// take the media source and build it into a full fledged view
			this.media = new MediaView(mediaSource,this);

		},

		// Default values for all of the attributes
		defaults: {
			size: {height: 'auto', width: 'auto'},
			css:{}
		},

		// activate stimulus listeners (maybe these shoud sit in one of the trial modules? call with apply)
		// ----------------------------------------------------------------------------------------------------------

		activate: function(){
			var self = this;
			var stimHandle = this.handle;
			this.timeStack = this.timeStack || [];
			this.pubsubStack = this.pubsubStack || [];

			// subscribe to start action
			// -------------------------
			pubsub.subscribe('stim:start', self.pubsubStack, function(handle){
				if (!_.include([stimHandle,'All'], handle)) {
					// make sure this publication is aimed at us
					return false;
				}

				// present the stimulus
				self.media.show();
			});

			// subscribe to set attribute action
			// ---------------------------------

			pubsub.subscribe('stim:setAttr', self.pubsubStack, function(handle,setter){
				if (!_.include([stimHandle,'All'], handle)) {
					// make sure this publication is aimed at us
					return false;
				}

				// if this is a function let it do whatever it wants with this model, otherwise simply call set.
				if (_.isFunction(setter)) {
					setter.apply(self);
				} else {
					var data = self.get('data') || {};
					data = _.extend(data, setter);
					self.set('data', data);
				}
			});

			// subscribe to stop stimulus action
			// ---------------------------------
			pubsub.subscribe('stim:stop', self.pubsubStack, function(handle){
				if (!_.include([stimHandle,'All'], handle)) {
					// make sure this publication is aimed at us
					return false;
				}

				// hide the stimulus
				self.media.hide();
			});
		},

		disable: function(){
			// hide the stimulus
			this.media.hide();

			// make sure the stacks exist
			this.timeStack = this.timeStack || [];
			this.pubsubStack = this.pubsubStack || [];

			_.each(this.pubsubStack, function(handle) {
				pubsub.unsubscribe(handle);
			});

			// empty stacks
			this.timeStack = [];
			this.pubsubStack = [];
		},

		name: function(){
			var attr = this.attributes;
			if (attr.data.alias) {return attr.data.alias;} // if we have an alias ues it
			if (attr.inherit && attr.inherit.set) {return attr.inherit.set;} // otherwise try using the set we inherited from
			if (attr.handle) {return attr.handle;} // otherwise use handle
			return 'Anonymous Stimulus'; // we're out of options here
		},

		mediaName: function(){
			var media = this.media.options;
			var fullpath = settings.logger && settings.logger.fullpath; // should we use the full path or just the file name
			if (media.alias) {return media.alias;} // if we have an alias ues it
			for (var prop in media) {
				if (prop != 'inherit') {
					if (_.contains(['image','template'],prop)) {
                        return fullpath ? media[prop] : media[prop].replace(/^.*[\\\/]/, '');
					}
				}
			}
		}

	});

	// Returns the Model class
	return Model;

});<|endoftext|>


<commit_before>import React from 'react'
import moment from 'moment-timezone'
import parseDuration from 'parse-duration'
import { DateRangePicker } from 'react-dates'
import BaseWidget from './Base'

//import 'react-dates/lib/css/_datepicker.css'
import '../../../css/datepicker.css'

class ControlsWidget extends BaseWidget {
	constructor () {
		super()
		this.state = {
			focusedInput: null,
			startDate: null,
			endDate: null,
		}
	}

	componentWillMount () {
		var shared = this.props.shared

		if ( ! shared.dateRange || ! shared.interval) {
			this.setDefaults()
		}
	}
	setDefaults () {
		var end = this.props.dateRange.end
		if (end === 'now') end = moment.utc().startOf('day')
		else end = moment.utc(end)

		var start = this.props.dateRange.start
		if (start.startsWith('-')) start = end.clone().subtract(parseDuration(start.substr(1)), 'milliseconds')
		else start = moment.utc(start)

		var interval = (this.props.interval.default || this.props.interval.options[0][0])

		this.setDateRange(start, end)
		this.setInterval(interval)
	}
	setDateRange (start, end) {
		if ( ! (start instanceof moment) || ! start.isValid()) {
			console.error('Invalid start date:', start)
			return
		}
		if ( ! (end instanceof moment) || ! end.isValid()) {
			console.error('Invalid end date:', end)
			return
		}
		this.props.onSetShared('dateRange', { start, end })
	}
	setInterval (interval) {
		this.props.onSetShared('interval', interval)
	}

	onFocusChange (focusedInput) {
		this.setState({ focusedInput })

		// On close
		if (focusedInput === null) {
			var { startDate, endDate } = this.state
			var dateRange = this.props.shared.dateRange

			// No change
			if ( ! startDate || ! endDate ) return

			var start = startDate.clone().startOf('day')
			var end = endDate.clone().startOf('day')

			// No change
			if (start.isSame(dateRange.start) && end.isSame(dateRange.end)) return

			this.setDateRange(start, end)
		}
	}
	onDateRangeChange ({ startDate, endDate }) {
		this.setState({ startDate, endDate })
	}
	onIntervalChange (ev) {
		this.setInterval(ev.target.value)
	}

	render () {
		var shared = this.props.shared
		var { focusedInput, startDate, endDate } = this.state
		var today = moment.utc().endOf('day')

		if ( ! startDate) startDate = shared.dateRange.start
		if ( ! endDate) endDate = shared.dateRange.end

		// Show previous month instead of next one (because we're working with historic data)
		var initialMonth = startDate.clone().startOf('month')
		if (initialMonth.isSame(endDate.clone().startOf('month'))) {
			initialMonth.subtract(1, 'month')
		}

		return (

						Date range

							<DateRangePicker
								focusedInput={focusedInput}
								startDate={startDate}
								endDate={endDate}
								displayFormat="DD-MM-YYYY"
								minimumNights={0}
								initialVisibleMonth={() => initialMonth}
								isOutsideRange={() => false}
								isDayBlocked={(date) => date.isAfter(today)}
								onFocusChange={this.onFocusChange.bind(this)}
								onDatesChange={this.onDateRangeChange.bind(this)} />

						Interval
						<select class="form-control" value={shared.interval} onChange={this.onIntervalChange.bind(this)}>
						{this.props.interval.options.map(([ value, label ]) => (
							<option key={value} value={value}>{label}</option>
						))}
						</select>

		)
	}
}

ControlsWidget.propTypes = Object.assign({}, BaseWidget.propTypes, {
	dateRange: React.PropTypes.shape({
		start: React.PropTypes.string.isRequired,
		end: React.PropTypes.string.isRequired,
	}),
	interval: React.PropTypes.shape({
		default: React.PropTypes.string,
		options: React.PropTypes.array.isRequired,
	}),
})

export default ControlsWidget
<commit_msg>Get/set date range and interval from/to URL in controls widget.<commit_after>import _ from 'underscore'
import React from 'react'
import moment from 'moment-timezone'
import parseDuration from 'parse-duration'
import { DateRangePicker } from 'react-dates'
import BaseWidget from './Base'

// Modified copy of 'react-dates/lib/css/_datepicker.css'
import '../../../css/datepicker.css'

class ControlsWidget extends BaseWidget {
	constructor () {
		super()
		this.state = {
			focusedInput: null,
			startDate: null,
			endDate: null,
		}
	}

	componentWillMount () {
		var shared = this.props.shared

		if ( ! shared.dateRange || ! shared.interval) {
			this.setDefaults()
		}
	}
	setDefaults () {
		var end = this.props.dateRange.end
		if (end === 'now') end = moment.utc().startOf('day')
		else end = moment.utc(end)

		var start = this.props.dateRange.start
		if (start.startsWith('-')) start = end.clone().subtract(parseDuration(start.substr(1)), 'milliseconds')
		else start = moment.utc(start)

		var interval = (this.props.interval.default || this.props.interval.options[0][0])

		if (this.props.fromURL) {
			var filter = this.getURLFilter()

			if (filter.startDate) start = filter.startDate
			if (filter.endDate) end = filter.endDate
			if (filter.interval) interval = filter.interval
		}

		this.setURLFilter(start, end, interval)
		this.setDateRange(start, end)
		this.setInterval(interval)
	}
	setDateRange (start, end) {
		if ( ! (start instanceof moment) || ! start.isValid()) {
			console.error('Invalid start date:', start)
			return
		}
		if ( ! (end instanceof moment) || ! end.isValid()) {
			console.error('Invalid end date:', end)
			return
		}
		this.props.onSetShared('dateRange', { start, end })
	}
	setInterval (interval) {
		this.props.onSetShared('interval', interval)
	}
	getURLFilter () {
		var { startDate, endDate, interval } = this.context.location.query

		if (startDate) {
			startDate = moment.utc(startDate, 'DD-MM-YYYY').startOf('day')
			startDate = (startDate.isValid() ? startDate.startOf('day') : undefined)
		}
		if (endDate) {
			endDate = moment.utc(endDate, 'DD-MM-YYYY').endOf('day')
			endDate = (endDate.isValid() ? endDate.endOf('day') : undefined)
		}
		if ((interval || '').match(/^[0-9]+$/)) {
			interval = parseInt(interval)
		}
		// Valid interval
		if (interval && ! _.find(this.props.interval.options, (option) => option[0] == interval)) {
			interval = undefined
		}

		return { startDate, endDate, interval }
	}
	setURLFilter (startDate, endDate, interval) {
		if ( ! this.props.fromURL) return // Disabled

		var location = this.context.location
		var query = Object.assign({}, location.query)
		query.startDate = startDate.format('DD-MM-YYYY')
		query.endDate = endDate.format('DD-MM-YYYY')
		query.interval = interval
		console.log(query)

		var route = Object.assign({}, location, {
			pathname: (location.pathname.startsWith('/') ? '' : '/') + location.pathname,
			query,
		})
		this.context.router.push(route)
	}

	onFocusChange (focusedInput) {
		this.setState({ focusedInput })

		// On close
		if (focusedInput === null) {
			// Wait for DateRangePicker.onDatesChange
			setTimeout(() => {
				var { startDate, endDate } = this.state
				var dateRange = this.props.shared.dateRange

				// No change
				if ( ! startDate || ! endDate ) return

				var start = startDate.clone().startOf('day')
				var end = endDate.clone().endOf('day')

				// No change
				if (start.isSame(dateRange.start) && end.isSame(dateRange.end)) return

				this.setURLFilter(start, end, this.props.shared.interval)
				this.setDateRange(start, end)
			}, 100)
		}
	}
	onDateRangeChange ({ startDate, endDate }) {
		this.setState({ startDate, endDate })
	}
	onIntervalChange (ev) {
		var interval = ev.target.value
		var shared = this.props.shared

		this.setURLFilter(shared.dateRange.start, shared.dateRange.end, interval)
		this.setInterval(interval)
	}

	render () {
		var shared = this.props.shared
		var { focusedInput, startDate, endDate } = this.state
		var today = moment.utc().endOf('day')

		if ( ! startDate) startDate = shared.dateRange.start
		if ( ! endDate) endDate = shared.dateRange.end

		// Show previous month instead of next one (because we're working with historic data)
		var initialMonth = startDate.clone().startOf('month')
		if (initialMonth.isSame(endDate.clone().startOf('month'))) {
			initialMonth.subtract(1, 'month')
		}

		return (

						Date range

							<DateRangePicker
								focusedInput={focusedInput}
								startDate={startDate}
								endDate={endDate}
								displayFormat="DD-MM-YYYY"
								minimumNights={0}
								initialVisibleMonth={() => initialMonth}
								isOutsideRange={() => false}
								isDayBlocked={(date) => date.isAfter(today)}
								onFocusChange={this.onFocusChange.bind(this)}
								onDatesChange={this.onDateRangeChange.bind(this)} />

						Interval
						<select class="form-control" value={shared.interval} onChange={this.onIntervalChange.bind(this)}>
						{this.props.interval.options.map(([ value, label ]) => (
							<option key={value} value={value}>{label}</option>
						))}
						</select>

		)
	}
}

ControlsWidget.propTypes = Object.assign({}, BaseWidget.propTypes, {
	fromURL: React.PropTypes.bool,
	dateRange: React.PropTypes.shape({
		start: React.PropTypes.string.isRequired,
		end: React.PropTypes.string.isRequired,
	}),
	interval: React.PropTypes.shape({
		default: React.PropTypes.string,
		options: React.PropTypes.array.isRequired,
	}),
})
ControlsWidget.contextTypes = {
	location: React.PropTypes.object,
	router: React.PropTypes.object,
}

export default ControlsWidget
<|endoftext|>


<commit_before>'use strict'

angular.module('github-directives')
    .directive('ghRepositoryCommits', function () {
        return {
            restrict: 'E',
            scope: {
                'user': '@',
                'repo': '@'
            },
            template:
                '
' +
                    '
Commits: {{ user }} - {{ repo }}
' +
                    '
' +
                        '
' +
                            '
' +
                                '{{ commit.commit.message }}' +
                                'By: {{ commit.commit.author.name }}' +
                            '
' +
                        '
' +
                    '
' +
                '
',
            controller: ['$scope', '$http', 'apiUrl', function($scope, $http, apiUrl) {
                $scope.commits = [];

                $scope.$watch('repo', function () {
                    if ($scope.user == undefined || $scope.repo == undefined) {
                        return;
                    }
                    $http({method: 'GET', url: apiUrl + '/repos/' + $scope.user + '/' + $scope.repo + '/commits'})
                        .success(function (data) {
                            $scope.commits = data;
                        });
                });
            }]
        };
    });

<commit_msg>Padding<commit_after>'use strict'

angular.module('github-directives')
    .directive('ghRepositoryCommits', function () {
        return {
            restrict: 'E',
            scope: {
                'user': '@',
                'repo': '@'
            },
            template:
                '
' +
                    '
Commits: {{ user }} - {{ repo }}
' +
                    '
' +
                        '
' +
                            '
' +
                                '{{ commit.commit.message }}' +
                                'By: {{ commit.commit.author.name }}' +
                            '
' +
                        '
' +
                    '
' +
                '
',
            controller: ['$scope', '$http', 'apiUrl', function($scope, $http, apiUrl) {
                $scope.commits = [];

                $scope.$watch('repo', function () {
                    if ($scope.user == undefined || $scope.repo == undefined) {
                        return;
                    }
                    $http({method: 'GET', url: apiUrl + '/repos/' + $scope.user + '/' + $scope.repo + '/commits'})
                        .success(function (data) {
                            $scope.commits = data;
                        });
                });
            }]
        };
    });

<|endoftext|>


<commit_before>import Request from './sessionSuperagent.js';
import Q from 'q';
import Cookies from 'js-cookie';

import StoreSingleton from '../redux/storeSingleton.js';

import { kGlobalConstants } from '../GlobalConstants.js';

export const fetchSubmissionMetadata = (submissionId) => {

    const deferred = Q.defer();

    Request.post(kGlobalConstants.API + 'check_status/')
            .send({'submission_id': submissionId})
            .end((errFile, res) => {
                if (errFile) {
                    deferred.reject(res);
                }
                else {
                    deferred.resolve(res.body);
                }

            });

    return deferred.promise;
}

export const generateFile = (type, submissionId, start, end) => {

    const deferred = Q.defer();

    // Request.post(kGlobalConstants.API + 'generate_file/')
    Request.post('http://localhost:5000/' + 'generate_file/')
            .send({
                'submission_id': submissionId,
                'file_type': type,
                'start': start,
                'end': end
            })
            .end((errFile, res) => {

                if (errFile) {
                    deferred.reject(res.body);
                }
                else {
                    deferred.resolve(res.body);
                }

            });

    return deferred.promise;

}

export const fetchFile = (type, submissionId) => {
    const deferred = Q.defer();

    // Request.post(kGlobalConstants.API + 'check_generation_status/')
    Request.post('http://localhost:5000/' + 'check_generation_status/')
            .send({
                'submission_id': submissionId,
                'file_type': type
            })
            .end((errFile, res) => {

                if (errFile) {
                    deferred.reject(res.body);
                }
                else {
                    deferred.resolve(res.body);
                }

            });

    return deferred.promise;
}<commit_msg>Use real API endpoints<commit_after>import Request from './sessionSuperagent.js';
import Q from 'q';
import Cookies from 'js-cookie';

import StoreSingleton from '../redux/storeSingleton.js';

import { kGlobalConstants } from '../GlobalConstants.js';

export const fetchSubmissionMetadata = (submissionId) => {

    const deferred = Q.defer();

    Request.post(kGlobalConstants.API + 'check_status/')
            .send({'submission_id': submissionId})
            .end((errFile, res) => {
                if (errFile) {
                    deferred.reject(res);
                }
                else {
                    deferred.resolve(res.body);
                }

            });

    return deferred.promise;
}

export const generateFile = (type, submissionId, start, end) => {

    const deferred = Q.defer();

    Request.post(kGlobalConstants.API + 'generate_file/')
            .send({
                'submission_id': submissionId,
                'file_type': type,
                'start': start,
                'end': end
            })
            .end((errFile, res) => {

                if (errFile) {
                    deferred.reject(res.body);
                }
                else {
                    deferred.resolve(res.body);
                }

            });

    return deferred.promise;

}

export const fetchFile = (type, submissionId) => {
    const deferred = Q.defer();

    Request.post(kGlobalConstants.API + 'check_generation_status/')
            .send({
                'submission_id': submissionId,
                'file_type': type
            })
            .end((errFile, res) => {

                if (errFile) {
                    deferred.reject(res.body);
                }
                else {
                    deferred.resolve(res.body);
                }

            });

    return deferred.promise;
}<|endoftext|>


<commit_before>define([
	"dojo/_base/declare", // declare
	"rishson/Base", //createTopicNamespace, _capitaliseTopicName
	"rishson/Globals", //TOPIC_NAMESPACE
	"dojo/_base/array", // forEach
	"dojo/_base/lang", // hitch
	"rishson/base/lang",
	"dojo/topic" // publish, subscribe
], function (declare, Base, Globals, arrayUtil, lang, rishsonLang, topic) {
	/**
	 * @class
	 * @name rishson.control._Controller
	 * @description This is the base class for Controller classes/widgets

	 * Controllers are classes that wire together the view (widgets) and the model.

	 * Application widgets are basically 'Controllers' in an MVC paradigm. Application widgets typically provide layout

	 * container functionality to child widgets and act as the controller for the enclosed child widgets.

	 * An Application widget knows about all views (child widgets) and models (stores) for the 'Application'.

	 * This class specifically adds the autowiring of topics between child widgets and the Application widget.

	 *

	 * Usage:

	 *

	 * myChildWidget.pubList({SOME_EVENT :'some/topic'});

	 * ...

	 * myApplicationWidget.injectWidget(myChildWidget);

	 * or
	 * myController.adopt(myChildWidget, {}, someDomNode);

	 *

	 * At this point, all the topic in mychildWidget.pubList are wired to event handlers in myApplicationWidget.
	 */
	return declare("rishson.control._Controller", [Base], {
		/**
		 * @field
		 * @name rishson._Controller._topicNamespace
		 * @type {string}
		 * @description This topic name space
		 */
		_topicNamespace: '',

		/**
		 * @constructor
		 */
		constructor: function () {
			// Create this controllers personalised topic namespace.
			this._topicNamespace = this.createTopicNamespace(this.declaredClass);
			this._id = this.declaredClass;

			this.subList = this.subList || {};

			// An array of topic name / subscription handle pairs
			// Needed for when the controller wants to unsubscribe from topics
			this.subListHandles = this.subListHandles || {};
		},

		/**
		 * @function
		 * @name rishson.control._Controller._autowirePubs
		 * @private
		 * @param {rishson.widget._Widget} child a widget that contains a pubList of topics that it can publish.
		 * @description autowire the published topics from the child widget to event handlers on the controller widget.
		 */
		_autowirePubs: function (child) {
			var topicObj;

			//iterate over each published topic of the passed in child - the application child need to subscribe to these
			for (topicObj in child.pubList) {
				if (child.pubList.hasOwnProperty(topicObj)) {
					this._wireSinglePub(child.pubList[topicObj]);
				}
			}
		},

		/**
		 * @function
		 * @name rishson.control._Controller._unAutoWireControllerPubs
		 * @description Un-subscribes this controller from subscriptions to the supplied widget
		 * @param {Object} The widget containing a list of published items
		 */
		_unAutoWirePubs: function (widget) {
			var pubList = widget.pubList || (widget.content || {}).pubList, // We want the actual widget if this widget is a ContentPane
				topicNamespace = this._topicNamespace;

			// Loop through the child widgets pubList
			rishsonLang.forEachObjProperty(pubList, function (pubHandleName) {
				// If the current controllers namespace appears within this widgets pubList item
				if (pubHandleName.indexOf(topicNamespace) !== -1) {
					var handle = this.subListHandles[pubHandleName];

					// If a handle was found then remove the subscription
					if (handle) {
						console.log("Unautowiring: " + pubHandleName);
						this.unsubscribe(handle);
						delete this.subListHandles[pubHandleName];
					}
				}
			}, this);
		},

		/**
		 * @function
		 * @name rishson.control._Controller._createHandlerFuncName
		 * @private
		 * @param {string} str the topicNamespace and topic string value
		 * @description returns a capitalised and slashes removed string.
		 * @return {string}
		 */
		_createHandlerFuncName: function (str) {
			var ret;
			if (str) {
				//capitalise the topic section names and remove slashes
				ret = this.capitaliseTopicName(str);
				ret = '_handle' + ret.replace(/[//]/g, '');
				if (ret) {
					return ret;
				}
			}
			return '';
		},

		/**
		 * @function
		 * @name rishson.control._Controller._wireSinglePub
		 * @private
		 * @param {string} topicName the string of the topic name
		 * @description autowire a single published topic from the child widget to an event handler on the controller widget.
		 */
		_wireSinglePub: function (topicName, initialWire) {
			var handlerFuncName, handlerFunc;

			// If event to wire is child initialised skip wiring as this was already wired in constructor.
			if (!initialWire && topicName.indexOf(Globals.CHILD_INTIALISED_TOPIC_NAME) !== -1) {
				return;
			}

			handlerFuncName = this._createHandlerFuncName(topicName);

			//the implementing class needs to have _handle[topicName] functions by convention
			handlerFunc = this[handlerFuncName];

			if (handlerFuncName && handlerFunc) {
				// Subscribe to topic and keep a reference to the handle for unsubscribing
				this.subListHandles[topicName] = this.subscribe(topicName, lang.hitch(this, handlerFunc));
			} else {
				console.error('Autowire failure for topic: ' + topicName + '. No handler: ' + handlerFuncName);
			}
		},

		/**
		 * @function
		 * @name rishson.control._Controller.injectWidget
		 * @param {rishson.widget._Widget} widget a widget to examine for topics
		 * @description widgets injected into this class will be examined to autowire its publish and subscribes.

		 * This function should be called for declarativly created widgets.
		 */
		injectWidget: function (widget) {
			this._autowirePubs(widget);
		},

		/**
		 * @function
		 * @name rishson.control._Controller.adopt
		 * @description widgets injected into this class will be examined to autowire its publish and subscribes.

		 * This function should be called for programatically created widgets.
		 * @param {Object} Cls
		 * @param {Object=} props
		 * @param node
		 */
		adopt: function (Cls, props, node) {
			var child;
			props = props || {};
			// Pass in parents topic name space to all child views and controllers.
			props.parentTopicNamespace = this._topicNamespace;

			child = new Cls(props, node);

			if (!this._supportingWidgets) {
				this._supportingWidgets = [];	//awkward but this is a mixin class
			}
			this._supportingWidgets.push(child);

			this._autowirePubs(child);
			return child;
		}
	});
});<commit_msg>Remove console.log used for testing<commit_after>define([
	"dojo/_base/declare", // declare
	"rishson/Base", //createTopicNamespace, _capitaliseTopicName
	"rishson/Globals", //TOPIC_NAMESPACE
	"dojo/_base/array", // forEach
	"dojo/_base/lang", // hitch
	"rishson/base/lang",
	"dojo/topic" // publish, subscribe
], function (declare, Base, Globals, arrayUtil, lang, rishsonLang, topic) {
	/**
	 * @class
	 * @name rishson.control._Controller
	 * @description This is the base class for Controller classes/widgets

	 * Controllers are classes that wire together the view (widgets) and the model.

	 * Application widgets are basically 'Controllers' in an MVC paradigm. Application widgets typically provide layout

	 * container functionality to child widgets and act as the controller for the enclosed child widgets.

	 * An Application widget knows about all views (child widgets) and models (stores) for the 'Application'.

	 * This class specifically adds the autowiring of topics between child widgets and the Application widget.

	 *

	 * Usage:

	 *

	 * myChildWidget.pubList({SOME_EVENT :'some/topic'});

	 * ...

	 * myApplicationWidget.injectWidget(myChildWidget);

	 * or
	 * myController.adopt(myChildWidget, {}, someDomNode);

	 *

	 * At this point, all the topic in mychildWidget.pubList are wired to event handlers in myApplicationWidget.
	 */
	return declare("rishson.control._Controller", [Base], {
		/**
		 * @field
		 * @name rishson._Controller._topicNamespace
		 * @type {string}
		 * @description This topic name space
		 */
		_topicNamespace: '',

		/**
		 * @constructor
		 */
		constructor: function () {
			// Create this controllers personalised topic namespace.
			this._topicNamespace = this.createTopicNamespace(this.declaredClass);
			this._id = this.declaredClass;

			this.subList = this.subList || {};

			// An array of topic name / subscription handle pairs
			// Needed for when the controller wants to unsubscribe from topics
			this.subListHandles = this.subListHandles || {};
		},

		/**
		 * @function
		 * @name rishson.control._Controller._autowirePubs
		 * @private
		 * @param {rishson.widget._Widget} child a widget that contains a pubList of topics that it can publish.
		 * @description autowire the published topics from the child widget to event handlers on the controller widget.
		 */
		_autowirePubs: function (child) {
			var topicObj;

			//iterate over each published topic of the passed in child - the application child need to subscribe to these
			for (topicObj in child.pubList) {
				if (child.pubList.hasOwnProperty(topicObj)) {
					this._wireSinglePub(child.pubList[topicObj]);
				}
			}
		},

		/**
		 * @function
		 * @name rishson.control._Controller._unAutoWireControllerPubs
		 * @description Un-subscribes this controller from subscriptions to the supplied widget
		 * @param {Object} The widget containing a list of published items
		 */
		_unAutoWirePubs: function (widget) {
			var pubList = widget.pubList || (widget.content || {}).pubList, // We want the actual widget if this widget is a ContentPane
				topicNamespace = this._topicNamespace;

			// Loop through the child widgets pubList
			rishsonLang.forEachObjProperty(pubList, function (pubHandleName) {
				// If the current controllers namespace appears within this widgets pubList item
				if (pubHandleName.indexOf(topicNamespace) !== -1) {
					var handle = this.subListHandles[pubHandleName];

					// If a handle was found then remove the subscription
					if (handle) {
						this.unsubscribe(handle);
						delete this.subListHandles[pubHandleName];
					}
				}
			}, this);
		},

		/**
		 * @function
		 * @name rishson.control._Controller._createHandlerFuncName
		 * @private
		 * @param {string} str the topicNamespace and topic string value
		 * @description returns a capitalised and slashes removed string.
		 * @return {string}
		 */
		_createHandlerFuncName: function (str) {
			var ret;
			if (str) {
				//capitalise the topic section names and remove slashes
				ret = this.capitaliseTopicName(str);
				ret = '_handle' + ret.replace(/[//]/g, '');
				if (ret) {
					return ret;
				}
			}
			return '';
		},

		/**
		 * @function
		 * @name rishson.control._Controller._wireSinglePub
		 * @private
		 * @param {string} topicName the string of the topic name
		 * @description autowire a single published topic from the child widget to an event handler on the controller widget.
		 */
		_wireSinglePub: function (topicName, initialWire) {
			var handlerFuncName, handlerFunc;

			// If event to wire is child initialised skip wiring as this was already wired in constructor.
			if (!initialWire && topicName.indexOf(Globals.CHILD_INTIALISED_TOPIC_NAME) !== -1) {
				return;
			}

			handlerFuncName = this._createHandlerFuncName(topicName);

			//the implementing class needs to have _handle[topicName] functions by convention
			handlerFunc = this[handlerFuncName];

			if (handlerFuncName && handlerFunc) {
				// Subscribe to topic and keep a reference to the handle for unsubscribing
				this.subListHandles[topicName] = this.subscribe(topicName, lang.hitch(this, handlerFunc));
			} else {
				console.error('Autowire failure for topic: ' + topicName + '. No handler: ' + handlerFuncName);
			}
		},

		/**
		 * @function
		 * @name rishson.control._Controller.injectWidget
		 * @param {rishson.widget._Widget} widget a widget to examine for topics
		 * @description widgets injected into this class will be examined to autowire its publish and subscribes.

		 * This function should be called for declarativly created widgets.
		 */
		injectWidget: function (widget) {
			this._autowirePubs(widget);
		},

		/**
		 * @function
		 * @name rishson.control._Controller.adopt
		 * @description widgets injected into this class will be examined to autowire its publish and subscribes.

		 * This function should be called for programatically created widgets.
		 * @param {Object} Cls
		 * @param {Object=} props
		 * @param node
		 */
		adopt: function (Cls, props, node) {
			var child;
			props = props || {};
			// Pass in parents topic name space to all child views and controllers.
			props.parentTopicNamespace = this._topicNamespace;

			child = new Cls(props, node);

			if (!this._supportingWidgets) {
				this._supportingWidgets = [];	//awkward but this is a mixin class
			}
			this._supportingWidgets.push(child);

			this._autowirePubs(child);
			return child;
		}
	});
});<|endoftext|>


<commit_before>/* eslint-disable no-unused-vars */
import React from 'react';
/* eslint-enable no-unused-vars */

import JobValidatorUtil from '../../utils/JobValidatorUtil';
import MetadataStore from '../../stores/MetadataStore';
import ValidatorUtil from '../../utils/ValidatorUtil';

const Schedule = {
  title: 'Schedule',
  description: 'Set time and date for the job to run',
  type: 'object',
  properties: {
    runOnSchedule: {
      label: 'Run on a schedule',
      showLabel: true,
      title: 'Run on a schedule',
      type: 'boolean',
      getter(job) {
        const [schedule] = job.getSchedules();

        return schedule != null;
      }
    },
    cron: {
      title: 'CRON Schedule',
      helpBlock: (

          Use cron format to set your schedule, e.g. 0 0 20 * * *. View documentation.

      ),
      type: 'string',
      getter(job) {
        const [schedule = {}] = job.getSchedules();

        return schedule.cron;
      },
      externalValidator({schedule}, definition) {
        if (!schedule.runOnSchedule) {
          return true;
        }

        if (!JobValidatorUtil.isValidCronSchedule(schedule.cron)) {
          definition.showError = 'CRON Schedule must not be empty and it must '+
          'follow the correct CRON format specifications';
          return false;
        }

        return true;
      }
    },
    timezone: {
      title: 'Time Zone',
      description: (

          Enter time zone in TZ format, e.g. America/New_York.

      ),
      type: 'string',
      getter(job) {
        const [schedule = {}] = job.getSchedules();

        return schedule.timezone;
      }
    },
    startingDeadlineSeconds: {
      title: 'Starting Deadline',
      description: 'Time in seconds to start the job if it misses ' +
      'scheduled time for any reason. Missed jobs executions will be ' +
      'counted as failed ones.',
      type: 'number',
      getter(job) {
        const [schedule = {}] = job.getSchedules();

        return schedule.startingDeadlineSeconds;
      },
      externalValidator({schedule}, definition) {
        if (!schedule.runOnSchedule) {
          return true;
        }

        if (!ValidatorUtil.isDefined(schedule.startingDeadlineSeconds)) {
          return true;
        }

        if (!ValidatorUtil.isNumberInRange(schedule.startingDeadlineSeconds)) {
          definition.showError = 'Expecting a positive number here';
          return true;
        }

        return true;
      }
    }
  },
  required: ['cron']

};

module.exports = Schedule;
<commit_msg>Fix job schedule CRON example<commit_after>/* eslint-disable no-unused-vars */
import React from 'react';
/* eslint-enable no-unused-vars */

import JobValidatorUtil from '../../utils/JobValidatorUtil';
import MetadataStore from '../../stores/MetadataStore';
import ValidatorUtil from '../../utils/ValidatorUtil';

const Schedule = {
  title: 'Schedule',
  description: 'Set time and date for the job to run',
  type: 'object',
  properties: {
    runOnSchedule: {
      label: 'Run on a schedule',
      showLabel: true,
      title: 'Run on a schedule',
      type: 'boolean',
      getter(job) {
        const [schedule] = job.getSchedules();

        return schedule != null;
      }
    },
    cron: {
      title: 'CRON Schedule',
      helpBlock: (

          Use cron format to set your schedule, e.g. 0 0 20 * *. View documentation.

      ),
      type: 'string',
      getter(job) {
        const [schedule = {}] = job.getSchedules();

        return schedule.cron;
      },
      externalValidator({schedule}, definition) {
        if (!schedule.runOnSchedule) {
          return true;
        }

        if (!JobValidatorUtil.isValidCronSchedule(schedule.cron)) {
          definition.showError = 'CRON Schedule must not be empty and it must '+
          'follow the correct CRON format specifications';
          return false;
        }

        return true;
      }
    },
    timezone: {
      title: 'Time Zone',
      description: (

          Enter time zone in TZ format, e.g. America/New_York.

      ),
      type: 'string',
      getter(job) {
        const [schedule = {}] = job.getSchedules();

        return schedule.timezone;
      }
    },
    startingDeadlineSeconds: {
      title: 'Starting Deadline',
      description: 'Time in seconds to start the job if it misses ' +
      'scheduled time for any reason. Missed jobs executions will be ' +
      'counted as failed ones.',
      type: 'number',
      getter(job) {
        const [schedule = {}] = job.getSchedules();

        return schedule.startingDeadlineSeconds;
      },
      externalValidator({schedule}, definition) {
        if (!schedule.runOnSchedule) {
          return true;
        }

        if (!ValidatorUtil.isDefined(schedule.startingDeadlineSeconds)) {
          return true;
        }

        if (!ValidatorUtil.isNumberInRange(schedule.startingDeadlineSeconds)) {
          definition.showError = 'Expecting a positive number here';
          return true;
        }

        return true;
      }
    }
  },
  required: ['cron']

};

module.exports = Schedule;
<|endoftext|>