<commit_before>// Most of this file is from the https://github.com/axemclion/grunt-saucelabs project

var request = require('request');
var SauceTunnel = require('sauce-tunnel');
var Q = require('q');
var fs = require('fs');
var http = require('http');
var path = require('path');
var url = require('url');
var mime = require('mime');
var chalk = require('chalk');

function log() {
	console.log.apply(this, arguments);
}

var rqst = request.defaults({
	jar: false
});

var resultParsers = {
	qunit: function(result) {
		if (result.passed === undefined) {
			return undefined;
		}

		return result.passed == result.total;
	}
};

var TestResult = function(jobId, user, key, framework, testInterval) {
	var url = 'https://saucelabs.com/rest/v1/' + user + '/js-tests/status';
	var deferred = Q.defer();

	var requestParams = {
		method: 'post',
		url: url,
		auth: {
			user: user,
			pass: key
		},
		json: true,
		body: {
			"js tests": [jobId]
		}
	};

	var checkStatus = function() {
		rqst(requestParams, function(error, response, body) {
			if (error) {
				deferred.resolve({
					passed: undefined,
					result: {
						message: "Error connecting to api to get test status: " + error.toString()
					}
				});

				return;
			}

			var testInfo = body['js tests'][0];

			if (testInfo.status == "test error"){
				deferred.resolve({
					passed: undefined,
					result: {
						message: "Test Error"
					}
				});

				return;
			}

			if (!body.completed){
				setTimeout(checkStatus ,testInterval);
			} else {
				testInfo.passed = testInfo.result ? resultParsers[framework](testInfo.result) : false;
				deferred.resolve(testInfo);
			}
		});
	};

	checkStatus();

	return deferred.promise;
};

var TestRunner = function(user, key, testInterval) {
	this.user = user;
	this.key = key;
	this.url = 'https://saucelabs.com/rest/v1/' + this.user + '/js-tests';
	this.testInterval = testInterval;
	this.results = [];
};

TestRunner.prototype.runTests = function(browsers, urls, framework, tunnelIdentifier, testname, tags, build, onTestComplete, callback) {
	var me = this;
	var numberOfJobs = browsers.length * urls.length;

	var addResultPromise = function(promise){
		me.results.push(promise);

		log(me.results.length, "/", numberOfJobs, 'tests started');

		if (me.results.length == numberOfJobs) {
			Q.all(me.results).then(function(results) {
				results = results.map(function(result) {
					return result.valueOf().passed;
				});

				callback(results);
			});
		}
	};

	urls.forEach(function(url) {
		me.runTest(browsers, url, framework, tunnelIdentifier, testname, tags, build, function(taskIds) {
			taskIds.forEach(function(taskId) {
				var resultPromise = new TestResult(taskId, me.user, me.key, framework, me.testInterval);

				addResultPromise(resultPromise);
				resultPromise.then(function(result) {
					var alteredResult = onTestComplete(result);

					if (alteredResult !== undefined){
						result.passed = alteredResult;
					}

					if (result.passed === undefined) {
						log(chalk.red("[FAILED] %s"), result.platform, result.result.message);
					} else {
						if (result.passed) {
							log(chalk.green("[PASSED] %s"), result.platform);
						} else {
							log(chalk.red("[FAILED] %s"), result.platform);
						}
					}

					//log("Url %s", result.url);
				}, function(e) {
					log('some error? %s', e);
				});
			});
		});
	});
};

TestRunner.prototype.runTest = function(browsers, url, framework, tunnelIdentifier, testname, tags, build, callback) {
	var parsePlatforms = function(browsers) {
		return browsers.map(function(browser){
			return [browser.platform || "", browser.browserName || "", browser.version || ""];
		});
	};

	var requestParams = {
		method: 'post',
		url: this.url,
		auth: {
			user: this.user,
			pass: this.key
		},
		json: true,
		body: {
			platforms: parsePlatforms(browsers),
			url: url,
			framework: framework,
			name: testname,
			tags: tags,
			build: build
		}
	};

	if (tunnelIdentifier){
		requestParams.body.tunnel = "tunnel-identifier:" + tunnelIdentifier;
	}

	rqst(requestParams, function(error, response, body) {
		if (error){
			log("Could not connect to Sauce Labs api: %s", error);
			throw error;
		}

		if (!body['js tests'] || !body['js tests'].length) {
			log('Error starting tests through Sauce API: %s', JSON.stringify(body));
			throw new Error('Could not start tests through Sauce API');
		}

		callback(body['js tests']);
	});
};

function configureLogEvents(tunnel) {
	var methods = ['write', 'writeln', 'error', 'ok', 'debug'];

	methods.forEach(function (method) {
		tunnel.on('log:' + method, function (text) {
			log(text);
		});

		tunnel.on('verbose:' + method, function (text) {
			//log(text);
		});
	});
}

function runTask(arg, framework, callback) {
	var test = new TestRunner(arg.username, arg.key, arg.testInterval);
	var webserver = new WebServer();

	webserver.start(function() {
		var tunnel = new SauceTunnel(arg.username, arg.key, arg.identifier, arg.tunneled);
		log("Starting Tunnel to Sauce Labs");
		configureLogEvents(tunnel);

		tunnel.start(function(isCreated) {
			if (!isCreated) {
				log("Could not create tunnel to Sauce Labs");
				callback(false);
				webserver.stop();
				return;
			}

			log("Connected to Saucelabs");

			try {
				test.runTests(
					arg.browsers,
					arg.urls,
					framework,
					arg.identifier,
					arg.testname,
					arg.tags,
					arg.build,
					arg.onTestComplete,
					function(status) {
						status = status.every(function(passed){ return passed; });
						//log("All tests completed with status %s", status);
						//log("Stopping Tunnel to Sauce Labs".inverse.bold);
						tunnel.stop(function() {
							callback(status);
						});

						webserver.stop();
					}
				);
			} catch (ex) {
				webserver.stop();
				throw ex;
			}
		});
	});
}

function qunit(settings) {
	var defaults = {
		username: process.env.SAUCE_USERNAME,
		key: process.env.SAUCE_ACCESS_KEY,
		build: process.env.TRAVIS_JOB_ID,
		identifier: Math.floor((new Date()).getTime() / 1000 - 1230768000).toString(),
		tunneled: true,
		tunnelTimeout: 120,
		testInterval: 1000 * 5,
		testReadyTimeout: 1000 * 5,
		testname: 'Tests',
		framework: 'qunit',
		onTestComplete: function() {},
		tags: [],
		urls: ['http://127.0.0.1:9999/tests/index.html'],
		browsers: []
	};

	for (var name in defaults) {
		if (name in settings) {
			continue;
		}

		settings[name] = defaults[name];
	}

	runTask(settings, 'qunit', function() {});
}

function WebServer(settings) {
	var server;

	settings = settings || {};

	this.start = function(callback) {
		server = http.createServer(function(req, res) {
			var uri = url.parse(req.url).pathname;

			if (uri === '/') {
				uri = "index.html";
			}

			var filename = path.join(process.cwd(), uri);
			fs.exists(filename, function(exists) {
					if (!exists) {
						res.writeHead(404, {'Content-Type': 'text/plain'});
						res.end('404 Not Found\n');
						return;
				}

				res.writeHead(200, {'Content-Type': mime.lookup(filename)});
				fs.createReadStream(filename).pipe(res);
			});
		});

		server.listen(settings.port || 9999, settings.host || '0.0.0.0', function() {
			if (settings.verbose) {
				log('Webserver started:', host, 'port', port);
			}

			callback();
		});
	};

	this.stop = function() {
		server.close();
	};
}

exports.saucelabs = {
	qunit: qunit
};
<commit_msg>Hard coded saucelabs log file name.<commit_after>// Most of this file is from the https://github.com/axemclion/grunt-saucelabs project

var request = require('request');
var SauceTunnel = require('sauce-tunnel');
var Q = require('q');
var fs = require('fs');
var http = require('http');
var path = require('path');
var url = require('url');
var mime = require('mime');
var chalk = require('chalk');

function log() {
	console.log.apply(this, arguments);
}

var rqst = request.defaults({
	jar: false
});

var resultParsers = {
	qunit: function(result) {
		if (result.passed === undefined) {
			return undefined;
		}

		return result.passed == result.total;
	}
};

var TestResult = function(jobId, user, key, framework, testInterval) {
	var url = 'https://saucelabs.com/rest/v1/' + user + '/js-tests/status';
	var deferred = Q.defer();

	var requestParams = {
		method: 'post',
		url: url,
		auth: {
			user: user,
			pass: key
		},
		json: true,
		body: {
			"js tests": [jobId]
		}
	};

	var checkStatus = function() {
		rqst(requestParams, function(error, response, body) {
			if (error) {
				deferred.resolve({
					passed: undefined,
					result: {
						message: "Error connecting to api to get test status: " + error.toString()
					}
				});

				return;
			}

			var testInfo = body['js tests'][0];

			if (testInfo.status == "test error"){
				deferred.resolve({
					passed: undefined,
					result: {
						message: "Test Error"
					}
				});

				return;
			}

			if (!body.completed){
				setTimeout(checkStatus ,testInterval);
			} else {
				testInfo.passed = testInfo.result ? resultParsers[framework](testInfo.result) : false;
				deferred.resolve(testInfo);
			}
		});
	};

	checkStatus();

	return deferred.promise;
};

var TestRunner = function(user, key, testInterval) {
	this.user = user;
	this.key = key;
	this.url = 'https://saucelabs.com/rest/v1/' + this.user + '/js-tests';
	this.testInterval = testInterval;
	this.results = [];
};

TestRunner.prototype.runTests = function(browsers, urls, framework, tunnelIdentifier, testname, tags, build, onTestComplete, callback) {
	var me = this;
	var numberOfJobs = browsers.length * urls.length;

	var addResultPromise = function(promise){
		me.results.push(promise);

		log(me.results.length, "/", numberOfJobs, 'tests started');

		if (me.results.length == numberOfJobs) {
			Q.all(me.results).then(function(results) {
				results = results.map(function(result) {
					return result.valueOf().passed;
				});

				callback(results);
			});
		}
	};

	urls.forEach(function(url) {
		me.runTest(browsers, url, framework, tunnelIdentifier, testname, tags, build, function(taskIds) {
			taskIds.forEach(function(taskId) {
				var resultPromise = new TestResult(taskId, me.user, me.key, framework, me.testInterval);

				addResultPromise(resultPromise);
				resultPromise.then(function(result) {
					var alteredResult = onTestComplete(result);

					if (alteredResult !== undefined){
						result.passed = alteredResult;
					}

					if (result.passed === undefined) {
						log(chalk.red("[FAILED] %s"), result.platform, result.result.message);
					} else {
						if (result.passed) {
							log(chalk.green("[PASSED] %s"), result.platform);
						} else {
							log(chalk.red("[FAILED] %s"), result.platform);
						}
					}

					//log("Url %s", result.url);
				}, function(e) {
					log('some error? %s', e);
				});
			});
		});
	});
};

