<commit_before>
SampleWindow = (function()
{
	function SampleWindow(wm, name)
	{
		this.Name = name;

		// Sample digest for checking if grid needs to be repopulated
		this.NbSamples = 0;
		this.SampleDigest = null;

		this.Window = wm.AddWindow(name, 100, 100, 100, 100);
		this.Visible = true;

		// This initially be set but true but it would currently require the sample window to disable
		// it when it gets added to a tab. Not sure how best to fix that right now.
		// TODO: Fix.
		this.AllowUpdate = false;

		// Create a grid that's indexed by the unique sample ID
		this.Grid = this.Window.AddControl(new WM.Grid(0, 0, 380, 400));
		this.Grid.AnchorWidthToParent(20);
		this.Grid.AnchorHeightToParent(20);
		this.RootRow = this.Grid.Rows.Add({ "Name": "Samples" }, "GridGroup", { "Name": "GridGroup" });
		this.RootRow.Rows.AddIndex("_ID");
	}

	SampleWindow.prototype.SetPosition = function(x, y)
	{
		this.Window.SetPosition(x, y);
	}

	SampleWindow.prototype.SetSize = function(width, height)
	{
		this.Window.SetSize(width, height);
		this.Grid.SetSize(width - 20, height - 20);
	}

	SampleWindow.prototype.SetVisible = function(visible)
	{
		if (visible != this.Visible)
		{
			if (visible == true)
				this.Window.Show();
			else
				this.Window.Hide();

			this.Visible = visible;
		}
	}

	SampleWindow.prototype.SetAllowUpdate = function(allow_update)
	{
		this.AllowUpdate = allow_update;
	}

	SampleWindow.prototype.OnSamples = function(nb_samples, sample_digest, samples)
	{
		if (!this.Visible || !this.AllowUpdate)
			return;

		// Recreate all the HTML if the number of samples gets bigger
		if (nb_samples > this.NbSamples)
		{
			GrowGrid(this.RootRow, nb_samples);
			this.NbSamples = nb_samples;
		}

		// If the content of the samples changes from previous update, update them all
		if (this.SampleDigest != sample_digest)
		{
			this.RootRow.Rows.ClearIndex("_ID");
			var index = UpdateSamples(this.RootRow, samples, 0, "");
			this.SampleDigest = sample_digest;

			// Clear out any left-over rows
			for (var i = index; i < this.RootRow.Rows.Rows.length; i++)
			{
				var row = this.RootRow.Rows.Rows[i];
				DOM.Node.Hide(row.Node);
			}
		}

		else if (this.Visible)
		{
			// Otherwise just update the existing sample times
			UpdateSampleTimes(this.RootRow, samples);
		}
	}

	function GrowGrid(parent_row, nb_samples)
	{
		parent_row.Rows.Clear();

		for (var i = 0; i < nb_samples; i++)
		{
			var cell_data =
			{
				_ID: i,
				Name: "",
				Control: new WM.Label()
			};

			var cell_classes =
			{
				Name: "SampleNameCell",
			};

			parent_row.Rows.Add(cell_data, null, cell_classes);
		}
	}

	function UpdateSamples(parent_row, samples, index, indent)
	{
		for (var i in samples)
		{
			var sample = samples[i];

			// Match row allocation in GrowGrid
			var row = parent_row.Rows.Rows[index++];

			// Sample row may have been hidden previously
			DOM.Node.Show(row.Node);

			// Assign unique ID so that the common fast path of updating sample times only
			// can lookup target samples in the grid
			row.CellData._ID = sample.id;
			parent_row.Rows.AddRowToIndex("_ID", sample.id, row);

			// Set sample name and colour
			var name_node = row.CellNodes["Name"];
			name_node.innerHTML = indent + sample.name;
			DOM.Node.SetColour(name_node, sample.colour);

			row.CellData.Control.SetText(sample.us_length);

			index = UpdateSamples(parent_row, sample.children, index, indent + "     ");
		}

		return index;
	}

	function UpdateSampleTimes(parent_row, samples)
	{
		for (var i in samples)
		{
			var sample = samples[i];

			var row = parent_row.Rows.GetBy("_ID", sample.id);
			if (row)
				row.CellData.Control.SetText(sample.us_length);

			UpdateSampleTimes(parent_row, sample.children);
		}
	}

	return SampleWindow;
})();<commit_msg>Support for multiple roots in sample windows.<commit_after>
SampleRoot = (function()
{
	function SampleRoot(grid, name)
	{
		this.NbSamples = 0;
		this.SampleDigest = null;

		// Create a set of rows indexed by the unique sample ID
		this.RootRow = grid.Rows.Add({ "Name": name }, "GridGroup", { "Name": "GridGroup" });
		this.RootRow.Rows.AddIndex("_ID");
	}

	SampleRoot.prototype.OnSamples = function(nb_samples, sample_digest, samples)
	{
		// Recreate all the HTML if the number of samples gets bigger
		if (nb_samples > this.NbSamples)
			SetNbSamples(this, nb_samples);

		// If the content of the samples changes from previous update, update them all
		if (this.SampleDigest != sample_digest)
		{
			this.RootRow.Rows.ClearIndex("_ID");
			var index = UpdateSamples(this, samples, 0, "");
			this.SampleDigest = sample_digest;

			// Clear out any left-over rows
			for (var i = index; i < this.RootRow.Rows.Rows.length; i++)
			{
				var row = this.RootRow.Rows.Rows[i];
				DOM.Node.Hide(row.Node);
			}
		}

		else
		{
			// Otherwise just update the existing sample times
			UpdateSampleTimes(this, samples);
		}
	}

	function SetNbSamples(self, nb_samples)
	{
		self.RootRow.Rows.Clear();

		for (var i = 0; i < nb_samples; i++)
		{
			var cell_data =
			{
				_ID: i,
				Name: "",
				Control: new WM.Label()
			};

			var cell_classes =
			{
				Name: "SampleNameCell",
			};

			self.RootRow.Rows.Add(cell_data, null, cell_classes);
		}

		self.NbSamples = nb_samples;
	}

	function UpdateSamples(self, samples, index, indent)
	{
		for (var i in samples)
		{
			var sample = samples[i];

			// Match row allocation in GrowGrid
			var row = self.RootRow.Rows.Rows[index++];

			// Sample row may have been hidden previously
			DOM.Node.Show(row.Node);

			// Assign unique ID so that the common fast path of updating sample times only
			// can lookup target samples in the grid
			row.CellData._ID = sample.id;
			self.RootRow.Rows.AddRowToIndex("_ID", sample.id, row);

			// Set sample name and colour
			var name_node = row.CellNodes["Name"];
			name_node.innerHTML = indent + sample.name;
			DOM.Node.SetColour(name_node, sample.colour);

			row.CellData.Control.SetText(sample.us_length);

			index = UpdateSamples(self, sample.children, index, indent + "     ");
		}

		return index;
	}

	function UpdateSampleTimes(self, samples)
	{
		for (var i in samples)
		{
			var sample = samples[i];

			var row = self.RootRow.Rows.GetBy("_ID", sample.id);
			if (row)
				row.CellData.Control.SetText(sample.us_length);

			UpdateSampleTimes(self, sample.children);
		}
	}

	return SampleRoot;
})();

SampleWindow = (function()
{
	function SampleWindow(wm, name)
	{
		this.Name = name;

		// Sample digest for checking if grid needs to be repopulated
		this.NbSamples = 0;
		this.SampleDigest = null;

		this.Window = wm.AddWindow(name, 100, 100, 100, 100);
		this.Visible = true;

		// This initially be set but true but it would currently require the sample window to disable
		// it when it gets added to a tab. Not sure how best to fix that right now.
		// TODO: Fix.
		this.AllowUpdate = false;

		// A dictionary of grouped samples
		this.SampleRoots = { };

		// Create a grid that's indexed by the unique sample ID
		this.Grid = this.Window.AddControl(new WM.Grid(0, 0, 380, 400));
		this.Grid.AnchorWidthToParent(20);
		this.Grid.AnchorHeightToParent(20);
	}

	SampleWindow.prototype.SetPosition = function(x, y)
	{
		this.Window.SetPosition(x, y);
	}

	SampleWindow.prototype.SetSize = function(width, height)
	{
		this.Window.SetSize(width, height);
		this.Grid.SetSize(width - 20, height - 20);
	}

	SampleWindow.prototype.SetVisible = function(visible)
	{
		if (visible != this.Visible)
		{
			if (visible == true)
				this.Window.Show();
			else
				this.Window.Hide();

			this.Visible = visible;
		}
	}

	SampleWindow.prototype.SetAllowUpdate = function(allow_update)
	{
		this.AllowUpdate = allow_update;
	}

	SampleWindow.prototype.OnSamples = function(nb_samples, sample_digest, samples)
	{
		if (!this.Visible || !this.AllowUpdate)
			return;
		if (nb_samples == 0)
			return;

		// TODO: Handle Select in Timeline
		// TODO: Discard old sample roots after timeout
		// TODO: Revisit whether a "GridGroup" CSS per sample root is the right choice

		// Add roots on demand
		var root_name = samples[0].name;
		if (!(root_name in this.SampleRoots))
		{
			var sample_root = new SampleRoot(this.Grid, root_name);
			this.SampleRoots[root_name] = sample_root;
		}

		// Dispatch to sample root
		var sample_root = this.SampleRoots[root_name];
		sample_root.OnSamples(nb_samples, sample_digest, samples);
	}

	return SampleWindow;
})();<|endoftext|>


<commit_before>'use strict';
require('../globals');
var util = require('../util'),
  time = require('./time'),
  colorbrewer = require('colorbrewer'),
  interpolate = require('d3-color').interpolateHsl,
  schema = require('../schema/schema');

var scale = module.exports = {};

scale.names = function(props) {
  return util.keys(util.keys(props).reduce(function(a, x) {
    if (props[x] && props[x].scale) a[props[x].scale] = 1;
    return a;
  }, {}));
};

scale.defs = function(names, encoding, layout, stats, opt) {
  opt = opt || {};

  return names.reduce(function(a, name) {
    var s = {
      name: name,
      type: scale.type(name, encoding),
      domain: scale.domain(name, encoding, stats, opt)
    };

    s.sort = scale.sort(s.type, encoding, name) || undefined;

    scale.range(s, encoding, layout, stats, opt);

    return (a.push(s), a);
  }, []);
};

/**
 * Produce vega's scale `sort` property.
 * @return {Boolean|Object} Return undefined if the scale is not an ordinal scale.
 * For an ordinal scale, return the sort object if provided,
 * or return true otherwise.
 */
scale.sort = function(type, encoding, name) {
  if (type === 'ordinal') {
    return encoding.sort(name) || undefined;
  }
  return undefined;
};

scale.type = function(name, encoding) {

  switch (encoding.type(name)) {
    case N: //fall through
    case O: return 'ordinal';
    case T:
      var timeUnit = encoding.field(name).timeUnit;
      return timeUnit ? time.scale.type(timeUnit, name) : 'time';
    case Q:
      if (encoding.bin(name)) {
        // TODO: revise this
        return name === COLOR ? 'linear' : 'ordinal';
      }
      return encoding.scale(name).type;
  }
};

scale.domain = function (name, encoding, stats, opt) {
  var field = encoding.field(name);

  if (encoding.isType(name, T)) {
    var range = time.scale.domain(field.timeUnit, name);
    if(range) return range;
  }

  if (field.bin) {
    // TODO(kanitw): this must be changed in vg2
    var fieldStat = stats[field.name],
      bins = util.getbins(fieldStat, field.bin.maxbins || schema.MAXBINS_DEFAULT),
      numbins = (bins.stop - bins.start) / bins.step;
    return util.range(numbins).map(function(i) {
      return bins.start + bins.step * i;
    });
  }

  if (name == opt.stack) {
    return {
      data: STACKED,
      field: encoding.fieldRef(name, {
        prefn: (opt.facet ? 'max_' : '') + 'sum_'
      })
    };
  }
  var aggregate = encoding.aggregate(name),
    timeUnit = field.timeUnit,
    scaleUseRawDomain = encoding.scale(name).useRawDomain,
    useRawDomain = scaleUseRawDomain !== undefined ?
      scaleUseRawDomain : encoding.config('useRawDomain'),
    notCountOrSum = !aggregate || (aggregate !=='count' && aggregate !== 'sum');

  // FIXME revise this part

  if ( useRawDomain && notCountOrSum && (
      // Q always uses non-ordinal scale except when it's binned and thus uses ordinal scale.
      (encoding.isType(name, Q) && !field.bin) ||
      // T uses non-ordinal scale when there's no unit or when the unit is not ordinal.
      (encoding.isType(name, T) && (!timeUnit || !time.isOrdinalFn(timeUnit)))
    )
  ) {

    return {data: RAW, field: encoding.fieldRef(name)};
  }

  return {data: encoding.dataTable(), field: encoding.fieldRef(name)};
};

