<commit_before>angular.module('components')

.component('ioDoctor', {
    controller: function($scope, $rootScope, $timeout, $location) {
      this.importSchema = "";

	  if ((window.localStorage) && (window.localStorage.getItem('swagger2'))) {
	    try {
		  this.apiConfig = JSON.parse(window.localStorage.getItem('swagger2'));
		}
		catch (ex) {}
	  }
	  else {
	    this.apiConfig = angular.extend({},petstore);
	  }
	  this.importSchema = JSON.stringify(this.apiConfig,null,2);

	  this.apiConfig.resources = [];
	  this.apiConfig.schemas = [];
	  this.schemes = ['http','https','soap'];
	  var apiConfig = this.apiConfig;

      angular.forEach(apiConfig.paths, function(def, name) {
        resource = new Resource(name);
        resource.load(def, name, apiConfig);
        this.push(resource);
      }, this.apiConfig.resources);

      this.addResource = function() {
	    var newResource = new Resource('/newPath');
        this.apiConfig.resources.push(newResource);
		$location.hash(newResource.id);
      }

	  this.showResource = function(resource) {
		$location.hash(resource.id);
	  }

	  this.removeAll = function() {
	    bootbox.confirm('Remove all paths, are you sure?', function(result) {
          if (result) {
		    if (window.localStorage) window.localStorage.setItem('swagger2',JSON.stringify(apiConfig));
		    apiConfig.resources = [];
            $scope.$apply();
		  }
		});
      }

	  this.save = function() {
	    if (window.localStorage) {
		  window.localStorage.setItem('swagger2',JSON.stringify(this.apiConfig));
		}
	  }

	  this.undo = function() {
	    if (window.localStorage) {
		  this.apiConfig = JSON.parse(window.localStorage.getItem('swagger2'));
		}
	  }

      this.loadSchema = function() {
        var schema;
		try {
		  schema = JSON.parse(this.importSchema);
		  bootbox.alert('JSON definition loaded successfully');
		}
		catch (ex) {
		  try {
		    schema = jsyaml.safeLoad(this.importSchema);
			bootbox.alert('YAML definition loaded successfully');
		  }
		  catch (ex) {
		    bootbox.alert('The definition could not be parsed');
		  }
		}

        this.apiConfig = schema;
		if (window.localStorage) window.localStorage.setItem('swagger2',JSON.stringify(schema));
		this.apiConfig.resources = [];

        angular.forEach(schema.paths, function(def, name) {
          resource = new Resource(name);
          resource.load(def, name, schema);
          this.push(resource);
        }, this.apiConfig.resources);
      }

	  $rootScope.$on('removeResource', function(event, id) {
		if (window.localStorage) window.localStorage.setItem('swagger2',JSON.stringify(apiConfig));
		var result = jQuery.grep(apiConfig.resources, function(value) {
		  return value.id != id;
		});
	    apiConfig.resources = result;
	  });

      this.renderOutput = function() {
        // Pretty print has an issue correctly rendering output when we modify
        // the content in an already "prettified" element. This hack creates a
        // new element so prettyPrint() will correctly re-render the output
        $('#json-output').html('

');
        output = JSON.stringify(this.transformConfig(), undefined, 4);
        $('#pretty-json').html( output );
        clippy = new Clipboard('#copy-json');
        prettyPrint();
		var data = "text/json;charset=utf-8," + encodeURIComponent(output);
		$('#download-output').attr('href','data:' + data);
		$('#download-output').attr('download','swagger.json');
      }

      this.renderOutputYaml = function() {
        $('#yaml-output').html('

');
        try {
		  output = jsyaml.dump(this.transformConfig());
		}
		catch (ex) {
		  alert(ex.message);
		}
        $('#pretty-yaml').html( output );
        clippy = new Clipboard('#copy-yaml');
        prettyPrint();
		var data = "text/x-yaml;charset=utf-8," + encodeURIComponent(output);
		$('#download-yaml').attr('href','data:' + data);
		$('#download-yaml').attr('download','swagger.yaml');
      }

      this.transformConfig = function() {
        var transformedConfig = angular.extend({},this.apiConfig);
		transformedConfig.paths = {};

        angular.forEach(this.apiConfig.resources, function(resource) {
          transformedConfig.paths[resource.name] = resource.render();
        });

		delete transformedConfig.resources;
		delete transformedConfig.schemas;
		return transformedConfig;

      };
    },
    templateUrl: 'src/app/iodoctor.html'
  }
)
<commit_msg>Add/remove tags with undo support<commit_after>angular.module('components')

.component('ioDoctor', {
    controller: function($scope, $rootScope, $timeout, $location) {
      this.importSchema = "";

	  if ((window.localStorage) && (window.localStorage.getItem('swagger2'))) {
	    try {
		  this.apiConfig = JSON.parse(window.localStorage.getItem('swagger2'));
		}
		catch (ex) {}
	  }
	  else {
	    this.apiConfig = angular.extend({},petstore);
	  }
	  this.importSchema = JSON.stringify(this.apiConfig,null,2);

	  this.apiConfig.resources = [];
	  this.apiConfig.schemas = [];
	  this.schemes = ['http','https','soap'];
	  var apiConfig = this.apiConfig;

      angular.forEach(apiConfig.paths, function(def, name) {
        resource = new Resource(name);
        resource.load(def, name, apiConfig);
        this.push(resource);
      }, this.apiConfig.resources);

      this.addResource = function() {
	    var newResource = new Resource('/newPath');
        this.apiConfig.resources.push(newResource);
		$location.hash(newResource.id);
      }

	  this.showResource = function(resource) {
		$location.hash(resource.id);
	  }

	  this.removeAll = function() {
	    bootbox.confirm('Remove all paths, are you sure?', function(result) {
          if (result) {
		    if (window.localStorage) window.localStorage.setItem('swagger2',JSON.stringify(apiConfig));
		    apiConfig.resources = [];
            $scope.$apply();
		  }
		});
      }

	  this.save = function() {
	    if (window.localStorage) {
		  window.localStorage.setItem('swagger2',JSON.stringify(this.apiConfig));
		}
	  }

	  this.undo = function() {
	    if (window.localStorage) {
		  this.apiConfig = JSON.parse(window.localStorage.getItem('swagger2'));
		}
	  }

      this.loadSchema = function() {
        var schema;
		try {
		  schema = JSON.parse(this.importSchema);
		  bootbox.alert('JSON definition loaded successfully');
		}
		catch (ex) {
		  try {
		    schema = jsyaml.safeLoad(this.importSchema);
			bootbox.alert('YAML definition loaded successfully');
		  }
		  catch (ex) {
		    bootbox.alert('The definition could not be parsed');
		  }
		}

        this.apiConfig = schema;
		if (window.localStorage) window.localStorage.setItem('swagger2',JSON.stringify(schema));
		this.apiConfig.resources = [];

        angular.forEach(schema.paths, function(def, name) {
          resource = new Resource(name);
          resource.load(def, name, schema);
          this.push(resource);
        }, this.apiConfig.resources);
      }

	  $rootScope.$on('removeResource', function(event, id) {
		if (window.localStorage) window.localStorage.setItem('swagger2',JSON.stringify(apiConfig));
		var result = jQuery.grep(apiConfig.resources, function(value) {
		  return value.id != id;
		});
	    apiConfig.resources = result;
	  });

	  this.addTag = function() {
	    var newTag = { name: 'New Tag', description: 'Description' };
	    this.apiConfig.tags.push(newTag);
	  };

	  this.removeTag = function(tag) {
	    var index = this.apiConfig.tags.indexOf(tag);
		if (index>=0) {
		  if (window.localStorage) window.localStorage.setItem('swagger2',JSON.stringify(apiConfig));
		  this.apiConfig.tags.splice(index,1);
		}
	  };

      this.renderOutput = function() {
        // Pretty print has an issue correctly rendering output when we modify
        // the content in an already "prettified" element. This hack creates a
        // new element so prettyPrint() will correctly re-render the output
        $('#json-output').html('

');
        output = JSON.stringify(this.transformConfig(), undefined, 4);
        $('#pretty-json').html( output );
        clippy = new Clipboard('#copy-json');
        prettyPrint();
		var data = "text/json;charset=utf-8," + encodeURIComponent(output);
		$('#download-output').attr('href','data:' + data);
		$('#download-output').attr('download','swagger.json');
      }

      this.renderOutputYaml = function() {
        $('#yaml-output').html('

');
        try {
		  output = jsyaml.dump(this.transformConfig());
		}
		catch (ex) {
		  alert(ex.message);
		}
        $('#pretty-yaml').html( output );
        clippy = new Clipboard('#copy-yaml');
        prettyPrint();
		var data = "text/x-yaml;charset=utf-8," + encodeURIComponent(output);
		$('#download-yaml').attr('href','data:' + data);
		$('#download-yaml').attr('download','swagger.yaml');
      }

      this.transformConfig = function() {
        var transformedConfig = angular.extend({},this.apiConfig);
		transformedConfig.paths = {};

        angular.forEach(this.apiConfig.resources, function(resource) {
          transformedConfig.paths[resource.name] = resource.render();
        });

		delete transformedConfig.resources;
		delete transformedConfig.schemas;
		return transformedConfig;

      };
    },
    templateUrl: 'src/app/iodoctor.html'
  }
)
<|endoftext|>


<commit_before>const merge = require('webpack-merge');
const validateOptions = require('./options-validator');

module.exports = (pattern, options) => {
    // Make the first argument optional, just passing a configuration
    // object should result in the default pattern being used
    if ( typeof options === 'undefined' && (typeof pattern === 'object' && pattern !== null) ) {
        options = pattern;
        pattern = '**/*.svg'
    }

    // Validate input
    validateOptions(pattern, options);

    // Format output (`null` values will be overwritten below the object initialization)
    const output = merge({
        input: {
            options: {}
        },
        output: {
            filename: 'spritemap.svg',
            svg: {
                sizes: null
            },
            chunk: {
                name: 'spritemap',
                delete: true
            },
            svg4everybody: false,
            svgo: true
        },
        sprite: {
            prefix: 'sprite-',
            gutter: 0,
            generate: {
                title: true,
                symbol: true,
                use: false,
                view: false
            }
        },
        styles: false
    }, options, {
        input: {
            patterns: typeof pattern === 'string' ? [pattern] : pattern
        }
    });

    // [output.svg.sizes] If no option is specified base this on the `sprite.generate.use` option
    if ( output.output.svg.sizes === null ) {
        output.output.svg.sizes = output.sprite.generate.use;
    }

    // [output.svgo] If enabled by by passing `true`, set it to an empty object
    if ( output.output.svgo === true ) {
        output.output.svgo = {};
    }

    // [output.svg4everybody] If enabled by by passing `true`, set it to an empty object
    if ( output.output.svg4everybody === true ) {
        output.output.svg4everybody = {};
    }

    // [sprite.prefix] If disabled by passing `false`, set it to an empty string
    if ( output.sprite.prefix === false ) {
        output.sprite.prefix = '';
    }

    // [sprite.gutter] Reformat `false` to 0
    if ( output.sprite.gutter === false ) {
        output.sprite.gutter = 0;
    }

    if ( output.styles ) {
        if ( typeof output.styles === 'string' ) {
            output.styles = {
                filename: output.styles
            };
        } else if ( output.styles === true ) {
            output.styles = {};
        }

        output.styles = merge({
            filename: '~sprites.css',
            format: 'data',
            variables: {
                sprites: 'sprites',
                sizes: 'sizes',
                variables: 'variables',
                mixin: 'sprite'
            }
        }, output.styles);
    }

    return output;
};
<commit_msg>Adds path normalization to make sure the correct slashes are used in the glob pattern<commit_after>const path = require('path');
const merge = require('webpack-merge');
const validateOptions = require('./options-validator');

module.exports = (pattern, options) => {
    // Make the first argument optional, just passing a configuration
    // object should result in the default pattern being used
    if ( typeof options === 'undefined' && (typeof pattern === 'object' && pattern !== null) ) {
        options = pattern;
        pattern = '**/*.svg'
    }

    // Normalize the path to make sure the correct slashes are used
    pattern = path.normalize(pattern);

    // Validate input
    validateOptions(pattern, options);

    // Format output (`null` values will be overwritten below the object initialization)
    const output = merge({
        input: {
            options: {}
        },
        output: {
            filename: 'spritemap.svg',
            svg: {
                sizes: null
            },
            chunk: {
                name: 'spritemap',
                delete: true
            },
            svg4everybody: false,
            svgo: true
        },
        sprite: {
            prefix: 'sprite-',
            gutter: 0,
            generate: {
                title: true,
                symbol: true,
                use: false,
                view: false
            }
        },
        styles: false
    }, options, {
        input: {
            patterns: typeof pattern === 'string' ? [pattern] : pattern
        }
    });

    // [output.svg.sizes] If no option is specified base this on the `sprite.generate.use` option
    if ( output.output.svg.sizes === null ) {
        output.output.svg.sizes = output.sprite.generate.use;
    }

    // [output.svgo] If enabled by by passing `true`, set it to an empty object
    if ( output.output.svgo === true ) {
        output.output.svgo = {};
    }

    // [output.svg4everybody] If enabled by by passing `true`, set it to an empty object
    if ( output.output.svg4everybody === true ) {
        output.output.svg4everybody = {};
    }

    // [sprite.prefix] If disabled by passing `false`, set it to an empty string
    if ( output.sprite.prefix === false ) {
        output.sprite.prefix = '';
    }

    // [sprite.gutter] Reformat `false` to 0
    if ( output.sprite.gutter === false ) {
        output.sprite.gutter = 0;
    }

    if ( output.styles ) {
        if ( typeof output.styles === 'string' ) {
            output.styles = {
                filename: output.styles
            };
        } else if ( output.styles === true ) {
            output.styles = {};
        }

        output.styles = merge({
            filename: '~sprites.css',
            format: 'data',
            variables: {
                sprites: 'sprites',
                sizes: 'sizes',
                variables: 'variables',
                mixin: 'sprite'
            }
        }, output.styles);
    }

    return output;
};
<|endoftext|>


<commit_before>var Clock = Backbone.Model.extend({

	initialize: function() {
		// console.log('Clock::initialize()');
		this.engine = 0; // setTimeout id
		this.tempo = 200 // TODO: convert to BPM from milliseconds
		this.count = 0; // counts number of steps
	},

	step: function() {
		var self = this;
		this.count += 1;
		this.engine = setTimeout(function() {
			self.trigger('step', {'stepNumber': self.count} );
			self.step();
		}, self.tempo );
	},

	start: function() {
		// console.log('Clock Start');
		this.count = 0;
		this.step();
	},

	stop: function() {
		// console.log('Clock Stop');
		if (this.engine !== 0) {
			clearTimeout(this.engine);
		}
		this.engine = 0;
	}

});;var Sequence = Backbone.Model.extend({

	initialize: function(attrs) {
		// console.log('Sequence::initialize()', attrs);
		this.context = this.getAudioContext();
		this.get('stepCollection').fetch().done( function() {
		});
	},

	getAudioContext: function() {
    var contextClass = ( window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext);
    if (contextClass) { // Web Audio API is available.
      return new contextClass();
    } else {
      alert('Web Audio API not supported by this browser.  :-(   ');
    }
  },

  createAndTriggerOscillator: function (freq, volume) {
    var vco = this.context.createOscillator();
    vco.frequency.value = freq;
    vco.type = "square";
    vco.connect(this.context.destination);

    var vca = this.context.createGain();
    var volume = Math.random();
    vca.gain.value = volume;
    vco.connect(vca);
    vca.connect(this.context.destination);

    vco.start(0);
    var self= this;
    setTimeout(function() {
        vco.stop(0);
        vco.disconnect(self.context.destination);
    }, 100)
  }

});;var Step = Backbone.Model.extend({

	defaults: {
		"frequency": 440
	},

	initialize: function(attrs) {
		// console.log('Step::initialize()', attrs);
	}

});;var StepCollection = Backbone.Collection.extend({

  model: Step,
  url: 'assets/json/steps.json',

  initialize: function(models, options) {
  	// console.log('StepCollection:initialize()');
  },

  parse: function(response) {
  	return response.steps
  }

});;var StepView = Backbone.View.extend({

  // TODO: use an external template mixin
  // template: _.template( $('#step-template').html() ),
	// template: _.template( '<%= myVar %>' ),

  className: 'step',

	events: {
    'click .trigger' : 'toggleStep',
    'mousemove .fader'  : 'handleMouseMove'
	},

	initialize: function(options) {
    // console.log('StepView:initialize()');

  },

	render: function() {
    this.template = _.template( $('#step-template').html() );
		this.$el.html(this.template({
      id: this.model.id
		}));
  	return this;
	},

  flashLed: function() {
    var $ledEl = $('.led_'+this.model.id);
    $ledEl.addClass('lit');
    setTimeout(function(){
      $ledEl.removeClass('lit');
    }, 200);
  },

  toggleStep: function() {
    console.log('toggleStep');
    var $triggerEl = $('.trigger_'+this.model.id);
    $triggerEl.toggleClass('step-active');

  },

  isActive: function() {
    var $triggerEl = $('.trigger_'+this.model.id);
    if ($triggerEl.hasClass('step-active')) {
      return true
    } else {
      return false;
    }
  }

});;var SequenceView = Backbone.View.extend({

  // TODO: use an external template mixin
  // template: _.template( $('#sequence-template').html() ),
	// template: _.template( '<%= myVar %>' ),

  className: 'sequence',

	events: {
    'click #start' : 'start',
    'click #stop' : 'stop',
	},

	initialize: function() {
		var self= this;
		this.stepCount = 1;
    this.clock = new Clock();
    this.listenTo(this.clock, 'step', this.stepWasTriggered);

    this.stepCollection = new StepCollection();
    this.stepCollection.fetch().done( function(){
    	self.createAndRenderStepViews();
    });
	  this.model = new Sequence({
	    "tempo": 100,
	    "stepCollection": this.stepCollection
	  });

	},

	render: function() {
    this.template = _.template( $('#sequence-template').html() );
		this.$el.html(this.template({

		}));
  	return this;
	},

	createAndRenderStepViews: function() {
		var self = this;
		this._stepViews = [];
		_.each(this.stepCollection.models, function (stepModel){
			var stepView = new StepView({model: stepModel});
			self._stepViews.push( stepView );
		});
		this.renderStepViews();
	},

	removeStepViews: function() {
		_.invoke(this.stepCollection, 'remove');
	},

	renderStepViews: function() {
		_.each(this._stepViews, function (stepView) {
			$('#step-views').append(stepView.render().$el);
		});
	},

  stepWasTriggered: function (e) {
    console.log ('step triggered', e);
    this.playNote();
  },

  start: function() {
  	console.log('SequenceView::start()');
    this.clock.start();
  },

  stop: function() {
  	console.log('SequenceView::stop()');
    this.clock.stop();
  },

  playNote: function() {
  	var self = this;
    if (this.stepCount-1 == this.stepCollection.length) {
      this.stepCount = 1;
    }
    // console.log('this.stepCount', this.stepCount);
    var currentStep = this.stepCollection.get(self.stepCount );
    // console.log('currentStep', currentStep);
    var stepFreq = currentStep.get('frequency');
    // console.log ( 'freq of step', pattern.sequence[stepper] );
    console.log ('step', this.stepCount, 'of', this.stepCollection.length, 'at', stepFreq, 'Hz');

    if (this._stepViews[this.stepCount-1].isActive() === true) {
    	this.model.createAndTriggerOscillator(stepFreq, .2);
  	}

    this.flashLed();
    this.stepCount++;
  },

  flashLed: function() {
  	this._stepViews[this.stepCount-1].flashLed();
  }

});;$( document ).ready(function() {

  var sequenceView = new SequenceView();
  $('#seq').append( sequenceView.render().$el );

});<commit_msg>latest concat<commit_after>var Clock = Backbone.Model.extend({

	initialize: function() {
		// console.log('Clock::initialize()');
		this.engine = 0; // setTimeout id
		this.tempo = 200 // TODO: convert to BPM from milliseconds
		this.count = 0; // counts number of steps
	},

	step: function() {
		var self = this;
		this.count += 1;
		this.engine = setTimeout(function() {
			self.trigger('step', {'stepNumber': self.count} );
			self.step();
		}, self.tempo );
	},

	start: function() {
		// console.log('Clock Start');
		this.count = 0;
		this.step();
	},

	stop: function() {
		// console.log('Clock Stop');
		if (this.engine !== 0) {
			clearTimeout(this.engine);
		}
		this.engine = 0;
	}

});;var Sequence = Backbone.Model.extend({

	initialize: function(attrs) {
		// console.log('Sequence::initialize()', attrs);
		this.context = this.getAudioContext();
		this.get('stepCollection').fetch().done( function() {
		});
	},

	getAudioContext: function() {
    var contextClass = ( window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext);
    if (contextClass) { // Web Audio API is available.
      return new contextClass();
    } else {
      alert('Web Audio API not supported by this browser.  :-(   ');
    }
  },

  createAndTriggerOscillator: function (freq, volume) {
    var vco = this.context.createOscillator();
    vco.frequency.value = freq;
    vco.type = "square";
    vco.connect(this.context.destination);

    var vca = this.context.createGain();
    var volume = Math.random();
    vca.gain.value = volume;
    vco.connect(vca);
    vca.connect(this.context.destination);

    vco.start(0);
    var self= this;
    setTimeout(function() {
        vco.stop(0);
        vco.disconnect(self.context.destination);
    }, 100)
  }

});;var Step = Backbone.Model.extend({

	defaults: {
		"frequency": 440
	},

	initialize: function(attrs) {
		// console.log('Step::initialize()', attrs);
	}

});;var StepCollection = Backbone.Collection.extend({

  model: Step,
  url: 'assets/json/steps.json',

  initialize: function(models, options) {
  	// console.log('StepCollection:initialize()');
  },

  parse: function(response) {
  	return response.steps
  }

});;var FaderView = Backbone.View.extend({

	template: _.template('<span id="fader_<%=id%>" class="fader">'),

	events: { 'drop:dropview': 'dropviewDropHandler'},

	initialize: function () {
		console.log('FaderView::initialize()');

		// this.$el.draggable({ axis: "y" });
		// var axis = $( ".selector" ).draggable( "option", "axis" );
		// console.log(axis);

		// this.$el.drags();

		// $(this.el).bind("dragStart",
		// 	function() {
		// 		window.dragging = this.model;
		// 	}, this);

		//remove reference for garbage collection purpose
		// $(this.el).bind("dragStop",
		// 	function() {
		// 		delete window.dragging;
		// 	}, this);

	},

	dropviewDropHandler: function() { console.log('drag'); },

  render: function() {
  	// $('.fader-view').append(stepView.render().$el);
  	// this.template = _.template( $('#step-template').html() );
		this.$el.html(this.template({
      id: this.model.id
		}));
  	return this;
  }

});;var StepView = Backbone.View.extend({

  // TODO: use an external template mixin
  // template: _.template( $('#step-template').html() ),
	// template: _.template( '<%= myVar %>' ),

  className: 'step',

	events: {
    'click .trigger' : 'toggleStep',
    'mousemove .fader'  : 'handleMouseMove'
	},

	initialize: function(options) {
    // console.log('StepView:initialize()');
    this.fader = new FaderView({ model: this.model });
  },

	render: function() {
    this.template = _.template( $('#step-template').html() );
		this.$el.html(this.template({
      id: this.model.id
		}));
    this.$('.fader-view').html( this.fader.render().$el );
  	return this;
	},

  flashLed: function() {
    var $ledEl = $('.led_'+this.model.id);
    $ledEl.addClass('lit');
    setTimeout(function(){
      $ledEl.removeClass('lit');
    }, 200);
  },

  toggleStep: function() {
    console.log('toggleStep');
    var $triggerEl = $('.trigger_'+this.model.id);
    $triggerEl.toggleClass('step-active');

  },

  isActive: function() {
    var $triggerEl = $('.trigger_'+this.model.id);
    if ($triggerEl.hasClass('step-active')) {
      return true
    } else {
      return false;
    }
  }

});;var SequenceView = Backbone.View.extend({

  // TODO: use an external template mixin
  // template: _.template( $('#sequence-template').html() ),
	// template: _.template( '<%= myVar %>' ),

  className: 'sequence',

	events: {
    'click #start' : 'start',
    'click #stop' : 'stop',
	},

	initialize: function() {
		var self= this;
		this.stepCount = 1;
    this.clock = new Clock();
    this.listenTo(this.clock, 'step', this.stepWasTriggered);

    this.stepCollection = new StepCollection();
    this.stepCollection.fetch().done( function(){
    	self.createAndRenderStepViews();
    });
	  this.model = new Sequence({
	    "tempo": 100,
	    "stepCollection": this.stepCollection
	  });

	},

	render: function() {
    this.template = _.template( $('#sequence-template').html() );
		this.$el.html(this.template({

		}));
  	return this;
	},

	createAndRenderStepViews: function() {
		var self = this;
		this._stepViews = [];
		_.each(this.stepCollection.models, function (stepModel){
			var stepView = new StepView({model: stepModel});
			self._stepViews.push( stepView );
		});
		this.renderStepViews();
	},

	removeStepViews: function() {
		_.invoke(this.stepCollection, 'remove');
	},

	renderStepViews: function() {
		_.each(this._stepViews, function (stepView) {
			$('#step-views').append(stepView.render().$el);
		});
	},

  stepWasTriggered: function (e) {
    console.log ('step triggered', e);
    this.playNote();
  },

  start: function() {
  	console.log('SequenceView::start()');
    this.clock.start();
  },

  stop: function() {
  	console.log('SequenceView::stop()');
    this.clock.stop();
  },

  playNote: function() {
  	var self = this;
    if (this.stepCount-1 == this.stepCollection.length) {
      this.stepCount = 1;
    }
    // console.log('this.stepCount', this.stepCount);
    var currentStep = this.stepCollection.get(self.stepCount );
    // console.log('currentStep', currentStep);
    var stepFreq = currentStep.get('frequency');
    // console.log ( 'freq of step', pattern.sequence[stepper] );
    console.log ('step', this.stepCount, 'of', this.stepCollection.length, 'at', stepFreq, 'Hz');

    if (this._stepViews[this.stepCount-1].isActive() === true) {
    	this.model.createAndTriggerOscillator(stepFreq, .2);
  	}

    this.flashLed();
    this.stepCount++;
  },

  flashLed: function() {
  	this._stepViews[this.stepCount-1].flashLed();
  }

});;$( document ).ready(function() {

  var sequenceView = new SequenceView();
  $('#seq').append( sequenceView.render().$el );

});<|endoftext|>


<commit_before>import { UnknownStateError, DuplicateStateError } from '../errors'

export default class Automaton {
	states = []
	alphabet = []
	initialState = null
	finalStates = []
	constructor(alphabet = []) {
		this.alphabet = alphabet
	}
	setInitialState(name) {
		if (!this.stateExists(name))
			throw new UnknownStateError(name)
		this.initialState = name
	}
	addState (name, isFinal) {
		if (this.stateExists(name)) throw new DuplicateStateError(name)

		this.states = [ ...this.states, new State(name) ]

		if (isFinal)
			this.finalStates = [ ...this.finalStates, name ]
	}
	editState (oldName, newName) {
		if (oldName !== newName && this.stateExists(newName))
			throw new DuplicateStateError(newName)

		this.states = this.states.map(e => {
			if (e.name === oldName)
				e.name = newName
			return e
		})

		this.finalStates.map(s => {
			if (s === oldName)
				return newName
			return s
		})

		if (this.initialState === oldName)
			this.initialState = newName
	}
	removeState (name) {
		if (!this.stateExists(name))
			throw new UnknownStateError(name)

		this.states = this.states.filter(e => e.name !== name)

		this.states = this.states.map(e => {
			e.transitions = e.transitions.filter(t => t.from !== name && t.to !== name)
			return e
		})

		this.removeFinal(name)

		if (name === this.initialState) this.initialState = null
	}
	getState (name) {
		return this.states.filter(e => e.name === name)[0]
	}
	addFinal (name) {
		if (!this.stateExists(name))
			throw new UnknownStateError(name)
		this.finalStates = [ ...this.finalStates, name ]
	}
	removeFinal (name) {
		this.finalStates = this.finalStates.filter(e => e.name !== name)
	}
	stateIsFinal (name) {
		return this.finalStates.filter(s => s === name)[0]
	}
	stateIsInitial (name) {
		return this.initialState === name
	}
	stateExists (name) {
		return this.states.filter(s => s.name === name)[0]
	}
	charInAlphabet (a) {
		return this.alphabet.filter(e => e === a)[0]
	}
}

export class State {
	transitions = []
	constructor (name) {
		this.name = name
	}
}

export class Transition {
	constructor (from, a, to) {
		this.from = from
		this.a = a
		this.to = to
	}
}<commit_msg>Clear initial state func and fix in remove final state<commit_after>import { UnknownStateError, DuplicateStateError } from '../errors'

export default class Automaton {
	states = []
	alphabet = []
	initialState = null
	finalStates = []
	constructor(alphabet = []) {
		this.alphabet = alphabet
	}
	setInitialState(name) {
		if (!this.stateExists(name))
			throw new UnknownStateError(name)
		this.initialState = name
	}
	clearInitialState() {
		this.initialState = null
	}
	addState (name, isFinal) {
		if (this.stateExists(name)) throw new DuplicateStateError(name)

		this.states = [ ...this.states, new State(name) ]

		if (isFinal)
			this.finalStates = [ ...this.finalStates, name ]
	}
	editState (oldName, newName) {
		if (oldName !== newName && this.stateExists(newName))
			throw new DuplicateStateError(newName)

		this.states = this.states.map(e => {
			if (e.name === oldName)
				e.name = newName
			return e
		})

		this.finalStates.map(s => {
			if (s === oldName)
				return newName
			return s
		})

		if (this.initialState === oldName)
			this.initialState = newName
	}
	removeState (name) {
		if (!this.stateExists(name))
			throw new UnknownStateError(name)

		this.states = this.states.filter(e => e.name !== name)

		this.states = this.states.map(e => {
			e.transitions = e.transitions.filter(t => t.from !== name && t.to !== name)
			return e
		})

		this.removeFinal(name)

		if (name === this.initialState) this.initialState = null
	}
	getState (name) {
		return this.states.filter(e => e.name === name)[0]
	}
	addFinal (name) {
		if (!this.stateExists(name))
			throw new UnknownStateError(name)
		this.finalStates = [ ...this.finalStates, name ]
	}
	removeFinal (name) {
		this.finalStates = this.finalStates.filter(e => e !== name)
	}
	stateIsFinal (name) {
		return this.finalStates.filter(s => s === name)[0]
	}
	stateIsInitial (name) {
		return this.initialState === name
	}
	stateExists (name) {
		return this.states.filter(s => s.name === name)[0]
	}
	charInAlphabet (a) {
		return this.alphabet.filter(e => e === a)[0]
	}
	addTransition(){}
	editTransition(){}
	removeTransition(){}
	run(){}
}

export class State {
	transitions = []
	constructor (name) {
		this.name = name
	}
}

export class Transition {
	constructor (from, a, to) {
		this.from = from
		this.a = a
		this.to = to
	}
}<|endoftext|>


<commit_before>/**
 * @file Tr component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, Fragment} from 'react';
import PropTypes from 'prop-types';

// Components
import Td from '../_Td';

// Statics
import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

// Vendors
import classNames from 'classnames';
import Util from '../_vendors/Util';
import TC from '../_vendors/TableCalculation';

class Tr extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    getTdStyle = (columnsSpan, column, colIndex) => {

        const {useDynamicRender, rowHeight, defaultColumnWidth} = this.props,
            result = useDynamicRender ? {
                ...column?.bodyStyle,
                height: rowHeight,
                paddingTop: 0,
                paddingBottom: 0
            } : {
                ...column?.bodyStyle
            };

        if (column.fixed === HorizontalAlign.LEFT) {
            result.position = 'sticky';
            result.left = TC.getColumnsSpanWidth(columnsSpan.slice(0, colIndex), defaultColumnWidth);
        }

        if (column.fixed === HorizontalAlign.RIGHT) {
            result.position = 'sticky';
            result.right = TC.getColumnsSpanWidth(columnsSpan.slice(colIndex + 1), defaultColumnWidth);
        }

        return result;

    };

    isCollapsed = () => {

        const {idField, data, expandRows} = this.props;

        if (!expandRows || expandRows.length < 1) {
            return true;
        }

        return TC.indexOfNodeInValue(data, expandRows, idField) === -1;

    };

    getColumnsSpan = () => {
        const {columns, data, rowIndex, onRequestColumnsSpan} = this.props;
        return onRequestColumnsSpan ?
            onRequestColumnsSpan(TableFragment.BODY, columns, data, rowIndex)
            :
            TC.getColumnsSpan(TableFragment.BODY, columns, data, rowIndex);
    };

    handleClick = e => {
        const {data, rowIndex, disabled, onRowClick} = this.props;
        !disabled && onRowClick && onRowClick(data, rowIndex, e);
    };

    render() {

        const {

                className, style, columns, rowIndex, data, parentData, tableData,
                isChecked, disabled, baseColIndex, ignoreColumnSpan, depth, index, path,
                useDynamicRender, rowHeight,

                ...respProps

            } = this.props,
            collapsed = this.isCollapsed(),
            columnsSpan = this.getColumnsSpan(),
            nodePath = path || [{index, node: data}];

        return (
            <Fragment>

                    {
                        columnsSpan && columnsSpan.map(({column, span}, colIndex) => column ?
                            <Td {...respProps}
                                key={colIndex}
                                className={column.bodyClassName}
                                style={this.getTdStyle(columnsSpan, column, colIndex)}
                                rowIndex={rowIndex}
                                colIndex={baseColIndex + colIndex}
                                data={data}
                                title={column.bodyTitle}
                                parentData={parentData}
                                tableData={tableData}
                                collapsed={collapsed}
                                renderer={column.bodyRenderer}
                                align={column.bodyAlign || column.align}
                                span={ignoreColumnSpan ? null : span}
                                disabled={disabled}
                                noWrap={TC.handleNoWrap(column.bodyNoWrap, column.noWrap, {
                                    data,
                                    rowIndex,
                                    colIndex: baseColIndex + colIndex,
                                    tableData
                                })}
                                depth={depth}
                                path={nodePath}
                                sortable={column.sortable}
                                sortingProp={column.sortingProp}/>
                            :
                            null
                        )
                    }

                {
                    /*rowHasChildren && */!collapsed && data && data.children && data.children.length > 0 ?
                    data.children.map((item, index) =>
                        <Tr {...this.props}
                            key={index}
                            index={index}
                            data={item}
                            parentData={data}
                            depth={depth + 1}
                            path={
                                nodePath ?
                                    [...nodePath, {index, node: item}]
                                    :
                                    [{index, node: item}]
                            }/>
                    )
                    :
                    null
                }

            </Fragment>
        );

    }
}