TestRunner.prototype.runTest = function(browsers, url, framework, tunnelIdentifier, testname, tags, build, callback) {
	var parsePlatforms = function(browsers) {
		return browsers.map(function(browser){
			return [browser.platform || "", browser.browserName || "", browser.version || ""];
		});
	};

	var requestParams = {
		method: 'post',
		url: this.url,
		auth: {
			user: this.user,
			pass: this.key
		},
		json: true,
		body: {
			platforms: parsePlatforms(browsers),
			url: url,
			framework: framework,
			name: testname,
			tags: tags,
			build: build
		}
	};

	if (tunnelIdentifier){
		requestParams.body.tunnel = "tunnel-identifier:" + tunnelIdentifier;
	}

	rqst(requestParams, function(error, response, body) {
		if (error){
			log("Could not connect to Sauce Labs api: %s", error);
			throw error;
		}

		if (!body['js tests'] || !body['js tests'].length) {
			log('Error starting tests through Sauce API: %s', JSON.stringify(body));
			throw new Error('Could not start tests through Sauce API');
		}

		callback(body['js tests']);
	});
};

function configureLogEvents(tunnel) {
	var methods = ['write', 'writeln', 'error', 'ok', 'debug'];

	methods.forEach(function (method) {
		tunnel.on('log:' + method, function (text) {
			log(text);
		});

		tunnel.on('verbose:' + method, function (text) {
			//log(text);
		});
	});
}

function runTask(arg, framework, callback) {
	var test = new TestRunner(arg.username, arg.key, arg.testInterval);
	var webserver = new WebServer();

	webserver.start(function() {
		var tunnel = new SauceTunnel(arg.username, arg.key, arg.identifier, arg.tunneled, ["-l sc.log"]);
		log("Starting Tunnel to Sauce Labs");
		configureLogEvents(tunnel);

		tunnel.start(function(isCreated) {
			if (!isCreated) {
				log("Could not create tunnel to Sauce Labs");
				callback(false);
				webserver.stop();
				return;
			}

			log("Connected to Saucelabs");

			try {
				test.runTests(
					arg.browsers,
					arg.urls,
					framework,
					arg.identifier,
					arg.testname,
					arg.tags,
					arg.build,
					arg.onTestComplete,
					function(status) {
						status = status.every(function(passed){ return passed; });
						//log("All tests completed with status %s", status);
						//log("Stopping Tunnel to Sauce Labs".inverse.bold);
						tunnel.stop(function() {
							callback(status);
						});

						webserver.stop();
					}
				);
			} catch (ex) {
				webserver.stop();
				throw ex;
			}
		});
	});
}

function qunit(settings) {
	var defaults = {
		username: process.env.SAUCE_USERNAME,
		key: process.env.SAUCE_ACCESS_KEY,
		build: process.env.TRAVIS_JOB_ID,
		identifier: Math.floor((new Date()).getTime() / 1000 - 1230768000).toString(),
		tunneled: true,
		tunnelTimeout: 120,
		testInterval: 1000 * 5,
		testReadyTimeout: 1000 * 5,
		testname: 'Tests',
		framework: 'qunit',
		onTestComplete: function() {},
		tags: [],
		urls: ['http://127.0.0.1:9999/tests/index.html'],
		browsers: []
	};

	for (var name in defaults) {
		if (name in settings) {
			continue;
		}

		settings[name] = defaults[name];
	}

	runTask(settings, 'qunit', function() {});
}

function WebServer(settings) {
	var server;

	settings = settings || {};

	this.start = function(callback) {
		server = http.createServer(function(req, res) {
			var uri = url.parse(req.url).pathname;

			if (uri === '/') {
				uri = "index.html";
			}

			var filename = path.join(process.cwd(), uri);
			fs.exists(filename, function(exists) {
					if (!exists) {
						res.writeHead(404, {'Content-Type': 'text/plain'});
						res.end('404 Not Found\n');
						return;
				}

				res.writeHead(200, {'Content-Type': mime.lookup(filename)});
				fs.createReadStream(filename).pipe(res);
			});
		});

		server.listen(settings.port || 9999, settings.host || '0.0.0.0', function() {
			if (settings.verbose) {
				log('Webserver started:', host, 'port', port);
			}

			callback();
		});
	};

	this.stop = function() {
		server.close();
	};
}

exports.saucelabs = {
	qunit: qunit
};
<|endoftext|>


<commit_before>/**
 * This file contains code for rendering (and managing) HTML forms
 * which are served via the django-drf API.
 *
 * The django DRF library provides an OPTIONS method for each API endpoint,
 * which allows us to introspect the available fields at any given endpoint.
 *
 * The OPTIONS method provides the following information for each available field:
 *
 * - Field name
 * - Field label (translated)
 * - Field help text (translated)
 * - Field type
 * - Read / write status
 * - Field required status
 * - min_value / max_value
 */

/*
 * Return true if the OPTIONS specify that the user
 * can perform a GET method at the endpoint.
 */
function canView(OPTIONS) {

    if ('actions' in OPTIONS) {
        return ('GET' in OPTIONS.actions);
    } else {
        return false;
    }
}

/*
 * Return true if the OPTIONS specify that the user
 * can perform a POST method at the endpoint
 */
function canCreate(OPTIONS) {

    if ('actions' in OPTIONS) {
        return ('POST' in OPTIONS.actions);
    } else {
        return false;
    }
}

/*
 * Return true if the OPTIONS specify that the user
 * can perform a PUT or PATCH method at the endpoint
 */
function canChange(OPTIONS) {

    if ('actions' in OPTIONS) {
        return ('PUT' in OPTIONS.actions || 'PATCH' in OPTIONS.actions);
    } else {
        return false;
    }
}

/*
 * Return true if the OPTIONS specify that the user
 * can perform a DELETE method at the endpoint
 */
function canDelete(OPTIONS) {

    if ('actions' in OPTIONS) {
        return ('DELETE' in OPTIONS.actions);
    } else {
        return false;
    }
}

/*
 * Get the API endpoint options at the provided URL,
 * using a HTTP options request.
 */
function getApiEndpointOptions(url, callback, options={}) {

    // Return the ajax request object
    $.ajax({
        url: url,
        type: 'OPTIONS',
        contentType: 'application/json',
        dataType: 'json',
        accepts: {
            json: 'application/json',
        },
        success: callback,
    });
}

/*
 * Request API OPTIONS data from the server,
 * and construct a modal form based on the response.
 *
 * arguments:
 * - method: The HTTP method e.g. 'PUT', 'POST', 'DELETE',
 *
 * options:
 * - method:
 */
function constructForm(url, method, options={}) {

    method = method.toUpperCase();

    // Request OPTIONS endpoint from the API
    getApiEndpointOptions(url, function(OPTIONS) {

        /*
         * Determine what "type" of form we want to construct,
         * based on the requested action.
         *
         * First we must determine if the user has the correct permissions!
         */

        switch (method) {
            case 'POST':
                if (canCreate(OPTIONS)) {
                    constructCreateForm(url, OPTIONS.actions.POST);
                } else {
                    // User does not have permission to POST to the endpoint
                    console.log('cannot POST');
                    // TODO
                }
                break;
            case 'PUT':
            case 'PATCH':
                if (canChange(OPTIONS)) {
                    console.log("change");
                } else {
                    // User does not have permission to PUT/PATCH to the endpoint
                    // TODO
                    console.log('cannot edit');
                }
                break;
            case 'DELETE':
                if (canDelete(OPTIONS)) {
                    console.log('delete');
                } else {
                    // User does not have permission to DELETE to the endpoint
                    // TODO
                    console.log('cannot delete');
                }
                break;
            case 'GET':
                if (canView(OPTIONS)) {
                    console.log('view');
                } else {
                    // User does not have permission to GET to the endpoint
                    // TODO
                    console.log('cannot view');
                }
                break;
            default:
                console.log(`constructForm() called with invalid method '${method}'`);
                break;
        }
    });
}

/*
 * Construct a 'creation' (POST) form, to create a new model in the database.
 *
 * arguments:
 * - fields: The 'actions' object provided by the OPTIONS endpoint
 *
 * options:
 * -
 */
function constructCreateForm(url, fields, options={}) {

    var html = '';

    for (const key in fields) {

        var field = fields[key];

        var f = constructField(key, field, options);

        html += f;
    }

    var modal = '#modal-form';

    modalEnable(modal, true);

    $(modal).find('.modal-form-content').html(html);

    $(modal).modal('show');

    attachToggle(modal);
    attachSelect(modal);
}

/*
 * Construct a single form 'field' for rendering in a form.
 *
 * arguments:
 * - name: The 'name' of the field
 * - parameters: The field parameters supplied by the DRF OPTIONS method
 *
 * options:
 * -
 *
 * The function constructs a fieldset which mostly replicates django "crispy" forms:
 *
 * - Field name
 * - Field <input> (depends on specified field type)
 * - Field description (help text)
 * - Field errors
 */
function constructField(name, parameters, options={}) {

    var field_name = `id_${name}`;

    var form_classes = 'form-group';

    if (parameters.errors) {
        form_classes += ' has-error';
    }

    var html = `<div id='div_${field_name}' class='${form_classes}'>`;

    // Add a label
    html += constructLabel(name, parameters);

    html += `<div class='controls'>`;

    html += constructInput(name, parameters, options);

    if (parameters.errors) {
        html += constructErrorMessage(name, parameters, options);
    }

    if (parameters.help_text) {
        html += constructHelpText(name, parameters, options);
    }

    html += `</div>`;   // controls

    html += `</div>`;   // form-group

    return html;
}

/*
 * Construct a 'label' div
 *
 * arguments:
 * - name: The name of the field
 * - required: Is this a required field?
 */
function constructLabel(name, parameters) {

    var label_classes = 'control-label';

    if (parameters.required) {
        label_classes += ' requiredField';
    }

    var html = `<label class='${label_classes}' for='id_${name}'>`;

    if (parameters.label) {
        html += `${parameters.label}`;
    } else {
        html += `${name}`;
    }

    if (parameters.required) {
        html += `<span class='asteriskField'>*</span>`;
    }

    html += `</label>`;

    return html;
}

/*
 * Construct a form input based on the field parameters
 *
 * arguments:
 * - name: The name of the field
 * - parameters: Field parameters returned by the OPTIONS method
 *
 */
function constructInput(name, parameters, options={}) {

    var html = '';

    var func = null;

    switch (parameters.type) {
        case 'boolean':
            func = constructCheckboxInput;
            break;
        case 'string':
            func = constructTextInput;
            break;
        case 'url':
            func = constructTextInput;
            break;
        case 'email':
            func = constructTextInput;
            break;
        case 'integer':
            func = constructNumberInput;
            break;
        case 'float':
            func = constructNumberInput;
            break;
        case 'decimal':
            func = constructNumberInput;
            break;
        case 'choice':
            func = constructChoiceInput;
            break;
        case 'field':
            // TODO: foreign key field!
            break;
        default:
            // Unsupported field type!
            break;
        }

    if (func != null) {
        html = func(name, parameters, options);
    } else {
        console.log(`WARNING: Unhandled form field type: '${parameters.type}'`);
    }

    return html;
}