scale.range = function (s, encoding, layout, stats) {
  var spec = encoding.scale(s.name),
    field = encoding.field(s.name),
    timeUnit = field.timeUnit;

  switch (s.name) {
    case X:
      s.range = layout.cellWidth ? [0, layout.cellWidth] : 'width';
      if (s.type === 'ordinal') {
        s.bandWidth = encoding.bandSize(X, layout.x.useSmallBand);
      } else {
        if (encoding.isType(s.name,T) && timeUnit === 'year') {
          s.zero = false;
        } else {
          s.zero = spec.zero === undefined ? true : spec.zero;
        }

        s.reverse = spec.reverse;
      }
      s.round = true;
      if (s.type === 'time') {
        s.nice = timeUnit || encoding.config('timeScaleNice');
      }else {
        s.nice = true;
      }
      break;
    case Y:
      if (s.type === 'ordinal') {
        s.range = layout.cellHeight ?
          (field.bin ? [layout.cellHeight, 0] : [0, layout.cellHeight]) :
          'height';
        s.bandWidth = encoding.bandSize(Y, layout.y.useSmallBand);
      } else {
        s.range = layout.cellHeight ? [layout.cellHeight, 0] : 'height';
        if (encoding.isType(s.name,T) && timeUnit === 'year') {
          s.zero = false;
        } else {
          s.zero = spec.zero === undefined ? true : spec.zero;
        }

        s.reverse = spec.reverse;
      }

      s.round = true;

      if (s.type === 'time') {
        s.nice = timeUnit || encoding.config('timeScaleNice');
      }else {
        s.nice = true;
      }
      break;
    case ROW: // support only ordinal
      s.bandWidth = layout.cellHeight;
      s.round = true;
      s.nice = true;
      break;
    case COL: // support only ordinal
      s.bandWidth = layout.cellWidth;
      s.round = true;
      s.nice = true;
      break;
    case SIZE:
      if (encoding.is('bar')) {
        // FIXME this is definitely incorrect
        // but let's fix it later since bar size is a bad encoding anyway
        s.range = [3, Math.max(encoding.bandSize(X), encoding.bandSize(Y))];
      } else if (encoding.is(TEXT)) {
        s.range = [8, 40];
      } else { //point
        var bandSize = Math.min(encoding.bandSize(X), encoding.bandSize(Y)) - 1;
        s.range = [10, 0.8 * bandSize*bandSize];
      }
      s.round = true;
      s.zero = false;
      break;
    case SHAPE:
      s.range = 'shapes';
      break;
    case COLOR:
      s.range = scale.color(s, encoding, stats);
      if (s.type !== 'ordinal') s.zero = false;
      break;
    default:
      throw new Error('Unknown encoding name: '+ s.name);
  }

  // FIXME(kanitw): Jul 29, 2015 - consolidate this with above
  switch (s.name) {
    case ROW:
    case COL:
      s.padding = encoding.config('cellPadding');
      s.outerPadding = 0;
      break;
    case X:
    case Y:
      if (s.type === 'ordinal') { //&& !s.bandWidth
        s.points = true;
        s.padding = encoding.field(s.name).band.padding;
      }
  }
};

scale.color = function(s, encoding, stats) {
  var colorScale = encoding.scale(COLOR),
    range = colorScale.range,
    cardinality = encoding.cardinality(COLOR, stats),
    type = encoding.type(COLOR);

  if (range === undefined) {
    var ordinalPalette = colorScale.ordinalPalette,
      quantitativeRange = colorScale.quantitativeRange;

    if (s.type === 'ordinal') {
      if (type === N) {
        // use categorical color scale
        if (cardinality <= 10) {
          range = colorScale.c10palette;
        } else {
          range = colorScale.c20palette;
        }
        return scale.color.palette(range, cardinality, type);
      } else {
        if (ordinalPalette) {
          return scale.color.palette(ordinalPalette, cardinality, type);
        }
        return scale.color.interpolate(quantitativeRange[0], quantitativeRange[1], cardinality);
      }
    } else { //time or quantitative
      return [quantitativeRange[0], quantitativeRange[1]];
    }
  }
};

scale.color.palette = function(range, cardinality, type) {
  // FIXME(kanitw): Jul 29, 2015 - check range is string
  switch (range) {
    case 'category10k':
      // tableau's category 10, ordered by perceptual kernel study results
      // https://github.com/uwdata/perceptual-kernels
      return ['#2ca02c', '#e377c2', '#7f7f7f', '#17becf', '#8c564b', '#d62728', '#bcbd22', '#9467bd', '#ff7f0e', '#1f77b4'];

    // d3/tableau category10/20/20b/20c
    case 'category10':
      return ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'];

    case 'category20':
      return ['#1f77b4', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c', '#98df8a', '#d62728', '#ff9896', '#9467bd', '#c5b0d5', '#8c564b', '#c49c94', '#e377c2', '#f7b6d2', '#7f7f7f', '#c7c7c7', '#bcbd22', '#dbdb8d', '#17becf', '#9edae5'];

    case 'category20b':
      return ['#393b79', '#5254a3', '#6b6ecf', '#9c9ede', '#637939', '#8ca252', '#b5cf6b', '#cedb9c', '#8c6d31', '#bd9e39', '#e7ba52', '#e7cb94', '#843c39', '#ad494a', '#d6616b', '#e7969c', '#7b4173', '#a55194', '#ce6dbd', '#de9ed6'];

    case 'category20c':
      return ['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#e6550d', '#fd8d3c', '#fdae6b', '#fdd0a2', '#31a354', '#74c476', '#a1d99b', '#c7e9c0', '#756bb1', '#9e9ac8', '#bcbddc', '#dadaeb', '#636363', '#969696', '#bdbdbd', '#d9d9d9'];
  }

  // TODO add our own set of custom ordinal color palette

  if (range in colorbrewer) {
    var palette = colorbrewer[range];

    // if cardinality pre-defined, use it.
    if (cardinality in palette) return palette[cardinality];

    // if not, use the highest cardinality one for nominal
    if (type === N) {
      return palette[Math.max.apply(null, util.keys(palette))];
    }

    // otherwise, interpolate
    var ps = cardinality < 3 ? 3 : Math.max.apply(null, util.keys(palette)),
      from = 0 , to = ps - 1;
    // FIXME add config for from / to

    return scale.color.interpolate(palette[ps][from], palette[ps][to], cardinality);
  }

  return range;
};

scale.color.interpolate = function (start, end, cardinality) {

  var interpolator = interpolate(start, end);
  return util.range(cardinality).map(function(i) { return interpolator(i*1.0/(cardinality-1)); });
};
<commit_msg>add sort property to the domain<commit_after>'use strict';
require('../globals');
var util = require('../util'),
  time = require('./time'),
  colorbrewer = require('colorbrewer'),
  interpolate = require('d3-color').interpolateHsl,
  schema = require('../schema/schema');

var scale = module.exports = {};

scale.names = function(props) {
  return util.keys(util.keys(props).reduce(function(a, x) {
    if (props[x] && props[x].scale) a[props[x].scale] = 1;
    return a;
  }, {}));
};

scale.defs = function(names, encoding, layout, stats, opt) {
  opt = opt || {};

  return names.reduce(function(a, name) {
    var s = {
      name: name,
      type: scale.type(name, encoding)
    };

    s.domain = scale.domain(s, encoding, stats, opt);
    scale.range(s, encoding, layout, stats, opt);

    return (a.push(s), a);
  }, []);
};

scale.type = function(name, encoding) {

  switch (encoding.type(name)) {
    case N: //fall through
    case O: return 'ordinal';
    case T:
      var timeUnit = encoding.field(name).timeUnit;
      return timeUnit ? time.scale.type(timeUnit, name) : 'time';
    case Q:
      if (encoding.bin(name)) {
        // TODO: revise this
        return name === COLOR ? 'linear' : 'ordinal';
      }
      return encoding.scale(name).type;
  }
};

scale.domain = function (s, encoding, stats, opt) {
  opt = opt || {};

  var name = s.name;

  var field = encoding.field(name);

  if (encoding.isType(name, T)) {
    var range = time.scale.domain(field.timeUnit, name);
    if(range) return range;
  }

  if (field.bin) {
    // TODO(kanitw): this must be changed in vg2
    var fieldStat = stats[field.name],
      bins = util.getbins(fieldStat, field.bin.maxbins || schema.MAXBINS_DEFAULT),
      numbins = (bins.stop - bins.start) / bins.step;
    return util.range(numbins).map(function(i) {
      return bins.start + bins.step * i;
    });
  }

  if (name == opt.stack) {
    return {
      data: STACKED,
      field: encoding.fieldRef(name, {
        prefn: (opt.facet ? 'max_' : '') + 'sum_'
      })
    };
  }
  var aggregate = encoding.aggregate(name),
    timeUnit = field.timeUnit,
    scaleUseRawDomain = encoding.scale(name).useRawDomain,
    useRawDomain = scaleUseRawDomain !== undefined ?
      scaleUseRawDomain : encoding.config('useRawDomain'),
    notCountOrSum = !aggregate || (aggregate !=='count' && aggregate !== 'sum');

  var dataTable = encoding.dataTable();
  if ( useRawDomain && notCountOrSum && (
      // Q always uses non-ordinal scale except when it's binned and thus uses ordinal scale.
      (encoding.isType(name, Q) && !field.bin) ||
      // T uses non-ordinal scale when there's no unit or when the unit is not ordinal.
      (encoding.isType(name, T) && (!timeUnit || !time.isOrdinalFn(timeUnit)))
    )
  ) {
    dataTable = RAW;
  }

  var domain = {
    data: dataTable,
    field: encoding.fieldRef(name)
  };

  // For ordinal scale, add domain's property if provided.
  var sort = s.type === 'ordinal' && encoding.sort(name);
  if (sort) { domain.sort = sort; }

  return domain;
};

scale.range = function (s, encoding, layout, stats) {
  var spec = encoding.scale(s.name),
    field = encoding.field(s.name),
    timeUnit = field.timeUnit;

  switch (s.name) {
    case X:
      s.range = layout.cellWidth ? [0, layout.cellWidth] : 'width';
      if (s.type === 'ordinal') {
        s.bandWidth = encoding.bandSize(X, layout.x.useSmallBand);
      } else {
        if (encoding.isType(s.name,T) && timeUnit === 'year') {
          s.zero = false;
        } else {
          s.zero = spec.zero === undefined ? true : spec.zero;
        }

        s.reverse = spec.reverse;
      }
      s.round = true;
      if (s.type === 'time') {
        s.nice = timeUnit || encoding.config('timeScaleNice');
      }else {
        s.nice = true;
      }
      break;
    case Y:
      if (s.type === 'ordinal') {
        s.range = layout.cellHeight ?
          (field.bin ? [layout.cellHeight, 0] : [0, layout.cellHeight]) :
          'height';
        s.bandWidth = encoding.bandSize(Y, layout.y.useSmallBand);
      } else {
        s.range = layout.cellHeight ? [layout.cellHeight, 0] : 'height';
        if (encoding.isType(s.name,T) && timeUnit === 'year') {
          s.zero = false;
        } else {
          s.zero = spec.zero === undefined ? true : spec.zero;
        }

        s.reverse = spec.reverse;
      }

      s.round = true;

      if (s.type === 'time') {
        s.nice = timeUnit || encoding.config('timeScaleNice');
      }else {
        s.nice = true;
      }
      break;
    case ROW: // support only ordinal
      s.bandWidth = layout.cellHeight;
      s.round = true;
      s.nice = true;
      break;
    case COL: // support only ordinal
      s.bandWidth = layout.cellWidth;
      s.round = true;
      s.nice = true;
      break;
    case SIZE:
      if (encoding.is('bar')) {
        // FIXME this is definitely incorrect
        // but let's fix it later since bar size is a bad encoding anyway
        s.range = [3, Math.max(encoding.bandSize(X), encoding.bandSize(Y))];
      } else if (encoding.is(TEXT)) {
        s.range = [8, 40];
      } else { //point
        var bandSize = Math.min(encoding.bandSize(X), encoding.bandSize(Y)) - 1;
        s.range = [10, 0.8 * bandSize*bandSize];
      }
      s.round = true;
      s.zero = false;
      break;
    case SHAPE:
      s.range = 'shapes';
      break;
    case COLOR:
      s.range = scale.color(s, encoding, stats);
      if (s.type !== 'ordinal') s.zero = false;
      break;
    default:
      throw new Error('Unknown encoding name: '+ s.name);
  }

  // FIXME(kanitw): Jul 29, 2015 - consolidate this with above
  switch (s.name) {
    case ROW:
    case COL:
      s.padding = encoding.config('cellPadding');
      s.outerPadding = 0;
      break;
    case X:
    case Y:
      if (s.type === 'ordinal') { //&& !s.bandWidth
        s.points = true;
        s.padding = encoding.field(s.name).band.padding;
      }
  }
};

scale.color = function(s, encoding, stats) {
  var colorScale = encoding.scale(COLOR),
    range = colorScale.range,
    cardinality = encoding.cardinality(COLOR, stats),
    type = encoding.type(COLOR);

  if (range === undefined) {
    var ordinalPalette = colorScale.ordinalPalette,
      quantitativeRange = colorScale.quantitativeRange;

    if (s.type === 'ordinal') {
      if (type === N) {
        // use categorical color scale
        if (cardinality <= 10) {
          range = colorScale.c10palette;
        } else {
          range = colorScale.c20palette;
        }
        return scale.color.palette(range, cardinality, type);
      } else {
        if (ordinalPalette) {
          return scale.color.palette(ordinalPalette, cardinality, type);
        }
        return scale.color.interpolate(quantitativeRange[0], quantitativeRange[1], cardinality);
      }
    } else { //time or quantitative
      return [quantitativeRange[0], quantitativeRange[1]];
    }
  }
};

scale.color.palette = function(range, cardinality, type) {
  // FIXME(kanitw): Jul 29, 2015 - check range is string
  switch (range) {
    case 'category10k':
      // tableau's category 10, ordered by perceptual kernel study results
      // https://github.com/uwdata/perceptual-kernels
      return ['#2ca02c', '#e377c2', '#7f7f7f', '#17becf', '#8c564b', '#d62728', '#bcbd22', '#9467bd', '#ff7f0e', '#1f77b4'];

    // d3/tableau category10/20/20b/20c
    case 'category10':
      return ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'];

    case 'category20':
      return ['#1f77b4', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c', '#98df8a', '#d62728', '#ff9896', '#9467bd', '#c5b0d5', '#8c564b', '#c49c94', '#e377c2', '#f7b6d2', '#7f7f7f', '#c7c7c7', '#bcbd22', '#dbdb8d', '#17becf', '#9edae5'];

    case 'category20b':
      return ['#393b79', '#5254a3', '#6b6ecf', '#9c9ede', '#637939', '#8ca252', '#b5cf6b', '#cedb9c', '#8c6d31', '#bd9e39', '#e7ba52', '#e7cb94', '#843c39', '#ad494a', '#d6616b', '#e7969c', '#7b4173', '#a55194', '#ce6dbd', '#de9ed6'];

    case 'category20c':
      return ['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#e6550d', '#fd8d3c', '#fdae6b', '#fdd0a2', '#31a354', '#74c476', '#a1d99b', '#c7e9c0', '#756bb1', '#9e9ac8', '#bcbddc', '#dadaeb', '#636363', '#969696', '#bdbdbd', '#d9d9d9'];
  }

  // TODO add our own set of custom ordinal color palette

  if (range in colorbrewer) {
    var palette = colorbrewer[range];

    // if cardinality pre-defined, use it.
    if (cardinality in palette) return palette[cardinality];

    // if not, use the highest cardinality one for nominal
    if (type === N) {
      return palette[Math.max.apply(null, util.keys(palette))];
    }

    // otherwise, interpolate
    var ps = cardinality < 3 ? 3 : Math.max.apply(null, util.keys(palette)),
      from = 0 , to = ps - 1;
    // FIXME add config for from / to

    return scale.color.interpolate(palette[ps][from], palette[ps][to], cardinality);
  }

  return range;
};

scale.color.interpolate = function (start, end, cardinality) {

  var interpolator = interpolate(start, end);
  return util.range(cardinality).map(function(i) { return interpolator(i*1.0/(cardinality-1)); });
};
<|endoftext|>


<commit_before>import '../styles/App.css';
import React, { Component, PropTypes } from 'react';
import CSSTransitionGroup from 'react-addons-css-transition-group';
import { Link } from 'react-router';
import { toggleMenu, closeMenu } from '../actions/UIActions';
import Overview from '../components/Overview';
import Header from './Header';
import Icon from '../components/Icon';

const MENU_ITEMS = [
  ['/events', 'Arrangementer'],
  ['', 'readme'],
  ['', 'Karriere'],
  ['', 'BDB'],
  ['', 'Møter'],
  ['', 'Utland'],
  ['', 'Spørreskjema'],
  ['', 'Butikk']
];

export default class App extends Component {

  static propTypes = {
    children: PropTypes.any,
    auth: PropTypes.object.isRequired,
    dispatch: PropTypes.func.isRequired,
    menuOpen: PropTypes.bool.isRequired,
    loginOpen: PropTypes.bool.isRequired,
    search: PropTypes.object.isRequired,
    loggedIn: PropTypes.bool.isRequired
  }

  render() {
    const { dispatch, menuOpen } = this.props;

    return (

 dispatch(closeMenu())}>

               (e.stopPropagation(), dispatch(toggleMenu()))} className={menuOpen ? 'active' : ''}>
                <Icon name={menuOpen ? 'times' : 'bars'} />

        <CSSTransitionGroup transitionName='menu'>
          {menuOpen &&

            {MENU_ITEMS.map((item, i) => <Link to={item[0]} key={i}>{item[1]}</Link>)}

}
        </CSSTransitionGroup>

        {React.cloneElement(this.props.children, this.props)}

Abakus er best

    );
  }
}
<commit_msg>Create basic user profile page<commit_after>import '../styles/App.css';
import React, { Component, PropTypes } from 'react';
import CSSTransitionGroup from 'react-addons-css-transition-group';
import { Link } from 'react-router';
import { toggleMenu, closeMenu } from '../actions/UIActions';
import Overview from '../components/Overview';
import Header from './Header';
import Icon from '../components/Icon';