Tr.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    rowIndex: PropTypes.number,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * fixed position of column ( 'left' / 'right' ).
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column.
         */
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * minimum width of column.
         */
        minWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * align of current column.
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * no wrap of current column.
         */
        noWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * The title in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headTitle: PropTypes.any,

        /**
         * column span of table header.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table header.
         */
        headNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell.
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * The title in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyTitle: PropTypes.any,

        /**
         * column span of table body.
         *  (1) function callback:
         *      function (rowData, colIndex, rowIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table body.
         */
        bodyNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * The title in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footTitle: PropTypes.any,

        /**
         * column span of table foot.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table foot.
         */
        footNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.object,
    parentData: PropTypes.object,
    tableData: PropTypes.array,
    isChecked: PropTypes.bool,
    disabled: PropTypes.bool,
    expandRows: PropTypes.array,
    baseColIndex: PropTypes.number,
    depth: PropTypes.number,
    index: PropTypes.number,
    path: PropTypes.array,
    idField: PropTypes.string,
    isMouseEventForbidden: PropTypes.bool,
    ignoreColumnSpan: PropTypes.bool,
    scrollEl: PropTypes.object,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),

    /**
     * Dynamic Render
     */
    useDynamicRender: PropTypes.bool,
    rowHeight: PropTypes.number,

    /**
     * column resizable
     */
    defaultColumnWidth: PropTypes.number,

    /**
     * callback
     */
    onRowClick: PropTypes.func,
    onCellClick: PropTypes.func,
    onExpandChange: PropTypes.func,
    onRequestColumnsSpan: PropTypes.func

};