// Construct a set of default input options which apply to all input types
function constructInputOptions(name, classes, type, parameters) {

    var opts = [];

    opts.push(`id='id_${name}'`);

    opts.push(`class='${classes}'`);

    opts.push(`name='${name}'`);

    opts.push(`type='${type}'`);

    // Maximum input length
    if (parameters.max_length) {
        opts.push(`maxlength='${parameters.max_length}'`);
    }

    // Minimum input length
    if (parameters.min_length) {
        opts.push(`minlength='${parameters.min_length}'`);
    }

    // Maximum value
    if (parameters.max_value != null) {
        opts.push(`max='${parameters.max_value}'`);
    }

    // Minimum value
    if (parameters.min_value != null) {
        opts.push(`min='${parameters.min_value}'`);
    }

    // Field is required?
    if (parameters.required) {
        opts.push(`required=''`);
    }

    // Placeholder?
    if (parameters.placeholder) {
        opts.push(`placeholder='${parameters.placeholder}'`);
    }

    return `<input ${opts.join(' ')}>`;
}

// Construct a "checkbox" input
function constructCheckboxInput(name, parameters, options={}) {

    return constructInputOptions(
        name,
        'checkboxinput',
        'checkbox',
        parameters
    );

}

// Construct a "text" input
function constructTextInput(name, parameters, options={}) {

    var classes = '';
    var type = '';

    switch (parameters.type) {
        default:
            classes = 'textinput textInput form-control';
            type = 'text';
            break;
        case 'url':
            classes = 'urlinput form-control';
            type = 'url';
            break;
        case 'email':
            classes = 'emailinput form-control';
            type = 'email';
            break;
    }

    return constructInputOptions(
        name,
        classes,
        type,
        parameters
    );
}

// Construct a "number" field
function constructNumberInput(name, parameters, options={}) {

    return constructInputOptions(
        name,
        'numberinput form-control',
        'number',
        parameters
    );
}

// Construct a "choice" input
function constructChoiceInput(name, parameters, options={}) {

    var html = `<select id='id_${name}' class='select form-control' name='${name}'>`;

    var choices = parameters.choices || [];

    // TODO: Select the selected value!

    for (var idx = 0; idx < choices.length; idx++) {

        var choice = choices[idx];

        html += `<option value='${choice.value}'>`;
        html += `${choice.display_name}`;
        html += `</option>`;
    }

    html += `</select>`;

    return html;
}

/*
 * Construct a 'help text' div based on the field parameters
 *
 * arguments:
 * - name: The name of the field
 * - parameters: Field parameters returned by the OPTIONS method
 *
 */
function constructHelpText(name, parameters, options={}) {

    var html = `<div id='hint_id_${name}' class='help-block'>${parameters.help_text}</div>`;

    return html;
}

/*
 * Construct an 'error message' div for the field
 *
 * arguments:
 * - name: The name of the field
 * - parameters: Field parameters returned by the OPTIONS method
 */
function constructErrorMessage(name, parameters, options={}) {

    var errors_html = '';

    for (var idx = 0; idx < parameters.errors.length; idx++) {

        var err = parameters.errors[idx];

        var html = '';

        html += `<span id='error_${idx+1}_id_${name}' class='help-block'>`;
        html += `<strong>${err}</strong>`;
        html += `</span>`;

        errors_html += html;

    }

    return errors_html;
}<commit_msg>Working on a 'update' form<commit_after>/**
 * This file contains code for rendering (and managing) HTML forms
 * which are served via the django-drf API.
 *
 * The django DRF library provides an OPTIONS method for each API endpoint,
 * which allows us to introspect the available fields at any given endpoint.
 *
 * The OPTIONS method provides the following information for each available field:
 *
 * - Field name
 * - Field label (translated)
 * - Field help text (translated)
 * - Field type
 * - Read / write status
 * - Field required status
 * - min_value / max_value
 */

/*
 * Return true if the OPTIONS specify that the user
 * can perform a GET method at the endpoint.
 */
function canView(OPTIONS) {

    if ('actions' in OPTIONS) {
        return ('GET' in OPTIONS.actions);
    } else {
        return false;
    }
}

/*
 * Return true if the OPTIONS specify that the user
 * can perform a POST method at the endpoint
 */
function canCreate(OPTIONS) {

    if ('actions' in OPTIONS) {
        return ('POST' in OPTIONS.actions);
    } else {
        return false;
    }
}

/*
 * Return true if the OPTIONS specify that the user
 * can perform a PUT or PATCH method at the endpoint
 */
function canChange(OPTIONS) {

    if ('actions' in OPTIONS) {
        return ('PUT' in OPTIONS.actions || 'PATCH' in OPTIONS.actions);
    } else {
        return false;
    }
}

/*
 * Return true if the OPTIONS specify that the user
 * can perform a DELETE method at the endpoint
 */
function canDelete(OPTIONS) {

    if ('actions' in OPTIONS) {
        return ('DELETE' in OPTIONS.actions);
    } else {
        return false;
    }
}

/*
 * Get the API endpoint options at the provided URL,
 * using a HTTP options request.
 */
function getApiEndpointOptions(url, callback, options={}) {

    // Return the ajax request object
    $.ajax({
        url: url,
        type: 'OPTIONS',
        contentType: 'application/json',
        dataType: 'json',
        accepts: {
            json: 'application/json',
        },
        success: callback,
        error: function(request, status, error) {
            // TODO: Handle error
            console.log(`ERROR in getApiEndpointOptions at '${url}'`);
        }
    });
}

/*
 * Request API OPTIONS data from the server,
 * and construct a modal form based on the response.
 *
 * arguments:
 * - method: The HTTP method e.g. 'PUT', 'POST', 'DELETE',
 *
 * options:
 * - method:
 */
function constructForm(url, method, options={}) {

    method = method.toUpperCase();

    // Store the method in the options struct
    options.method = method;

    // Request OPTIONS endpoint from the API
    getApiEndpointOptions(url, function(OPTIONS) {

        /*
         * Determine what "type" of form we want to construct,
         * based on the requested action.
         *
         * First we must determine if the user has the correct permissions!
         */

        switch (method) {
            case 'POST':
                if (canCreate(OPTIONS)) {
                    constructCreateForm(url, OPTIONS.actions.POST, options);
                } else {
                    // User does not have permission to POST to the endpoint
                    console.log('cannot POST');
                    // TODO
                }
                break;
            case 'PUT':
            case 'PATCH':
                if (canChange(OPTIONS)) {
                    constructChangeForm(url, OPTIONS.actions.PUT, options);
                } else {
                    // User does not have permission to PUT/PATCH to the endpoint
                    // TODO
                    console.log('cannot edit');
                }
                break;
            case 'DELETE':
                if (canDelete(OPTIONS)) {
                    console.log('delete');
                } else {
                    // User does not have permission to DELETE to the endpoint
                    // TODO
                    console.log('cannot delete');
                }
                break;
            case 'GET':
                if (canView(OPTIONS)) {
                    console.log('view');
                } else {
                    // User does not have permission to GET to the endpoint
                    // TODO
                    console.log('cannot view');
                }
                break;
            default:
                console.log(`constructForm() called with invalid method '${method}'`);
                break;
        }
    });
}

/*
 * Construct a 'creation' (POST) form, to create a new model in the database.
 *
 * arguments:
 * - fields: The 'actions' object provided by the OPTIONS endpoint
 *
 * options:
 * -
 */
function constructCreateForm(url, fields, options={}) {

    var html = '';

    for (const key in fields) {

        // Ignore any PK fields
        if (key.toLowerCase() in ['pk', 'id']) {
            continue;
        }

        var field = fields[key];

        var f = constructField(key, field, options);

        html += f;
    }

    var modal = '#modal-form';

    modalEnable(modal, true);

    $(modal).find('.modal-form-content').html(html);

    $(modal).modal('show');

    attachToggle(modal);
    attachSelect(modal);
}

/*
 * Construct a 'change' (PATCH) form, to create a new model in the database.
 *
 * arguments:
 * - fields: The 'actions' object provided by the OPTIONS endpoint
 *
 * options:
 * -
 */
function constructChangeForm(url, fields, options={}) {

    // Request existing data from the API endpoint
    $.ajax({
        url: url,
        type: 'GET',
        contentType: 'application/json',
        dataType: 'json',
        accepts: {
            json: 'application/json',
        },
        success: function(data) {

            // Push existing 'value' to each field
            for (const field in data) {

                if (field in fields) {
                    fields[field].value = data[field];
                }
            }

            constructCreateForm(url, fields, options);
        },
        error: function(request, status, error) {
            // TODO: Handle error here
            console.log(`ERROR in constructChangeForm at '${url}'`);
        }
    })

}

/*
 * Construct a single form 'field' for rendering in a form.
 *
 * arguments:
 * - name: The 'name' of the field
 * - parameters: The field parameters supplied by the DRF OPTIONS method
 *
 * options:
 * -
 *
 * The function constructs a fieldset which mostly replicates django "crispy" forms:
 *
 * - Field name
 * - Field <input> (depends on specified field type)
 * - Field description (help text)
 * - Field errors
 */
function constructField(name, parameters, options={}) {

    var field_name = `id_${name}`;

    var form_classes = 'form-group';

    if (parameters.errors) {
        form_classes += ' has-error';
    }

    var html = `<div id='div_${field_name}' class='${form_classes}'>`;

    // Add a label
    html += constructLabel(name, parameters);

    html += `<div class='controls'>`;

    html += constructInput(name, parameters, options);

    if (parameters.errors) {
        html += constructErrorMessage(name, parameters, options);
    }

    if (parameters.help_text) {
        html += constructHelpText(name, parameters, options);
    }

    html += `</div>`;   // controls

    html += `</div>`;   // form-group

    return html;
}

/*
 * Construct a 'label' div
 *
 * arguments:
 * - name: The name of the field
 * - required: Is this a required field?
 */
function constructLabel(name, parameters) {

    var label_classes = 'control-label';

    if (parameters.required) {
        label_classes += ' requiredField';
    }

    var html = `<label class='${label_classes}' for='id_${name}'>`;

    if (parameters.label) {
        html += `${parameters.label}`;
    } else {
        html += `${name}`;
    }

    if (parameters.required) {
        html += `<span class='asteriskField'>*</span>`;
    }

    html += `</label>`;

    return html;
}

/*
 * Construct a form input based on the field parameters
 *
 * arguments:
 * - name: The name of the field
 * - parameters: Field parameters returned by the OPTIONS method
 *
 */