const MENU_ITEMS = [
  ['/events', 'Arrangementer'],
  ['', 'readme'],
  ['', 'Karriere'],
  ['', 'BDB'],
  ['', 'Møter'],
  ['', 'Utland'],
  ['', 'Spørreskjema'],
  ['', 'Butikk']
];

export default class App extends Component {

  static propTypes = {
    children: PropTypes.any,
    auth: PropTypes.object.isRequired,
    dispatch: PropTypes.func.isRequired,
    menuOpen: PropTypes.bool.isRequired,
    loginOpen: PropTypes.bool.isRequired,
    search: PropTypes.object.isRequired,
    loggedIn: PropTypes.bool.isRequired
  }

  renderChildren() {
    if (this.props.children) {
      return React.cloneElement(this.props.children, this.props);
    }

    return <Overview {...this.props} />;
  }

  render() {
    const { dispatch, menuOpen } = this.props;

    return (

 dispatch(closeMenu())}>

               (e.stopPropagation(), dispatch(toggleMenu()))} className={menuOpen ? 'active' : ''}>
                <Icon name={menuOpen ? 'times' : 'bars'} />

        <CSSTransitionGroup transitionName='menu'>
          {menuOpen &&

            {MENU_ITEMS.map((item, i) => <Link to={item[0]} key={i}>{item[1]}</Link>)}

}
        </CSSTransitionGroup>

        {this.renderChildren()}

Abakus er best

    );
  }
}
<|endoftext|>


<commit_before>'use strict';
var injectTapEventPlugin = require("react-tap-event-plugin");
//Needed for onTouchTap
//Can go away when react 1.0 release
//Check this repo:
//https://github.com/zilverline/react-tap-event-plugin
injectTapEventPlugin();
require('normalize.css');

require('../styles/fonts.css');
require('../styles/main.less');
var React = require('react');
var mui = require('material-ui');
var ThemeManager = new mui.Styles.ThemeManager();

var Editor = require('./Editor');

var App = React.createClass({

  childContextTypes: {
    muiTheme: React.PropTypes.object
  },

  getChildContext: function() {
    return {
      muiTheme: ThemeManager.getCurrentTheme()
    };
  },

  render: function() {
    return (

        <Editor />

    );
  }
});
React.render(<App />, document.getElementById('content'));

module.exports = App;
<commit_msg>move theme out of app<commit_after>'use strict';
var injectTapEventPlugin = require("react-tap-event-plugin");
//Needed for onTouchTap
//Can go away when react 1.0 release
//Check this repo:
//https://github.com/zilverline/react-tap-event-plugin
injectTapEventPlugin();
require('normalize.css');

require('../styles/fonts.css');
require('mdi/css/materialdesignicons.css');
require('../styles/main.less');
var React = require('react');

var Editor = require('./Editor');

var App = React.createClass({

  render() {
    return (

        <Editor />

    );
  }
});
React.render(<App />, document.getElementById('content'));

module.exports = App;
<|endoftext|>


<commit_before>// @flow
import React from 'react';
import ClassNames from 'classnames';

import Display from './Display';
import ViewLayerList from './ViewLayerList';
import {ActionLayer, DRAW_LINE, ERASER} from './actionLayer/ActionLayer';
import ImageListManage from './imageListManage/ImageListManage';
import Header from './header/Header';

import {
  synthesizeImageData,
  convertBlobToImageData,
  convertImageDataToBlob,
  resizeImageData,
} from '../imageData';
import {invertNegaPosi} from '../editImageDataPixel';
import {
  generateImageList,
  SPECIFY_IMAGE_PROPERTY,
  ADD_NEW_IMAGE,
} from '../state/generateImageList';
import {
  generateActionLayerSettings,
  SPECIFY_CONTEXT_PROPERTY,
} from '../state/generateActionLayerSettings';
import {
  generateImageListHistory,
  BACK,
  FORWARD,
  UPDATE,
  START_OMIT_LENGTH_COUNT,
  OMIT,
} from '../state/generateImageListHistory';
import initialState from '../state/initialState';

import type {DisplayType} from './Display';
import type {Image} from '../image';
import type {ActionLayerName} from './actionLayer/ActionLayer';
import type {ActionLayerSettings} from '../state/generateActionLayerSettings';
import type {ImageListHistory} from '../state/generateImageListHistory';

const MIME_PING = 'image/png';
const MIME_JPEG = 'image/jpeg';
const ALLOW_FILE_TYPES = [MIME_PING, MIME_JPEG];

type Props = {||};
type State = {
  isDragOver: boolean,
  imageListHistory: ImageListHistory,
  display: DisplayType,
  activeActionLayer: ActionLayerName,
  actionLayerSettings: ActionLayerSettings,
};

function isAllowedFileType(uploadedFileType: string): boolean {
  return ALLOW_FILE_TYPES.some(
    allowFileType => allowFileType === uploadedFileType
  );
}