Tr.defaultProps = {

    rowIndex: 0,
    isChecked: false,
    disabled: false,
    expandRows: [],
    baseColIndex: 0,
    depth: 0,
    idField: 'id',
    isMouseEventForbidden: false,
    ignoreColumnSpan: false,

    /**
     * Dynamic Render
     */
    useDynamicRender: false,
    rowHeight: 50,

    /**
     * column resizable
     */
    defaultColumnWidth: 100

};

export default Tr;
<commit_msg>update Tr<commit_after>/**
 * @file Tr component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, Fragment} from 'react';
import PropTypes from 'prop-types';

// Components
import Td from '../_Td';

// Statics
import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

// Vendors
import classNames from 'classnames';
import Util from '../_vendors/Util';
import TC from '../_vendors/TableCalculation';

class Tr extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    getTdStyle = (columnsSpan, column, colIndex) => {

        const {useDynamicRender, rowHeight, defaultColumnWidth} = this.props,
            result = useDynamicRender ? {
                ...column?.bodyStyle,
                height: rowHeight,
                paddingTop: 0,
                paddingBottom: 0
            } : {
                ...column?.bodyStyle
            };

        if (column.fixed === HorizontalAlign.LEFT) {
            result.position = 'sticky';
            result.left = TC.getColumnsSpanWidth(columnsSpan.slice(0, colIndex), defaultColumnWidth);
        }

        if (column.fixed === HorizontalAlign.RIGHT) {
            result.position = 'sticky';
            result.right = TC.getColumnsSpanWidth(columnsSpan.slice(colIndex + 1), defaultColumnWidth);
        }

        return result;

    };

    isCollapsed = () => {

        const {idField, data, expandRows} = this.props;

        if (!expandRows || expandRows.length < 1) {
            return true;
        }

        return TC.indexOfNodeInValue(data, expandRows, idField) === -1;

    };

    getColumnsSpan = () => {
        const {columns, data, rowIndex, onRequestColumnsSpan} = this.props;
        return onRequestColumnsSpan ?
            onRequestColumnsSpan(TableFragment.BODY, columns, data, rowIndex)
            :
            TC.getColumnsSpan(TableFragment.BODY, columns, data, rowIndex);
    };

    handleClick = e => {
        const {data, rowIndex, disabled, onRowClick} = this.props;
        !disabled && onRowClick && onRowClick(data, rowIndex, e);
    };

    render() {

        const {

                className, style, columns, rowIndex, data, parentData, tableData,
                isChecked, disabled, ignoreColumnSpan, depth, index, path,
                useDynamicRender, rowHeight,

                ...respProps

            } = this.props,
            collapsed = this.isCollapsed(),
            columnsSpan = this.getColumnsSpan(),
            nodePath = path || [{index, node: data}];

        return (
            <Fragment>

                    {
                        columnsSpan && columnsSpan.map(({column, span}, colIndex) => column ?
                            <Td {...respProps}
                                key={colIndex}
                                className={column.bodyClassName}
                                style={this.getTdStyle(columnsSpan, column, colIndex)}
                                rowIndex={rowIndex}
                                colIndex={colIndex}
                                data={data}
                                title={column.bodyTitle}
                                parentData={parentData}
                                tableData={tableData}
                                collapsed={collapsed}
                                renderer={column.bodyRenderer}
                                align={column.bodyAlign || column.align}
                                span={ignoreColumnSpan ? null : span}
                                disabled={disabled}
                                noWrap={TC.handleNoWrap(column.bodyNoWrap, column.noWrap, {
                                    data,
                                    rowIndex,
                                    colIndex: colIndex,
                                    tableData
                                })}
                                depth={depth}
                                path={nodePath}
                                sortable={column.sortable}
                                sortingProp={column.sortingProp}/>
                            :
                            null
                        )
                    }

                {
                    /*rowHasChildren && */!collapsed && data && data.children && data.children.length > 0 ?
                    data.children.map((item, index) =>
                        <Tr {...this.props}
                            key={index}
                            index={index}
                            data={item}
                            parentData={data}
                            depth={depth + 1}
                            path={
                                nodePath ?
                                    [...nodePath, {index, node: item}]
                                    :
                                    [{index, node: item}]
                            }/>
                    )
                    :
                    null
                }

            </Fragment>
        );

    }
}