function constructInput(name, parameters, options={}) {

    var html = '';

    var func = null;

    switch (parameters.type) {
        case 'boolean':
            func = constructCheckboxInput;
            break;
        case 'string':
            func = constructTextInput;
            break;
        case 'url':
            func = constructTextInput;
            break;
        case 'email':
            func = constructTextInput;
            break;
        case 'integer':
            func = constructNumberInput;
            break;
        case 'float':
            func = constructNumberInput;
            break;
        case 'decimal':
            func = constructNumberInput;
            break;
        case 'choice':
            func = constructChoiceInput;
            break;
        case 'field':
            // TODO: foreign key field!
            break;
        default:
            // Unsupported field type!
            break;
        }

    if (func != null) {
        html = func(name, parameters, options);
    } else {
        console.log(`WARNING: Unhandled form field type: '${parameters.type}'`);
    }

    return html;
}

// Construct a set of default input options which apply to all input types
function constructInputOptions(name, classes, type, parameters) {

    var opts = [];

    opts.push(`id='id_${name}'`);

    opts.push(`class='${classes}'`);

    opts.push(`name='${name}'`);

    opts.push(`type='${type}'`);

    // Existing value?
    if (parameters.value) {
        opts.push(`value='${parameters.value}'`);
    }

    // Maximum input length
    if (parameters.max_length) {
        opts.push(`maxlength='${parameters.max_length}'`);
    }

    // Minimum input length
    if (parameters.min_length) {
        opts.push(`minlength='${parameters.min_length}'`);
    }

    // Maximum value
    if (parameters.max_value != null) {
        opts.push(`max='${parameters.max_value}'`);
    }

    // Minimum value
    if (parameters.min_value != null) {
        opts.push(`min='${parameters.min_value}'`);
    }

    // Field is required?
    if (parameters.required) {
        opts.push(`required=''`);
    }

    // Placeholder?
    if (parameters.placeholder) {
        opts.push(`placeholder='${parameters.placeholder}'`);
    }

    return `<input ${opts.join(' ')}>`;
}

// Construct a "checkbox" input
function constructCheckboxInput(name, parameters, options={}) {

    return constructInputOptions(
        name,
        'checkboxinput',
        'checkbox',
        parameters
    );

}

// Construct a "text" input
function constructTextInput(name, parameters, options={}) {

    var classes = '';
    var type = '';

    switch (parameters.type) {
        default:
            classes = 'textinput textInput form-control';
            type = 'text';
            break;
        case 'url':
            classes = 'urlinput form-control';
            type = 'url';
            break;
        case 'email':
            classes = 'emailinput form-control';
            type = 'email';
            break;
    }

    return constructInputOptions(
        name,
        classes,
        type,
        parameters
    );
}

// Construct a "number" field
function constructNumberInput(name, parameters, options={}) {

    return constructInputOptions(
        name,
        'numberinput form-control',
        'number',
        parameters
    );
}

// Construct a "choice" input
function constructChoiceInput(name, parameters, options={}) {

    var html = `<select id='id_${name}' class='select form-control' name='${name}'>`;

    var choices = parameters.choices || [];

    // TODO: Select the selected value!

    for (var idx = 0; idx < choices.length; idx++) {

        var choice = choices[idx];

        var selected = '';

        if (parameters.value && parameters.value == choice.value) {
            selected = ` selected=''`;
        }

        html += `<option value='${choice.value}'${selected}>`;
        html += `${choice.display_name}`;
        html += `</option>`;
    }

    html += `</select>`;

    return html;
}

/*
 * Construct a 'help text' div based on the field parameters
 *
 * arguments:
 * - name: The name of the field
 * - parameters: Field parameters returned by the OPTIONS method
 *
 */
function constructHelpText(name, parameters, options={}) {

    var html = `<div id='hint_id_${name}' class='help-block'>${parameters.help_text}</div>`;

    return html;
}

/*
 * Construct an 'error message' div for the field
 *
 * arguments:
 * - name: The name of the field
 * - parameters: Field parameters returned by the OPTIONS method
 */
function constructErrorMessage(name, parameters, options={}) {

    var errors_html = '';

    for (var idx = 0; idx < parameters.errors.length; idx++) {

        var err = parameters.errors[idx];

        var html = '';

        html += `<span id='error_${idx+1}_id_${name}' class='help-block'>`;
        html += `<strong>${err}</strong>`;
        html += `</span>`;

        errors_html += html;

    }

    return errors_html;
}<|endoftext|>


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

'use strict';

const rw = require('rw');
const path = require('path');
const globby = require('globby');
const Linter = require('../lib/index');
const chalk = require('chalk');

const STDIN = '/dev/stdin';

function printErrors(errors) {
  const quiet = process.argv.indexOf('--quiet') !== -1;

  let errorCount = 0;
  let warningCount = 0;

  Object.keys(errors).forEach(filePath => {
    let fileErrors = errors[filePath] || [];

    let errorsFiltered = fileErrors.filter(error => error.severity === Linter.ERROR_SEVERITY);
    let warnings = quiet
      ? []
      : fileErrors.filter(error => error.severity === Linter.WARNING_SEVERITY);

    errorCount += errorsFiltered.length;
    warningCount += warnings.length;

    errors[filePath] = errorsFiltered.concat(warnings);
  });

  if (process.argv.indexOf('--json') + 1) {
    console.log(JSON.stringify(errors, null, 2));
  } else {
    Object.keys(errors).forEach(filePath => {
      let options = {};
      let fileErrors = errors[filePath] || [];

      if (process.argv.indexOf('--verbose') + 1) {
        options.verbose = true;
      }

      const messages = Linter.errorsToMessages(filePath, fileErrors, options);
      if (messages !== '') {
        console.log(messages);
      }
    });

    const count = errorCount + warningCount;

    if (count > 0) {
      console.log(
        chalk.red(
          chalk.bold(`✖ ${count} problems (${errorCount} errors, ${warningCount} warnings)`)
        )
      );
    }
  }
}

function lintFile(linter, filePath, moduleId) {
  let source = rw.readFileSync(filePath, { encoding: 'utf8' });
  return linter.verify({ source, moduleId });
}

function expandFileGlobs(fileArgs) {
  return fileArgs.reduce((filePaths, fileArg) => {
    let files;
    if (['-', STDIN].includes(fileArg)) {
      if (filePaths.includes(STDIN)) {
        return filePaths;
      }
      files = [STDIN];
    } else {
      files = globby
        .sync(fileArg, {
          ignore: ['**/dist/**', '**/tmp/**', '**/node_modules/**'],
          gitignore: true,
        })
        .filter(filePath => filePath.slice(-4) === '.hbs');
    }
    return filePaths.concat(files);
  }, []);
}

function parseArgv(argv) {
  let arg;
  let options = { positional: [], named: {} };
  argvConsumption: while ((arg = argv.shift())) {
    switch (arg) {
      case '--config-path':
        options.named.configPath = argv.shift();
        break;
      case '--filename':
        options.named.filename = argv.shift();
        break;
      case '--':
        options.positional = [...options.positional, ...argv];
        break argvConsumption;
      default:
        options.positional.push(arg);
    }
  }
  return options;
}

function run() {
  let {
    named: { configPath, filename: filePathFromArgs = '' },
    positional: fileArgs,
  } = parseArgv(process.argv.slice(2));

  let linter;
  try {
    linter = new Linter({ configPath });
  } catch (e) {
    console.error(e.message);
    process.exitCode = 1;
    return;
  }

  let errors = {};
  let relativeFilePaths = fileArgs.length === 0 ? [STDIN] : expandFileGlobs(fileArgs);

  for (let relativeFilePath of new Set(relativeFilePaths)) {
    let filePath = path.resolve(relativeFilePath);
    let fileName = relativeFilePath === STDIN ? filePathFromArgs : relativeFilePath;
    let fileErrors = lintFile(linter, filePath, fileName.slice(0, -4));

    if (
      fileErrors.some(function(err) {
        return err.severity > 1;
      })
    ) {
      process.exitCode = 1;
    }

    if (fileErrors.length) {
      errors[filePath] = fileErrors;
    }
  }

  if (Object.keys(errors).length) {
    printErrors(errors);
  }
}

run();
<commit_msg>Export utility functions from bin script for easier testing<commit_after>#!/usr/bin/env node

'use strict';

const rw = require('rw');
const path = require('path');
const globby = require('globby');
const Linter = require('../lib/index');
const chalk = require('chalk');

const STDIN = '/dev/stdin';

function printErrors(errors) {
  const quiet = process.argv.indexOf('--quiet') !== -1;

  let errorCount = 0;
  let warningCount = 0;

  Object.keys(errors).forEach(filePath => {
    let fileErrors = errors[filePath] || [];

    let errorsFiltered = fileErrors.filter(error => error.severity === Linter.ERROR_SEVERITY);
    let warnings = quiet
      ? []
      : fileErrors.filter(error => error.severity === Linter.WARNING_SEVERITY);

    errorCount += errorsFiltered.length;
    warningCount += warnings.length;

    errors[filePath] = errorsFiltered.concat(warnings);
  });

  if (process.argv.indexOf('--json') + 1) {
    console.log(JSON.stringify(errors, null, 2));
  } else {
    Object.keys(errors).forEach(filePath => {
      let options = {};
      let fileErrors = errors[filePath] || [];

      if (process.argv.indexOf('--verbose') + 1) {
        options.verbose = true;
      }

      const messages = Linter.errorsToMessages(filePath, fileErrors, options);
      if (messages !== '') {
        console.log(messages);
      }
    });

    const count = errorCount + warningCount;

    if (count > 0) {
      console.log(
        chalk.red(
          chalk.bold(`✖ ${count} problems (${errorCount} errors, ${warningCount} warnings)`)
        )
      );
    }
  }
}

function lintFile(linter, filePath, moduleId) {
  let source = rw.readFileSync(filePath, { encoding: 'utf8' });
  return linter.verify({ source, moduleId });
}

function expandFileGlobs(fileArgs) {
  return fileArgs.reduce((filePaths, fileArg) => {
    let files;
    if (['-', STDIN].includes(fileArg)) {
      if (filePaths.includes(STDIN)) {
        return filePaths;
      }
      files = [STDIN];
    } else {
      files = globby
        .sync(fileArg, {
          ignore: ['**/dist/**', '**/tmp/**', '**/node_modules/**'],
          gitignore: true,
        })
        .filter(filePath => filePath.slice(-4) === '.hbs');
    }
    return filePaths.concat(files);
  }, []);
}

function parseArgv(argv) {
  let arg;
  let options = { positional: [], named: {} };
  argvConsumption: while ((arg = argv.shift())) {
    switch (arg) {
      case '--config-path':
        options.named.configPath = argv.shift();
        break;
      case '--filename':
        options.named.filename = argv.shift();
        break;
      case '--':
        options.positional = [...options.positional, ...argv];
        break argvConsumption;
      default:
        options.positional.push(arg);
    }
  }
  return options;
}