export default class App extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = initialState;
  }
  getActiveImage(): Image {
    const {history, position} = this.state.imageListHistory;
    return history[position].filter(image => image.isActive === true)[0];
  }
  updateImageList(imageList: Image[]): void {
    this.setState({
      imageListHistory: generateImageListHistory({
        type: UPDATE,
        currentState: this.state.imageListHistory,
        imageList,
      }),
    });
  }
  updateImageListHistory(imageListHistory: ImageListHistory): void {
    this.setState({imageListHistory});
  }
  uploadImageFile(files: FileList): void {
    if (files.length > 1) {
      this.handleError('複数のファイルは選べません');
      return;
    }
    const file = files[0];
    if (!file) return; // ファイルアップロードのダイアログでキャンセルした場合の対応
    if (!isAllowedFileType(file.type)) {
      this.handleError('対応しているファイルはjpegとpngのみです');
      return;
    }
    convertBlobToImageData(file).then(imageData => {
      const {history, position} = this.state.imageListHistory;
      const updatedState = generateImageList({
        type: ADD_NEW_IMAGE,
        data: {imageData},
        currentState: history[position],
      });
      const {width, height} = this.state.display;
      const changeWidth = imageData.width > width ? imageData.width : width;
      const changeHeight =
        imageData.height > height ? imageData.height : height;
      if (changeWidth !== width || changeHeight !== height) {
        this.changeDisplaySize(changeWidth, changeHeight);
      }
      this.updateImageList(updatedState);
    });
  }
  downloadImageFile(): void {
    this.generateDisplayImageData()
      .then(imageData => convertImageDataToBlob(imageData).then(blob => blob))
      .then(blob => {
        const url = URL.createObjectURL(blob);
        const elem = document.createElement('a');
        elem.href = url;
        elem.download = `${new Date().toISOString()}.png`;
        elem.click();
        URL.revokeObjectURL(url);
      });
  }
  generateDisplayImageData(): Promise<ImageData> {
    const {history, position} = this.state.imageListHistory;
    const targetImageDatas = history[position]
      .concat()
      .filter(i => i.isShow)
      .map(i => i.imageData)
      .reverse();
    const {width, height} = this.state.display;
    return synthesizeImageData(targetImageDatas, width, height).then(
      result => result
    );
  }
  /* eslint-disable */
  handleError(error: string): void {
    console.log(error);
    // TODO: 受け取った値に応じてエラーメッセージを返すようにする
  }
  /* eslint-enable */
  changeDisplaySize(width: number, height: number): void {
    this.setState({
      display: Object.assign({}, this.state.display, {width, height}),
    });
  }
  render() {
    const {
      isDragOver,
      imageListHistory,
      display,
      activeActionLayer,
      actionLayerSettings,
    } = this.state;
    const {history, position} = imageListHistory;
    const imageList = history[position];
    const activeImage = this.getActiveImage();
    const classNames = ClassNames({
      app: true,
      'file-drag-over-area': isDragOver,
    });
    return (

 {
          e.preventDefault();
          this.setState({isDragOver: false});
          this.uploadImageFile(e.dataTransfer.files);
        }}
        onDragOver={e => {
          e.preventDefault();
          e.dataTransfer.dropEffect = 'copy';
        }}
        onDragEnter={e => {
          e.preventDefault();
          this.setState({isDragOver: true});
        }}
        onDragLeave={e => {
          e.preventDefault();
          if (e.clientX === 0) this.setState({isDragOver: false});
        }}
      >
        <button
          onClick={() => {
            this.setState({
              activeActionLayer:
                this.state.activeActionLayer === DRAW_LINE ? ERASER : DRAW_LINE,
            });
          }}
        >
          ペン ⇔ 消しゴム
        </button>
        <button
          onClick={() => {
            const newValue =
              actionLayerSettings[DRAW_LINE].ctx.lineWidth === 1 ? 15 : 1;
            const newSetting = generateActionLayerSettings({
              type: SPECIFY_CONTEXT_PROPERTY,
              currentState: actionLayerSettings,
              data: {lineWidth: newValue},
              target: DRAW_LINE,
            });
            this.setState({actionLayerSettings: newSetting});
          }}
        >
          ペン（太） ⇔　ペン（細）
        </button>
        <button onClick={() => this.downloadImageFile()}>ダウンロード</button>
        <button
          onClick={() => {
            const imageData = invertNegaPosi(activeImage.imageData);
            const updatedState = generateImageList({
              type: SPECIFY_IMAGE_PROPERTY,
              data: {imageData},
              currentState: imageList,
              target: activeImage.id,
            });
            this.updateImageList(updatedState);
          }}
        >
          ネガポジ
        </button>
        <button
          onClick={() => {
            const imageData = resizeImageData(activeImage.imageData, 50);
            const updatedState = generateImageList({
              type: SPECIFY_IMAGE_PROPERTY,
              data: {imageData},
              currentState: imageList,
              target: activeImage.id,
            });
            this.updateImageList(updatedState);
          }}
        >
          50%縮小
        </button>
        <button
          onClick={() => {
            this.setState({
              imageListHistory: generateImageListHistory({
                type: BACK,
                currentState: imageListHistory,
              }),
            });
          }}
        >
          undo
        </button>
        <button
          onClick={() => {
            this.setState({
              imageListHistory: generateImageListHistory({
                type: FORWARD,
                currentState: imageListHistory,
              }),
            });
          }}
        >
          redo
        </button>
        <Display {...display}>
          <ViewLayerList viewLayerDataList={imageList} />
          <ActionLayer
            activeActionLayer={activeActionLayer}
            imageData={activeImage.imageData}
            setting={actionLayerSettings[activeActionLayer]}
            display={display}
            updateImageData={imageData => {
              const updatedState = generateImageList({
                type: SPECIFY_IMAGE_PROPERTY,
                data: {imageData},
                currentState: imageList,
                target: activeImage.id,
              });
              this.updateImageList(updatedState);
            }}
            startOmitLengthCount={() => {
              this.setState({
                imageListHistory: generateImageListHistory({
                  type: START_OMIT_LENGTH_COUNT,
                  currentState: imageListHistory,
                }),
              });
            }}
            omitImageListHistory={() => {
              if (!imageListHistory.omitLength) return;
              this.setState({
                imageListHistory: generateImageListHistory({
                  type: OMIT,
                  currentState: imageListHistory,
                }),
              });
            }}
          />
        </Display>
        <ImageListManage
          imageList={imageList}
          updateImageList={updatedImageList => {
            this.updateImageList(updatedImageList);
          }}
          display={{width: display.width, height: display.height}}
        />
         this.downloadImageFile()}
          uploadImageFile={fileList => this.uploadImageFile(fileList)}
          imageListHistory={imageListHistory}
          updateImageListHistory={updatedState =>
            this.updateImageListHistory(updatedState)}
        />
        {isDragOver && (

画像をドロップすると新しくレイヤーが作られます

        )}

    );
  }
}
<commit_msg>仮引数の名前を分かりやすくした。<commit_after>// @flow
import React from 'react';
import ClassNames from 'classnames';

import Display from './Display';
import ViewLayerList from './ViewLayerList';
import {ActionLayer, DRAW_LINE, ERASER} from './actionLayer/ActionLayer';
import ImageListManage from './imageListManage/ImageListManage';
import Header from './header/Header';

import {
  synthesizeImageData,
  convertBlobToImageData,
  convertImageDataToBlob,
  resizeImageData,
} from '../imageData';
import {invertNegaPosi} from '../editImageDataPixel';
import {
  generateImageList,
  SPECIFY_IMAGE_PROPERTY,
  ADD_NEW_IMAGE,
} from '../state/generateImageList';
import {
  generateActionLayerSettings,
  SPECIFY_CONTEXT_PROPERTY,
} from '../state/generateActionLayerSettings';
import {
  generateImageListHistory,
  BACK,
  FORWARD,
  UPDATE,
  START_OMIT_LENGTH_COUNT,
  OMIT,
} from '../state/generateImageListHistory';
import initialState from '../state/initialState';

import type {DisplayType} from './Display';
import type {Image} from '../image';
import type {ActionLayerName} from './actionLayer/ActionLayer';
import type {ActionLayerSettings} from '../state/generateActionLayerSettings';
import type {ImageListHistory} from '../state/generateImageListHistory';

const MIME_PING = 'image/png';
const MIME_JPEG = 'image/jpeg';
const ALLOW_FILE_TYPES = [MIME_PING, MIME_JPEG];

type Props = {||};
type State = {
  isDragOver: boolean,
  imageListHistory: ImageListHistory,
  display: DisplayType,
  activeActionLayer: ActionLayerName,
  actionLayerSettings: ActionLayerSettings,
};

function isAllowedFileType(uploadedFileType: string): boolean {
  return ALLOW_FILE_TYPES.some(
    allowFileType => allowFileType === uploadedFileType
  );
}

export default class App extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = initialState;
  }
  getActiveImage(): Image {
    const {history, position} = this.state.imageListHistory;
    return history[position].filter(image => image.isActive === true)[0];
  }
  updateImageList(imageList: Image[]): void {
    this.setState({
      imageListHistory: generateImageListHistory({
        type: UPDATE,
        currentState: this.state.imageListHistory,
        imageList,
      }),
    });
  }
  updateImageListHistory(imageListHistory: ImageListHistory): void {
    this.setState({imageListHistory});
  }
  uploadImageFile(files: FileList): void {
    if (files.length > 1) {
      this.handleError('複数のファイルは選べません');
      return;
    }
    const file = files[0];
    if (!file) return; // ファイルアップロードのダイアログでキャンセルした場合の対応
    if (!isAllowedFileType(file.type)) {
      this.handleError('対応しているファイルはjpegとpngのみです');
      return;
    }
    convertBlobToImageData(file).then(imageData => {
      const {history, position} = this.state.imageListHistory;
      const updatedState = generateImageList({
        type: ADD_NEW_IMAGE,
        data: {imageData},
        currentState: history[position],
      });
      const {width, height} = this.state.display;
      const changeWidth = imageData.width > width ? imageData.width : width;
      const changeHeight =
        imageData.height > height ? imageData.height : height;
      if (changeWidth !== width || changeHeight !== height) {
        this.changeDisplaySize(changeWidth, changeHeight);
      }
      this.updateImageList(updatedState);
    });
  }
  downloadImageFile(): void {
    this.generateDisplayImageData()
      .then(imageData => convertImageDataToBlob(imageData).then(blob => blob))
      .then(blob => {
        const url = URL.createObjectURL(blob);
        const elem = document.createElement('a');
        elem.href = url;
        elem.download = `${new Date().toISOString()}.png`;
        elem.click();
        URL.revokeObjectURL(url);
      });
  }
  generateDisplayImageData(): Promise<ImageData> {
    const {history, position} = this.state.imageListHistory;
    const targetImageDatas = history[position]
      .concat()
      .filter(i => i.isShow)
      .map(i => i.imageData)
      .reverse();
    const {width, height} = this.state.display;
    return synthesizeImageData(targetImageDatas, width, height).then(
      result => result
    );
  }
  /* eslint-disable */
  handleError(error: string): void {
    console.log(error);
    // TODO: 受け取った値に応じてエラーメッセージを返すようにする
  }
  /* eslint-enable */
  changeDisplaySize(width: number, height: number): void {
    this.setState({
      display: Object.assign({}, this.state.display, {width, height}),
    });
  }
  render() {
    const {
      isDragOver,
      imageListHistory,
      display,
      activeActionLayer,
      actionLayerSettings,
    } = this.state;
    const {history, position} = imageListHistory;
    const imageList = history[position];
    const activeImage = this.getActiveImage();
    const classNames = ClassNames({
      app: true,
      'file-drag-over-area': isDragOver,
    });
    return (

 {
          e.preventDefault();
          this.setState({isDragOver: false});
          this.uploadImageFile(e.dataTransfer.files);
        }}
        onDragOver={e => {
          e.preventDefault();
          e.dataTransfer.dropEffect = 'copy';
        }}
        onDragEnter={e => {
          e.preventDefault();
          this.setState({isDragOver: true});
        }}
        onDragLeave={e => {
          e.preventDefault();
          if (e.clientX === 0) this.setState({isDragOver: false});
        }}
      >
        <button
          onClick={() => {
            this.setState({
              activeActionLayer:
                this.state.activeActionLayer === DRAW_LINE ? ERASER : DRAW_LINE,
            });
          }}
        >
          ペン ⇔ 消しゴム
        </button>
        <button
          onClick={() => {
            const newValue =
              actionLayerSettings[DRAW_LINE].ctx.lineWidth === 1 ? 15 : 1;
            const newSetting = generateActionLayerSettings({
              type: SPECIFY_CONTEXT_PROPERTY,
              currentState: actionLayerSettings,
              data: {lineWidth: newValue},
              target: DRAW_LINE,
            });
            this.setState({actionLayerSettings: newSetting});
          }}
        >
          ペン（太） ⇔　ペン（細）
        </button>
        <button onClick={() => this.downloadImageFile()}>ダウンロード</button>
        <button
          onClick={() => {
            const imageData = invertNegaPosi(activeImage.imageData);
            const updatedState = generateImageList({
              type: SPECIFY_IMAGE_PROPERTY,
              data: {imageData},
              currentState: imageList,
              target: activeImage.id,
            });
            this.updateImageList(updatedState);
          }}
        >
          ネガポジ
        </button>
        <button
          onClick={() => {
            const imageData = resizeImageData(activeImage.imageData, 50);
            const updatedState = generateImageList({
              type: SPECIFY_IMAGE_PROPERTY,
              data: {imageData},
              currentState: imageList,
              target: activeImage.id,
            });
            this.updateImageList(updatedState);
          }}
        >
          50%縮小
        </button>
        <button
          onClick={() => {
            this.setState({
              imageListHistory: generateImageListHistory({
                type: BACK,
                currentState: imageListHistory,
              }),
            });
          }}
        >
          undo
        </button>
        <button
          onClick={() => {
            this.setState({
              imageListHistory: generateImageListHistory({
                type: FORWARD,
                currentState: imageListHistory,
              }),
            });
          }}
        >
          redo
        </button>
        <Display {...display}>
          <ViewLayerList viewLayerDataList={imageList} />
          <ActionLayer
            activeActionLayer={activeActionLayer}
            imageData={activeImage.imageData}
            setting={actionLayerSettings[activeActionLayer]}
            display={display}
            updateImageData={imageData => {
              const updatedState = generateImageList({
                type: SPECIFY_IMAGE_PROPERTY,
                data: {imageData},
                currentState: imageList,
                target: activeImage.id,
              });
              this.updateImageList(updatedState);
            }}
            startOmitLengthCount={() => {
              this.setState({
                imageListHistory: generateImageListHistory({
                  type: START_OMIT_LENGTH_COUNT,
                  currentState: imageListHistory,
                }),
              });
            }}
            omitImageListHistory={() => {
              if (!imageListHistory.omitLength) return;
              this.setState({
                imageListHistory: generateImageListHistory({
                  type: OMIT,
                  currentState: imageListHistory,
                }),
              });
            }}
          />
        </Display>
        <ImageListManage
          imageList={imageList}
          updateImageList={updatedImageList => {
            this.updateImageList(updatedImageList);
          }}
          display={{width: display.width, height: display.height}}
        />
         this.downloadImageFile()}
          uploadImageFile={fileList => this.uploadImageFile(fileList)}
          imageListHistory={imageListHistory}
          updateImageListHistory={changedImageListHistory =>
            this.updateImageListHistory(changedImageListHistory)}
        />
        {isDragOver && (

画像をドロップすると新しくレイヤーが作られます

        )}

    );
  }
}
<|endoftext|>