Tr.propTypes = {

    className: PropTypes.string,
    style: PropTypes.object,

    rowIndex: PropTypes.number,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * unique keyof column.
         */
        key: PropTypes.string,

        /**
         * fixed position of column ( 'left' / 'right' ).
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column.
         */
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * minimum width of column.
         */
        minWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * align of current column.
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * no wrap of current column.
         */
        noWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * The title in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headTitle: PropTypes.any,

        /**
         * column span of table header.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table header.
         */
        headNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell.
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * The title in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyTitle: PropTypes.any,

        /**
         * column span of table body.
         *  (1) function callback:
         *      function (rowData, colIndex, rowIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table body.
         */
        bodyNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * The title in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footTitle: PropTypes.any,

        /**
         * column span of table foot.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table foot.
         */
        footNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.object,
    parentData: PropTypes.object,
    tableData: PropTypes.array,
    isChecked: PropTypes.bool,
    disabled: PropTypes.bool,
    expandRows: PropTypes.array,
    depth: PropTypes.number,
    index: PropTypes.number,
    path: PropTypes.array,
    idField: PropTypes.string,
    isMouseEventForbidden: PropTypes.bool,
    ignoreColumnSpan: PropTypes.bool,
    scrollEl: PropTypes.object,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),

    /**
     * Dynamic Render
     */
    useDynamicRender: PropTypes.bool,
    rowHeight: PropTypes.number,

    /**
     * column resizable
     */
    defaultColumnWidth: PropTypes.number,

    /**
     * callback
     */
    onRowClick: PropTypes.func,
    onCellClick: PropTypes.func,
    onExpandChange: PropTypes.func,
    onRequestColumnsSpan: PropTypes.func

};