function run() {
  let {
    named: { configPath, filename: filePathFromArgs = '' },
    positional: fileArgs,
  } = parseArgv(process.argv.slice(2));

  let linter;
  try {
    linter = new Linter({ configPath });
  } catch (e) {
    console.error(e.message);
    process.exitCode = 1;
    return;
  }

  let errors = {};
  let relativeFilePaths = fileArgs.length === 0 ? [STDIN] : expandFileGlobs(fileArgs);

  for (let relativeFilePath of new Set(relativeFilePaths)) {
    let filePath = path.resolve(relativeFilePath);
    let fileName = relativeFilePath === STDIN ? filePathFromArgs : relativeFilePath;
    let fileErrors = lintFile(linter, filePath, fileName.slice(0, -4));

    if (
      fileErrors.some(function(err) {
        return err.severity > 1;
      })
    ) {
      process.exitCode = 1;
    }

    if (fileErrors.length) {
      errors[filePath] = fileErrors;
    }
  }

  if (Object.keys(errors).length) {
    printErrors(errors);
  }
}

// exports are for easier unit testing
module.exports = {
  _parseArgv: parseArgv,
  _expandFileGlobs: expandFileGlobs,
  _printErrors: printErrors,
};

if (require.main === module) {
  run();
}
<|endoftext|>


<commit_before>const execSync = require('child_process').execSync;

module.exports = function exec() {
  const args = Array.prototype.slice.call(args);

  console.log(`${args[1] && args[1].cwd || ''}$ ${args[0]}`);
  process.stdout.write(execSync(...args));
};
<commit_msg>Fix typo<commit_after>const execSync = require('child_process').execSync;

module.exports = function exec() {
  const args = Array.prototype.slice.call(arguments);

  console.log(`${args[1] && args[1].cwd || ''}$ ${args[0]}`);
  process.stdout.write(execSync(...args));
};
<|endoftext|>