<commit_before>/* globals Models Status */

Models = { // eslint-disable-line
  project: function () {
    return {
      name: '',
      industry: '',
      createdAt: '',
      description: '',
      owner: '',
      contributors: [],
      commands: [],
      notes: [],
      droneLog: []
    }
  },

  host: function () {
    return {
      projectId: '',
      longIpv4Addr: 0,
      ipv4: '',
      mac: '',
      hostnames: [],
      os: '',
      notes: [],
      statusMessage: '',
      tags: [],
      status: Status.grey,
      lastModifiedBy: '',
      isFlagged: false
    }
  },

  authInterface: function () {
    return {
      projectId: '',
      isMultifactor: true,
      kind: '',
      url: '',
      description: ''
    }
  },

  netblock: function () {
    return {
      projectId: '',
      asn: '',
      asnCountryCode: '',
      asnCidr: '',
      asnDate: '',
      asnRegistry: '',
      cidr: '',
      abuseEmails: '',
      miscEmails: '',
      techEmails: '',
      name: '',
      city: '',
      country: '',
      postalCode: '',
      created: '',
      updated: '',
      description: '',
      handle: ''
    }
  },

  os: function () {
    return {
      tool: '',
      fingerprint: 'Unknown',
      weight: 0
    }
  },

  service: function () {
    return {
      projectId: '',
      hostId: '',
      port: 0,
      protocol: 'tcp',
      service: 'Unknown',
      product: 'Unknown',
      status: Status.grey,
      isFlagged: false,
      lastModifiedBy: ''
    }
  },

  issue: function () {
    return {
      projectId: '',
      title: '',
      cvss: 0,
      rating: '',
      isConfirmed: false,
      description: '',
      evidence: '',
      solution: '',
      hosts: [],
      pluginIds: [],
      cves: [],
      references: [],
      identifiedBy: [{
        tool: 'Manual'
      }],
      notes: [],
      isFlagged: false,
      status: Status.grey,
      lastModifiedBy: ''
    }
  },

  issueHost: function () {
    return {
      ipv4: '',
      port: 0,
      protocol: ''
    }
  },

  issueReference: function () {
    return {
      link: '',
      name: ''
    }
  },

  person: function () {
    return {
      projectId: '',
      principalName: '',
      samAccountName: '',
      distinguishedName: '',
      firstName: '',
      middleName: '',
      lastName: '',
      displayName: '',
      department: '',
      description: '',
      address: '',
      emails: [],
      phones: [],
      references: [],
      groups: [],
      lastLogon: '',
      lastLogoff: '',
      loggedIn: []
    }
  },

  personReference: function () {
    return {
      description: '',
      username: '',
      link: ''
    }
  },

  note: function () {
    return {
      title: '',
      content: '',
      lastModifiedBy: ''
    }
  },

  credential: function () {
    return {
      username: '',
      password: '',
      format: '',
      hash: '',
      host: '',
      service: ''
    }
  },

  webDirectory: function () {
    return {
      projectId: '',
      hostId: '',
      path: '',
      port: 0,
      responseCode: '',
      lastModifiedBy: '',
      isFlagged: false
    }
  },

  file: function () {
    return {
      projectid: '',
      hostId: '',
      serviceId: '',
      issueId: '',
      filename: '',
      url: ''
    }
  }
}
<commit_msg>Adds notes to service model<commit_after>/* globals Models Status */