Tr.defaultProps = {

    rowIndex: 0,
    isChecked: false,
    disabled: false,
    expandRows: [],
    depth: 0,
    idField: 'id',
    isMouseEventForbidden: false,
    ignoreColumnSpan: false,

    /**
     * Dynamic Render
     */
    useDynamicRender: false,
    rowHeight: 50,

    /**
     * column resizable
     */
    defaultColumnWidth: 100

};

export default Tr;
<|endoftext|>


<commit_before>import "./utils";
import TributeEvents from "./TributeEvents";
import TributeMenuEvents from "./TributeMenuEvents";
import TributeRange from "./TributeRange";
import TributeSearch from "./TributeSearch";

class Tribute {
    constructor({
        values = null,
        iframe = null,
        selectClass = 'highlight',
        trigger = '@',
        selectTemplate = null,
        menuItemTemplate = null,
        lookup = 'key',
        fillAttr = 'value',
        collection = null,
        menuContainer = null,
        noMatchTemplate = null
    }) {

        this.menuSelected = 0
        this.current = {}
        this.inputEvent = false
        this.isActive = false
        this.menuContainer = menuContainer

        if (values) {
            this.collection = [{
                // symbol that starts the lookup
                trigger: trigger,

                iframe: iframe,

                selectClass: selectClass,

                // function called on select that retuns the content to insert
                selectTemplate: (selectTemplate || Tribute.defaultSelectTemplate).bind(this),

                // function called that returns content for an item
                menuItemTemplate: (menuItemTemplate || Tribute.defaultMenuItemTemplate).bind(this),

                // function called when menu is empty, disables hiding of menu.
                noMatchTemplate: (t => {
                    if (typeof t === 'function') {
                        return t.bind(this)
                    }

                    return null
                })(noMatchTemplate),

                // column to search against in the object
                lookup: lookup,

                // column that contains the content to insert by default
                fillAttr: fillAttr,

                // array of objects
                values: values
            }]
        }
        else if (collection) {
            this.collection = collection.map(item => {
                return {
                    trigger: item.trigger || trigger,
                    iframe: item.iframe || iframe,
                    selectClass: item.selectClass || selectClass,
                    selectTemplate: (item.selectTemplate || Tribute.defaultSelectTemplate).bind(this),
                    menuItemTemplate: (item.menuItemTemplate || Tribute.defaultMenuItemTemplate).bind(this),
                    // function called when menu is empty, disables hiding of menu.
                    noMatchTemplate: (t => {
                        if (typeof t === 'function') {
                            return t.bind(this)
                        }

                        return null
                    })(noMatchTemplate),
                    lookup: item.lookup || lookup,
                    fillAttr: item.fillAttr || fillAttr,
                    values: item.values
                }
            })
        }
        else {
            throw new Error('[Tribute] No collection specified.')
        }

        new TributeRange(this)
        new TributeEvents(this)
        new TributeMenuEvents(this)
        new TributeSearch(this)
    }

    static defaultSelectTemplate(item) {
        return `@${item.original[this.current.collection.fillAttr]}`
    }

    static defaultMenuItemTemplate(matchItem) {
        return matchItem.string
    }

    static inputTypes() {
        return ['TEXTAREA', 'INPUT']
    }

    triggers() {
        return this.collection.map(config => {
            return config.trigger
        })
    }

    attach(el) {
        if (!el) {
            throw new Error('[Tribute] Must pass in a DOM node or NodeList.')
        }

        // Check if it is a jQuery collection
        if (typeof jQuery !== 'undefined' && el instanceof jQuery) {
            el = el.get()
        }

        // Is el an Array/Array-like object?
        if (el.constructor === NodeList || el.constructor === HTMLCollection || el.constructor === Array) {
            let length = el.length
            for (var i = 0; i < length; ++i) {
                this._attach(el[i])
            }
        }
        else {
            this._attach(el)
        }
    }

    _attach(el) {
        if (el.hasAttribute('data-tribute')) {
            console.warn('Tribute was already bound to ' + el.nodeName)
        }

        this.ensureEditable(el)
        this.events.bind(el)
        el.setAttribute('data-tribute', true)
    }

    ensureEditable(element) {
        if (Tribute.inputTypes().indexOf(element.nodeName) === -1) {
            if (element.contentEditable) {
                element.contentEditable = true
            }
            else {
                throw new Error('[Tribute] Cannot bind to ' + element.nodeName)
            }
        }
    }

    createMenu() {
        let wrapper = this.range.getDocument().createElement('div'),
            ul = this.range.getDocument().createElement('ul')

        wrapper.className = 'tribute-container'
        wrapper.appendChild(ul)

        if (this.menuContainer) {
            return this.menuContainer.appendChild(wrapper)
        }

        return this.range.getDocument().body.appendChild(wrapper)
    }