<commit_before>$(document).ready(function(){
    var available_filter_args;

    function parse_filters(query_id, query_num, json){
        if (json['a']['a'] == undefined) {
            if (available_filter_args[query_id] == undefined){
                available_filter_args[query_id] = {};
                available_filter_args[query_id]['display_name'] = null;
                available_filter_args[query_id]['filter_args'] = [];
                console.log(JSON.stringify(available_filter_args));
            }
            console.log(JSON.stringify(available_filter_args));
            available_filter_args[query_id]['display_name'] = query_num;
            available_filter_args[query_id]['filter_args'].push(json);
        }
        else {
            parse_filters(query_id, query_num, json['a']);
            parse_filters(query_id, query_num, json['b']);
        }
    }

    $("#add_argument_popbtn").popover({
        html: true,
        animation:true,
        trigger: 'manual',
        content: function() {
            return $('#argument-select-container').html();
        }
    }).click(function(e) {
        $(this).popover('toggle');

        available_filter_args = JSON.parse('{}');
        $('#selected-queries-table tbody tr').each(function( index ) {
            console.log( index + ": " + JSON.stringify(JSON.parse($( this ).children().eq(3).text().replace(/u'/g , "'").replace(/'/g , '"').replace(/False/g , '"False"').replace(/True/g , '"True"'))['filters']) );
            parse_filters($( this ).children().eq(0).text(), $( this ).children().eq(1).text(), JSON.parse($( this ).children().eq(3).text().replace(/u'/g , "'").replace(/'/g , '"').replace(/False/g , '"False"').replace(/True/g , '"True"'))['filters']) ;
        });

        $('#query-argument-select').empty();
        $('#query-argument-select').append('<option disabled selected>-- select one of the available filters --</option>');
        // var keys = [];
        // for(var k in available_filter_args) keys.push(k);
        for(var query in available_filter_args){
            console.log(query);
            for(var arg_idx in available_filter_args[query]['filter_args']) {
                var display_name = available_filter_args[query]['display_name'];
                var arg = available_filter_args[query]['filter_args'][arg_idx];
                var arg_a = arg['a'];
                var arg_op = arg['op'];
                var arg_b = arg['b'];
                $('#query-argument-select').append('<option  data-query-id="'+query+'" data-display_name="'+display_name+'" data-arg-a="'+arg_a+'" data-arg-op="'+arg_op+'" data-arg-b="'+arg_b+'" title="' + display_name + '-' + arg_a +' '+ arg_op +' '+ arg_b + '"> ' + display_name + '-' + arg_a +' '+ arg_op +' '+ arg_b + ' </option>');
            }
        }
        $('.popover-content #query-argument-select').select2();
        // available_filter_args.forEach(function(value) {
        //   console.log(value);
        //   $('#query-argument-select').append('<option  value="'+value+'" title="'+value+'"> '+value+' </option>');
        // });

        var new_arg_query_id;
        var new_arg_query_display_name;
        var new_arg_a;
        var new_arg_op;
        var new_arg_b;
        $('.popover-content #query-argument-select').on('change', function() {
            new_arg_query_id = $(this).children(":selected").attr("data-query-id");
            new_arg_query_display_name = $(this).children(":selected").attr("data-display_name");
            new_arg_a = $(this).children(":selected").attr("data-arg-a");
            new_arg_op = $(this).children(":selected").attr("data-arg-op");
            new_arg_b = $(this).children(":selected").attr("data-arg-b");
        });

        $('.popover-content #add_new_argument_btn').click(function (e) {
            var new_arg_tr_string = "
 "+new_arg_query_id+"	 "+new_arg_query_display_name+"	 "+new_arg_a+' '+new_arg_op +"	 <input value='"+new_arg_b+"'/>	 <input value=''/>	 <textarea rows='3' cols='50'/>
";
            $('#selected-arguments-table tbody').append(new_arg_tr_string);

            $('#add_argument_popbtn').popover("hide");
        })
    });

});

// $(document).ready(function(){
//     $('#query-argument-select').select2();
// });
<commit_msg>fixed bug if query does not have filters<commit_after>$(document).ready(function(){
    var available_filter_args;

    function parse_filters(query_id, query_num, json){
        if (json['a']['a'] == undefined) {
            if (available_filter_args[query_id] == undefined){
                available_filter_args[query_id] = {};
                available_filter_args[query_id]['display_name'] = null;
                available_filter_args[query_id]['filter_args'] = [];
                console.log(JSON.stringify(available_filter_args));
            }
            console.log(JSON.stringify(available_filter_args));
            available_filter_args[query_id]['display_name'] = query_num;
            available_filter_args[query_id]['filter_args'].push(json);
        }
        else {
            parse_filters(query_id, query_num, json['a']);
            parse_filters(query_id, query_num, json['b']);
        }
    }

    $("#add_argument_popbtn").popover({
        html: true,
        animation:true,
        trigger: 'manual',
        content: function() {
            return $('#argument-select-container').html();
        }
    }).click(function(e) {
        $(this).popover('toggle');

        available_filter_args = JSON.parse('{}');
        $('#selected-queries-table tbody tr').each(function( index ) {
            console.log( index + ": " + JSON.stringify(JSON.parse($( this ).children().eq(3).text().replace(/u'/g , "'").replace(/'/g , '"').replace(/False/g , '"False"').replace(/True/g , '"True"'))['filters']) );
            var query_doc = JSON.parse($( this ).children().eq(3).text().replace(/u'/g , "'").replace(/'/g , '"').replace(/False/g , '"False"').replace(/True/g , '"True"'));
            var filters = query_doc['filters'];
            if (filters != undefined){
                parse_filters($( this ).children().eq(0).text(), $( this ).children().eq(1).text(), filters) ;
            }
        });

        $('#query-argument-select').empty();
        $('#query-argument-select').append('<option disabled selected>-- select one of the available filters --</option>');
        // var keys = [];
        // for(var k in available_filter_args) keys.push(k);
        for(var query in available_filter_args){
            console.log(query);
            for(var arg_idx in available_filter_args[query]['filter_args']) {
                var display_name = available_filter_args[query]['display_name'];
                var arg = available_filter_args[query]['filter_args'][arg_idx];
                var arg_a = arg['a'];
                var arg_op = arg['op'];
                var arg_b = arg['b'];
                $('#query-argument-select').append('<option  data-query-id="'+query+'" data-display_name="'+display_name+'" data-arg-a="'+arg_a+'" data-arg-op="'+arg_op+'" data-arg-b="'+arg_b+'" title="' + display_name + '-' + arg_a +' '+ arg_op +' '+ arg_b + '"> ' + display_name + '-' + arg_a +' '+ arg_op +' '+ arg_b + ' </option>');
            }
        }
        $('.popover-content #query-argument-select').select2();
        // available_filter_args.forEach(function(value) {
        //   console.log(value);
        //   $('#query-argument-select').append('<option  value="'+value+'" title="'+value+'"> '+value+' </option>');
        // });

        var new_arg_query_id;
        var new_arg_query_display_name;
        var new_arg_a;
        var new_arg_op;
        var new_arg_b;
        $('.popover-content #query-argument-select').on('change', function() {
            new_arg_query_id = $(this).children(":selected").attr("data-query-id");
            new_arg_query_display_name = $(this).children(":selected").attr("data-display_name");
            new_arg_a = $(this).children(":selected").attr("data-arg-a");
            new_arg_op = $(this).children(":selected").attr("data-arg-op");
            new_arg_b = $(this).children(":selected").attr("data-arg-b");
        });

        $('.popover-content #add_new_argument_btn').click(function (e) {
            var new_arg_tr_string = "
 "+new_arg_query_id+"	 "+new_arg_query_display_name+"	 "+new_arg_a+' '+new_arg_op +"	 <input value='"+new_arg_b+"'/>	 <input value=''/>	 <textarea rows='3' cols='50'/>
";
            $('#selected-arguments-table tbody').append(new_arg_tr_string);

            $('#add_argument_popbtn').popover("hide");
        })
    });

});

// $(document).ready(function(){
//     $('#query-argument-select').select2();
// });
<|endoftext|>


<commit_before>var exports = module.exports = {};

/*
 * shall we output debug logs?
 * if so start the app with:
 *    DEBUG=ledconodel node app.js
 */
const debug = require('debug')('ledconodel');
const name = 'ledconodel';
debug('booting %s', name);

/*
 * require rpio2 node module to drive GPIO pins and use hardware pin numbering
 */
const Gpio = require('rpio2').Gpio;
var options = {
  gpiomem: true,          /* Use /dev/gpiomem */
  mapping: 'physical',    /* Use the P1-P40 numbering scheme */
}

/*
 * set the hardware pins for the 3 leds as a new instance of Gpio
 */
const greenled = new Gpio(19);
const redled = new Gpio(13);
const blueled = new Gpio(26);

/*
 * Set the initial state to low.  The state is set prior to the pin becoming
 * active, so is safe for devices which require a stable setup.
 */
greenled.open(Gpio.OUTPUT, Gpio.LOW);
redled.open(Gpio.OUTPUT, Gpio.LOW);
blueled.open(Gpio.OUTPUT, Gpio.LOW);

/*
 * include the adafruit.io client library to watch the feed
 */
//require xxx as adaio

/*
 * the name of the Adafruit.io feed we want to watch
 */
var feedname = "ledfeeder";

/*
 * the blinker function will get calls with the GPIO object of the pin,
 * how many times to blink the led and how long the led shall be turned on
 */
function blinkled(ledToBlink, howManyTimes=5, interval=500) {
  debug('blinkled called, payload is %s howManyTimes is %s and interval is %s', ledToBlink, howManyTimes, interval);
	if (ledToBlink == "red") {
    for (var i=0; i<howManyTimes; i++) {
      debug('red on');
      redled.open(Gpio.OUTPUT, Gpio.HIGH);
      redled.sleep(interval);
      debug('red off');
		  redled.open(Gpio.OUTPUT, Gpio.LOW);
    }
	} else if (ledToBlink == "green") {
    for (var i=0; i<howManyTimes; i++) {
      debug('green on');
      greenled.open(Gpio.OUTPUT, Gpio.HIGH);
      greenled.sleep(interval);
      debug('green off');
		  greenled.open(Gpio.OUTPUT, Gpio.LOW);
    }
	} else if (ledToBlink == "blue") {
    for (var i=0; i<howManyTimes; i++) {
      debug('blue on');
      blueled.open(Gpio.OUTPUT, Gpio.HIGH);
      blueled.sleep(interval);
      debug('blue off');
		  blueled.open(Gpio.OUTPUT, Gpio.LOW);
    }
	} else {
		debug('unrecognized payload %s', ledToBlink);
	}
}

/*
 * the main watcher function - need to do this asynchronously
 */
function watchfeed(){
  blinkled("red",5,1000);
  blinkled("green",5,1000);
  blinkled("blue",5,1000);
}

watchfeed();
debug('closing GPIO');
redled.close();
greenled.close();
blueled.close();
debug('shutdown!');
process.exit(0);

/*
process.on("SIGINT", function(){
  redled.close();
  greenled.close();
  blueled.close();
  debug('shutdown!');
  process.exit(0);
});
*/
<commit_msg>changed led on time to 10000ms<commit_after>var exports = module.exports = {};

/*
 * shall we output debug logs?
 * if so start the app with:
 *    DEBUG=ledconodel node app.js
 */
const debug = require('debug')('ledconodel');
const name = 'ledconodel';
debug('booting %s', name);

/*
 * require rpio2 node module to drive GPIO pins and use hardware pin numbering
 */
const Gpio = require('rpio2').Gpio;
var options = {
  gpiomem: true,          /* Use /dev/gpiomem */
  mapping: 'physical',    /* Use the P1-P40 numbering scheme */
}

/*
 * set the hardware pins for the 3 leds as a new instance of Gpio
 */
const greenled = new Gpio(19);
const redled = new Gpio(13);
const blueled = new Gpio(26);

/*
 * Set the initial state to low.  The state is set prior to the pin becoming
 * active, so is safe for devices which require a stable setup.
 */
greenled.open(Gpio.OUTPUT, Gpio.LOW);
redled.open(Gpio.OUTPUT, Gpio.LOW);
blueled.open(Gpio.OUTPUT, Gpio.LOW);

/*
 * include the adafruit.io client library to watch the feed
 */
//require xxx as adaio

/*
 * the name of the Adafruit.io feed we want to watch
 */
var feedname = "ledfeeder";

/*
 * the blinker function will get calls with the GPIO object of the pin,
 * how many times to blink the led and how long the led shall be turned on
 */
function blinkled(ledToBlink, howManyTimes=5, interval=500) {
  debug('blinkled called, payload is %s howManyTimes is %s and interval is %s', ledToBlink, howManyTimes, interval);
	if (ledToBlink == "red") {
    for (var i=0; i<howManyTimes; i++) {
      debug('red on');
      redled.open(Gpio.OUTPUT, Gpio.HIGH);
      redled.sleep(interval);
      debug('red off');
		  redled.open(Gpio.OUTPUT, Gpio.LOW);
    }
	} else if (ledToBlink == "green") {
    for (var i=0; i<howManyTimes; i++) {
      debug('green on');
      greenled.open(Gpio.OUTPUT, Gpio.HIGH);
      greenled.sleep(interval);
      debug('green off');
		  greenled.open(Gpio.OUTPUT, Gpio.LOW);
    }
	} else if (ledToBlink == "blue") {
    for (var i=0; i<howManyTimes; i++) {
      debug('blue on');
      blueled.open(Gpio.OUTPUT, Gpio.HIGH);
      blueled.sleep(interval);
      debug('blue off');
		  blueled.open(Gpio.OUTPUT, Gpio.LOW);
    }
	} else {
		debug('unrecognized payload %s', ledToBlink);
	}
}

/*
 * the main watcher function - need to do this asynchronously
 */
function watchfeed(){
  blinkled("red",5,10000);
  blinkled("green",5,10000);
  blinkled("blue",5,10000);
}

watchfeed();
debug('closing GPIO');
redled.close();
greenled.close();
blueled.close();
debug('shutdown!');
process.exit(0);

/*
process.on("SIGINT", function(){
  redled.close();
  greenled.close();
  blueled.close();
  debug('shutdown!');
  process.exit(0);
});
*/
<|endoftext|>


<commit_before>module.exports = (globalJSON, content) => {
    const fs = require('fs');
    const renderMenu = require('./renderMenu.js')
    if (! globalJSON) {
        globalJSON = JSON.parse(fs.readFileSync('./docs/globalJSON.json', 'utf8'));
    }

    if (! content) {
        const wrap = (el) => {
            const html = el.html ? `<div class="sample">${JSON.parse(el.html)}</div>` : '';

            const sample = (type, content) => {
                return `

                            <button class="clipbrd-btn" data-clipboard-target="#copy_code-${type}-${el.name}"  alt="Copy to clipboard"></button>

${content}

Show ${type} sample

                `
            }

            const codeSample = el.codeExample ? sample('code', JSON.parse(el.codeExample)) : '';
            const jsSample = el.jsExample ? sample('js', JSON.parse(el.jsExample)) : '';

            return `

${JSON.parse(el.markDown)}

                   ${html} ${codeSample} ${jsSample}

            `
        }
        let type = [];
        let group = [];
        content = Object.keys(globalJSON)
                .map((el, index) => {
                    let content = '';
                    if (group.indexOf(globalJSON[el].group) === - 1) {
                        if (index != 0) {
                            content += `<hr>`;
                            content += '
';
                        }
                        content += `<div id="${globalJSON[el].group}-link" class="positon-anchor">`
                    }
                    if (type.indexOf(globalJSON[el].type) === - 1) {
                        type.push(globalJSON[el].type);
                        content += `<h2 class="type_name">${globalJSON[el].type}</h2>`;
                    }
                    content += wrap(globalJSON[el])
                    group.push(globalJSON[el].group);
                    return content;
                }).join('\n') || 'empty';
    }

    let scriptsFiles = [
        'dist/showcar-icons.js',
        'dist/showcar-tracking.js',
        'dist/showcar-ui.js',
        'docs/assets/js/highlight.min.js',
        'docs/assets/js/clipboard.min.js',
        'docs/assets/js/smooth-scroll.min.js',
        'docs/assets/js/docs.js',
    ];
    let stylesFiles = [
        'docs/assets/styles/github.min.css',
        'dist/showcar-ui.css',
        'docs/assets/styles/docs.css',
    ];

    scriptsFiles = scriptsFiles.map(script => {
        return `<script src="/showcar-ui/${script}"></script>`
    }).join('\n');

    stylesFiles = stylesFiles.map(style => {
        return `<link rel="stylesheet" href="/showcar-ui/${style}">`
    }).join('\n');
    const polyfils = require('./polyfils.js')

    const head = `
        <!DOCTYPE html>

                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width">
                <title v-text="ShowCar UI docs"></title>
                <link rel="shortcut icon" type="image/png" href="favicon.png"/>

                ${scriptsFiles}
                ${stylesFiles}

    `;

    const menu = renderMenu(globalJSON);

    const leftMenu = `

ShowCar UI

Show all code samples

                ${menu}

    `;

    const body = `

${content}

    `;

    const footer = `

    `;

    const html = head + leftMenu + body + footer;
    return html;
}

<commit_msg>fox code highlight at js sample<commit_after>module.exports = (globalJSON, content) => {
    const fs = require('fs');
    const renderMenu = require('./renderMenu.js')
    if (! globalJSON) {
        globalJSON = JSON.parse(fs.readFileSync('./docs/globalJSON.json', 'utf8'));
    }

    if (! content) {
        const wrap = (el) => {
            const html = el.html ? `<div class="sample">${JSON.parse(el.html)}</div>` : '';

            const sample = (type, content) => {
                return `

                            <button class="clipbrd-btn" data-clipboard-target="#copy_code-${type}-${el.name}"  alt="Copy to clipboard"></button>

                                    ${content}

Show ${type} sample

                `
            }

            const codeSample = el.codeExample ? sample('code', JSON.parse(el.codeExample)) : '';
            const jsSample = el.jsExample ? sample('js', JSON.parse(el.jsExample)) : '';

            return `

${JSON.parse(el.markDown)}

                   ${html} ${codeSample} ${jsSample}

            `
        }
        let type = [];
        let group = [];
        content = Object.keys(globalJSON)
                .map((el, index) => {
                    let content = '';
                    if (group.indexOf(globalJSON[el].group) === - 1) {
                        if (index != 0) {
                            content += `<hr>`;
                            content += '
';
                        }
                        content += `<div id="${globalJSON[el].group}-link" class="positon-anchor">`
                    }
                    if (type.indexOf(globalJSON[el].type) === - 1) {
                        type.push(globalJSON[el].type);
                        content += `<h2 class="type_name">${globalJSON[el].type}</h2>`;
                    }
                    content += wrap(globalJSON[el])
                    group.push(globalJSON[el].group);
                    return content;
                }).join('\n') || 'empty';
    }

    let scriptsFiles = [
        'dist/showcar-icons.js',
        'dist/showcar-tracking.js',
        'dist/showcar-ui.js',
        'docs/assets/js/highlight.min.js',
        'docs/assets/js/clipboard.min.js',
        'docs/assets/js/smooth-scroll.min.js',
        'docs/assets/js/docs.js',
    ];
    let stylesFiles = [
        'docs/assets/styles/github.min.css',
        'dist/showcar-ui.css',
        'docs/assets/styles/docs.css',
    ];

    scriptsFiles = scriptsFiles.map(script => {
        return `<script src="/showcar-ui/${script}"></script>`
    }).join('\n');

    stylesFiles = stylesFiles.map(style => {
        return `<link rel="stylesheet" href="/showcar-ui/${style}">`
    }).join('\n');
    const polyfils = require('./polyfils.js')

    const head = `
        <!DOCTYPE html>

                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width">
                <title v-text="ShowCar UI docs"></title>
                <link rel="shortcut icon" type="image/png" href="favicon.png"/>

                ${scriptsFiles}
                ${stylesFiles}

    `;

    const menu = renderMenu(globalJSON);

    const leftMenu = `

ShowCar UI

Show all code samples

                ${menu}

    `;

    const body = `

${content}

    `;

    const footer = `

    `;

    const html = head + leftMenu + body + footer;
    return html;
}

<|endoftext|>


<commit_before>// Copyright (c) 2008 gocept gmbh & co. kg
// See also LICENSE.txt

MochiKit.Signal.connect(window, 'onload', function() {
    var class_names = ['answers', 'questions']; // order is important
    forEach(class_names, function(class_name) {
        forEach(getElementsByTagAndClassName('ol', class_name),
                function(list) {
            MochiKit.Sortable.Sortable.create(
                list.id, {
                only: ['question', 'answer'],
            });
        });
    });

    MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
                            function (event) {
                                event.element.dragging = true;
                            });

    var questions = getFirstElementByTagAndClassName('ol', 'questions');
    MochiKit.Signal.connect(questions, 'onclick', function(event) {
        var item = event._event.target.parentNode
        if (item.dragging) {
            event.stop();
            item.dragging = false;
        };
    });
});
<commit_msg>umsortieren clickt links nicht<commit_after>// Copyright (c) 2008 gocept gmbh & co. kg
// See also LICENSE.txt

MochiKit.Signal.connect(window, 'onload', function() {
    var class_names = ['answers', 'questions']; // order is important
    forEach(class_names, function(class_name) {
        forEach(getElementsByTagAndClassName('ol', class_name),
                function(list) {
            MochiKit.Sortable.Sortable.create(
                list.id, {
                only: ['question', 'answer'],
            });
        });
    });

    MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
                            function (event) {
                                event.element.dragging = true;
                            });

    var questions = getFirstElementByTagAndClassName('ol', 'questions');
    MochiKit.Signal.connect(questions, 'onclick', function(event) {
        var item = getFirstParentByTagAndClassName(event.target(), 'li');
        if (item.dragging) {
            event.stop();
            item.dragging = false;
        };
    });
});
<|endoftext|>


<commit_before>const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const Metadata = require('./src/utils/metadata')

module.exports = {
  output: {
    filename: 'offmar.user.js'
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ['style-loader', 'postcss-loader']
      },
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        uglifyOptions: {
          output: {
            beautify: false,
            preamble: Metadata.generate()
          }
        }
      })
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.BannerPlugin({
      banner: Metadata.generate(),
      raw: true,
      entryOnly: true
    })
  ]
}
<commit_msg>[chore] use longname as artifact build result<commit_after>const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const Metadata = require('./src/utils/metadata')
const package = require('./package.json')

module.exports = {
  output: {
    filename: `${package.longName.replace(/\s+/g, '_')}.user.js`
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ['style-loader', 'postcss-loader']
      },
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        uglifyOptions: {
          output: {
            beautify: false,
            preamble: Metadata.generate()
          }
        }
      })
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.BannerPlugin({
      banner: Metadata.generate(),
      raw: true,
      entryOnly: true
    })
  ]
}
<|endoftext|>


<commit_before>// ---------------------------------------------------------------------------
// Usage: npm run transpileWs
// ---------------------------------------------------------------------------

"use strict";

const fs = require ('fs')
    , log = require ('ololog')
    , ansi = require ('ansicolor').nice
    , { unCamelCase, precisionConstants, safeString, unique } = require ('../js/base/functions.js')
    , {
        createFolderRecursively,
        overwriteFile,
        replaceInFile,
    } = require ('./fs.js')
    , errors = require ('../js/base/errors.js')
    , Transpiler = require ('./transpile.js')
    , Exchange = require ('../js/ws/base/Exchange.js')
    // , tsFilename = './ccxt.pro.d.ts'
    , tsFilename = './ccxt.d.ts'

// ============================================================================

class CCXTProTranspiler extends Transpiler {

    getBaseClass () {
        return new Exchange ()
    }

    getPHPPreamble () {
        return [
            "<?php",
            "namespace ccxtpro;",
            "include_once __DIR__ . '../../../vendor/autoload.php';",
            "// ----------------------------------------------------------------------------",
            "",
            "// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:",
            "// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code",
            "",
            "// -----------------------------------------------------------------------------",
            "",
        ].join ("\n")
    }

    createPythonClassDeclaration (className, baseClass) {
        const baseClasses = (baseClass.indexOf ('Rest') >= 0) ?
            [ 'Exchange', baseClass ] :
            [ baseClass ]
        return 'class ' + className + '(' + baseClasses.join (', ') + '):'
    }

    createPythonClassImports (baseClass, async = false) {

        const baseClasses = {
            'Exchange': 'base.exchange',
        }

        async = (async ? '.async_support' : '')

        if (baseClass.indexOf ('Rest') >= 0) {
            baseClass = baseClass.replace ('Rest', '')
            return [
                'from ccxt.ws.base.exchange import Exchange',
                'from ccxt.rest.async_support.' + baseClass + ' import ' + baseClass + ' as ' + baseClass + 'Rest'
            ]
        } else {
            return [
                // 'from ccxt.rest.async_support.' + safeString (baseClasses, baseClass, baseClass) + ' import ' + baseClass
                'from ccxt.ws.' + baseClass + ' import ' + baseClass // on the JS side we add to append `Rest` to the base class name
            ]
        }
        // return [
        //     (baseClass.indexOf ('ccxt.') === 0) ?
        //         ('import ccxt' + async + ' as ccxt') :
        //         ('from ccxtpro.' + safeString (baseClasses, baseClass, baseClass) + ' import ' + baseClass)
        // ]
    }

    createPythonClassHeader (ccxtImports, bodyAsString) {
        const imports = [
            ... ccxtImports,
        ]
        const arrayCacheClasses = bodyAsString.match (/\bArrayCache(?:[A-Z][A-Za-z]+)?\b/g)
        if (arrayCacheClasses) {
            const uniqueArrayCacheClasses = unique (arrayCacheClasses).sort ()
            const arrayCacheImport = 'from ccxt.ws.base.cache import ' + uniqueArrayCacheClasses.join (', ')
            imports.push (arrayCacheImport)
        }
        return [
            "# -*- coding: utf-8 -*-",
            "",
            "# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:",
            "# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code",
            "",
            ... imports,
        ]
    }

    createPHPClassDeclaration (className, baseClass) {
        let lines = [
            'class ' + className + ' extends ' + '\\ccxt\\rest\\async\\' +  baseClass.replace ('Rest', '') + ' {',
        ]
        if (baseClass.indexOf ('Rest') >= 0) {
            lines = lines.concat ([
                '',
                '    use ClientTrait;'
            ])
        }
        return lines.join ("\n")
    }

    createPHPClassHeader (className, baseClass, bodyAsString) {
        return [
            "<?php",
            "",
            "namespace ccxtpro;",
            "",
            "// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:",
            "// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code",
            "",
            "use Exception; // a common import",
        ]
    }

    sortExchangeCapabilities (code) {
        return false
    }

    // ------------------------------------------------------------------------

    transpileOrderBookTest () {
        const jsFile = './js/ws/test/base/test.OrderBook.js'
        const pyFile = './python/ccxt/ws/test/test_order_book.py'
        const phpFile = './php/ws/test/OrderBook.php'
        const pyImports = [
            '',
            'from ccxt.ws.base.order_book import OrderBook, IndexedOrderBook, CountedOrderBook  # noqa: F402',
            '',
        ].join ('\n')
        this.transpileTest (jsFile, pyFile, phpFile, pyImports)
    }

    // ------------------------------------------------------------------------

    transpileCacheTest () {
        const jsFile = './js/ws/test/base/test.Cache.js'
        const pyFile = './python/ccxt/ws/test/test_cache.py'
        const phpFile = './php/ws/test/Cache.php'
        const pyImports = [
            '',
            'from ccxt.ws.base.cache import ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById  # noqa: F402',
            '',
        ].join ('\n')
        this.transpileTest (jsFile, pyFile, phpFile, pyImports)
    }

    // ------------------------------------------------------------------------

    transpileTest (jsFile, pyFile, phpFile, pyImports) {

        log.magenta ('Transpiling from', jsFile.yellow)

        let js = fs.readFileSync (jsFile).toString ()

        js = this.regexAll (js, [
            [ /\'use strict\';?\s+/g, '' ],
            [ /[^\n]+require[^\n]+\n/g, '' ],
            [ /function equals \([\S\s]+?return true;\n}\n/g, '' ],
        ])

        const options = { js, removeEmptyLines: false }
        const transpiled = this.transpileJavaScriptToPythonAndPHP (options)
        const { python3Body, python2Body, phpBody } = transpiled
        const pythonHeader = [
            '',
            '',
            'def equals(a, b):',
            '    return a == b',
            '',
        ].join ('\n')

        const phpHeader = [
            '',
            'function equals($a, $b) {',
            '    return json_encode($a) === json_encode($b);',
            '}',
        ].join ('\n')

        const python = this.getPythonPreamble () + pyImports + pythonHeader + python2Body
        const php = this.getPHPPreamble () + phpHeader + phpBody

        log.magenta ('→', pyFile.yellow)
        log.magenta ('→', phpFile.yellow)

        overwriteFile (pyFile, python)
        overwriteFile (phpFile, php)
    }

    // ------------------------------------------------------------------------

    transpileEverything (force = false) {

        // default pattern is '.js'
        const [ /* node */, /* script */, pattern ] = process.argv.filter (x => !x.startsWith ('--'))
            // , python2Folder = './python/ccxtpro/', // CCXT Pro does not support Python 2
            , python3Folder = './python/ccxt/ws/'
            , phpAsyncFolder     = './php/ws/'
            , options = { /* python2Folder, */ python3Folder, phpAsyncFolder }

        // createFolderRecursively (python2Folder)
        createFolderRecursively (python3Folder)
        createFolderRecursively (phpAsyncFolder)

        this.transpileCacheTest ()
        this.transpileOrderBookTest ()
        const classes = this.transpileDerivedExchangeFiles ('./js/ws/', options, pattern, force)

        if (classes === null) {
            log.bright.yellow ('0 files transpiled.')
            return;
        }

        // HINT: if we're going to support specific class definitions
        // this process won't work anymore as it will override the definitions
        this.exportTypeScriptDeclarations (tsFilename, classes)

        //*/

        this.transpileErrorHierarchy ({ tsFilename })

        // transpilePrecisionTests ()
        // transpileDateTimeTests ()
        // transpileCryptoTests ()

        log.bright.green ('Transpiled successfully.')
    }
}

// ============================================================================
// main entry point

if (require.main === module) {

    // if called directly like `node module`

    const transpiler = new CCXTProTranspiler ()
    const force = process.argv.includes ('--force')
    log.bright.green ({ force })
    transpiler.transpileEverything (force)

} else {

    // do nothing if required as a module
}

// ============================================================================

module.exports = CCXTProTranspiler
<commit_msg>php tests path<commit_after>// ---------------------------------------------------------------------------
// Usage: npm run transpileWs
// ---------------------------------------------------------------------------

"use strict";

const fs = require ('fs')
    , log = require ('ololog')
    , ansi = require ('ansicolor').nice
    , { unCamelCase, precisionConstants, safeString, unique } = require ('../js/base/functions.js')
    , {
        createFolderRecursively,
        overwriteFile,
        replaceInFile,
    } = require ('./fs.js')
    , errors = require ('../js/base/errors.js')
    , Transpiler = require ('./transpile.js')
    , Exchange = require ('../js/ws/base/Exchange.js')
    // , tsFilename = './ccxt.pro.d.ts'
    , tsFilename = './ccxt.d.ts'

// ============================================================================

class CCXTProTranspiler extends Transpiler {

    getBaseClass () {
        return new Exchange ()
    }

    getPHPPreamble () {
        return [
            "<?php",
            "namespace ccxtpro;",
            "include_once __DIR__ . '/../../../vendor/autoload.php';",
            "// ----------------------------------------------------------------------------",
            "",
            "// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:",
            "// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code",
            "",
            "// -----------------------------------------------------------------------------",
            "",
        ].join ("\n")
    }

    createPythonClassDeclaration (className, baseClass) {
        const baseClasses = (baseClass.indexOf ('Rest') >= 0) ?
            [ 'Exchange', baseClass ] :
            [ baseClass ]
        return 'class ' + className + '(' + baseClasses.join (', ') + '):'
    }

    createPythonClassImports (baseClass, async = false) {

        const baseClasses = {
            'Exchange': 'base.exchange',
        }

        async = (async ? '.async_support' : '')

        if (baseClass.indexOf ('Rest') >= 0) {
            baseClass = baseClass.replace ('Rest', '')
            return [
                'from ccxt.ws.base.exchange import Exchange',
                'from ccxt.rest.async_support.' + baseClass + ' import ' + baseClass + ' as ' + baseClass + 'Rest'
            ]
        } else {
            return [
                // 'from ccxt.rest.async_support.' + safeString (baseClasses, baseClass, baseClass) + ' import ' + baseClass
                'from ccxt.ws.' + baseClass + ' import ' + baseClass // on the JS side we add to append `Rest` to the base class name
            ]
        }
        // return [
        //     (baseClass.indexOf ('ccxt.') === 0) ?
        //         ('import ccxt' + async + ' as ccxt') :
        //         ('from ccxtpro.' + safeString (baseClasses, baseClass, baseClass) + ' import ' + baseClass)
        // ]
    }

    createPythonClassHeader (ccxtImports, bodyAsString) {
        const imports = [
            ... ccxtImports,
        ]
        const arrayCacheClasses = bodyAsString.match (/\bArrayCache(?:[A-Z][A-Za-z]+)?\b/g)
        if (arrayCacheClasses) {
            const uniqueArrayCacheClasses = unique (arrayCacheClasses).sort ()
            const arrayCacheImport = 'from ccxt.ws.base.cache import ' + uniqueArrayCacheClasses.join (', ')
            imports.push (arrayCacheImport)
        }
        return [
            "# -*- coding: utf-8 -*-",
            "",
            "# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:",
            "# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code",
            "",
            ... imports,
        ]
    }

    createPHPClassDeclaration (className, baseClass) {
        let lines = [
            'class ' + className + ' extends ' + '\\ccxt\\rest\\async\\' +  baseClass.replace ('Rest', '') + ' {',
        ]
        if (baseClass.indexOf ('Rest') >= 0) {
            lines = lines.concat ([
                '',
                '    use ClientTrait;'
            ])
        }
        return lines.join ("\n")
    }

    createPHPClassHeader (className, baseClass, bodyAsString) {
        return [
            "<?php",
            "",
            "namespace ccxtpro;",
            "",
            "// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:",
            "// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code",
            "",
            "use Exception; // a common import",
        ]
    }

    sortExchangeCapabilities (code) {
        return false
    }

    // ------------------------------------------------------------------------

    transpileOrderBookTest () {
        const jsFile = './js/ws/test/base/test.OrderBook.js'
        const pyFile = './python/ccxt/ws/test/test_order_book.py'
        const phpFile = './php/ws/test/OrderBook.php'
        const pyImports = [
            '',
            'from ccxt.ws.base.order_book import OrderBook, IndexedOrderBook, CountedOrderBook  # noqa: F402',
            '',
        ].join ('\n')
        this.transpileTest (jsFile, pyFile, phpFile, pyImports)
    }

    // ------------------------------------------------------------------------

    transpileCacheTest () {
        const jsFile = './js/ws/test/base/test.Cache.js'
        const pyFile = './python/ccxt/ws/test/test_cache.py'
        const phpFile = './php/ws/test/Cache.php'
        const pyImports = [
            '',
            'from ccxt.ws.base.cache import ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById  # noqa: F402',
            '',
        ].join ('\n')
        this.transpileTest (jsFile, pyFile, phpFile, pyImports)
    }

    // ------------------------------------------------------------------------

    transpileTest (jsFile, pyFile, phpFile, pyImports) {

        log.magenta ('Transpiling from', jsFile.yellow)

        let js = fs.readFileSync (jsFile).toString ()

        js = this.regexAll (js, [
            [ /\'use strict\';?\s+/g, '' ],
            [ /[^\n]+require[^\n]+\n/g, '' ],
            [ /function equals \([\S\s]+?return true;\n}\n/g, '' ],
        ])

        const options = { js, removeEmptyLines: false }
        const transpiled = this.transpileJavaScriptToPythonAndPHP (options)
        const { python3Body, python2Body, phpBody } = transpiled
        const pythonHeader = [
            '',
            '',
            'def equals(a, b):',
            '    return a == b',
            '',
        ].join ('\n')

        const phpHeader = [
            '',
            'function equals($a, $b) {',
            '    return json_encode($a) === json_encode($b);',
            '}',
        ].join ('\n')

        const python = this.getPythonPreamble () + pyImports + pythonHeader + python2Body
        const php = this.getPHPPreamble () + phpHeader + phpBody

        log.magenta ('→', pyFile.yellow)
        log.magenta ('→', phpFile.yellow)

        overwriteFile (pyFile, python)
        overwriteFile (phpFile, php)
    }

    // ------------------------------------------------------------------------

    transpileEverything (force = false) {

        // default pattern is '.js'
        const [ /* node */, /* script */, pattern ] = process.argv.filter (x => !x.startsWith ('--'))
            // , python2Folder = './python/ccxtpro/', // CCXT Pro does not support Python 2
            , python3Folder = './python/ccxt/ws/'
            , phpAsyncFolder     = './php/ws/'
            , options = { /* python2Folder, */ python3Folder, phpAsyncFolder }

        // createFolderRecursively (python2Folder)
        createFolderRecursively (python3Folder)
        createFolderRecursively (phpAsyncFolder)

        this.transpileCacheTest ()
        this.transpileOrderBookTest ()
        const classes = this.transpileDerivedExchangeFiles ('./js/ws/', options, pattern, force)

        if (classes === null) {
            log.bright.yellow ('0 files transpiled.')
            return;
        }

        // HINT: if we're going to support specific class definitions
        // this process won't work anymore as it will override the definitions
        this.exportTypeScriptDeclarations (tsFilename, classes)

        //*/

        this.transpileErrorHierarchy ({ tsFilename })

        // transpilePrecisionTests ()
        // transpileDateTimeTests ()
        // transpileCryptoTests ()

        log.bright.green ('Transpiled successfully.')
    }
}

// ============================================================================
// main entry point

if (require.main === module) {

    // if called directly like `node module`

    const transpiler = new CCXTProTranspiler ()
    const force = process.argv.includes ('--force')
    log.bright.green ({ force })
    transpiler.transpileEverything (force)

} else {

    // do nothing if required as a module
}

// ============================================================================

module.exports = CCXTProTranspiler
<|endoftext|>


<commit_before>(function() {

	if (!$.Lacuna.Game || typeof($.Lacuna.Game) === 'undefined') {

		$.Lacuna.Game = {
			BuildMainScreen: function() {
				// The Main screen doesn't contain very much. For the
				// moment, I'll only do the buildings view.

				$('#lacuna').html([
					'
',
					'
',
					'
',
					'
'
				].join(''))

				// Now for the fun stuff.
				this.GetBuildings($.Lacuna.GameData.Status.empire.home_planet_id);
			},

			GetBuildings: function(planetId) {

				$.Lacuna.send({
					module: '/body',
					method: 'get_buildings',
					params: [
						$.Lacuna.GetSession(),
						planetId
					],

					success: function(o) {
						var buildings = o.result.buildings,
							body      = o.result.body;
							keys      = Object.keys(buildings),
							content   = [];

						for (var i = 0; i < keys.length; i++) {
							var buildingId = keys[i],
								building   = buildings[buildingId];

							content[content.length] = [
								'
',
								'
'
							].join('');
						}

						$('#lacuna').css({
							'background-image' : 'url(\'' + window.assetsUrl + '/planet_side/' + body.surface_image + '.jpg\')'
						});
						$('#buildingsParent').html([
							'
',
								content.join(''),
							'
'
						].join('')).ready(function() {
							$('#buildingsDraggableChild').draggable({
								scroll: false
							});
						});
					}
				});
			}
		};
	}
})();<commit_msg>Redoing the buildings interface for future work.<commit_after>(function() {

	if (!$.Lacuna.Game || typeof($.Lacuna.Game) === 'undefined') {

		$.Lacuna.Game = {
			BuildMainScreen: function() {
				// The Main screen doesn't contain very much. For the
				// moment, I'll only do the buildings view.

				$('#lacuna').html([
					'
',
					'
',
					'
',
					'
'
				].join(''))

				// Now for the fun stuff.
				this.getBuildings($.Lacuna.GameData.Status.empire.home_planet_id);
			},

			getBuildings: function(id) {
				var buildingsTemplate = [];
				for (var x = -5; x < 6; x++) {
					for (var y = -5; y < 6; y++) {
						buildingsTemplate[buildingsTemplate.length] = [
							'
',
							'
'
						].join('');
					}
				}
				//console.log(buildingsTemplate.join('\n'));//debug

				// Send it to the DOM.
				$('#buildingsParent').html([
					'
',
					buildingsTemplate.join(''),
					'
'
				].join(''));

				// Right, now that that's out of the way, onward we must go...
				$.Lacuna.send({
					module: '/body',
					method: 'get_buildings',
					params: [
						$.Lacuna.GetSession(),
						id
					],

					success: function(o) {
						var buildings = o.result.buildings,
							body      = o.result.body;
							keys      = Object.keys(buildings),
							content   = [];

						for (var i = 0; i < keys.length; i++) {
							var buildingId = keys[i],
								building   = buildings[buildingId]
								el         = $('#plot_' + parseInt(building.x) + '_' + parseInt(building.y));

							// Woopsie! Long line alert!!
							el.css('background', 'url(\'' + window.assetsUrl + '/planet_side/100/' + building.image + '.png\') no-repeat transparent');
							el.attr('title', building.name);
						}

						$('#lacuna').css({
							'background-image' : 'url(\'' + window.assetsUrl + '/planet_side/' + body.surface_image + '.jpg\')'
						});

						// Start the Draggable.
						$('#buildingsDraggableChild').draggable({
							scroll: false
						});
					}
				});
			}
		};
	}
})();<|endoftext|>