Models = { // eslint-disable-line
  project: function () {
    return {
      name: '',
      industry: '',
      createdAt: '',
      description: '',
      owner: '',
      contributors: [],
      commands: [],
      notes: [],
      droneLog: []
    }
  },

  host: function () {
    return {
      projectId: '',
      longIpv4Addr: 0,
      ipv4: '',
      mac: '',
      hostnames: [],
      os: '',
      notes: [],
      statusMessage: '',
      tags: [],
      status: Status.grey,
      lastModifiedBy: '',
      isFlagged: false
    }
  },

  authInterface: function () {
    return {
      projectId: '',
      isMultifactor: true,
      kind: '',
      url: '',
      description: ''
    }
  },

  netblock: function () {
    return {
      projectId: '',
      asn: '',
      asnCountryCode: '',
      asnCidr: '',
      asnDate: '',
      asnRegistry: '',
      cidr: '',
      abuseEmails: '',
      miscEmails: '',
      techEmails: '',
      name: '',
      city: '',
      country: '',
      postalCode: '',
      created: '',
      updated: '',
      description: '',
      handle: ''
    }
  },

  os: function () {
    return {
      tool: '',
      fingerprint: 'Unknown',
      weight: 0
    }
  },

  service: function () {
    return {
      projectId: '',
      hostId: '',
      port: 0,
      protocol: 'tcp',
      service: 'Unknown',
      product: 'Unknown',
      status: Status.grey,
      isFlagged: false,
      lastModifiedBy: '',
      notes: []
    }
  },

  issue: function () {
    return {
      projectId: '',
      title: '',
      cvss: 0,
      rating: '',
      isConfirmed: false,
      description: '',
      evidence: '',
      solution: '',
      hosts: [],
      pluginIds: [],
      cves: [],
      references: [],
      identifiedBy: [{
        tool: 'Manual'
      }],
      notes: [],
      isFlagged: false,
      status: Status.grey,
      lastModifiedBy: ''
    }
  },

  issueHost: function () {
    return {
      ipv4: '',
      port: 0,
      protocol: ''
    }
  },

  issueReference: function () {
    return {
      link: '',
      name: ''
    }
  },

  person: function () {
    return {
      projectId: '',
      principalName: '',
      samAccountName: '',
      distinguishedName: '',
      firstName: '',
      middleName: '',
      lastName: '',
      displayName: '',
      department: '',
      description: '',
      address: '',
      emails: [],
      phones: [],
      references: [],
      groups: [],
      lastLogon: '',
      lastLogoff: '',
      loggedIn: []
    }
  },

  personReference: function () {
    return {
      description: '',
      username: '',
      link: ''
    }
  },

  note: function () {
    return {
      title: '',
      content: '',
      lastModifiedBy: ''
    }
  },

  credential: function () {
    return {
      username: '',
      password: '',
      format: '',
      hash: '',
      host: '',
      service: ''
    }
  },

  webDirectory: function () {
    return {
      projectId: '',
      hostId: '',
      path: '',
      port: 0,
      responseCode: '',
      lastModifiedBy: '',
      isFlagged: false
    }
  },

  file: function () {
    return {
      projectid: '',
      hostId: '',
      serviceId: '',
      issueId: '',
      filename: '',
      url: ''
    }
  }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import SearchBar from '../containers/search_bar'
import WeatherList from '../containers/weather_list'
import DummyContainer from '../containers/dummy_container'

export default class App extends Component {
  render () {
    return (

        <SearchBar />
        <WeatherList />
        <DummyContainer />

    );
  }
}
<commit_msg>Update app.js<commit_after>import React, { Component } from 'react';
import SearchBar from '../containers/search_bar'
import WeatherList from '../containers/weather_list'
//import DummyContainer from '../containers/dummy_container'

export default class App extends Component {
  render () {
    return (

        <SearchBar />
        <WeatherList />

    );
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import Navigation from './navigation';
import PropTypes from 'prop-types';
import Content from './content';
import RoundedToggle from './rounded_toggle';
import GithubSlugger from 'github-slugger';
import debounce from 'lodash.debounce';
import { brandNames, brandClasses } from '../custom';
import qs from 'querystring';

let slugger = new GithubSlugger();
let slug = title => { slugger.reset(); return slugger.slug(title); };

let languageOptions = [
  { title: 'cURL',
    short: 'cURL',
    value: 'curl' },
  { title: 'CLI',
    short: 'cli',
    value: 'cli' },
  { title: 'Python',
    short: 'Python',
    value: 'python' },
  { title: 'JavaScript',
    short: 'JS',
    value: 'javascript' },
  { title: 'Java',
    short: 'Java',
    value: 'java' },
  { title: 'Objective-C',
    short: 'ObjC',
    value: 'objc' },
  { title: 'Swift',
    short: 'Swift',
    value: 'swift' }
];

let defaultLanguage = languageOptions[0];

let debouncedReplaceState = debounce(hash => {
  window.history.replaceState('', '', hash);
}, 100);

export default class App extends React.PureComponent {
  static propTypes = {
    content: PropTypes.string.isRequired,
    ast: PropTypes.object.isRequired
  }
  constructor(props) {
    super(props);
    var active = 'Introduction';

    if (process.browser) {
      let hash = window.location.hash.split('#').pop();
      let languageFromURL = qs.parse(window.location.search.substring(1)).language;
      let language = languageOptions.find(option => option.title === languageFromURL) ||
        defaultLanguage;
      let mqls = [
        { name: 'widescreen', query: window.matchMedia('(min-width: 1200px)') },
        { name: 'desktop', query: window.matchMedia('(min-width: 961px)') },
        { name: 'tablet', query: window.matchMedia('(max-width: 960px)') },
        { name: 'mobile', query: window.matchMedia('(max-width: 640px)') }
      ];
      mqls.forEach(q => q.query.addListener(this.mediaQueryChanged));
      if (hash) {
        let headingForHash = this.props.ast.children
          .filter(child => child.type === 'heading')
          .find(heading => heading.data.id === hash);
        if (headingForHash) {
          active = headingForHash.children[0].value;
        }
      }
      this.state = {
        // media queryMatches
        mqls: mqls,
        // object of currently matched queries, like { desktop: true }
        queryMatches: {},
        language: language,
        columnMode: 2,
        activeSection: active,
        // for the toggle-able navigation on mobile
        showNav: false
      };
    } else {
      this.state = {
        mqls: { },
        queryMatches: {
          desktop: true
        },
        language: defaultLanguage,
        activeSection: '',
        showNav: false
      };
    }

	this.navigationItemClicked = this.navigationItemClicked.bind(this);
  }
  toggleNav() {
    this.setState({ showNav: !this.state.showNav });
  }
  componentDidMount() {
    this.mediaQueryChanged();
    this.onScroll = debounce(this.onScrollImmediate, 100);
    document.addEventListener('scroll', this.onScroll);
    this.onScrollImmediate();
  }
  onScrollImmediate = () => {
    var sections = document.querySelectorAll('div.section');
    if (!sections.length) return;
    for (var i = 0; i < sections.length; i++) {
      var rect = sections[i].getBoundingClientRect();
      if (rect.bottom > 0) {
        this.setState({
          activeSection: sections[i].getAttribute('data-title')
        });
        return;
      }
    }
  }
  mediaQueryChanged() {
    this.setState({
      queryMatches: this.state.mqls.reduce((memo, q) => {
        memo[q.name] = q.query.matches;
        return memo;
      }, {})
    });
  }
  componentWillUnmount() {
    this.state.mqls.forEach(q => q.removeListener(this.mediaQueryChanged));
    document.body.removeEventListener('scroll', this.onScroll);
  }
  onChangeLanguage = (language) => {
    this.setState({ language }, () => {
      if (window.history) {
        window.history.pushState(null, null,
          `?${qs.stringify({ language: language.title })}${window.location.hash}`);
      }
    });
  }
  componentDidUpdate(_, prevState) {
    if (prevState.activeSection !== this.state.activeSection) {
      // when the section changes, replace the hash
      debouncedReplaceState(`#${slug(this.state.activeSection)}`);
    } else if (prevState.language.title !== this.state.language.title ||
      prevState.columnMode !== this.state.columnMode) {
      // when the language changes, use the hash to set scroll
      window.location.hash = window.location.hash;
    }
  }
  navigationItemClicked(activeSection) {
    setTimeout(() => {
      this.setState({ activeSection });
    }, 10);
    if (!this.state.queryMatches.desktop) {
      this.toggleNav();
    }
  }
  toggleColumnMode() {
    this.setState({
      columnMode: this.state.columnMode === 1 ? 2 : 1
    });
  }
  render() {
    let ast = JSON.parse(JSON.stringify(this.props.ast));
    let { activeSection, queryMatches, showNav, columnMode } = this.state;
    let col1 = columnMode === 1 && queryMatches.desktop;
    return (

      {/* Content background */ }
      {(!col1 && !queryMatches.mobile) && <div className={`fixed-top fixed-right ${queryMatches.desktop && 'space-left16'}`}>

}

      {/* Desktop nav */ }
      {queryMatches.desktop &&

        <Navigation
          navigationItemClicked={this.navigationItemClicked}
          activeSection={activeSection}
          ast={ast} />

}

      {/* Content */ }
      <div className={`${queryMatches.desktop && 'space-left16'}`}>

          <Content
            leftClassname={col1 ? 'space-bottom4 pad2x prose clip' : 'space-bottom8 col6 pad2x prose clip'}
            rightClassname={col1 ? 'space-bottom2 pad2 prose clip fill-light space-top5' : 'space-bottom4 col6 pad2 prose clip fill-light space-top5'}
            ast={ast}
            language={this.state.language}/>

      {/* Language toggle */ }
      <div className={`fixed-top ${queryMatches.desktop && 'space-left16'}`}>
        <div className={`events fill-light bottom-shadow pad1 ${col1 ? '' : 'col6 pin-topright'} ${queryMatches.tablet ? 'dark fill-blue' : ''} ${queryMatches.mobile ? 'space-top5 fixed-topright' : ''}`}>

            Show examples in:

          <RoundedToggle
            short={!queryMatches.widescreen}
            options={languageOptions}
            onChange={this.onChangeLanguage}
            active={this.state.language} />

            {queryMatches.desktop ?
              <a
                title={`Display as ${col1 ? 2 : 1} column`}
                onClick={this.toggleColumnMode}
                style={{ cursor: 'pointer' }}
                className={`icon quiet caret-${col1 ? 'right' : 'left'} pad0 fill-darken0 round`} /> : null}

      {/* Header */ }
      <div className={`fill-dark dark bottom-shadow fixed-top ${queryMatches.tablet ? 'pad1y pad2x col6' : 'pad0 width16'}`}>
        <a href='/' className={`active space-top1 space-left1 pin-topleft icon round dark pad0 ${brandClasses}`} />

          {queryMatches.desktop ? brandNames.desktop :
            queryMatches.mobile ? brandNames.mobile : brandNames.tablet}

        {queryMatches.tablet &&

          <button
            onClick={this.toggleNav}
            className={`short quiet pin-topright button rcon ${showNav ? 'caret-up' : 'caret-down'} space-right1 space-top1`}>
            {activeSection}
          </button>
          {showNav &&

              <Navigation
                navigationItemClicked={this.navigationItemClicked}
                activeSection={activeSection}
                ast={ast} />

}

}

);
  }
}
<commit_msg>Update to property initializer syntax<commit_after>import React from 'react';
import Navigation from './navigation';
import PropTypes from 'prop-types';
import Content from './content';
import RoundedToggle from './rounded_toggle';
import GithubSlugger from 'github-slugger';
import debounce from 'lodash.debounce';
import { brandNames, brandClasses } from '../custom';
import qs from 'querystring';

let slugger = new GithubSlugger();
let slug = title => { slugger.reset(); return slugger.slug(title); };

let languageOptions = [
  { title: 'cURL',
    short: 'cURL',
    value: 'curl' },
  { title: 'CLI',
    short: 'cli',
    value: 'cli' },
  { title: 'Python',
    short: 'Python',
    value: 'python' },
  { title: 'JavaScript',
    short: 'JS',
    value: 'javascript' },
  { title: 'Java',
    short: 'Java',
    value: 'java' },
  { title: 'Objective-C',
    short: 'ObjC',
    value: 'objc' },
  { title: 'Swift',
    short: 'Swift',
    value: 'swift' }
];

let defaultLanguage = languageOptions[0];

let debouncedReplaceState = debounce(hash => {
  window.history.replaceState('', '', hash);
}, 100);

export default class App extends React.PureComponent {
  static propTypes = {
    content: PropTypes.string.isRequired,
    ast: PropTypes.object.isRequired
  }
  constructor(props) {
    super(props);
    var active = 'Introduction';

    if (process.browser) {
      let hash = window.location.hash.split('#').pop();
      let languageFromURL = qs.parse(window.location.search.substring(1)).language;
      let language = languageOptions.find(option => option.title === languageFromURL) ||
        defaultLanguage;
      let mqls = [
        { name: 'widescreen', query: window.matchMedia('(min-width: 1200px)') },
        { name: 'desktop', query: window.matchMedia('(min-width: 961px)') },
        { name: 'tablet', query: window.matchMedia('(max-width: 960px)') },
        { name: 'mobile', query: window.matchMedia('(max-width: 640px)') }
      ];
      mqls.forEach(q => q.query.addListener(this.mediaQueryChanged));
      if (hash) {
        let headingForHash = this.props.ast.children
          .filter(child => child.type === 'heading')
          .find(heading => heading.data.id === hash);
        if (headingForHash) {
          active = headingForHash.children[0].value;
        }
      }
      this.state = {
        // media queryMatches
        mqls: mqls,
        // object of currently matched queries, like { desktop: true }
        queryMatches: {},
        language: language,
        columnMode: 2,
        activeSection: active,
        // for the toggle-able navigation on mobile
        showNav: false
      };
    } else {
      this.state = {
        mqls: { },
        queryMatches: {
          desktop: true
        },
        language: defaultLanguage,
        activeSection: '',
        showNav: false
      };
    }
  }
  toggleNav() {
    this.setState({ showNav: !this.state.showNav });
  }
  componentDidMount() {
    this.mediaQueryChanged();
    this.onScroll = debounce(this.onScrollImmediate, 100);
    document.addEventListener('scroll', this.onScroll);
    this.onScrollImmediate();
  }
  onScrollImmediate = () => {
    var sections = document.querySelectorAll('div.section');
    if (!sections.length) return;
    for (var i = 0; i < sections.length; i++) {
      var rect = sections[i].getBoundingClientRect();
      if (rect.bottom > 0) {
        this.setState({
          activeSection: sections[i].getAttribute('data-title')
        });
        return;
      }
    }
  }
  mediaQueryChanged() {
    this.setState({
      queryMatches: this.state.mqls.reduce((memo, q) => {
        memo[q.name] = q.query.matches;
        return memo;
      }, {})
    });
  }
  componentWillUnmount() {
    this.state.mqls.forEach(q => q.removeListener(this.mediaQueryChanged));
    document.body.removeEventListener('scroll', this.onScroll);
  }
  onChangeLanguage = (language) => {
    this.setState({ language }, () => {
      if (window.history) {
        window.history.pushState(null, null,
          `?${qs.stringify({ language: language.title })}${window.location.hash}`);
      }
    });
  }
  componentDidUpdate(_, prevState) {
    if (prevState.activeSection !== this.state.activeSection) {
      // when the section changes, replace the hash
      debouncedReplaceState(`#${slug(this.state.activeSection)}`);
    } else if (prevState.language.title !== this.state.language.title ||
      prevState.columnMode !== this.state.columnMode) {
      // when the language changes, use the hash to set scroll
      window.location.hash = window.location.hash;
    }
  }
  navigationItemClicked = activeSection => {
    setTimeout(() => {
      this.setState({ activeSection });
    }, 10);
    if (!this.state.queryMatches.desktop) {
      this.toggleNav();
    }
  }
  toggleColumnMode() {
    this.setState({
      columnMode: this.state.columnMode === 1 ? 2 : 1
    });
  }
  render() {
    let ast = JSON.parse(JSON.stringify(this.props.ast));
    let { activeSection, queryMatches, showNav, columnMode } = this.state;
    let col1 = columnMode === 1 && queryMatches.desktop;
    return (

      {/* Content background */ }
      {(!col1 && !queryMatches.mobile) && <div className={`fixed-top fixed-right ${queryMatches.desktop && 'space-left16'}`}>

}

      {/* Desktop nav */ }
      {queryMatches.desktop &&

        <Navigation
          navigationItemClicked={this.navigationItemClicked}
          activeSection={activeSection}
          ast={ast} />

}

      {/* Content */ }
      <div className={`${queryMatches.desktop && 'space-left16'}`}>

          <Content
            leftClassname={col1 ? 'space-bottom4 pad2x prose clip' : 'space-bottom8 col6 pad2x prose clip'}
            rightClassname={col1 ? 'space-bottom2 pad2 prose clip fill-light space-top5' : 'space-bottom4 col6 pad2 prose clip fill-light space-top5'}
            ast={ast}
            language={this.state.language}/>

      {/* Language toggle */ }
      <div className={`fixed-top ${queryMatches.desktop && 'space-left16'}`}>
        <div className={`events fill-light bottom-shadow pad1 ${col1 ? '' : 'col6 pin-topright'} ${queryMatches.tablet ? 'dark fill-blue' : ''} ${queryMatches.mobile ? 'space-top5 fixed-topright' : ''}`}>

            Show examples in:

          <RoundedToggle
            short={!queryMatches.widescreen}
            options={languageOptions}
            onChange={this.onChangeLanguage}
            active={this.state.language} />

            {queryMatches.desktop ?
              <a
                title={`Display as ${col1 ? 2 : 1} column`}
                onClick={this.toggleColumnMode}
                style={{ cursor: 'pointer' }}
                className={`icon quiet caret-${col1 ? 'right' : 'left'} pad0 fill-darken0 round`} /> : null}

      {/* Header */ }
      <div className={`fill-dark dark bottom-shadow fixed-top ${queryMatches.tablet ? 'pad1y pad2x col6' : 'pad0 width16'}`}>
        <a href='/' className={`active space-top1 space-left1 pin-topleft icon round dark pad0 ${brandClasses}`} />

          {queryMatches.desktop ? brandNames.desktop :
            queryMatches.mobile ? brandNames.mobile : brandNames.tablet}

        {queryMatches.tablet &&

          <button
            onClick={this.toggleNav}
            className={`short quiet pin-topright button rcon ${showNav ? 'caret-up' : 'caret-down'} space-right1 space-top1`}>
            {activeSection}
          </button>
          {showNav &&

              <Navigation
                navigationItemClicked={this.navigationItemClicked}
                activeSection={activeSection}
                ast={ast} />

}

}

);
  }
}
<|endoftext|>


<commit_before>/**
 * SEO component that queries for data with
 *  Gatsby's useStaticQuery React hook
 *
 * See: https://www.gatsbyjs.org/docs/use-static-query/
 */

import React from "react"
import PropTypes from "prop-types"
import Helmet from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"

function SEO({ description, lang, meta, keywords, title }) {
  const { site } = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
            description
            author
          }
        }
      }
    `
  )

  const metaDescription = description || site.siteMetadata.description

  return (
    <Helmet
      htmlAttributes={{
        lang,
      }}
      title={title}
      titleTemplate={`%s | ${site.siteMetadata.title}`}
      meta={[
        {
          name: `description`,
          content: metaDescription,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:description`,
          content: metaDescription,
        },
        {
          property: `og:type`,
          content: `website`,
        },
        {
          name: `twitter:card`,
          content: `summary`,
        },
        {
          name: `twitter:creator`,
          content: site.siteMetadata.author,
        },
        {
          name: `twitter:title`,
          content: title,
        },
        {
          name: `twitter:description`,
          content: metaDescription,
        },
      ]
        .concat(
          keywords.length > 0
            ? {
                name: `keywords`,
                content: keywords.join(`, `),
              }
            : []
        )
        .concat(meta)}
    >
      <script src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
      <script>
      {`(adsbygoogle = window.adsbygoogle || []).push({
          google_ad_client: "ca-pub-5743316258017902",
          enable_page_level_ads: true
        });`}
      </script>
    </Helmet>
  )
}