    showMenuFor(element, scrollTo) {
        let items
            // create the menu if it doesn't exist.
        if (!this.menu) {
            this.menu = this.createMenu()
            this.menuEvents.bind(this.menu)
        }

        this.isActive = true
        this.menuSelected = 0

        if (!this.current.mentionText) {
            this.current.mentionText = ''
        }

        items = this.search.filter(this.current.mentionText, this.current.collection.values, {
            pre: '',
            post: '',
            extract: (el) => {
                if (typeof this.current.collection.lookup === 'string') {
                    return el[this.current.collection.lookup]
                } else if (typeof this.current.collection.lookup === 'function') {
                    return this.current.collection.lookup(el)
                } else {
                    throw new Error('Invalid lookup attribute, lookup must be string or function.')
                }
            }
        })

        this.current.filteredItems = items

        let ul = this.menu.querySelector('ul')

        if (!items.length) {
            let noMatchEvent = new CustomEvent('tribute-no-match', { detail: this.menu })
            this.current.element.dispatchEvent(noMatchEvent)
            if (!this.current.collection.noMatchTemplate) {
                this.hideMenu()
            } else {
                ul.innerHTML = this.current.collection.noMatchTemplate()
            }

            return
        }

        ul.innerHTML = ''

        items.forEach((item, index) => {
            let li = this.range.getDocument().createElement('li')
            li.setAttribute('data-index', index)
            if (this.menuSelected === index) {
                li.className = this.current.collection.selectClass
            }
            li.innerHTML = this.current.collection.menuItemTemplate(item)
            ul.appendChild(li)
        })

        this.range.positionMenuAtCaret(scrollTo)

    }

    hideMenu() {
        if (this.menu) {
            this.menu.style.cssText = 'display: none;'
            this.isActive = false
            this.menuSelected = 0
            this.current = {}
        }
    }

    selectItemAtIndex(index) {
        index = parseInt(index)
        if (typeof index !== 'number') return
        let item = this.current.filteredItems[index]
        let content = this.current.collection.selectTemplate(item)
        this.replaceText(content)
    }

    replaceText(content) {
        this.range.replaceTriggerText(content, true, true)
    }

    _append(collection, newValues, replace) {
        if (!replace) {
            collection.values = collection.values.concat(newValues)
        } else {
            collection.values = newValues
        }
    }

    append(collectionIndex, newValues, replace) {
        let index = parseInt(collectionIndex)
        if (typeof index !== 'number') throw new Error('please provide an index for the collection to update.')

        let collection = this.collection[index]

        this._append(collection, newValues, replace)
    }

    appendCurrent(newValues, replace) {
        if (this.isActive) {
            this._append(this.current.collection, newValues, replace)
        } else {
            throw new Error('No active state. Please use append instead and pass an index.')
        }
    }
}

export default Tribute;
<commit_msg>Fix indentation.<commit_after>import "./utils";
import TributeEvents from "./TributeEvents";
import TributeMenuEvents from "./TributeMenuEvents";
import TributeRange from "./TributeRange";
import TributeSearch from "./TributeSearch";

class Tribute {
    constructor({
        values = null,
        iframe = null,
        selectClass = 'highlight',
        trigger = '@',
        selectTemplate = null,
        menuItemTemplate = null,
        lookup = 'key',
        fillAttr = 'value',
        collection = null,
        menuContainer = null,
        noMatchTemplate = null
    }) {

        this.menuSelected = 0
        this.current = {}
        this.inputEvent = false
        this.isActive = false
        this.menuContainer = menuContainer

        if (values) {
            this.collection = [{
                // symbol that starts the lookup
                trigger: trigger,

                iframe: iframe,

                selectClass: selectClass,

                // function called on select that retuns the content to insert
                selectTemplate: (selectTemplate || Tribute.defaultSelectTemplate).bind(this),

                // function called that returns content for an item
                menuItemTemplate: (menuItemTemplate || Tribute.defaultMenuItemTemplate).bind(this),

                // function called when menu is empty, disables hiding of menu.
                noMatchTemplate: (t => {
                    if (typeof t === 'function') {
                        return t.bind(this)
                    }

                    return null
                })(noMatchTemplate),

                // column to search against in the object
                lookup: lookup,

                // column that contains the content to insert by default
                fillAttr: fillAttr,

                // array of objects
                values: values
            }]
        }
        else if (collection) {
            this.collection = collection.map(item => {
                return {
                    trigger: item.trigger || trigger,
                    iframe: item.iframe || iframe,
                    selectClass: item.selectClass || selectClass,
                    selectTemplate: (item.selectTemplate || Tribute.defaultSelectTemplate).bind(this),
                    menuItemTemplate: (item.menuItemTemplate || Tribute.defaultMenuItemTemplate).bind(this),
                    // function called when menu is empty, disables hiding of menu.
                    noMatchTemplate: (t => {
                        if (typeof t === 'function') {
                            return t.bind(this)
                        }

                        return null
                    })(noMatchTemplate),
                    lookup: item.lookup || lookup,
                    fillAttr: item.fillAttr || fillAttr,
                    values: item.values
                }
            })
        }
        else {
            throw new Error('[Tribute] No collection specified.')
        }

        new TributeRange(this)
        new TributeEvents(this)
        new TributeMenuEvents(this)
        new TributeSearch(this)
    }

    static defaultSelectTemplate(item) {
        return `@${item.original[this.current.collection.fillAttr]}`
    }

    static defaultMenuItemTemplate(matchItem) {
        return matchItem.string
    }

    static inputTypes() {
        return ['TEXTAREA', 'INPUT']
    }

    triggers() {
        return this.collection.map(config => {
            return config.trigger
        })
    }

    attach(el) {
        if (!el) {
            throw new Error('[Tribute] Must pass in a DOM node or NodeList.')
        }

        // Check if it is a jQuery collection
        if (typeof jQuery !== 'undefined' && el instanceof jQuery) {
            el = el.get()
        }

        // Is el an Array/Array-like object?
        if (el.constructor === NodeList || el.constructor === HTMLCollection || el.constructor === Array) {
            let length = el.length
            for (var i = 0; i < length; ++i) {
                this._attach(el[i])
            }
        } else {
            this._attach(el)
        }
    }

    _attach(el) {
        if (el.hasAttribute('data-tribute')) {
            console.warn('Tribute was already bound to ' + el.nodeName)
        }

        this.ensureEditable(el)
        this.events.bind(el)
        el.setAttribute('data-tribute', true)
    }

    ensureEditable(element) {
        if (Tribute.inputTypes().indexOf(element.nodeName) === -1) {
            if (element.contentEditable) {
                element.contentEditable = true
            } else {
                throw new Error('[Tribute] Cannot bind to ' + element.nodeName)
            }
        }
    }

    createMenu() {
        let wrapper = this.range.getDocument().createElement('div'),
            ul = this.range.getDocument().createElement('ul')

        wrapper.className = 'tribute-container'
        wrapper.appendChild(ul)

        if (this.menuContainer) {
            return this.menuContainer.appendChild(wrapper)
        }

        return this.range.getDocument().body.appendChild(wrapper)
    }

    showMenuFor(element, scrollTo) {
        let items
            // create the menu if it doesn't exist.
        if (!this.menu) {
            this.menu = this.createMenu()
            this.menuEvents.bind(this.menu)
        }

        this.isActive = true
        this.menuSelected = 0

        if (!this.current.mentionText) {
            this.current.mentionText = ''
        }

        items = this.search.filter(this.current.mentionText, this.current.collection.values, {
            pre: '',
            post: '',
            extract: (el) => {
                if (typeof this.current.collection.lookup === 'string') {
                    return el[this.current.collection.lookup]
                } else if (typeof this.current.collection.lookup === 'function') {
                    return this.current.collection.lookup(el)
                } else {
                    throw new Error('Invalid lookup attribute, lookup must be string or function.')
                }
            }
        })

        this.current.filteredItems = items

        let ul = this.menu.querySelector('ul')

        if (!items.length) {
            let noMatchEvent = new CustomEvent('tribute-no-match', { detail: this.menu })
            this.current.element.dispatchEvent(noMatchEvent)
            if (!this.current.collection.noMatchTemplate) {
                this.hideMenu()
            } else {
                ul.innerHTML = this.current.collection.noMatchTemplate()
            }

            return
        }

        ul.innerHTML = ''

        items.forEach((item, index) => {
            let li = this.range.getDocument().createElement('li')
            li.setAttribute('data-index', index)
            if (this.menuSelected === index) {
                li.className = this.current.collection.selectClass
            }
            li.innerHTML = this.current.collection.menuItemTemplate(item)
            ul.appendChild(li)
        })

        this.range.positionMenuAtCaret(scrollTo)

    }

    hideMenu() {
        if (this.menu) {
            this.menu.style.cssText = 'display: none;'
            this.isActive = false
            this.menuSelected = 0
            this.current = {}
        }
    }

    selectItemAtIndex(index) {
        index = parseInt(index)
        if (typeof index !== 'number') return
        let item = this.current.filteredItems[index]
        let content = this.current.collection.selectTemplate(item)
        this.replaceText(content)
    }

    replaceText(content) {
        this.range.replaceTriggerText(content, true, true)
    }

    _append(collection, newValues, replace) {
        if (!replace) {
            collection.values = collection.values.concat(newValues)
        } else {
            collection.values = newValues
        }
    }

    append(collectionIndex, newValues, replace) {
        let index = parseInt(collectionIndex)
        if (typeof index !== 'number') throw new Error('please provide an index for the collection to update.')

        let collection = this.collection[index]

        this._append(collection, newValues, replace)
    }

