<commit_before>/**
 * This allows dattables to function using semantic attributes
 *
 * Usage:
 *	nwt.plugin('Datatable', {node: '#mytable', data: jsonObj});
 *	nwt.plugin('Datatable', {node: el, data: '#some table .selector'});
 */

!function() {

/**
 * Standardizes the column definitions
 * E.g., if the user passes a string for a column def, fill out the defaults
 */
function standardizeCols(columns) {

	/**
	 * Gets the default column name
	 */
	function getDefaultFormatter(colName) {
		return function(o) {
			return o[colName];
		};
	}

	/**
	 * Gets the default column sorter
	 */
	function getDefaultSorter(colName) {
		return function(a, b, dir){

			var
				firstRec = dir == 'asc' ? a : b,
				secondRec = dir == 'asc' ? b : a,

				fA = firstRec[colName].toLowerCase(),
				fB = secondRec[colName].toLowerCase();

			// Handle numbers
			if (fA<fB) return -1
			if (fA>fB) return +1
			return 0
		};
	}

	for (var i in columns) {
		var column = columns[i];

		if (typeof column == "string") {
			column = {name: column};
		}

		column.dir = column.sortDir || 'asc';
		column.formatter = column.formatter || getDefaultFormatter(column.key || column.name);
		column.sorter = column.sorter || getDefaultSorter(column.key || column.name);

		columns[i] = column;
	}
	return columns;
}

/**
 * Datasource from a local JSON object
 */
function JSONDataSource(config) {
	// Default to the first col ASC for sorting
	this.colSortIdx = -1;

	this.data = config.data;
	this.columns = standardizeCols(config.columns);
}

/**
 * No updates required, just render
 */
JSONDataSource.prototype.update = function(callback) {
	var mythis = this;

	if (mythis.colSortIdx >= 0) {
		this.data.sort(function(a, b){
			return mythis.columns[mythis.colSortIdx].sorter(a, b, mythis.columns[mythis.colSortIdx].dir);
		});
	}

	callback();
};

/**
 * Datasource from a remote IO source
 */
function IODataSource(config) {
	this.columns = standardizeCols(config.columns);
	this.io = config.data;
	this.node = config.node;

	this.fetch = config.fetch || function(io, sort, dir) {
		io.post('sort=' + sort + '&dir=' + dir);
	}

	// Default to the first col ASC for sorting
	this.colSortIdx = 0;
}

/**
 * No updates required, just render
 */
IODataSource.prototype.update = function(callback) {
	var self = this;
	self.io.success(function(o){
		self.data = o.obj.results;

		callback();
		self.node.fire('update', o);
	});

	self.fetch(self.io, self.columns[self.colSortIdx].name, self.columns[self.colSortIdx].dir);
};

/**
 * All we do is transform the table into json and reutrn a JSONDataSource
 */
function ElementDataSource(config) {
	var newData = [],
		newColumns = [];

	var headings = config.data.all('tr th');

	headings.each(function(th){
		newColumns.push(th.getHtml());
	});

	config.data.all('tr').each(function(tr){
		var newRow = {},
			populated = false;

		for (var i = 0, numCols = headings.size(); i < numCols; i++) {

			if (!tr.all('td').item(i)) { continue; }

			newRow[headings.item(i).getHtml()] = tr.all('td').item(i).getHtml();
			populated = true;
		}

		if (populated) {
			newData.push(newRow);
		}
	});

	config.columns = newColumns;
	config.data = newData;

	return new JSONDataSource(config);
}

nwt.register({

	name: 'Datatable',

	methods: {
		/**
		 * Initializes a datatable
		 * Sets up listeners, etc
		 * @param object Receives a config object with the following:
		 * - node: String or node object, where to render the table
		 * - data: Data to use. Can be a JSON object, table, or nwt.io instance
		 * For JSON or IO datatable you need to specify a columns object, like so:
		 *  columns: [
		 		{
					name: "My Column", // Title of the column

					formatter: function(o){ // (Optional) Formats the return result
						return o.somekey;
					},

					sorter: function(a, b) { (Optional) Special way to sort this column
						return a - b;
					},

					key: "name" // (Optional) If not given we will use a numerical index
				}
			]
		 */
		init: function (config) {

			var mythis = this;

			// If there is no data, default to the node
			config.data = config.data || config.node;

			// Default the class of the
 element
			this.tableClass = config.tableClass || 'table table-striped table-bordered';

			// Set the node to render to
			this.node = typeof config.node == 'string' ? nwt.one(config.node) : config.node;

			// Determine the datasource
			if (typeof config.data == 'string' || typeof config.data == 'object' && config.data._node) {
				// Query selector
				this.source = new ElementDataSource(config);

			// TODO: Use instanceof here instead
			} else if(typeof config.data == 'object' && config.data.ioData !== undefined) {
				// n.io Object
				this.source = new IODataSource(config);

			} else if(typeof config.data == 'object') {
				this.source = new JSONDataSource(config);
			}

			this.source.update(function() {
				mythis.render();
			});
		},

		/**
		 * Sorts the datatable
		 */
		sort: function(el) {
			var mythis = this;

			this.source.colSortIdx = el.data('col-idx');
			this.source.columns[el.data('col-idx')].dir = this.source.columns[el.data('col-idx')].dir == 'asc' ? 'desc' : 'asc';

			this.source.update(function() {
				mythis.render();
			});
		},

		/**
		 * When we render, the datasource should be updated
		 */
		render: function() {

			var self = this;

			// Populate table html
			var content = ['

',
				'
'];

			for (var i in this.source.columns) {

				var sortContent = '',
					colDir = self.source.columns[i].dir;

				if (self.source.colSortIdx == i) {
					sortContent = '';
				}

				content.push('' + this.source.columns[i].name + ' ' + sortContent + '	');
			}

			content.push('

');

			for (var i = 0, rows = this.source.data.length; i < rows; i++) {
				var datum = this.source.data[i];
				content.push('
');

				for (var j in this.source.columns) {
					content.push('' + this.source.columns[j].formatter(datum) + '	');
				}

				content.push('
');
			}

			content.push('

');

			this.node.setHtml(content.join(''));

			this.node.one('table thead').on('click', function(e) {
				if (e.target.data('sort')) {
					self.sort(e.target);
					e.stop();
				}
			});
		}
	}
});

}();<commit_msg>Add render event<commit_after>/**
 * This allows dattables to function using semantic attributes
 *
 * Usage:
 *	nwt.plugin('Datatable', {node: '#mytable', data: jsonObj});
 *	nwt.plugin('Datatable', {node: el, data: '#some table .selector'});
 */

!function() {

/**
 * Standardizes the column definitions
 * E.g., if the user passes a string for a column def, fill out the defaults
 */
function standardizeCols(columns) {

	/**
	 * Gets the default column name
	 */
	function getDefaultFormatter(colName) {
		return function(o) {
			return o[colName];
		};
	}

	/**
	 * Gets the default column sorter
	 */
	function getDefaultSorter(colName) {
		return function(a, b, dir){

			var
				firstRec = dir == 'asc' ? a : b,
				secondRec = dir == 'asc' ? b : a,

				fA = firstRec[colName].toLowerCase(),
				fB = secondRec[colName].toLowerCase();

			// Handle numbers
			if (fA<fB) return -1
			if (fA>fB) return +1
			return 0
		};
	}

	for (var i in columns) {
		var column = columns[i];

		if (typeof column == "string") {
			column = {name: column};
		}

		column.dir = column.sortDir || 'asc';
		column.formatter = column.formatter || getDefaultFormatter(column.key || column.name);
		column.sorter = column.sorter || getDefaultSorter(column.key || column.name);

		columns[i] = column;
	}
	return columns;
}

/**
 * Datasource from a local JSON object
 */
function JSONDataSource(config) {
	// Default to the first col ASC for sorting
	this.colSortIdx = -1;

	this.data = config.data;
	this.columns = standardizeCols(config.columns);
}

/**
 * No updates required, just render
 */
JSONDataSource.prototype.update = function(callback) {
	var mythis = this;

	if (mythis.colSortIdx >= 0) {
		this.data.sort(function(a, b){
			return mythis.columns[mythis.colSortIdx].sorter(a, b, mythis.columns[mythis.colSortIdx].dir);
		});
	}

	callback();
};

/**
 * Datasource from a remote IO source
 */
function IODataSource(config) {
	this.columns = standardizeCols(config.columns);
	this.io = config.data;
	this.node = config.node;

	this.fetch = config.fetch || function(io, sort, dir) {
		io.post('sort=' + sort + '&dir=' + dir);
	}

	// Default to the first col ASC for sorting
	this.colSortIdx = 0;
}

/**
 * No updates required, just render
 */
IODataSource.prototype.update = function(callback) {
	var self = this;
	self.io.success(function(o){
		self.data = o.obj.results;

		callback();
		self.node.fire('update', o);
	});

	self.fetch(self.io, self.columns[self.colSortIdx].name, self.columns[self.colSortIdx].dir);
};

/**
 * All we do is transform the table into json and reutrn a JSONDataSource
 */
function ElementDataSource(config) {
	var newData = [],
		newColumns = [];

	var headings = config.data.all('tr th');

	headings.each(function(th){
		newColumns.push(th.getHtml());
	});

	config.data.all('tr').each(function(tr){
		var newRow = {},
			populated = false;

		for (var i = 0, numCols = headings.size(); i < numCols; i++) {

			if (!tr.all('td').item(i)) { continue; }

			newRow[headings.item(i).getHtml()] = tr.all('td').item(i).getHtml();
			populated = true;
		}

		if (populated) {
			newData.push(newRow);
		}
	});

	config.columns = newColumns;
	config.data = newData;

	return new JSONDataSource(config);
}

nwt.register({

	name: 'Datatable',

	methods: {
		/**
		 * Initializes a datatable
		 * Sets up listeners, etc
		 * @param object Receives a config object with the following:
		 * - node: String or node object, where to render the table
		 * - data: Data to use. Can be a JSON object, table, or nwt.io instance
		 * For JSON or IO datatable you need to specify a columns object, like so:
		 *  columns: [
		 		{
					name: "My Column", // Title of the column

					formatter: function(o){ // (Optional) Formats the return result
						return o.somekey;
					},

					sorter: function(a, b) { (Optional) Special way to sort this column
						return a - b;
					},

					key: "name" // (Optional) If not given we will use a numerical index
				}
			]
		 */
		init: function (config) {

			var mythis = this;

			// If there is no data, default to the node
			config.data = config.data || config.node;

			// Default the class of the
 element
			this.tableClass = config.tableClass || 'table table-striped table-bordered';

			// Set the node to render to
			this.node = typeof config.node == 'string' ? nwt.one(config.node) : config.node;

			// Determine the datasource
			if (typeof config.data == 'string' || typeof config.data == 'object' && config.data._node) {
				// Query selector
				this.source = new ElementDataSource(config);

			// TODO: Use instanceof here instead
			} else if(typeof config.data == 'object' && config.data.ioData !== undefined) {
				// n.io Object
				this.source = new IODataSource(config);

			} else if(typeof config.data == 'object') {
				this.source = new JSONDataSource(config);
			}

			this.source.update(function() {
				mythis.render();
			});
		},

		/**
		 * Sorts the datatable
		 */
		sort: function(el) {
			var mythis = this;

			this.source.colSortIdx = el.data('col-idx');
			this.source.columns[el.data('col-idx')].dir = this.source.columns[el.data('col-idx')].dir == 'asc' ? 'desc' : 'asc';

			this.source.update(function() {
				mythis.render();
			});
		},

		/**
		 * When we render, the datasource should be updated
		 */
		render: function() {

			var self = this;

			// Populate table html
			var content = ['

',
				'
'];

			for (var i in this.source.columns) {

				var sortContent = '',
					colDir = self.source.columns[i].dir;

				if (self.source.colSortIdx == i) {
					sortContent = '';
				}

				content.push('' + this.source.columns[i].name + ' ' + sortContent + '	');
			}

			content.push('

');

			for (var i = 0, rows = this.source.data.length; i < rows; i++) {
				var datum = this.source.data[i];
				content.push('
');

				for (var j in this.source.columns) {
					content.push('' + this.source.columns[j].formatter(datum) + '	');
				}

				content.push('
');
			}

			content.push('

');

			this.node.setHtml(content.join(''));

			this.node.one('table thead').on('click', function(e) {
				if (e.target.data('sort')) {
					self.sort(e.target);
					e.stop();
				}
			});
			this.node.fire('render')
		}
	}
});

}();<|endoftext|>


<commit_before>require('module-alias/register')

const fs = require('fs')
const path = require('path')
const glob = require('glob')
const esbuild = require('esbuild')
const sassPlugin = require('esbuild-plugin-sass')

const { makePromise } = require('@/cjs/promises')
const { composePaths } = require('@/cjs/compose-paths')
const { loadTextFile, fileOnly } = require('@/cjs/files')

const MINIFY_DISTRIBUTION = false
const PLUGIN_SOURCE_NAME = 'plugin.js'

const paths = composePaths(`
  ${__dirname}
    /src                               = SRC
      /plugins
        /**/plugin.json                = SRC_PLUGINS

      /ui
        /index.js                      = SRC_UI
        /styles
          /statements-browser/
            /all.scss                  = SRC_STATEMENTS_CSS

      /bookmarklet.js                  = SRC_BOOKMARKLET
      /main.js                         = SRC_MAIN

      /_mock-server
        /index.js                      = SERVER_SCRIPT

    /dist                              = DIST
      /plugins                         = DIST_PLUGINS
      /plugins.js                      = DIST_PLUGIN_JS
      /ui.js                           = DIST_UI
      /bookmarklet.js                  = DIST_BOOKMARKLET
      /main.js                         = DIST_MAIN
      /statement.css                   = DIST_STATEMENTS_CSS
`)

// Require plugins folder before moving on...

if (!fs.statSync(paths.DIST_PLUGINS).isDirectory()) {
  process.exit(255)
}

const RUN_MOCK_SERVER = process.argv.some(arg => arg === '--mock-server')
const IS_LOCAL = (process.env.NODE_ENV || 'local') === 'local'
const SOURCE_MAPS = false // IS_LOCAL
const BUILD_REPLACEMENTS = {
  'process.env.NODE_ENV': `"${process.env.NODE_ENV}"`,
  'process.env.HYDRATE': `"${process.env.HYDRATE}"`
}

console.log('IS_LOCAL', IS_LOCAL)

function main() {
  return buildBookmarklet()
    .then(buildMain)
    .then(buildPlugins)
    .then(buildUi)
    .then(buildStatementsCss)
    .then(maybeRunMockServer)
}

function maybeRunMockServer() {
  if (!RUN_MOCK_SERVER) {
    return
  }

  const nodemon = require('nodemon')
  nodemon({
    script: paths.SERVER_SCRIPT,
    ext: 'js,jsx,json,scss',
    env: { HYDRATE: process.env.HYDRATE }
  })
    .on('start', () => {
      console.log('nodemon started')
    })
    .on('crash', error => {
      console.log('script crashed for some reason')
      console.error(error)
    })

  process.on('SIGINT', function () {
    console.log('Caught interrupt signal')
    nodemon.emit('quit')
    process.exit()
  })
}

//
// Builders
//

function buildBookmarklet() {
  return esbuild
    .build({
      define: BUILD_REPLACEMENTS,
      entryPoints: [paths.SRC_BOOKMARKLET],
      bundle: true,
      minify: true, // Always minify bookmarklet
      platform: 'browser',
      sourcemap: SOURCE_MAPS,
      outfile: paths.DIST_BOOKMARKLET
    })
    .then(() => loadTextFile(paths.DIST_BOOKMARKLET))
    .then(bookmarkletContent =>
      fs.writeFileSync(
        paths.DIST_BOOKMARKLET,
        'javascript:' + bookmarkletContent.toString()
      )
    )
}

function buildMain() {
  return esbuild.build({
    define: BUILD_REPLACEMENTS,
    entryPoints: [paths.SRC_MAIN],
    bundle: true,
    minify: MINIFY_DISTRIBUTION,
    platform: 'browser',
    sourcemap: IS_LOCAL,
    outfile: paths.DIST_MAIN
  })
}

function buildUi() {
  return esbuild.build({
    define: BUILD_REPLACEMENTS,
    entryPoints: [paths.SRC_UI],
    bundle: true,
    minify: MINIFY_DISTRIBUTION,
    platform: 'browser',
    jsxFactory: 'm',
    jsxFragment: 'm.Fragment',
    plugins: [sassPlugin()],
    sourcemap: SOURCE_MAPS,
    outfile: paths.DIST_UI
  })
}

function buildStatementsCss() {
  return esbuild.build({
    entryPoints: [paths.SRC_STATEMENTS_CSS],
    bundle: true,
    minify: MINIFY_DISTRIBUTION,
    loader: { '.scss': 'css' },
    plugins: [sassPlugin()],
    sourcemap: IS_LOCAL,
    outfile: paths.DIST_STATEMENTS_CSS
  })
}

function buildPlugins() {
  return buildAndMinifyPlugins().then(results => {
    const allPluginMeta = results.map(({ pluginMeta }) => pluginMeta)
    const allPluginContent = results.map(({ pluginContent, pluginMeta }) => ({
      dist: pluginMeta.dist,
      content: pluginContent
    }))

    const pluginPromises = allPluginContent.map(({ dist, content }) => {
      const [promise, resolve, reject] = makePromise()
      fs.writeFile(dist, content, err => (err ? reject(err) : resolve()))
      return promise
    })

    const pluginRegistryJs = buildPluginsRegistryContent(allPluginMeta)
    const [registryPromise, resolve, reject] = makePromise()
    fs.writeFile(paths.DIST_PLUGIN_JS, pluginRegistryJs, err =>
      err ? reject(err) : resolve()
    )

    return Promise.all(pluginPromises.concat(registryPromise))
  })
}

//
// Plugin building helpers
//

function buildPluginsRegistryContent(allPluginMeta) {
  const pluginInfo = allPluginMeta.map(result => {
    // eslint-disable-next-line no-unused-vars
    const { src, dist, ...restValue } = result
    return restValue
  })

  return `obis.registerPlugins(${JSON.stringify(pluginInfo, null, 2)});`
}

function buildAndMinifyPlugins() {
  return (
    metaForAllAvailablePlugins()
      // Bundle/minify plugins
      .then(allPluginMeta =>
        Promise.allSettled(
          allPluginMeta.map(pluginMeta => {
            return esbuild
              .build({
                define: BUILD_REPLACEMENTS,
                entryPoints: [pluginMeta.src],
                bundle: true,
                minify: MINIFY_DISTRIBUTION,
                platform: 'browser',
                sourcemap: SOURCE_MAPS,
                write: false
              })
              .then(build => {
                return {
                  pluginMeta,
                  pluginContent: getFullEsbuildContent(build)
                }
              })
          })
        )
      )
      .then(results =>
        results
          .filter(result => result.status === 'fulfilled')
          .map(result => result.value)
      )
  )
}

function metaForAllAvailablePlugins() {
  const loadPluginFile = fileName =>
    loadTextFile(fileName).then(src => ({ fileName, src }))

  return (
    allPluginFileNames()
      // Load all plugins
      .then(pluginsFiles =>
        Promise.allSettled(pluginsFiles.map(loadPluginFile))
      )
      // Build plugins.js output (but don't write it yet)
      .then(results =>
        results
          .filter(result => result.status === 'fulfilled')
          .map(result => result.value)
          .map(details => {
            const { fileName, src } = details
            const { name, description, urls } = JSON.parse(src)
            const { dir } = path.parse(fileName)
            const srcJs = path.join(dir, PLUGIN_SOURCE_NAME)
            const distJs = path.join(paths.DIST_PLUGINS, `${name}.js`)
            return {
              src: srcJs,
              dist: distJs,
              name,
              description,
              urls
            }
          })
      )
  )
}

function allPluginFileNames() {
  const [promise, resolve, reject] = makePromise()

  glob(paths.SRC_PLUGINS, {}, (err, files) => {
    return err
      ? reject(err)
      : Promise.all(files.map(fileOnly)).then(resolve, reject)
  })

  return promise
}

main()

//
// Helpers
//

function getFullEsbuildContent(build) {
  return mergeTypedArrays(
    build.outputFiles.map(out => out.contents),
    Uint8Array
  )
}

// https://stackoverflow.com/a/56993335/127928
const mergeTypedArrays = (arrays, type = Uint8Array) => {
  const result = new type(arrays.reduce((acc, arr) => acc + arr.byteLength, 0))
  let offset = 0
  arrays.forEach(arr => {
    result.set(arr, offset)
    offset += arr.byteLength
  })
  return result
}
<commit_msg>Optionally avoid writing output for buildMain() + buildStatementsCss()<commit_after>require('module-alias/register')

const fs = require('fs')
const path = require('path')
const glob = require('glob')
const esbuild = require('esbuild')
const sassPlugin = require('esbuild-plugin-sass')

const { makePromise } = require('@/cjs/promises')
const { composePaths } = require('@/cjs/compose-paths')
const { loadTextFile, fileOnly } = require('@/cjs/files')

const MINIFY_DISTRIBUTION = false
const PLUGIN_SOURCE_NAME = 'plugin.js'

const paths = composePaths(`
  ${__dirname}
    /src                               = SRC
      /plugins
        /**/plugin.json                = SRC_PLUGINS

      /ui
        /index.js                      = SRC_UI
        /styles
          /statements-browser/
            /all.scss                  = SRC_STATEMENTS_CSS

      /bookmarklet.js                  = SRC_BOOKMARKLET
      /main.js                         = SRC_MAIN

      /_mock-server
        /index.js                      = SERVER_SCRIPT

    /dist                              = DIST
      /plugins                         = DIST_PLUGINS
      /plugins.js                      = DIST_PLUGIN_JS
      /ui.js                           = DIST_UI
      /bookmarklet.js                  = DIST_BOOKMARKLET
      /main.js                         = DIST_MAIN
      /statement.css                   = DIST_STATEMENTS_CSS
`)

// Require plugins folder before moving on...

if (!fs.statSync(paths.DIST_PLUGINS).isDirectory()) {
  process.exit(255)
}

const DO_NOT_WRITE = true
const RUN_MOCK_SERVER = process.argv.some(arg => arg === '--mock-server')
const IS_LOCAL = (process.env.NODE_ENV || 'local') === 'local'
const SOURCE_MAPS = false // IS_LOCAL
const BUILD_REPLACEMENTS = {
  'process.env.NODE_ENV': `"${process.env.NODE_ENV}"`,
  'process.env.HYDRATE': `"${process.env.HYDRATE}"`
}

console.log('IS_LOCAL', IS_LOCAL)

function main() {
  return buildBookmarklet()
    .then(buildMain)
    .then(buildPlugins)
    .then(buildUi)
    .then(buildStatementsCss)
    .then(maybeRunMockServer)
}

function maybeRunMockServer() {
  if (!RUN_MOCK_SERVER) {
    return
  }

  const nodemon = require('nodemon')
  nodemon({
    script: paths.SERVER_SCRIPT,
    ext: 'js,jsx,json,scss',
    env: { HYDRATE: process.env.HYDRATE }
  })
    .on('start', () => {
      console.log('nodemon started')
    })
    .on('crash', error => {
      console.log('script crashed for some reason')
      console.error(error)
    })

  process.on('SIGINT', function () {
    console.log('Caught interrupt signal')
    nodemon.emit('quit')
    process.exit()
  })
}

//
// Builders
//

function buildBookmarklet() {
  return esbuild
    .build({
      define: BUILD_REPLACEMENTS,
      entryPoints: [paths.SRC_BOOKMARKLET],
      bundle: true,
      minify: true, // Always minify bookmarklet
      platform: 'browser',
      sourcemap: SOURCE_MAPS,
      outfile: paths.DIST_BOOKMARKLET
    })
    .then(() => loadTextFile(paths.DIST_BOOKMARKLET))
    .then(bookmarkletContent =>
      fs.writeFileSync(
        paths.DIST_BOOKMARKLET,
        'javascript:' + bookmarkletContent.toString()
      )
    )
}

function buildMain(doNotWrite) {
  const options = {
    define: BUILD_REPLACEMENTS,
    entryPoints: [paths.SRC_MAIN],
    bundle: true,
    minify: MINIFY_DISTRIBUTION,
    platform: 'browser',
    sourcemap: SOURCE_MAPS,
    write: !doNotWrite,
    ...(!doNotWrite && { outfile: paths.DIST_MAIN })
  }
  return esbuild.build(options)
}

function buildUi() {
  return esbuild.build({
    define: BUILD_REPLACEMENTS,
    entryPoints: [paths.SRC_UI],
    bundle: true,
    minify: MINIFY_DISTRIBUTION,
    platform: 'browser',
    jsxFactory: 'm',
    jsxFragment: 'm.Fragment',
    plugins: [sassPlugin()],
    sourcemap: SOURCE_MAPS,
    outfile: paths.DIST_UI
  })
}

function buildStatementsCss(doNotWrite) {
  const options = {
    entryPoints: [paths.SRC_STATEMENTS_CSS],
    bundle: true,
    minify: MINIFY_DISTRIBUTION,
    loader: { '.scss': 'css' },
    plugins: [sassPlugin()],
    sourcemap: SOURCE_MAPS,
    write: !doNotWrite,
    ...(!doNotWrite && { outfile: paths.DIST_STATEMENTS_CSS })
  }
  return esbuild.build(options)
}

function buildPlugins() {
  return buildAndMinifyPlugins().then(results => {
    const allPluginMeta = results.map(({ pluginMeta }) => pluginMeta)
    const allPluginContent = results.map(({ pluginContent, pluginMeta }) => ({
      dist: pluginMeta.dist,
      content: pluginContent
    }))

    const pluginPromises = allPluginContent.map(({ dist, content }) => {
      const [promise, resolve, reject] = makePromise()
      fs.writeFile(dist, content, err => (err ? reject(err) : resolve()))
      return promise
    })

    const pluginRegistryJs = buildPluginsRegistryContent(allPluginMeta)
    const [registryPromise, resolve, reject] = makePromise()
    fs.writeFile(paths.DIST_PLUGIN_JS, pluginRegistryJs, err =>
      err ? reject(err) : resolve()
    )

    return Promise.all(pluginPromises.concat(registryPromise))
  })
}

//
// Plugin building helpers
//

function buildPluginsRegistryContent(allPluginMeta) {
  const pluginInfo = allPluginMeta.map(result => {
    // eslint-disable-next-line no-unused-vars
    const { src, dist, ...restValue } = result
    return restValue
  })

  return `obis.registerPlugins(${JSON.stringify(pluginInfo, null, 2)});`
}

function buildAndMinifyPlugins() {
  return (
    metaForAllAvailablePlugins()
      // Bundle/minify plugins
      .then(allPluginMeta =>
        Promise.allSettled(
          allPluginMeta.map(pluginMeta => {
            return esbuild
              .build({
                define: BUILD_REPLACEMENTS,
                entryPoints: [pluginMeta.src],
                bundle: true,
                minify: MINIFY_DISTRIBUTION,
                platform: 'browser',
                sourcemap: SOURCE_MAPS,
                write: false
              })
              .then(build => {
                return {
                  pluginMeta,
                  pluginContent: getFullEsbuildContent(build)
                }
              })
          })
        )
      )
      .then(results =>
        results
          .filter(result => result.status === 'fulfilled')
          .map(result => result.value)
      )
  )
}

function metaForAllAvailablePlugins() {
  const loadPluginFile = fileName =>
    loadTextFile(fileName).then(src => ({ fileName, src }))

  return (
    allPluginFileNames()
      // Load all plugins
      .then(pluginsFiles =>
        Promise.allSettled(pluginsFiles.map(loadPluginFile))
      )
      // Build plugins.js output (but don't write it yet)
      .then(results =>
        results
          .filter(result => result.status === 'fulfilled')
          .map(result => result.value)
          .map(details => {
            const { fileName, src } = details
            const { name, description, urls } = JSON.parse(src)
            const { dir } = path.parse(fileName)
            const srcJs = path.join(dir, PLUGIN_SOURCE_NAME)
            const distJs = path.join(paths.DIST_PLUGINS, `${name}.js`)
            return {
              src: srcJs,
              dist: distJs,
              name,
              description,
              urls
            }
          })
      )
  )
}

function allPluginFileNames() {
  const [promise, resolve, reject] = makePromise()

  glob(paths.SRC_PLUGINS, {}, (err, files) => {
    return err
      ? reject(err)
      : Promise.all(files.map(fileOnly)).then(resolve, reject)
  })

  return promise
}

main()

//
// Helpers
//

function getFullEsbuildContent(build) {
  return mergeTypedArrays(
    build.outputFiles.map(out => out.contents),
    Uint8Array
  )
}

// https://stackoverflow.com/a/56993335/127928
const mergeTypedArrays = (arrays, type = Uint8Array) => {
  const result = new type(arrays.reduce((acc, arr) => acc + arr.byteLength, 0))
  let offset = 0
  arrays.forEach(arr => {
    result.set(arr, offset)
    offset += arr.byteLength
  })
  return result
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var paka = require('../../paka.js');
var path = require('path');
var util = require('util');

var PROGRAM = path.basename(process.argv[1]);

function help() {
    console.log('Example: ' + PROGRAM + '{ "k1" : "v1", "k2" : 123, "k3" : false, "k4" : null }');
}

function parse(src) {
    var INT = paka.INT;
    var EOF = paka.EOF;
    var _SEQ_ = paka._SEQ_;
    var OR = paka.OR;
    var REPEAT = paka.REPEAT;
    var OPT = paka.OPT;
    var STR = paka.STR;
    var CHAR = paka.CHAR;
    var NCHAR = paka.NCHAR;
    var $ = paka.$;

    var grammar = {
        'JSON' : _SEQ_('{', OPT($('KeyValueList')), '}', EOF),
        'KeyValueList' : _SEQ_($('KeyValuePair'), REPEAT(_SEQ_(',', $('KeyValuePair')), 0)),
        'KeyValuePair' : _SEQ_($('Key'), ':', $('Value')),
        'Key' : $('String'),
        'Value' : OR($('Num'), $('Null'), $('Bool'), $('String')),
        'Num' : INT(),
        'Null' : STR('null'),
        'Bool' : OR('false', 'true'),
        'String' : _SEQ_('"', REPEAT(NCHAR('"'), 0), '"')
    };

    var action = {
    }

    var parser = paka.define(grammar, action);
    var ast = parser.parse('JSON', src);

    //console.log(util.inspect(ast, false, 10));

    return ast;
}

module.exports = { parse : parse };
<commit_msg>Minor refactor<commit_after>#!/usr/bin/env node

var paka = require('../../paka.js');
var path = require('path');
var util = require('util');

var PROGRAM = path.basename(process.argv[1]);

function help() {
    console.log('Example: ' + PROGRAM + '{ "k1" : "v1", "k2" : 123, "k3" : false, "k4" : null }');
}

function parse(src) {
    var INT = paka.INT;
    var EOF = paka.EOF;
    var _SEQ_ = paka._SEQ_;
    var OR = paka.OR;
    var REPEAT = paka.REPEAT;
    var OPT = paka.OPT;
    var STR = paka.STR;
    var CHAR = paka.CHAR;
    var NCHAR = paka.NCHAR;
    var $ = paka.$;

    var grammar = {
        'JSON' : _SEQ_('{', OPT($('KeyValueList')), '}', EOF),
        'KeyValueList' : _SEQ_($('KeyValuePair'), REPEAT(_SEQ_(',', $('KeyValuePair')), 0)),
        'KeyValuePair' : _SEQ_($('Key'), ':', $('Value')),
        'Key' : $('String'),
        'Value' : OR($('Num'), $('Null'), $('Bool'), $('String')),
        'Num' : INT(),
        'Null' : 'null',
        'Bool' : OR('false', 'true'),
        'String' : _SEQ_('"', REPEAT(NCHAR('"'), 0), '"')
    };

    var action = {
    }

    var parser = paka.define(grammar, action);
    var ast = parser.parse('JSON', src);

    //console.log(util.inspect(ast, false, 10));

    return ast;
}

module.exports = { parse : parse };
<|endoftext|>


<commit_before>/*global require, $, _, psData*/
import $ from 'jquery';
import _ from 'underscore';
import Promise from 'bluebird';

export default function() {
  var studentRows = $('.studentrow');
  var ids = $.map(studentRows, row => $(row).attr('id').slice(5));

  fetch('/ws/schema/query/org.irondistrict.iep.queries.attendance_alert', {
      credentials: 'include',
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        cc_ids: ids.join(',')
      })
    })
    .then(response => response.json())
    .then(results => {
      if (typeof results.record !== 'undefined') {
        results.record.forEach(alert => {
          var alertTemplate = $('#alert-template').html();
          var compiledTemplate = _.template(alertTemplate);
          var select = studentRows.filter(`[id$=${alert.cc_id}]`).find('td').eq(1);
          select.append(compiledTemplate({
            studentfrn: '001' + alert.studentsdcid
          }));
        });
      }
    });
}
<commit_msg>filter alert records that have a blank caseload field<commit_after>/*global require, $, _, psData*/
import $ from 'jquery';
import _ from 'underscore';
import Promise from 'bluebird';

export default function() {
  var studentRows = $('.studentrow');
  var ids = $.map(studentRows, row => $(row).attr('id').slice(5));

  fetch('/ws/schema/query/org.irondistrict.iep.queries.attendance_alert', {
      credentials: 'include',
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        cc_ids: ids.join(',')
      })
    })
    .then(response => response.json())
    .then(results => {
      if (typeof results.record !== 'undefined') {
        results.record
          .filter(alert => !!alert.caseload)
          .forEach(alert => {
            var alertTemplate = $('#alert-template').html();
            var compiledTemplate = _.template(alertTemplate);
            var select = studentRows.filter(`[id$=${alert.cc_id}]`).find('td').eq(1);
            select.append(compiledTemplate({
              studentfrn: '001' + alert.studentsdcid
            }));
          });
      }
    });
}
<|endoftext|>


<commit_before>module.exports = (db, Sequelize, User) => {
  var Business = db.define('business', {
    id: {
      type: Sequelize.INTEGER,
      autoIncrement: true,
      primaryKey: true
    },
    name: Sequelize.STRING,
    address: Sequelize.STRING,
    license: Sequelize.STRING,
    user_id: Sequelize.INTEGER
  });

  return Business;
};<commit_msg>Fix styleguide issues in business.js<commit_after>module.exports = (db, Sequelize) => {
  const Business = db.define('business', {
    id: {
      type: Sequelize.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    name: Sequelize.STRING,
    address: Sequelize.STRING,
    license: Sequelize.STRING,
    user_id: Sequelize.INTEGER,
  });

  return Business;
};
<|endoftext|>


<commit_before>'use strict';

var angular = require('angular');
var angularMaterial = require('angular-material');
var angularAnimate = require('angular-animate');
var angularAria = require('angular-aria');
require('../../node_modules/angular-material-icons/angular-material-icons');

module.exports = angular.module('ToDo', ['ngMaterial', 'ngAnimate', 'ngAria', 'ngMdIcons'])
    .directive('confirmButton', require('./ToDoConfirmButtonDirective'))
    .controller('ToDoController', require('./ToDoController'))
    .factory('ToDoService', require('./ToDoService'));
<commit_msg>registered ToDoNewController and ToDoDetailController<commit_after>'use strict';

var angular = require('angular');
var angularMaterial = require('angular-material');
var angularAnimate = require('angular-animate');
var angularAria = require('angular-aria');
require('../../node_modules/angular-material-icons/angular-material-icons');

module.exports = angular.module('ToDo', ['ngMaterial', 'ngAnimate', 'ngAria', 'ngMdIcons'])
    .controller('ToDoController', require('./ToDoController'))
    .controller('ToDoNewController', require('./ToDoNewController'))
    .controller('ToDoDetailController', require('./ToDoDetailController'))
    .factory('ToDoService', require('./ToDoService'));
<|endoftext|>


<commit_before>var BBEvents = require('backbone-events-standalone');
var extend = require('extend-object');

var result = function (obj, prop) {
    if (typeof obj[prop] === 'function') return obj[prop]();
    return prop;
};

function FormView(opts) {
    this.el = opts.el;
    this.validCallback = opts.validCallback || this.validCallback || function () {};
    this.submitCallback = opts.submitCallback || this.submitCallback || function () {};

    if (opts.data) this.data = opts.data;
    if (opts.model) this.model = opts.model;

    this.clean = opts.clean || function (res) { return res; };
    this.valid = false;
    this.preventDefault = opts.preventDefault === false ? false : true;
    this.autoAppend = opts.autoAppend === false ? false : true;

    // storage for our fields
    this._fieldViews = {};
    this._fieldViewsArray = [];

    // add all our fields
    this.render();

    (opts.fields || result(this, 'fields') || []).forEach(this.addField.bind(this));

    if (this.initialize) this.initialize();

    //defer till after returning from initialize
    setTimeout(function () {
        this.checkValid(true);
    }.bind(this), 0);
}

extend(FormView.prototype, BBEvents, {
    data: null,
    model: null,
    fields: null,

    addField: function (fieldView) {
        this._fieldViews[fieldView.name] = fieldView;
        this._fieldViewsArray.push(fieldView);
        if (this.fieldContainerEl) {
            fieldView.parent = this;
            fieldView.render();
            this.fieldContainerEl.appendChild(fieldView.el);
        }
    },

    removeField: function (name) {
        delete this._fieldViews[fieldView.name];
        this._fieldViewsArray.splice(this._fieldViewsArray.indexOf(field), 1);
        this.getField(name).remove();
    },

    getField: function (name) {
        return this._fieldViews[name];
    },

    setValid: function (now, forceFire) {
        var prev = this.valid;
        this.valid = now;
        if (prev !== now || forceFire) {
            this.validCallback(now);
        }
    },

    checkValid: function (forceFire) {
        var valid = this._fieldViewsArray.every(function (field) {
            return field.valid;
        });
        this.setValid(valid, forceFire);
        return valid;
    },

    beforeSubmit: function () {
        this._fieldViewsArray.forEach(function (field) {
            if (field.beforeSubmit) field.beforeSubmit();
        });
    },

    update: function (field) {
        this.trigger('change:' + field.name, field);
        // if this one's good check 'em all
        if (field.valid) {
            this.checkValid();
        } else {
            this.setValid(false);
        }
    },

    remove: function () {
        this.el.removeEventListener('submit', this.handleSubmit, false);
        var parent = this.el.parentNode;
        if (parent) parent.removeChild(this.el);
        this._fieldViewsArray.forEach(function (field) {
            field.remove();
        });
    },

    handleSubmit: function (e) {
        this.beforeSubmit();
        this.checkValid();
        if (!this.valid) {
            e.preventDefault();
            return false;
        }

        if (this.preventDefault) {
            e.preventDefault();
            this.submitCallback(this.getData());
            return false;
        }
    },

    getData: function () {
        var res = {};
        for (var key in this._fieldViews) {
            res[key] = this._fieldViews[key].value;
        }
        return this.clean(res);
    },

    render: function () {
        if (this.rendered) return;
        if (!this.el) {
            this.el = document.createElement('form');
        }
        if (this.autoAppend) {
            this.fieldContainerEl = this.el.querySelector('[data-hook~=field-container]') || this.el;
        }
        this.handleSubmit = this.handleSubmit.bind(this);
        this.el.addEventListener('submit', this.handleSubmit, false);
        this.rendered = true;
    }
});

FormView.extend = function (obj) {
    var child = function () {
       FormView.apply(this, arguments);
    };

    extend(child.prototype, FormView.prototype);
    extend(child.prototype, obj);

    return child;
};

module.exports = FormView;
<commit_msg>Fixing bug in result() function<commit_after>var BBEvents = require('backbone-events-standalone');
var extend = require('extend-object');

var result = function (obj, prop) {
    if (typeof obj[prop] === 'function') return obj[prop]();
    return obj[prop];
};

function FormView(opts) {
    this.el = opts.el;
    this.validCallback = opts.validCallback || this.validCallback || function () {};
    this.submitCallback = opts.submitCallback || this.submitCallback || function () {};

    if (opts.data) this.data = opts.data;
    if (opts.model) this.model = opts.model;

    this.clean = opts.clean || function (res) { return res; };
    this.valid = false;
    this.preventDefault = opts.preventDefault === false ? false : true;
    this.autoAppend = opts.autoAppend === false ? false : true;

    // storage for our fields
    this._fieldViews = {};
    this._fieldViewsArray = [];

    // add all our fields
    this.render();

    (opts.fields || result(this, 'fields') || []).forEach(this.addField.bind(this));

    if (this.initialize) this.initialize();

    //defer till after returning from initialize
    setTimeout(function () {
        this.checkValid(true);
    }.bind(this), 0);
}

extend(FormView.prototype, BBEvents, {
    data: null,
    model: null,
    fields: null,

    addField: function (fieldView) {
        this._fieldViews[fieldView.name] = fieldView;
        this._fieldViewsArray.push(fieldView);
        if (this.fieldContainerEl) {
            fieldView.parent = this;
            fieldView.render();
            this.fieldContainerEl.appendChild(fieldView.el);
        }
    },

    removeField: function (name) {
        delete this._fieldViews[fieldView.name];
        this._fieldViewsArray.splice(this._fieldViewsArray.indexOf(field), 1);
        this.getField(name).remove();
    },

    getField: function (name) {
        return this._fieldViews[name];
    },

    setValid: function (now, forceFire) {
        var prev = this.valid;
        this.valid = now;
        if (prev !== now || forceFire) {
            this.validCallback(now);
        }
    },

    checkValid: function (forceFire) {
        var valid = this._fieldViewsArray.every(function (field) {
            return field.valid;
        });
        this.setValid(valid, forceFire);
        return valid;
    },

    beforeSubmit: function () {
        this._fieldViewsArray.forEach(function (field) {
            if (field.beforeSubmit) field.beforeSubmit();
        });
    },

    update: function (field) {
        this.trigger('change:' + field.name, field);
        // if this one's good check 'em all
        if (field.valid) {
            this.checkValid();
        } else {
            this.setValid(false);
        }
    },

    remove: function () {
        this.el.removeEventListener('submit', this.handleSubmit, false);
        var parent = this.el.parentNode;
        if (parent) parent.removeChild(this.el);
        this._fieldViewsArray.forEach(function (field) {
            field.remove();
        });
    },

    handleSubmit: function (e) {
        this.beforeSubmit();
        this.checkValid();
        if (!this.valid) {
            e.preventDefault();
            return false;
        }

        if (this.preventDefault) {
            e.preventDefault();
            this.submitCallback(this.getData());
            return false;
        }
    },

    getData: function () {
        var res = {};
        for (var key in this._fieldViews) {
            res[key] = this._fieldViews[key].value;
        }
        return this.clean(res);
    },

    render: function () {
        if (this.rendered) return;
        if (!this.el) {
            this.el = document.createElement('form');
        }
        if (this.autoAppend) {
            this.fieldContainerEl = this.el.querySelector('[data-hook~=field-container]') || this.el;
        }
        this.handleSubmit = this.handleSubmit.bind(this);
        this.el.addEventListener('submit', this.handleSubmit, false);
        this.rendered = true;
    }
});

FormView.extend = function (obj) {
    var child = function () {
       FormView.apply(this, arguments);
    };

    extend(child.prototype, FormView.prototype);
    extend(child.prototype, obj);

    return child;
};

module.exports = FormView;
<|endoftext|>


<commit_before>const config = require("../../config.json");
const { isMod } = require("../../util");

exports.run = async function (message, args, bot, db, showOnlyNew) {
  db.query(
    "SELECT * FROM trivia_questions WHERE id = ?",
    [args],
    function (err, rows) {
      if (rows[0] == null) {
        message.reply("That question does not exist.");
        return;
      }
      if (
        rows[0].user !== message.author.id &&
        message.author.id !== config.botAdminUserId
      ) {
        message.reply("You do not have permission to view these answers.");
        return;
      }
      getAnswerList(message, rows[0], showOnlyNew, bot, db);
    }
  );
};

async function getAnswerList(message, questionRow, showOnlyNew, bot, db) {
  let id = questionRow.id;
  let question = questionRow.question;
  let questionAsker = questionRow.user;
  let query =
    "SELECT user, answer FROM trivia_answers WHERE questionid = ? ORDER BY id";
  if (showOnlyNew) {
    query =
      "SELECT user, answer FROM trivia_answers WHERE questionid = ? AND viewed = 0 ORDER BY id";
  }
  const questionStatus = questionRow.isopen ? "Open" : "Closed";
  db.query(query, [id], async function (err, rows) {
    let responseMessages = [];
    let response =
      "**Answers for question #" +
      id +
      ": " +
      question +
      " (" +
      questionStatus +
      ")**\n";
    for (let i = 0; i < rows.length; i++) {
      let answer = rows[i].answer;
      let user = await bot.users.fetch(rows[i].user);
      let username = user ? "@" + user.tag : "Unknown " + rows[i].user;
      let answerEntry = "**" + username + "**\n" + answer + "\n\n";
      if (response.length + answerEntry > 4000) {
        responseMessages.push(response);
        response = "";
      }
      response += answerEntry;
    }
    responseMessages.push(response);
    const url = config.baseUrl + "question_tool.php?key=" + questionRow.web_key;
    if (message.author.id === questionAsker) {
      db.query("UPDATE trivia_answers SET viewed=1 WHERE questionid = ?", [id]);
    }
    const total = responseMessages.length;
    for (let i = 0; i < responseMessages.length; i++) {
      const part = i + 1;
      message.channel.send({
        embeds: [
          {
            title:
              "Answers part " + part + "/" + total + " (click for award tool)",
            url: url,
            description: responseMessages[i],
          },
        ],
      });
    }
  });
}
<commit_msg>change handling of long answer responses<commit_after>const config = require("../../config.json");
const { isMod } = require("../../util");

exports.run = async function (message, args, bot, db, showOnlyNew) {
  db.query(
    "SELECT * FROM trivia_questions WHERE id = ?",
    [args],
    function (err, rows) {
      if (rows[0] == null) {
        message.reply("That question does not exist.");
        return;
      }
      if (
        rows[0].user !== message.author.id &&
        message.author.id !== config.botAdminUserId
      ) {
        message.reply("You do not have permission to view these answers.");
        return;
      }
      getAnswerList(message, rows[0], showOnlyNew, bot, db);
    }
  );
};

async function getAnswerList(message, questionRow, showOnlyNew, bot, db) {
  let id = questionRow.id;
  let question = questionRow.question;
  let questionAsker = questionRow.user;
  let query =
    "SELECT user, answer FROM trivia_answers WHERE questionid = ? ORDER BY id";
  if (showOnlyNew) {
    query =
      "SELECT user, answer FROM trivia_answers WHERE questionid = ? AND viewed = 0 ORDER BY id";
  }
  const questionStatus = questionRow.isopen ? "Open" : "Closed";
  db.query(query, [id], async function (err, rows) {
    let responseMessages = [];
    let response =
      "**Answers for question #" +
      id +
      ": " +
      question +
      " (" +
      questionStatus +
      ")**\n";
    for (let i = 0; i < rows.length; i++) {
      let answer = rows[i].answer;
      let user = await bot.users.fetch(rows[i].user);
      let username = user ? "@" + user.tag : "Unknown " + rows[i].user;
      let answerEntry = "**" + username + "**\n" + answer + "\n\n";
      if (response.length + answerEntry > 4000) {
        response = "Too many answers, please view the webpage.";
        break;
      }
      response += answerEntry;
    }
    const url = config.baseUrl + "question_tool.php?key=" + questionRow.web_key;
    if (message.author.id === questionAsker) {
      db.query("UPDATE trivia_answers SET viewed=1 WHERE questionid = ?", [id]);
    }
    message.channel.send({
      embeds: [
        {
          title: "Answers (click for award tool)",
          url: url,
          description: response,
        },
      ],
    });
  });
}

exports.interaction = function (interaction, bot, db) {
  const id = interaction.options.getInteger("id");
  db.query(
    "SELECT * FROM trivia_questions WHERE id = ?",
    [id],
    function (err, rows) {
      if (rows[0] == null) {
        interaction.reply({
          content: "That question does not exist.",
          ephemeral: true,
        });
        return;
      }
      if (
        rows[0].user !== interaction.user.id &&
        interaction.user.id !== config.botAdminUserId
      ) {
        interaction.reply({
          content: "You do not have permission to view these answers.",
          ephemeral: true,
        });
        return;
      }
      const url = config.baseUrl + "question_tool.php?key=" + rows[0].web_key;
      interaction.reply({
        content: url,
        ephemeral: true,
      });
    }
  );
};
<|endoftext|>


<commit_before>(function() {
    var statusbarController;
    try { statusbarController = DE.getController('Statusbar'); } catch(e) {}
    if (statusbarController && !statusbarController.statusbar.mode.isReviewOnly &&
        (typeof (statusbarController.statusbar.mode.customization) == 'object') && !!statusbarController.statusbar.mode.customization.showReviewChanges) {
        var onReviewToggle = function(btn, state) {
            btn.toggle(false, true);
            Common.NotificationCenter.trigger('edit:complete', statusbarController.statusbar);
        };
        statusbarController.statusbar.btnReview.on('toggle', onReviewToggle);
        statusbarController.statusbar.mnuTrackChanges && statusbarController.statusbar.mnuTrackChanges.setDisabled(true);
    }
})();<commit_msg>Fix plugin valgenesis.<commit_after>(function() {
    var statusbarController;
    try { statusbarController = DE.getController('Statusbar'); } catch(e) {}
    if (statusbarController && !statusbarController.statusbar.mode.isReviewOnly &&
        (typeof (statusbarController.statusbar.mode.customization) == 'object') && !!statusbarController.statusbar.mode.customization.showReviewChanges) {
        var onReviewToggle = function(btn, state) {
            btn.toggle(false, true);
            statusbarController.statusbar.mnuTrackChanges.setChecked(false, true);
            if (statusbarController.api) {
                statusbarController.api.asc_SetTrackRevisions(false);
            }

            Common.NotificationCenter.trigger('edit:complete', statusbarController.statusbar);
        };
        statusbarController.statusbar.btnReview.on('toggle', onReviewToggle);
        statusbarController.statusbar.mnuTrackChanges && statusbarController.statusbar.mnuTrackChanges.setDisabled(true);
    }
})();<|endoftext|>


<commit_before><commit_msg>@barthec/fixes (#3077)<commit_after><|endoftext|>


<commit_before>import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import SimpleWebRTC from 'simplewebrtc'

const W = 87
const A = 65
const S = 83
const D = 68
const maxSpeed = 255
const turnSpeed = maxSpeed / 1.5

function clamp (value, min, max) {
  if (value > max) return max
  if (value < min) return min
  return value
}

function clampSpeed (value) {
  return clamp(value, -maxSpeed, maxSpeed)
}

export class App extends Component {
  constructor (props, context) {
    super(props, context)
    this.state = { keys: [] }
    this.handleKeyDown = this.handleKeyDown.bind(this)
    this.handleKeyUp = this.handleKeyUp.bind(this)
  }

  componentDidMount () {
    document.addEventListener('keydown', this.handleKeyDown)
    document.addEventListener('keyup', this.handleKeyUp)
    this._webrtc = new SimpleWebRTC({
      localVideoEl: this.refs.local,
      remoteVideosEl: this.refs.remotes,
      autoRequestMedia: true,
      debug: true
    }).once('readyToCall', () => {
      this._webrtc.joinRoom('tractor-beam')
    })
  }

  componentWillUnmount () {
    document.removeEventListener('keydown', this.handleKeyDown)
    document.removeEventListener('keyup', this.handleKeyUp)
    this._webrtc.leaveRoom()
  }

  updateSpeeds (keys) {
    let direction = 1
    const speeds = [0, 0]
    if (~keys.indexOf(W)) {
      speeds[0] = maxSpeed
      speeds[1] = maxSpeed
    } else if (~keys.indexOf(S)) {
      direction = -1
      speeds[0] = -maxSpeed
      speeds[1] = -maxSpeed
    }
    if (~keys.indexOf(A)) {
      speeds[0] = clampSpeed(speeds[0] - turnSpeed * direction)
      speeds[1] = clampSpeed(speeds[1] + turnSpeed * direction)
    } else if (~keys.indexOf(D)) {
      speeds[0] = clampSpeed(speeds[0] + turnSpeed * direction)
      speeds[1] = clampSpeed(speeds[1] - turnSpeed * direction)
    }
    this._webrtc.sendDirectlyToAll('control', 'speeds', speeds)
  }

  handleKeyDown (e) {
    const keys = this.state.keys.concat(e.keyCode)
    this.setState({ keys })
    this.updateSpeeds(keys)
  }

  handleKeyUp (e) {
    const keys = this.state.keys.filter(k => k !== e.keyCode)
    this.setState({ keys })
    this.updateSpeeds(keys)
  }

  render () {
    return (

        <video className='local' ref='local'/>

    )
  }
}
<commit_msg>allow arrow key control and increase turn rate<commit_after>import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import SimpleWebRTC from 'simplewebrtc'

// Key Codes
const W = 87
const A = 65
const S = 83
const D = 68
const LEFT = 37
const UP = 38
const RIGHT = 39
const DOWN = 40

const MAX_SPEED = 255
const TURN_SPEED = MAX_SPEED / 1.4

function clamp (value, min, max) {
  if (value > max) return max
  if (value < min) return min
  return value
}

function clampSpeed (value) {
  return clamp(value, -MAX_SPEED, MAX_SPEED)
}

export class App extends Component {
  constructor (props, context) {
    super(props, context)
    this.state = { keys: [] }
    this.handleKeyDown = this.handleKeyDown.bind(this)
    this.handleKeyUp = this.handleKeyUp.bind(this)
  }

  componentDidMount () {
    document.addEventListener('keydown', this.handleKeyDown)
    document.addEventListener('keyup', this.handleKeyUp)
    this._webrtc = new SimpleWebRTC({
      localVideoEl: this.refs.local,
      remoteVideosEl: this.refs.remotes,
      autoRequestMedia: true,
      debug: true
    }).once('readyToCall', () => {
      this._webrtc.joinRoom('tractor-beam')
    })
  }

  componentWillUnmount () {
    document.removeEventListener('keydown', this.handleKeyDown)
    document.removeEventListener('keyup', this.handleKeyUp)
    this._webrtc.leaveRoom()
  }

  updateSpeeds (keys) {
    let direction = 1
    const speeds = [0, 0]
    if (~keys.indexOf(W) || ~keys.indexOf(UP)) {
      speeds[0] = MAX_SPEED
      speeds[1] = MAX_SPEED
    } else if (~keys.indexOf(S) || ~keys.indexOf(DOWN)) {
      direction = -1
      speeds[0] = -MAX_SPEED
      speeds[1] = -MAX_SPEED
    }
    if (~keys.indexOf(A) || ~keys.indexOf(LEFT)) {
      speeds[0] = clampSpeed(speeds[0] - TURN_SPEED * direction)
      speeds[1] = clampSpeed(speeds[1] + TURN_SPEED * direction)
    } else if (~keys.indexOf(D) || ~keys.indexOf(RIGHT)) {
      speeds[0] = clampSpeed(speeds[0] + TURN_SPEED * direction)
      speeds[1] = clampSpeed(speeds[1] - TURN_SPEED * direction)
    }
    this._webrtc.sendDirectlyToAll('control', 'speeds', speeds)
  }

  handleKeyDown (e) {
    const keys = this.state.keys.concat(e.keyCode)
    this.setState({ keys })
    this.updateSpeeds(keys)
  }

  handleKeyUp (e) {
    const keys = this.state.keys.filter(k => k !== e.keyCode)
    this.setState({ keys })
    this.updateSpeeds(keys)
  }

  render () {
    return (

        <video className='local' ref='local'/>

    )
  }
}
<|endoftext|>


<commit_before>/*
  Apply this mixin to your vue components to get reactive information about window sizes.

  For example:

    <script>

      import responsiveWindow from 'kolibri.coreVue.mixins.responsiveWindow';

      export default {
        mixins: [responsiveWindow],
        props: {
    ...

  This adds a few new reactive properties to your vue model:

    this.windowHeight       // height in pixels
    this.windowWidth        // width in pixels
    this.windowBreakpoint   // breakpoint level as described below
    this.windowIsSmall      // boolean for small range (level < 2)
    this.windowIsMedium     // boolean for medium range (level = 2)
    this.windowIsLarge      // boolean for large range (level > 2)
    this.windowGridColumns  // number of grid columns for the current level
    this.windowGutter       // gutter width for the current window size

  The breakpoint levels are numbers following Material guidelinse:
    https://material.io/guidelines/layout/responsive-ui.html#responsive-ui-breakpoints

  Breakpoint Breakdown:

    level 0 (small)
      < 480 px
      portrait handset, xsmall window
      4 columns, 16px gutter

    level 1 (small)
      < 600 px
      landscape or large portait handset, small portrait tablet, xsmall window,
      4 columns, 16px gutter

    level 2 (medium)
      < 840 px
      large landscape handset, large portrait tablet, small window,
      8 columns, 16px gutter

    level 3 (large)
      < 960 px
      large landscape handset, large portrait tablet, small window,
      12 columns, 16px gutter

    level 4 (large)
      < 1280 px
      landscape tablet, small or medium window
      12 columns, 24px gutter

    level 5 (large)
      < 1440 px
      large landscape tablet, medium window
      12 columns, 24px gutter

    level 6 (large)
      < 1600 px
      large window
      12 columns, 24px gutter

    level 7 (large)
      >= 1600 px
      large or xlarge window
      12 columns, 24px gutter
*/

import { throttle } from 'frame-throttle';

/* module internal state */

const windowListeners = [];

/* methods */

function windowMetrics() {
  return {
    width: window.innerWidth,
    height: window.innerHeight,
  };
}

const windowResizeHandler = throttle(() => {
  const metrics = windowMetrics();
  windowListeners.forEach(cb => cb(metrics));
});

function addWindowListener(cb) {
  windowListeners.push(cb);
  cb(windowMetrics()); // call it once initially
}

function removeWindowListener(cb) {
  windowListeners.splice(windowListeners.indexOf(cb), 1);
}

/* setup */

if (window.addEventListener) {
  window.addEventListener('resize', windowResizeHandler, true);
} else if (window.attachEvent) {
  window.attachEvent('onresize', windowResizeHandler);
}

windowResizeHandler(); // call it once initially

/* export mixin */

export default {
  data() {
    return {
      windowWidth: undefined,
      windowHeight: undefined,

      /*
        Implementing these as data controlled by watchers to work around
        optimization issue: https://github.com/vuejs/vue/issues/8540

        If that issue ever gets addressed, we should make them computed props.
      */
      windowBreakpoint: undefined,
      windowGutter: 16,
    };
  },
  watch: {
    windowWidth() {
      let newBreakpoint = undefined;
      const SCROLL_BAR = 16;
      if (this.windowWidth < 480) {
        newBreakpoint = 0;
      } else if (this.windowWidth < 600) {
        newBreakpoint = 1;
      } else if (this.windowWidth < 840) {
        newBreakpoint = 2;
      } else if (this.windowWidth < 960 - SCROLL_BAR) {
        newBreakpoint = 3;
      } else if (this.windowWidth < 1280 - SCROLL_BAR) {
        newBreakpoint = 4;
      } else if (this.windowWidth < 1440 - SCROLL_BAR) {
        newBreakpoint = 5;
      } else if (this.windowWidth < 1600 - SCROLL_BAR) {
        newBreakpoint = 6;
      } else {
        newBreakpoint = 7;
      }
      if (this.windowBreakpoint !== newBreakpoint) {
        this.windowBreakpoint = newBreakpoint;
      }
      this._updateGutter();
    },
    windowHeight() {
      this._updateGutter();
    },
  },
  computed: {
    /*
      CAUTION: do not reference windowWidth or windowHeight in computed props.
    */
    windowIsLarge() {
      return this.windowBreakpoint > 2;
    },
    windowIsMedium() {
      return this.windowBreakpoint === 2;
    },
    windowIsSmall() {
      return this.windowBreakpoint < 2;
    },
    windowGridColumns() {
      if (this.windowIsSmall) {
        return 4;
      }
      if (this.windowIsMedium) {
        return 8;
      }
      // windowIsLarge
      return 12;
    },
  },
  methods: {
    _updateWindow(metrics) {
      this.windowWidth = metrics.width;
      this.windowHeight = metrics.height;
    },
    _updateGutter() {
      if (this.windowIsSmall) {
        this.windowGutter = 16;
        return;
      }
      // 16px when the smallest dimension of the window is < 600
      if (this.windowBreakpoint < 4 && Math.min(this.windowWidth, this.windowHeight) < 600) {
        this.windowGutter = 16;
        return;
      }
      this.windowGutter = 24;
    },
  },
  mounted() {
    addWindowListener(this._updateWindow);
  },
  beforeDestroy() {
    removeWindowListener(this._updateWindow);
  },
};
<commit_msg>remove unnecessary complexity<commit_after>/*
  Apply this mixin to your vue components to get reactive information about window sizes.

  For example:

    <script>

      import responsiveWindow from 'kolibri.coreVue.mixins.responsiveWindow';

      export default {
        mixins: [responsiveWindow],
        props: {
    ...

  This adds a few new reactive properties to your vue model:

    this.windowHeight       // height in pixels
    this.windowWidth        // width in pixels
    this.windowBreakpoint   // breakpoint level as described below
    this.windowIsSmall      // boolean for small range (level < 2)
    this.windowIsMedium     // boolean for medium range (level = 2)
    this.windowIsLarge      // boolean for large range (level > 2)
    this.windowGridColumns  // number of grid columns for the current level
    this.windowGutter       // gutter width for the current window size

  The breakpoint levels are numbers following Material guidelinse:
    https://material.io/guidelines/layout/responsive-ui.html#responsive-ui-breakpoints

  Breakpoint Breakdown:

    level 0 (small)
      < 480 px
      portrait handset, xsmall window
      4 columns, 16px gutter

    level 1 (small)
      < 600 px
      landscape or large portait handset, small portrait tablet, xsmall window,
      4 columns, 16px gutter

    level 2 (medium)
      < 840 px
      large landscape handset, large portrait tablet, small window,
      8 columns, 16px gutter

    level 3 (large)
      < 960 px
      large landscape handset, large portrait tablet, small window,
      12 columns, 16px gutter

    level 4 (large)
      < 1280 px
      landscape tablet, small or medium window
      12 columns, 24px gutter

    level 5 (large)
      < 1440 px
      large landscape tablet, medium window
      12 columns, 24px gutter

    level 6 (large)
      < 1600 px
      large window
      12 columns, 24px gutter

    level 7 (large)
      >= 1600 px
      large or xlarge window
      12 columns, 24px gutter
*/

import { throttle } from 'frame-throttle';

/* module internal state */

const windowListeners = [];

/* methods */

function windowMetrics() {
  return {
    width: window.innerWidth,
    height: window.innerHeight,
  };
}

const windowResizeHandler = throttle(() => {
  const metrics = windowMetrics();
  windowListeners.forEach(cb => cb(metrics));
});

function addWindowListener(cb) {
  windowListeners.push(cb);
  cb(windowMetrics()); // call it once initially
}

function removeWindowListener(cb) {
  windowListeners.splice(windowListeners.indexOf(cb), 1);
}

/* setup */

if (window.addEventListener) {
  window.addEventListener('resize', windowResizeHandler, true);
} else if (window.attachEvent) {
  window.attachEvent('onresize', windowResizeHandler);
}

windowResizeHandler(); // call it once initially

/* export mixin */

export default {
  data() {
    return {
      windowWidth: undefined,
      windowHeight: undefined,

      /*
        Implementing these as data controlled by watchers to work around
        optimization issue: https://github.com/vuejs/vue/issues/8540

        If that issue ever gets addressed, we should make them computed props.
      */
      windowBreakpoint: undefined,
      windowGutter: 16,
    };
  },
  watch: {
    windowWidth() {
      this._updateBreakpoint();
      this._updateGutter();
    },
    windowHeight() {
      this._updateGutter();
    },
  },
  computed: {
    /*
      CAUTION: do not reference windowWidth or windowHeight in computed props.
    */
    windowIsLarge() {
      return this.windowBreakpoint > 2;
    },
    windowIsMedium() {
      return this.windowBreakpoint === 2;
    },
    windowIsSmall() {
      return this.windowBreakpoint < 2;
    },
    windowGridColumns() {
      if (this.windowIsSmall) {
        return 4;
      }
      if (this.windowIsMedium) {
        return 8;
      }
      // windowIsLarge
      return 12;
    },
  },
  methods: {
    _updateWindow(metrics) {
      this.windowWidth = metrics.width;
      this.windowHeight = metrics.height;
    },
    _updateBreakpoint() {
      const SCROLL_BAR = 16;
      if (this.windowWidth < 480) {
        this.windowBreakpoint = 0;
      } else if (this.windowWidth < 600) {
        this.windowBreakpoint = 1;
      } else if (this.windowWidth < 840) {
        this.windowBreakpoint = 2;
      } else if (this.windowWidth < 960 - SCROLL_BAR) {
        this.windowBreakpoint = 3;
      } else if (this.windowWidth < 1280 - SCROLL_BAR) {
        this.windowBreakpoint = 4;
      } else if (this.windowWidth < 1440 - SCROLL_BAR) {
        this.windowBreakpoint = 5;
      } else if (this.windowWidth < 1600 - SCROLL_BAR) {
        this.windowBreakpoint = 6;
      } else {
        this.windowBreakpoint = 7;
      }
    },
    _updateGutter() {
      if (this.windowIsSmall) {
        this.windowGutter = 16;
      } else if (this.windowBreakpoint < 4 && Math.min(this.windowWidth, this.windowHeight) < 600) {
        // 16px when the smallest dimension of the window is < 600
        this.windowGutter = 16;
      } else {
        this.windowGutter = 24;
      }
    },
  },
  mounted() {
    addWindowListener(this._updateWindow);
  },
  beforeDestroy() {
    removeWindowListener(this._updateWindow);
  },
};
<|endoftext|>


<commit_before>define([
  'angular',
  'lodash',
  'kbn'
],
function (angular, _, kbn) {
  'use strict';

  var module = angular.module('grafana.controllers');

  module.controller('OpenTSDBQueryCtrl', function($scope, $timeout) {

    $scope.init = function() {
      $scope.target.errors = validateTarget($scope.target);
      $scope.aggregators = ['avg', 'sum', 'min', 'max', 'dev', 'zimsum', 'mimmin', 'mimmax'];

      if (!$scope.target.aggregator) {
        $scope.target.aggregator = 'sum';
      }

      if (!$scope.target.downsampleAggregator) {
        $scope.target.downsampleAggregator = 'avg';
      }
    };

    $scope.targetBlur = function() {
      $scope.target.errors = validateTarget($scope.target);

      // this does not work so good
      if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
        $scope.oldTarget = angular.copy($scope.target);
        $scope.get_data();
      }
    };

    $scope.duplicate = function() {
      var clone = angular.copy($scope.target);
      $scope.panel.targets.push(clone);
    };

    $scope.getTextValues = function(metricFindResult) {
      return _.map(metricFindResult, function(value) { return value.text; });
    };

    $scope.suggestMetrics = function(query, callback) {
      $scope.datasource.metricFindQuery('metrics(' + query + ')')
        .then($scope.getTextValues)
        .then(callback);
    };

    $scope.suggestTagKeys = function(query, callback) {
      $scope.datasource.metricFindQuery('tag_names(' + $scope.target.metric + ')')
        .then($scope.getTextValues)
        .then(callback);
    };

    $scope.suggestTagValues = function(query, callback) {
      $scope.datasource.metricFindQuery('tag_values(' + $scope.target.metric + ',' + $scope.target.currentTagKey + ')')
        .then($scope.getTextValues)
        .then(callback);
    };

    $scope.addTag = function() {
      if (!$scope.addTagMode) {
        $scope.addTagMode = true;
        return;
      }

      if (!$scope.target.tags) {
        $scope.target.tags = {};
      }

      $scope.target.errors = validateTarget($scope.target);

      if (!$scope.target.errors.tags) {
        $scope.target.tags[$scope.target.currentTagKey] = $scope.target.currentTagValue;
        $scope.target.currentTagKey = '';
        $scope.target.currentTagValue = '';
        $scope.targetBlur();
      }

      $scope.addTagMode = false;
    };

    $scope.removeTag = function(key) {
      delete $scope.target.tags[key];
      $scope.targetBlur();
    };

    function validateTarget(target) {
      var errs = {};

      if (target.shouldDownsample) {
        try {
          if (target.downsampleInterval) {
            kbn.describe_interval(target.downsampleInterval);
          } else {
            errs.downsampleInterval = "You must supply a downsample interval (e.g. '1m' or '1h').";
          }
        } catch(err) {
          errs.downsampleInterval = err.message;
        }
      }

      if (target.tags && _.has(target.tags, target.currentTagKey)) {
        errs.tags = "Duplicate tag key '" + target.currentTagKey + "'.";
      }

      return errs;
    }

    $scope.init();
  });

});
<commit_msg>fix(jscs): fixed failing js style check<commit_after>define([
  'angular',
  'lodash',
  'kbn'
],
function (angular, _, kbn) {
  'use strict';

  var module = angular.module('grafana.controllers');

  module.controller('OpenTSDBQueryCtrl', function($scope) {

    $scope.init = function() {
      $scope.target.errors = validateTarget($scope.target);
      $scope.aggregators = ['avg', 'sum', 'min', 'max', 'dev', 'zimsum', 'mimmin', 'mimmax'];

      if (!$scope.target.aggregator) {
        $scope.target.aggregator = 'sum';
      }

      if (!$scope.target.downsampleAggregator) {
        $scope.target.downsampleAggregator = 'avg';
      }
    };

    $scope.targetBlur = function() {
      $scope.target.errors = validateTarget($scope.target);

      // this does not work so good
      if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) {
        $scope.oldTarget = angular.copy($scope.target);
        $scope.get_data();
      }
    };

    $scope.duplicate = function() {
      var clone = angular.copy($scope.target);
      $scope.panel.targets.push(clone);
    };

    $scope.getTextValues = function(metricFindResult) {
      return _.map(metricFindResult, function(value) { return value.text; });
    };

    $scope.suggestMetrics = function(query, callback) {
      $scope.datasource.metricFindQuery('metrics(' + query + ')')
        .then($scope.getTextValues)
        .then(callback);
    };

    $scope.suggestTagKeys = function(query, callback) {
      $scope.datasource.metricFindQuery('tag_names(' + $scope.target.metric + ')')
        .then($scope.getTextValues)
        .then(callback);
    };

    $scope.suggestTagValues = function(query, callback) {
      $scope.datasource.metricFindQuery('tag_values(' + $scope.target.metric + ',' + $scope.target.currentTagKey + ')')
        .then($scope.getTextValues)
        .then(callback);
    };

    $scope.addTag = function() {
      if (!$scope.addTagMode) {
        $scope.addTagMode = true;
        return;
      }

      if (!$scope.target.tags) {
        $scope.target.tags = {};
      }

      $scope.target.errors = validateTarget($scope.target);

      if (!$scope.target.errors.tags) {
        $scope.target.tags[$scope.target.currentTagKey] = $scope.target.currentTagValue;
        $scope.target.currentTagKey = '';
        $scope.target.currentTagValue = '';
        $scope.targetBlur();
      }

      $scope.addTagMode = false;
    };

    $scope.removeTag = function(key) {
      delete $scope.target.tags[key];
      $scope.targetBlur();
    };

    function validateTarget(target) {
      var errs = {};

      if (target.shouldDownsample) {
        try {
          if (target.downsampleInterval) {
            kbn.describe_interval(target.downsampleInterval);
          } else {
            errs.downsampleInterval = "You must supply a downsample interval (e.g. '1m' or '1h').";
          }
        } catch(err) {
          errs.downsampleInterval = err.message;
        }
      }

      if (target.tags && _.has(target.tags, target.currentTagKey)) {
        errs.tags = "Duplicate tag key '" + target.currentTagKey + "'.";
      }

      return errs;
    }

    $scope.init();
  });

});
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  grunt.initConfig({
    traceur: {
      options: {
        experimental: true
      },
      custom: {
        files: [{
          expand: true,
          cwd: 'js',
          src: ['*.js'],
          dest: 'transpiled'
        }]
      }
    },

    concat: {
      custom: {
        files: {
          'build/app.js': ['transpiled/**/*.js']
        }
      }
    },

    watch: {
      source: {
        files: 'js/**/*.js',
        tasks: ['traceur', 'concat'],
      },
      compiled: {
        files: 'build/**/*.js',
        options: {
          livereload: true
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-traceur-latest');
};<commit_msg>add default task<commit_after>module.exports = function(grunt) {
  grunt.initConfig({
    traceur: {
      options: {
        experimental: true
      },
      custom: {
        files: [{
          expand: true,
          cwd: 'js',
          src: ['*.js'],
          dest: 'transpiled'
        }]
      }
    },

    concat: {
      custom: {
        files: {
          'build/app.js': ['transpiled/**/*.js']
        }
      }
    },

    watch: {
      source: {
        files: 'js/**/*.js',
        tasks: ['traceur', 'concat'],
      },
      compiled: {
        files: 'build/**/*.js',
        options: {
          livereload: true
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-traceur-latest');

  grunt.registerTask('default', ['traceur', 'concat', 'watch']);
};<|endoftext|>


<commit_before>'use strict'

module.exports = function (grunt) {
  var node = grunt.option('node') || process.env.nodejs_version || process.env.TRAVIS_NODE_VERSION || ''
  var platform = grunt.option('platform') || process.env.PLATFORM || process.env.TRAVIS ? 'x64' : ''
  var os = grunt.option('os') || process.env.APPVEYOR ? 'windows' : process.env.TRAVIS ? 'linux' : ''

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    uglify: {
      js: {
        files: {
          'app/tmp/juice-shop.min.js': [ 'app/tmp/juice-shop.js' ]
        },
        options: {
          mangle: true
        }
      },
      dist: {
        files: {
          'app/dist/juice-shop.min.js': [ 'app/tmp/juice-shop.min.js' ]
        }
      }
    },

    ngtemplates: {
      juiceShop: {
        cwd: 'app',
        src: [ 'views/*.html' ],
        dest: 'app/tmp/views.js'
      }
    },

    clean: {
      temp: {
        src: [ 'app/tmp' ]
      },
      dist: {
        src: [ 'app/dist' ]
      },
      pckg: {
        src: [ 'dist' ]
      }
    },

    concat: {
      options: {
        separator: ';'
      },
      js: {
        src: [ 'app/js/**/*.js' ],
        dest: 'app/tmp/juice-shop.js'
      },
      dist: {
        src: [ 'app/tmp/juice-shop.min.js', 'app/tmp/*.js' ],
        dest: 'app/tmp/juice-shop.min.js'
      }
    },

    compress: {
      pckg: {
        options: {
          mode: os === 'linux' ? 'tgz' : 'zip',
          archive: 'dist/<%= pkg.name %>-<%= pkg.version %>' + (node ? ('_node' + node) : '') + (os ? ('_' + os) : '') + (platform ? ('_' + platform) : '') + (os === 'linux' ? '.tgz' : '.zip')
        },
        files: [
          {
            src: [
              '*.md',
              'app.js',
              'server.js',
              'package.json',
              'ctf.key',
              'swagger.yml',
              'app/index.template.html',
              'app/node_modules/**',
              'app/css/*.css',
              'app/css/geo-bootstrap/**',
              'app/dist/juice-shop.min.js',
              'app/i18n/*.json',
              'app/private/**',
              'app/public/**',
              'config/*.yml',
              'data/*.js',
              'data/static/*.yml',
              'encryptionkeys/**',
              'ftp/**',
              'lib/*.js',
              'models/*.js',
              'routes/*.js',
              'node_modules/**'
            ]
          }
        ]
      }
    }
  })

  grunt.loadNpmTasks('grunt-angular-templates')
  grunt.loadNpmTasks('grunt-contrib-clean')
  grunt.loadNpmTasks('grunt-contrib-concat')
  grunt.loadNpmTasks('grunt-contrib-uglify')
  grunt.loadNpmTasks('grunt-contrib-compress')

  grunt.registerTask('minify', [ 'clean:dist', 'concat:js', 'uglify:js', 'ngtemplates:juiceShop', 'concat:dist', 'uglify:dist', 'clean:temp' ])
  grunt.registerTask('package', [ 'clean:pckg', 'minify', 'compress:pckg' ])
}
<commit_msg>Package into dedicated subfolder<commit_after>'use strict'

module.exports = function (grunt) {
  var node = grunt.option('node') || process.env.nodejs_version || process.env.TRAVIS_NODE_VERSION || ''
  var platform = grunt.option('platform') || process.env.PLATFORM || process.env.TRAVIS ? 'x64' : ''
  var os = grunt.option('os') || process.env.APPVEYOR ? 'windows' : process.env.TRAVIS ? 'linux' : ''

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    uglify: {
      js: {
        files: {
          'app/tmp/juice-shop.min.js': [ 'app/tmp/juice-shop.js' ]
        },
        options: {
          mangle: true
        }
      },
      dist: {
        files: {
          'app/dist/juice-shop.min.js': [ 'app/tmp/juice-shop.min.js' ]
        }
      }
    },

    ngtemplates: {
      juiceShop: {
        cwd: 'app',
        src: [ 'views/*.html' ],
        dest: 'app/tmp/views.js'
      }
    },

    clean: {
      temp: {
        src: [ 'app/tmp' ]
      },
      dist: {
        src: [ 'app/dist' ]
      },
      pckg: {
        src: [ 'dist' ]
      }
    },

    concat: {
      options: {
        separator: ';'
      },
      js: {
        src: [ 'app/js/**/*.js' ],
        dest: 'app/tmp/juice-shop.js'
      },
      dist: {
        src: [ 'app/tmp/juice-shop.min.js', 'app/tmp/*.js' ],
        dest: 'app/tmp/juice-shop.min.js'
      }
    },

    compress: {
      pckg: {
        options: {
          mode: os === 'linux' ? 'tgz' : 'zip',
          archive: 'dist/<%= pkg.name %>-<%= pkg.version %>' + (node ? ('_node' + node) : '') + (os ? ('_' + os) : '') + (platform ? ('_' + platform) : '') + (os === 'linux' ? '.tgz' : '.zip')
        },
        files: [
          {
            src: [
              '*.md',
              'app.js',
              'server.js',
              'package.json',
              'ctf.key',
              'swagger.yml',
              'app/index.template.html',
              'app/node_modules/**',
              'app/css/*.css',
              'app/css/geo-bootstrap/**',
              'app/dist/juice-shop.min.js',
              'app/i18n/*.json',
              'app/private/**',
              'app/public/**',
              'config/*.yml',
              'data/*.js',
              'data/static/*.yml',
              'encryptionkeys/**',
              'ftp/**',
              'lib/*.js',
              'models/*.js',
              'routes/*.js',
              'node_modules/**'
            ],
            dest: 'juice-shop_<%= pkg.version %>/'
          }
        ]
      }
    }
  })

  grunt.loadNpmTasks('grunt-angular-templates')
  grunt.loadNpmTasks('grunt-contrib-clean')
  grunt.loadNpmTasks('grunt-contrib-concat')
  grunt.loadNpmTasks('grunt-contrib-uglify')
  grunt.loadNpmTasks('grunt-contrib-compress')

  grunt.registerTask('minify', [ 'clean:dist', 'concat:js', 'uglify:js', 'ngtemplates:juiceShop', 'concat:dist', 'uglify:dist', 'clean:temp' ])
  grunt.registerTask('package', [ 'clean:pckg', 'minify', 'compress:pckg' ])
}
<|endoftext|>


<commit_before>module.exports = {
  // Specify lowercase or uppercase for hex colors.
  'color-hex-case': 'lower',
  // Specify short or long notation for hex colors.
  'color-hex-length': 'long',
  // Require (where possible) or disallow named colors.
  'color-named': null,
  // Disallow hex colors.
  'color-no-hex': true,
  // Disallow invalid hex colors.
  'color-no-invalid-hex': true,
};
<commit_msg>style(style-lint): allow hex colors<commit_after>module.exports = {
  // Specify lowercase or uppercase for hex colors.
  'color-hex-case': 'lower',
  // Specify short or long notation for hex colors.
  'color-hex-length': 'long',
  // Require (where possible) or disallow named colors.
  'color-named': null,
  // Disallow hex colors.
  'color-no-hex': null,
  // Disallow invalid hex colors.
  'color-no-invalid-hex': true,
};
<|endoftext|>


<commit_before><commit_msg>to work in the Destination autocomplete<commit_after>//$(document).ready(function() {
//    $("#hotel_destination").autocomplete({
//        source: '/taxons/hotel_autocomplete.json',
//        messages: {
//          noResults: '',
//          results: function() {}
//    }});
//});<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2019 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// MAIN //

require( 'ignore-styles' );

require( '@babel/register' )({
	ignore: [ /(node_modules)/ ],
	root:"./server",
	plugins: [
		"@babel/plugin-transform-react-jsx",
		"@babel/plugin-proposal-function-bind",

		"@babel/plugin-proposal-export-default-from",
		"@babel/plugin-proposal-logical-assignment-operators",
		["@babel/plugin-proposal-optional-chaining", { "loose": false }],
		["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }],
		["@babel/plugin-proposal-nullish-coalescing-operator", { "loose": false }],
		"@babel/plugin-proposal-do-expressions",

		["@babel/plugin-proposal-decorators", { "legacy": true }],
		"@babel/plugin-proposal-function-sent",
		"@babel/plugin-proposal-export-namespace-from",
		"@babel/plugin-proposal-numeric-separator",
		"@babel/plugin-proposal-throw-expressions",

		"@babel/plugin-transform-modules-commonjs",
		"@babel/plugin-syntax-dynamic-import",
		"@babel/plugin-syntax-import-meta",
		["@babel/plugin-proposal-class-properties", { "loose": false }],
		"@babel/plugin-proposal-json-strings"
	]
});

require( './server.js' );
<commit_msg>Add comments<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2019 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// MAIN //

// @babel/register hook to ignore imported style files when running in Node.js:
require( 'ignore-styles' );

// Register `require` hooks to allow import JSX and other non-standard Node.js behavior when dynamically compiling the React-based web application:
require( '@babel/register' )({
	ignore: [ /(node_modules)/ ],
	root:"./server",
	plugins: [
		"@babel/plugin-transform-react-jsx",
		"@babel/plugin-proposal-function-bind",

		"@babel/plugin-proposal-export-default-from",
		"@babel/plugin-proposal-logical-assignment-operators",
		["@babel/plugin-proposal-optional-chaining", { "loose": false }],
		["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }],
		["@babel/plugin-proposal-nullish-coalescing-operator", { "loose": false }],
		"@babel/plugin-proposal-do-expressions",

		["@babel/plugin-proposal-decorators", { "legacy": true }],
		"@babel/plugin-proposal-function-sent",
		"@babel/plugin-proposal-export-namespace-from",
		"@babel/plugin-proposal-numeric-separator",
		"@babel/plugin-proposal-throw-expressions",

		"@babel/plugin-transform-modules-commonjs",
		"@babel/plugin-syntax-dynamic-import",
		"@babel/plugin-syntax-import-meta",
		["@babel/plugin-proposal-class-properties", { "loose": false }],
		"@babel/plugin-proposal-json-strings"
	]
});

// Run the web server:
require( './server.js' );
<|endoftext|>