SEO.defaultProps = {
  lang: `en`,
  meta: [],
  keywords: [],
  description: ``,
}

SEO.propTypes = {
  description: PropTypes.string,
  lang: PropTypes.string,
  meta: PropTypes.arrayOf(PropTypes.object),
  keywords: PropTypes.arrayOf(PropTypes.string),
  title: PropTypes.string.isRequired,
}

export default SEO
<commit_msg>Remove google ads :wave:<commit_after>/**
 * SEO component that queries for data with
 *  Gatsby's useStaticQuery React hook
 *
 * See: https://www.gatsbyjs.org/docs/use-static-query/
 */

import React from "react"
import PropTypes from "prop-types"
import Helmet from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"

function SEO({ description, lang, meta, keywords, title }) {
  const { site } = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
            description
            author
          }
        }
      }
    `
  )

  const metaDescription = description || site.siteMetadata.description

  return (
    <Helmet
      htmlAttributes={{
        lang,
      }}
      title={title}
      titleTemplate={`%s | ${site.siteMetadata.title}`}
      meta={[
        {
          name: `description`,
          content: metaDescription,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:description`,
          content: metaDescription,
        },
        {
          property: `og:type`,
          content: `website`,
        },
        {
          name: `twitter:card`,
          content: `summary`,
        },
        {
          name: `twitter:creator`,
          content: site.siteMetadata.author,
        },
        {
          name: `twitter:title`,
          content: title,
        },
        {
          name: `twitter:description`,
          content: metaDescription,
        },
      ]
        .concat(
          keywords.length > 0
            ? {
                name: `keywords`,
                content: keywords.join(`, `),
              }
            : []
        )
        .concat(meta)}
    >
    </Helmet>
  )
}

SEO.defaultProps = {
  lang: `en`,
  meta: [],
  keywords: [],
  description: ``,
}

SEO.propTypes = {
  description: PropTypes.string,
  lang: PropTypes.string,
  meta: PropTypes.arrayOf(PropTypes.object),
  keywords: PropTypes.arrayOf(PropTypes.string),
  title: PropTypes.string.isRequired,
}

export default SEO
<|endoftext|>


<commit_before>// Styles
require('./main.sass');

// Scripts
require('./browsercheck.js');
require('./gol.js');
require('./helpers.js');
require('./init.js');
require('./navigation-anim.js');
require('./navigation.js');
require('./projects.js');

// Files to be copied
require('./index.html');
<commit_msg>Game of Life no longer needs to be required from index.js<commit_after>// Styles
require('./main.sass');

// Scripts
require('./browsercheck.js');
require('./helpers.js');
require('./init.js');
require('./navigation-anim.js');
require('./navigation.js');
require('./projects.js');

// Files to be copied
require('./index.html');
<|endoftext|>


<commit_before>'use strict'

if (require('electron-squirrel-startup')) {
    return
}

const electron = require('electron')
const app = electron.app

const config = require('../config')
const windows = require('./windows')
const crashReporter = require('../lib/crash-reporter')
const tray = require('../lib/tray')
const autoStart = require('../lib/auto-start')
const machineIdInit = require('../lib/machine-id')
const updater = require('../lib/updater')
const monitor = require('../lib/monitor')
const enums = require('../lib/enums')

const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
    windows.main.init(enums.WindowType.ABOUT)
})

if (shouldQuit) {
    app.quit()
    return
}

global.machineId = null

function delayedStart() {
    monitor.init()
}

app.on('will-finish-launching', () => {
    crashReporter.init({'scope': 'main'})
    machineIdInit.init()
    if (!config.IS_DEVELOPMENT) {
        autoStart.init()
        updater.init()
    }
})

app.on('window-all-closed', () => {
})

app.on('quit', () => {
})

app.on('ready', () => {
    windows.main.init(enums.WindowType.ABOUT)
    tray.init()
    setTimeout(delayedStart, config.DELAY_START_TIME)
})
<commit_msg>new sotrage<commit_after>'use strict'

if (require('electron-squirrel-startup')) {
    return
}

const electron = require('electron')
const app = electron.app

const config = require('../config')
const windows = require('./windows')
const crashReporter = require('../lib/crash-reporter')
const tray = require('../lib/tray')
const autoStart = require('../lib/auto-start')
const machineIdInit = require('../lib/machine-id')
const updater = require('../lib/updater')
const monitor = require('../lib/monitor')
const enums = require('../lib/enums')

const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
    windows.main.init(enums.WindowType.ABOUT)
})

if (shouldQuit) {
    app.quit()
    return
}

global.machineId = null

function delayedStart() {
    monitor.init()
    if (!config.IS_DEVELOPMENT) {
        updater.init()
    }
}

app.on('will-finish-launching', () => {
    crashReporter.init({'scope': 'main'})
    machineIdInit.init()
    if (!config.IS_DEVELOPMENT) {
        autoStart.init()
    }
})

app.on('window-all-closed', () => {
})

app.on('quit', () => {
})

app.on('ready', () => {
    windows.main.init(enums.WindowType.ABOUT)
    tray.init()
    setTimeout(delayedStart, config.DELAY_START_TIME)
})
<|endoftext|>


<commit_before>var ItemsStore = require("items-store/ItemsStore");
var async = require("async");
var request = require("superagent");

// a few helper methods for a REST API

function writeAndReadSingleItem(path, resultHandler) {
	resultHandler = resultHandler || function(result) { return result; };
	return function(options, callback) {
		request.post(path + options.id)
			.set("Accept", "application/json")
			.type("json")
			.send(options.update)
			.end(function(err, res) {
				if(err) return callback(err);
				callback(null, resultHandler(res.body));
			});
	}
}

function readSingleItem(path, resultHandler) {
	resultHandler = resultHandler || function(result) { return result; };
	return function(options, callback) {
		request.get(path + options.id)
			.set("Accept", "application/json")
			.type("json")
			.end(function(err, res) {
				if(err) return callback(err);
				callback(null, resultHandler(res.body));
			});
	}
}

function readMultipleItems(path, resultHandler) {
	resultHandler = resultHandler || function(result) { return result; };
	return function(optionsArr, callback) {
		request.get(path + optionsArr.map(function(options) {
			return options.id;
		}).join("+"))
			.set("Accept", "application/json")
			.type("json")
			.end(function(err, res) {
				if(err) return callback(err);
				callback(null, resultHandler(res.body));
			});
	}
}

// a queue that allows only one REST request at a time
// it also defers the requests to next tick, to aggregate multiple changes
var queue = async.queue(function(fn, callback) {
	process.nextTick(function() {
		fn(callback);
	});
}, 1);

// load embedded initial store data from prerendering if available
var initialData = typeof __StoreData === "object" ? __StoreData : {};

// take the store descriptions as base
var desc = require("./mainStoresDescriptions");

var stores = module.exports = {
	Router: new ItemsStore(desc.Router),

	TodoList: new ItemsStore(Object.assign({
		// REST API at "/_/list/"
		// the API also returns "TodoItem"s for requests

		writeAndReadSingleItem: writeAndReadSingleItem("/_/list/", function(result) {
			Object.keys(result.items).forEach(function(key) {
				stores.TodoItem.setItemData(key.substr(1), result.items[key]);
			});
			return result.list;
		}),
		readSingleItem: readSingleItem("/_/list/", function(result) {
			Object.keys(result.items).forEach(function(key) {
				stores.TodoItem.setItemData(key.substr(1), result.items[key]);
			});
			return result.list;
		}),

		queueRequest: queue.push.bind(queue),
	}, desc.TodoList), initialData.TodoList),

	TodoItem: new ItemsStore(Object.assign({
		// REST API at "/_/todo"
		// it supports reading up to 10 items at once

		writeAndReadSingleItem: writeAndReadSingleItem("/_/todo/"),
		readSingleItem: readSingleItem("/_/todo/"),
		readMultipleItems: readMultipleItems("/_/todo/"),

		queueRequest: queue.push.bind(queue),
		maxWriteItems: 10
	}, desc.TodoItem), initialData.TodoItem)
};

// bind actions to stores

var actions = require("./actions");

actions.Todo.add.listen(function(list, item) {
	stores.TodoList.updateItem(list, { $push: [item] });
});

actions.Todo.update.listen(function(id, update) {
	stores.TodoItem.updateItem(id, update);
});
<commit_msg>batch updates<commit_after>var ItemsStore = require("items-store/ItemsStore");
var async = require("async");
var request = require("superagent");
var ReactUpdates = require("react/lib/ReactUpdates");

// a few helper methods for a REST API

function batchedCallback(callback) {
	return function(err, res) {
		ReactUpdates.batchedUpdates(callback.bind(null, err, res));
	}
}

function writeAndReadSingleItem(path, resultHandler) {
	resultHandler = resultHandler || function(result) { return result; };
	return function(options, callback) {
		request.post(path + options.id)
			.set("Accept", "application/json")
			.type("json")
			.send(options.update)
			.end(batchedCallback(function(err, res) {
				if(err) return callback(err);
				callback(null, resultHandler(res.body));
			}));
	}
}

function readSingleItem(path, resultHandler) {
	resultHandler = resultHandler || function(result) { return result; };
	return function(options, callback) {
		request.get(path + options.id)
			.set("Accept", "application/json")
			.type("json")
			.end(batchedCallback(function(err, res) {
				if(err) return callback(err);
				callback(null, resultHandler(res.body));
			}));
	}
}

function readMultipleItems(path, resultHandler) {
	resultHandler = resultHandler || function(result) { return result; };
	return function(optionsArr, callback) {
		request.get(path + optionsArr.map(function(options) {
			return options.id;
		}).join("+"))
			.set("Accept", "application/json")
			.type("json")
			.end(batchedCallback(function(err, res) {
				if(err) return callback(err);
				callback(null, resultHandler(res.body));
			}));
	}
}