    appendCurrent(newValues, replace) {
        if (this.isActive) {
            this._append(this.current.collection, newValues, replace)
        } else {
            throw new Error('No active state. Please use append instead and pass an index.')
        }
    }
}

export default Tribute;
<|endoftext|>


<commit_before>const Command = require('../Command')

module.exports =
class WelcomeMessageCommand extends Command {
  constructor (client) {
    super(client, {
      name: 'welcomemessage',
      properName: 'WelcomeMessage',
      aliases: ['roverwelcomemessage'],
      description: '`<Message>` Set the message the user gets when they join your server. This is only shown to verified members. Available replacements are %USERNAME%, %USERID%, %SERVER%, %DISCORDNAME%, and %DISCORDID%. Default: Welcome to %SERVER%, %USERNAME%!.',

      args: [
        {
          key: 'message',
          label: 'message',
          prompt: 'Welcome message',
          type: 'string',
          default: false,
          optional: true
        }
      ]
    })
  }

  async fn (msg, args) {
    if (args.message) {
      this.server.setSetting('welcomeMessage', args.message)
      msg.reply(`Set welcome message to \`${args.message}\``)
    } else {
      this.server.setSetting('welcomeMessage', undefined)
      msg.reply('Set welcome message back to default')
    }
  }
}
<commit_msg>Update WelcomeMessageCommand.js<commit_after>const Command = require('../Command')

module.exports =
class WelcomeMessageCommand extends Command {
  constructor (client) {
    super(client, {
      name: 'welcomemessage',
      properName: 'WelcomeMessage',
      aliases: ['roverwelcomemessage'],
      description: '`<Message>` Set the message the user gets when they join your server. This is only shown to verified members. Available replacements are %USERNAME%, %USERID%, %SERVER%, %DISCORDNAME%, and %DISCORDID%. Default: Welcome to %SERVER%, %USERNAME%!.',

      args: [
        {
          key: 'message',
          label: 'message',
          prompt: 'Welcome message',
          type: 'string',
          default: false,
          optional: true
        }
      ]
    })
  }

  async fn (msg, args) {
    if (this.server.ongoingSettingsUpdate) return msg.reply('Server settings are currently being saved - please try again in a few moments.')
    if (args.message) {
      this.server.setSetting('welcomeMessage', args.message)
      msg.reply(`Set welcome message to \`${args.message}\``)
    } else {
      this.server.setSetting('welcomeMessage', undefined)
      msg.reply('Set welcome message back to default')
    }
  }
}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth.twofactor',
  name: 'GoogleTOTPAuthService',
  extends: 'foam.nanos.auth.twofactor.AbstractTOTPAuthService',

  documentation: 'Google Authenticator Time-based One-time Password Service (TOTP)',

  javaImports: [
    'com.google.common.io.BaseEncoding',

    'foam.dao.DAO',
    'foam.nanos.app.EmailConfig',
    'foam.nanos.auth.Subject',
    'foam.nanos.auth.User',
    'foam.nanos.session.Session',

    'io.nayuki.qrcodegen.QrCode',
    'java.net.URI'
  ],

  constants: [
    {
      name: 'KEY_SIZE',
      value: 10,
      type: 'Integer'
    },
    {
      name: 'STEP_SIZE',
      value: 30 * 1000,
      type: 'Long'
    },
    {
      name: 'WINDOW',
      value: 3,
      type: 'Integer'
    }
  ],

  properties: [
    [ 'algorithm', 'SHA1' ]
  ],

  methods: [
    {
      name: 'generateKeyAndQR',
      javaCode: `
        Subject subject = (Subject) x.get("subject");
        User user = subject.getRealUser();
        DAO userDAO = (DAO) x.get("localUserDAO");

        // fetch from localUserDAO to get updated user before setting TwoFactorSecret
        user = (User) userDAO.find(user.getId());

        // generate secret key, encode as base32 and store
        String key = BaseEncoding.base32().encode(generateSecret(KEY_SIZE));
        key = key.replaceFirst("[=]*$", "");

        // update user with secret key
        user = (User) user.fclone();
        user.setTwoFactorSecret(key);
        userDAO.put_(x, user);

        try {
          EmailConfig service = (EmailConfig) x.get("emailConfig");
          String name = service == null ? "FOAM" : service.getDisplayName();
          String path = String.format("/%s:%s", name, user.getEmail());
          String query = String.format("secret=%s&issuer=%s&algorithm=%s", key, name, getAlgorithm());
          URI uri = new URI("otpauth", "totp", path, query, null);

          return new OTPKey.Builder(x)
            .setKey(key)
            .setQrCode("data:image/svg+xml;charset=UTF-8,"+
              QrCode.encodeText(uri.toASCIIString(), QrCode.Ecc.MEDIUM).toSvgString(0))
            .build();
        } catch ( Throwable t ) {
          throw new RuntimeException("Error when generating QR code.", t);
        }
      `
    },
    {
      name: 'verifyToken',
      javaCode: `
        long code;
        try {
          code = Long.parseLong(token, 10);
        } catch(Exception e){
          return false;
        }

        Subject subject = (Subject) x.get("subject");
        User user       = subject.getRealUser();
        DAO userDAO     = (DAO) x.get("localUserDAO");
        DAO sessionDAO  = (DAO) x.get("localSessionDAO");

        // fetch from user dao to get secret key
        user = (User) userDAO.find(user.getId());

        if ( checkCode(BaseEncoding.base32().decode(user.getTwoFactorSecret()), code, STEP_SIZE, WINDOW) ) {
          if ( ! user.getTwoFactorEnabled() ) {
            user = (User) user.fclone();
            user.setTwoFactorEnabled(true);
            userDAO.put(user);
          }

          Subject sessionSubject = new Subject();
          sessionSubject.setUser(user);
          // update session with two factor success set to true
          Session session = x.get(Session.class);
          session.setContext(session.getContext().put("subject", sessionSubject).put("twoFactorSuccess", true));
          sessionDAO.put(session);
          return true;
        }

        return false;
      `
    },
    {
      name: 'disable',
      javaCode: `
        if ( verifyToken(x, token) ) {
          Subject subject = (Subject) x.get("subject");
          User user = subject.getRealUser();
          DAO userDAO = (DAO) x.get("localUserDAO");

          // fetch user from DAO and set two factor secret to null
          user = (User) userDAO.find(user.getId()).fclone();
          user.setTwoFactorEnabled(false);
          user.setTwoFactorSecret(null);
          userDAO.put_(x, user);

          return true;
        }

        return false;
      `
    }
  ]
});
<commit_msg>do not set two factor secret key to null when disablig 2fa (#3635)<commit_after>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth.twofactor',
  name: 'GoogleTOTPAuthService',
  extends: 'foam.nanos.auth.twofactor.AbstractTOTPAuthService',

  documentation: 'Google Authenticator Time-based One-time Password Service (TOTP)',

  javaImports: [
    'com.google.common.io.BaseEncoding',

    'foam.dao.DAO',
    'foam.nanos.app.EmailConfig',
    'foam.nanos.auth.Subject',
    'foam.nanos.auth.User',
    'foam.nanos.session.Session',

    'io.nayuki.qrcodegen.QrCode',
    'java.net.URI'
  ],

  constants: [
    {
      name: 'KEY_SIZE',
      value: 10,
      type: 'Integer'
    },
    {
      name: 'STEP_SIZE',
      value: 30 * 1000,
      type: 'Long'
    },
    {
      name: 'WINDOW',
      value: 3,
      type: 'Integer'
    }
  ],

  properties: [
    [ 'algorithm', 'SHA1' ]
  ],

  methods: [
    {
      name: 'generateKeyAndQR',
      javaCode: `
        Subject subject = (Subject) x.get("subject");
        User user = subject.getRealUser();
        DAO userDAO = (DAO) x.get("localUserDAO");

        // fetch from localUserDAO to get updated user before setting TwoFactorSecret
        user = (User) userDAO.find(user.getId());

        // generate secret key, encode as base32 and store
        String key = BaseEncoding.base32().encode(generateSecret(KEY_SIZE));
        key = key.replaceFirst("[=]*$", "");

        // update user with secret key
        user = (User) user.fclone();
        user.setTwoFactorSecret(key);
        userDAO.put_(x, user);

        try {
          EmailConfig service = (EmailConfig) x.get("emailConfig");
          String name = service == null ? "FOAM" : service.getDisplayName();
          String path = String.format("/%s:%s", name, user.getEmail());
          String query = String.format("secret=%s&issuer=%s&algorithm=%s", key, name, getAlgorithm());
          URI uri = new URI("otpauth", "totp", path, query, null);

          return new OTPKey.Builder(x)
            .setKey(key)
            .setQrCode("data:image/svg+xml;charset=UTF-8,"+
              QrCode.encodeText(uri.toASCIIString(), QrCode.Ecc.MEDIUM).toSvgString(0))
            .build();
        } catch ( Throwable t ) {
          throw new RuntimeException("Error when generating QR code.", t);
        }
      `
    },
    {
      name: 'verifyToken',
      javaCode: `
        long code;
        try {
          code = Long.parseLong(token, 10);
        } catch(Exception e){
          return false;
        }

        Subject subject = (Subject) x.get("subject");
        User user       = subject.getRealUser();
        DAO userDAO     = (DAO) x.get("localUserDAO");
        DAO sessionDAO  = (DAO) x.get("localSessionDAO");

        // fetch from user dao to get secret key
        user = (User) userDAO.find(user.getId());

        if ( checkCode(BaseEncoding.base32().decode(user.getTwoFactorSecret()), code, STEP_SIZE, WINDOW) ) {
          if ( ! user.getTwoFactorEnabled() ) {
            user = (User) user.fclone();
            user.setTwoFactorEnabled(true);
            userDAO.put(user);
          }

          Subject sessionSubject = new Subject();
          sessionSubject.setUser(user);
          // update session with two factor success set to true
          Session session = x.get(Session.class);
          session.setContext(session.getContext().put("subject", sessionSubject).put("twoFactorSuccess", true));
          sessionDAO.put(session);
          return true;
        }

        return false;
      `
    },
    {
      name: 'disable',
      javaCode: `
        if ( verifyToken(x, token) ) {
          Subject subject = (Subject) x.get("subject");
          User user = subject.getRealUser();
          DAO userDAO = (DAO) x.get("localUserDAO");

          // fetch user from DAO and set two factor secret to null
          user = (User) userDAO.find(user.getId()).fclone();
          user.setTwoFactorEnabled(false);
          userDAO.put_(x, user);

          return true;
        }

        return false;
      `
    }
  ]
});
<|endoftext|>


<commit_before>require('./utils');
var q = require('q');
var path = require('path');
var logger = require('./logger');
var mkdirp = require('mkdirp');
var exec = require('child_process').exec;

module.exports = function PublicRepoCache(options) {
	_init();
	function _init() {
		return _createDirectory(options.repoCacheRoot)
			.then(_startGitDaemon)
			.fail(function(err) {
				logger.log('Failed to initialize public repository cache'.red);
				throw new Error(err);
			});
	}

	function _cacheRepo(repoName, repoUrl) {
		var deferred = q.defer();

		var packageDirectory = path.join(options.repoCacheRoot, repoName);

		_createDirectory(packageDirectory)
			.then(function() {
                logger.log('clone')
				return _cloneGitRepo(repoUrl, packageDirectory, repoName);
			})
			.then(function() {
                logger.log('git')
				deferred.resolve({
					name: repoName,
					repo: 'git://{0}:{1}/{2}'
                        .format(options.hostName, options.port, repoName)
				});
			})
			.fail(function() {
				logger.log('Failed to clone '.red + repoUrl);
				deferred.reject();
			});

		return deferred.promise;
	}

	function _createDirectory(dir) {
		var deferred = q.defer();
        logger.log('create dir')
        mkdirp(dir, function(err) {
			if(err) {
                logger.log('error creating dir.')
				deferred.reject();
				return;
			}

			deferred.resolve();
		});

        return deferred.promise;
	}

	function _startGitDaemon() {
		var deferred = q.defer();

		process.chdir(options.repoCacheRoot);

		var gitCommand = 'git daemon --verbose --base-path="{0}" --listen={1} --port={2} --export-all'
			.format(options.repoCacheRoot, options.hostName, options.port);

        logger.log('Starting git cache server');

        exec(gitCommand, function(error, stdout, stderr) {
            if(error) {
				deferred.reject(stderr);
				return;
			}

            deferred.resolve();
        });

        return deferred.promise;
	}

	function _cloneGitRepo(repoUrl, packageDirectory, repoName) {
		var deferred = q.defer();

		process.chdir(packageDirectory);

        logger.log('Cloning {0} ...'.format(repoName));
exec('git config --global http.proxy http://localhost:3128');
        exec('git config --global https.proxy http://localhost:3128');
        exec('git clone {0} ./'.format(repoUrl), function(error, stdout, stderr) {
            if(error) {
                logger.log('error ' +error)
				deferred.reject(stderr);
				return;
			}

            logger.log('Cloned {0} git repository to private'.format(repoName));

            deferred.resolve();
        });

        return deferred.promise;
	}

	return {
		cacheRepo: _cacheRepo
	};
};<commit_msg>sety git proxy<commit_after>require('./utils');
var q = require('q');
var path = require('path');
var logger = require('./logger');
var mkdirp = require('mkdirp');
var exec = require('child_process').exec;

module.exports = function PublicRepoCache(options) {
	_init();
	function _init() {
		return _createDirectory(options.repoCacheRoot)
			.then(_startGitDaemon)
			.fail(function(err) {
				logger.log('Failed to initialize public repository cache'.red);
				throw new Error(err);
			});
	}

	function _cacheRepo(repoName, repoUrl) {
		var deferred = q.defer();

		var packageDirectory = path.join(options.repoCacheRoot, repoName);

		_createDirectory(packageDirectory)
			.then(function() {
                logger.log('clone')
				return _cloneGitRepo(repoUrl, packageDirectory, repoName);
			})
			.then(function() {
                logger.log('git')
				deferred.resolve({
					name: repoName,
					repo: 'git://{0}:{1}/{2}'
                        .format(options.hostName, options.port, repoName)
				});
			})
			.fail(function() {
				logger.log('Failed to clone '.red + repoUrl);
				deferred.reject();
			});

		return deferred.promise;
	}

	function _createDirectory(dir) {
		var deferred = q.defer();
        logger.log('create dir')
        mkdirp(dir, function(err) {
			if(err) {
                logger.log('error creating dir.')
				deferred.reject();
				return;
			}

			deferred.resolve();
		});

        return deferred.promise;
	}

	function _startGitDaemon() {
		var deferred = q.defer();

		process.chdir(options.repoCacheRoot);

		var gitCommand = 'git daemon --verbose --base-path="{0}" --listen={1} --port={2} --export-all'
			.format(options.repoCacheRoot, options.hostName, options.port);

        logger.log('Starting git cache server');

        exec(gitCommand, function(error, stdout, stderr) {
            if(error) {
				deferred.reject(stderr);
				return;
			}

            deferred.resolve();
        });

        return deferred.promise;
	}

	function _cloneGitRepo(repoUrl, packageDirectory, repoName) {
		var deferred = q.defer();

		process.chdir(packageDirectory);

        logger.log('Cloning {0} ...'.format(repoName));
exec('git config --global http.proxy http://localhost:3128');
        exec('git config --global https.proxy http://localhost:3128');

        logger.log('repo url ' +repoUrl)

        exec('git clone {0} ./'.format(repoUrl), function(error, stdout, stderr) {
            if(error) {
                logger.log('error ' +error)
				deferred.reject(stderr);
				return;
			}

            logger.log('Cloned {0} git repository to private'.format(repoName));

            deferred.resolve();
        });

        return deferred.promise;
	}

	return {
		cacheRepo: _cacheRepo
	};
};<|endoftext|>


<commit_before>import { h } from 'preact'

const Loading = (props) => {
  return (

Loading...

  )
}

export default Loading
<commit_msg>style loading<commit_after>import { h } from 'preact'

const Loading = (props) => {
  return (

Loading...

  )
}

export default Loading
<|endoftext|>


<commit_before>// Dynamic queue handler
// Allows to create a promise queue, where new promises can be added to queue until last promise in
// a queue resolves. Queue promise resolves with `undefined` value, when last promises resolves.

"use strict";

var aFrom          = require("es5-ext/array/from")
  , ensureIterable = require("es5-ext/iterable/validate-object")
  , assign         = require("es5-ext/object/assign")
  , deferred       = require("./deferred")
  , isPromise      = require("./is-promise")
  , assimilate     = require("./assimilate");

var DynamicQueue;

module.exports = DynamicQueue = function (list) {
	if (!(this instanceof DynamicQueue)) return new DynamicQueue(list);
	list = aFrom(ensureIterable(list));

	assign(this, deferred());
	list.every(this.add, this);
	if (!this.waiting) {
		this.resolve();
		return;
	}
	this.initialized = true;
};

DynamicQueue.prototype = {
	waiting: 0,
	initialized: false,
	add: function (value) {
		if (this.promise.resolved) throw new Error("Queue was already resolved");
		++this.waiting;
		value = assimilate(value);
		if (isPromise(value)) {
			if (!value.resolved) {
				value.done(this._processValue.bind(this), this.reject);
				return true;
			}
			if (value.failed) {
				this.reject(value.value);
				return false;
			}
		}
		return this._processValue();
	},
	_processValue: function () {
		if (this.promise.resolved) return;
		if (!--this.waiting && this.initialized) this.resolve();
		return true;
	}
};
<commit_msg>refactor: lint<commit_after>// Dynamic queue handler
// Allows to create a promise queue, where new promises can be added to queue until last promise in
// a queue resolves. Queue promise resolves with `undefined` value, when last promises resolves.

"use strict";

var aFrom          = require("es5-ext/array/from")
  , ensureIterable = require("es5-ext/iterable/validate-object")
  , assign         = require("es5-ext/object/assign")
  , deferred       = require("./deferred")
  , isPromise      = require("./is-promise")
  , assimilate     = require("./assimilate");

var DynamicQueue;

module.exports = DynamicQueue = function (list) {
	if (!(this instanceof DynamicQueue)) return new DynamicQueue(list);
	list = aFrom(ensureIterable(list));

	assign(this, deferred());
	list.every(this.add, this);
	if (!this.waiting) {
		this.resolve();
		return null;
	}
	this.initialized = true;
	return null;
};

DynamicQueue.prototype = {
	waiting: 0,
	initialized: false,
	add: function (value) {
		if (this.promise.resolved) throw new Error("Queue was already resolved");
		++this.waiting;
		value = assimilate(value);
		if (isPromise(value)) {
			if (!value.resolved) {
				value.done(this._processValue.bind(this), this.reject);
				return true;
			}
			if (value.failed) {
				this.reject(value.value);
				return false;
			}
		}
		return this._processValue();
	},
	_processValue: function () {
		if (this.promise.resolved) return null;
		if (!--this.waiting && this.initialized) this.resolve();
		return true;
	}
};
<|endoftext|>