// a queue that allows only one REST request at a time
// it also defers the requests to next tick, to aggregate multiple changes
var queue = async.queue(function(fn, callback) {
	process.nextTick(function() {
		fn(callback);
	});
}, 1);

// load embedded initial store data from prerendering if available
var initialData = typeof __StoreData === "object" ? __StoreData : {};

// take the store descriptions as base
var desc = require("./mainStoresDescriptions");

var stores = module.exports = {
	Router: new ItemsStore(desc.Router),

	TodoList: new ItemsStore(Object.assign({
		// REST API at "/_/list/"
		// the API also returns "TodoItem"s for requests

		writeAndReadSingleItem: writeAndReadSingleItem("/_/list/", function(result) {
			Object.keys(result.items).forEach(function(key) {
				stores.TodoItem.setItemData(key.substr(1), result.items[key]);
			});
			return result.list;
		}),
		readSingleItem: readSingleItem("/_/list/", function(result) {
			Object.keys(result.items).forEach(function(key) {
				stores.TodoItem.setItemData(key.substr(1), result.items[key]);
			});
			return result.list;
		}),

		queueRequest: queue.push.bind(queue),
	}, desc.TodoList), initialData.TodoList),

	TodoItem: new ItemsStore(Object.assign({
		// REST API at "/_/todo"
		// it supports reading up to 10 items at once

		writeAndReadSingleItem: writeAndReadSingleItem("/_/todo/"),
		readSingleItem: readSingleItem("/_/todo/"),
		readMultipleItems: readMultipleItems("/_/todo/"),

		queueRequest: queue.push.bind(queue),
		maxWriteItems: 10
	}, desc.TodoItem), initialData.TodoItem)
};

// bind actions to stores

var actions = require("./actions");

actions.Todo.add.listen(function(list, item) {
	stores.TodoList.updateItem(list, { $push: [item] });
});

actions.Todo.update.listen(function(id, update) {
	stores.TodoItem.updateItem(id, update);
});
<|endoftext|>


<commit_before>import { Platform } from 'react-native';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducers';

const middlewares = [thunk];

let enhancer;
if (__DEV__) {
  const installDevTools = require('immutable-devtools').default;
  installDevTools(Immutable);

  const devTools = require('remote-redux-devtools');
  enhancer = compose(
    applyMiddleware(...middlewares),
    devTools({
      name: Platform.OS,
      hostname: 'localhost',
      port: 5678
    })
  );
} else {
  enhancer = applyMiddleware(...middlewares);
}

export default function configureStore(initialState) {
  const store = createStore(reducer, initialState, enhancer);
  if (module.hot) {
    module.hot.accept(() => {
      store.replaceReducer(require('./reducers'));
    });
  }
  return store;
}
<commit_msg>Fix immutable-devtools<commit_after>import { Platform } from 'react-native';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducers';

const middlewares = [thunk];

let enhancer;
if (__DEV__) {
  const installDevTools = require('immutable-devtools');
  installDevTools(Immutable);

  const devTools = require('remote-redux-devtools');
  enhancer = compose(
    applyMiddleware(...middlewares),
    devTools({
      name: Platform.OS,
      hostname: 'localhost',
      port: 5678
    })
  );
} else {
  enhancer = applyMiddleware(...middlewares);
}

export default function configureStore(initialState) {
  const store = createStore(reducer, initialState, enhancer);
  if (module.hot) {
    module.hot.accept(() => {
      store.replaceReducer(require('./reducers'));
    });
  }
  return store;
}
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import {connect} from 'react-redux';
import PanelLeft from './PanelLeft.js';
import PanelMiddle from './PanelMiddle.js';
import PanelRight from './PanelRight.js';

class AppContainer extends Component {
  highlight(obj) {
    if (0 === obj.clickedClassName) {
      return;
    }
    for (let i = 0; i < obj.contrastList.length; i++) {
      const tag = document.getElementsByClassName(obj.clickedClassName)[i];
      if (undefined === tag) {
        return;
      }
      tag.className = obj.clickedClassName + ' ' + obj.contrastList[i]
                      + ' ' + obj.highlight;
    }
  }

  clearOldHighlight(obj) {
    if (0 === obj.lastClickedClassName) {
      return;
    }
    for (let i = 0; i < obj.contrastList.length; i++) {
      const tag = document.getElementsByClassName(obj.lastClickedClassName)[i];
      if (undefined === tag) {
        return;
      }
      tag.className = obj.lastClickedClassName + ' ' + obj.contrastList[i];
    }
  }

  scrollToId(obj) {
    if ('' === obj.clickedSutraName) {
      return;
    }
    const idx = obj.contrastList.indexOf(obj.clickedSutraName);
    for (let i = 0; i < obj.contrastList.length; i++) {
      const tag = document.getElementsByClassName(obj.clickedClassName)[i];
      if (idx !== i && undefined !== tag) {
        tag.scrollIntoView();
        let tagScrolledHeight = document.getElementById(obj.contrastList[i] + 'Content').scrollTop;
        document.getElementById(obj.contrastList[i] + 'Content').scrollTop = tagScrolledHeight - obj.elementClientY + 80;
      }
    }
    console.log('end');
  }

  render() {
    this.scrollToId(this.props.contrast);
    this.clearOldHighlight(this.props.contrast);
    this.highlight(this.props.contrast);
    return (

          Tibetain-Chinese Sutra Contrast Reading UI on Gocaraparisuddhi

          <PanelLeft />
          <PanelMiddle />
          <PanelRight />

    );
  }
}

const mapStateToProps = (state) => {
  return {
    contrast: state.contrast
  };
};

const App = connect(mapStateToProps)(AppContainer);

export default App;
<commit_msg>remove console<commit_after>import React, {Component} from 'react';
import {connect} from 'react-redux';
import PanelLeft from './PanelLeft.js';
import PanelMiddle from './PanelMiddle.js';
import PanelRight from './PanelRight.js';

class AppContainer extends Component {
  highlight(obj) {
    if (0 === obj.clickedClassName) {
      return;
    }
    for (let i = 0; i < obj.contrastList.length; i++) {
      const tag = document.getElementsByClassName(obj.clickedClassName)[i];
      if (undefined === tag) {
        return;
      }
      tag.className = obj.clickedClassName + ' ' + obj.contrastList[i]
                      + ' ' + obj.highlight;
    }
  }

  clearOldHighlight(obj) {
    if (0 === obj.lastClickedClassName) {
      return;
    }
    for (let i = 0; i < obj.contrastList.length; i++) {
      const tag = document.getElementsByClassName(obj.lastClickedClassName)[i];
      if (undefined === tag) {
        return;
      }
      tag.className = obj.lastClickedClassName + ' ' + obj.contrastList[i];
    }
  }

  scrollToId(obj) {
    if ('' === obj.clickedSutraName) {
      return;
    }
    const idx = obj.contrastList.indexOf(obj.clickedSutraName);
    for (let i = 0; i < obj.contrastList.length; i++) {
      const tag = document.getElementsByClassName(obj.clickedClassName)[i];
      if (idx !== i && undefined !== tag) {
        tag.scrollIntoView();
        let tagScrolledHeight = document.getElementById(obj.contrastList[i] + 'Content').scrollTop;
        document.getElementById(obj.contrastList[i] + 'Content').scrollTop = tagScrolledHeight - obj.elementClientY + 80;
      }
    }
  }

  render() {
    this.scrollToId(this.props.contrast);
    this.clearOldHighlight(this.props.contrast);
    this.highlight(this.props.contrast);
    return (

          Tibetain-Chinese Sutra Contrast Reading UI on Gocaraparisuddhi

          <PanelLeft />
          <PanelMiddle />
          <PanelRight />

    );
  }
}

const mapStateToProps = (state) => {
  return {
    contrast: state.contrast
  };
};

const App = connect(mapStateToProps)(AppContainer);

export default App;
<|endoftext|>


<commit_before>function processPage(projects) {
    var path = window.location.pathname;
    var projectMap = {};

    for (var i = 0, len = projects.length; i < len; i++) {
        projectMap[projects[i].name] = projects[i].id;
    }

    function isNewsPage() {
        if (/.+dashboard$/.test(path)) {
            return true;
        } else if (path === '/' && document.getElementById('dashboard')) {
            return true;
        }
        return false;
    }

    function isProjectPage() {
    }

    function isCommitsPage() {
    }

    function isCommitPage() {
    }

    function convertCommitMessage(msg) {
        return msg;
    }

    function processNewsPage() {
        var newsDiv = document.querySelector('#dashboard .news');
        var alertDivs = newsDiv.querySelectorAll('.alert');
        var alertDiv;
        var titleDiv;
        var projName;
        var projId;
        var commitMsgElems;

        for (var i = 0, aLen = alertDivs.length; i < aLen; i++) {
            alertDiv = alertDivs[i];
            titleDiv = alertDiv.querySelector('.title');
            projName = titleDiv.lastElementChild.innerHTML.split('/')[1];
            projId = projectMap[projName];
            if (projId) {
                commitMsgElems = alertDiv.querySelectorAll('.details .commits .message blockquote');
                for (var j = 0, cLen = commitMsgElems.length; j < cLen; j++) {
                    commitMsgElems.innerHTML = convertCommitMessage(commitMsgElems.innerHTML);
                }
            }
        }
    }

    function processProjectPage() {
    }

    function processCommitsPage() {
    }

    function processCommitPage() {
    }

    if (isNewsPage()) {
        processNewsPage();
    } else if (isProjectPage()) {
        processProjectPage();
    } else if (isCommitsPage()) {
        processCommitsPage();
    } else if (isCommitPage()) {
        processCommitPage();
    }
}

chrome.runtime.sendMessage({fn: 'loadProjects'}, function(response) {
    var err = response.error;
    var projects = response.results[0];

    if (err || !projects || projects.length < 1) {
        return;
    }

    processPage(projects);
});

<commit_msg>Implemented process project page<commit_after>function processPage(projects) {
    var path = window.location.pathname;
    console.log('path = ' + path);
    var projectMap = {};

    for (var i = 0, len = projects.length; i < len; i++) {
        projectMap[projects[i].name] = projects[i].id;
    }

    function isNewsPage() {
        if (/.+dashboard$/.test(path)) {
            return true;
        } else if (path === '/' && document.getElementById('dashboard')) {
            return true;
        }
        return false;
    }

    function isProjectPage() {
        var projName = path.split('/')[2];
        return projName in projectMap;
    }

    function isCommitsPage() {
    }

    function isCommitPage() {
    }

    function convertCommitMessage(msg) {
        return msg;
    }

    function processNewsPage() {
        var newsDiv = document.querySelector('#dashboard .news');
        var alertDivs = newsDiv.querySelectorAll('.alert');
        var alertDiv;
        var titleDiv;
        var projName;
        var projId;
        var commitMsgElems;

        for (var i = 0, aLen = alertDivs.length; i < aLen; i++) {
            alertDiv = alertDivs[i];
            titleDiv = alertDiv.querySelector('.title');
            projName = titleDiv.lastElementChild.innerHTML.split('/')[1];
            projId = projectMap[projName];
            if (projId) {
                commitMsgElems = alertDiv.querySelectorAll('.details .commits .message blockquote');
                for (var j = 0, cLen = commitMsgElems.length; j < cLen; j++) {
                    commitMsgElems.innerHTML = convertCommitMessage(commitMsgElems.innerHTML);
                }
            }
        }
    }

    function processProjectPage() {
        var commitMsgElems = document.querySelectorAll('a.message');

        for (var i = 0, len = commitMsgElems.length; i < len; i++) {
            commitMsgElems[i].innerHTML = convertCommitMessage(commitMsgElems[i].innerHTML);
        }
    }

    function processCommitsPage() {
    }

    function processCommitPage() {
    }

    if (isNewsPage()) {
        processNewsPage();
    } else if (isProjectPage()) {
        processProjectPage();
    } else if (isCommitsPage()) {
        processCommitsPage();
    } else if (isCommitPage()) {
        processCommitPage();
    }
}

chrome.runtime.sendMessage({fn: 'loadProjects'}, function(response) {
    var err = response.error;
    var projects = response.results[0];

    if (err || !projects || projects.length < 1) {
        return;
    }

    processPage(projects);
});

<|endoftext|>