<commit_before>/* global LocusZoom,d3 */
/* eslint-env browser */
/* eslint-disable no-console */

"use strict";

/**

  LocusZoom.Panel Class

  A panel is an abstract class representing a subdivision of the LocusZoom stage
  to display a distinct data representation

*/

LocusZoom.Panel = function() {

    this.id     = null;
    this.parent = null;
    this.svg    = null;

    this.view = {
        width:  0,
        height: 0,
        origin: { x: 0, y: 0 },
        margin: { top: 0, right: 0, bottom: 0, left: 0 },
        cliparea: {
            width: 0,
            height: 0,
            origin: { x: 0, y: 0 }
        }
    };

    this.state = {};

    this._data_layers = {};
    this.data_layer_ids_by_z_index = [];
    this.data_promises = [];

    this.axes = {
        x:  { render:        false,
              ticks:         [],
              label:         null },
        y1: { render:        false,
              data_layer_id: null,
              ticks:         [],
              label:         null },
        y2: { render:        false,
              data_layer_id: null,
              ticks:         [],
              label:         null }
    };

    this.xExtent  = null;
    this.y1Extent = null;
    this.y2Extent = null;

    this.renderData = function(){};

    this.getBaseId = function(){
        return this.parent.id + "." + this.id;
    };

    return this;

};

LocusZoom.Panel.prototype.setDimensions = function(width, height){
    if (typeof width  !== "undefined"){ this.view.width  = +width;  }
    if (typeof height !== "undefined"){ this.view.height = +height; }
    this.view.cliparea.width = this.view.width - (this.view.margin.left + this.view.margin.right);
    this.view.cliparea.height = this.view.height - (this.view.margin.top + this.view.margin.bottom);
    return this;
};

LocusZoom.Panel.prototype.setOrigin = function(x, y){
    if (typeof x !== "undefined"){ this.view.origin.x = +x; }
    if (typeof y !== "undefined"){ this.view.origin.y = +y; }
    return this;
};

LocusZoom.Panel.prototype.setMargin = function(top, right, bottom, left){
    if (typeof top    !== "undefined"){ this.view.margin.top    = +top;    }
    if (typeof right  !== "undefined"){ this.view.margin.right  = +right;  }
    if (typeof bottom !== "undefined"){ this.view.margin.bottom = +bottom; }
    if (typeof left   !== "undefined"){ this.view.margin.left   = +left;   }
    this.view.cliparea.width = this.view.width - (this.view.margin.left + this.view.margin.right);
    this.view.cliparea.height = this.view.height - (this.view.margin.top + this.view.margin.bottom);
    this.view.cliparea.origin.x = this.view.margin.left;
    this.view.cliparea.origin.y = this.view.margin.top;
    return this;
};

// Initialize a panel
LocusZoom.Panel.prototype.initialize = function(){

    // Append a container group element to house the main panel group element and the clip path
    var container = this.parent.svg.append("g")
        .attr("id", this.getBaseId() + ".panel_container")
        .attr("transform", "translate(" + this.view.origin.x +  "," + this.view.origin.y + ")");

    // Append clip path to the parent svg element
    container.append("clipPath")
        .attr("id", this.getBaseId() + ".clip")
        .append("rect")
        .attr("width", this.view.width)
        .attr("height", this.view.height);

    // Append svg group for rendering all panel child elements, clipped by the clip path
    this.svg = container.append("g")
        .attr("id", this.getBaseId() + ".panel")
        .attr("clip-path", "url(#" + this.getBaseId() + ".clip)");

    // Initialize child Data Layers
    for (var id in this._data_layers){
        this._data_layers[id].initialize();
    }

    // Initialize Axes
    if (this.axes.x.render){
        this.state.x_scale = d3.scale.linear().domain([0,1]).range([0, this.view.cliparea.width]);
        this.state.x_axis  = d3.svg.axis().scale(this.state.x_scale).orient("bottom");
        this.svg.append("g")
            .attr("class", "lz-x lz-axis")
            .attr("transform", "translate(" + this.view.margin.left + "," + (this.view.height - this.view.margin.bottom) + ")")
            .call(this.state.x_axis);
    }
    if (this.axes.y1.render){
        this.state.y1_scale = d3.scale.linear().domain([0,1]).range([this.view.cliparea.height, 0]).nice();
        this.state.y1_axis  = d3.svg.axis().scale(this.state.y1_scale).orient("left");
        this.svg.append("g")
            .attr("class", "lz-y lz-y1 lz-axis")
            .attr("transform", "translate(" + this.view.margin.left + "," + this.view.margin.top + ")")
            .call(this.state.y1_axis);
    }
    if (this.axes.y2.render){
        this.state.y2_scale = d3.scale.linear().domain([0,1]).range([this.view.cliparea.height, 0]).nice();
        this.state.y2_axis  = d3.svg.axis().scale(this.state.y2_scale).orient("right");
        this.svg.append("g")
            .attr("class", "lz-y lz-y2 lz-axis")
            .attr("transform", "translate(" + (this.view.width - this.view.margin.right) + "," + this.view.margin.top + ")")
            .call(this.state.y2_axis);
    }

    return this;

};

// Create a new data layer by data layer class
LocusZoom.Panel.prototype.addDataLayer = function(DataLayerClass){
    if (typeof DataLayerClass !== "function"){
        return false;
    }
    var data_layer = new DataLayerClass();
    data_layer.parent = this;
    this._data_layers[data_layer.id] = data_layer;
    this.data_layer_ids_by_z_index.push(data_layer.id);
    return this._data_layers[data_layer.id];
};

// Re-Map a panel to new positions according to the parent instance's state
LocusZoom.Panel.prototype.reMap = function(){
    this.data_promises = [];
    // Trigger reMap on each Data Layer
    for (var id in this._data_layers){
        this.data_promises.push(this._data_layers[id].reMap());
    }
    // When all finished trigger a render
    Promise.all(this.data_promises).then(function(){
        this.render();
    }.bind(this));
    return this;
};

// Render a given panel
LocusZoom.Panel.prototype.render = function(){

    // Generate extents and scales.
    if (typeof this.xExtent == "function"){
        this.state.x_extent = this.xExtent();
        this.axes.x.ticks = LocusZoom.prettyTicks(this.state.x_extent, this.view.cliparea.width/120, true);
        this.state.x_scale = d3.scale.linear()
            .domain([this.state.x_extent[0], this.state.x_extent[1]])
            .range([0, this.view.cliparea.width]);
    }
    // Pad out y scales for pretty ticks, regardless of axis rendering
    if (typeof this.y1Extent == "function"){
        this.state.y1_extent = this.y1Extent();
        this.axes.y1.ticks = LocusZoom.prettyTicks(this.state.y1_extent);
        this.state.y1_scale = d3.scale.linear()
            .domain([this.axes.y1.ticks[0], this.axes.y1.ticks[this.axes.y1.ticks.length-1]])
            .range([this.view.cliparea.height, 0]);
    }
    if (typeof this.y2Extent == "function"){
        this.state.y2_extent = this.y2Extent();
        this.axes.y2.ticks = LocusZoom.prettyTicks(this.state.y2_extent);
        this.state.y2_scale = d3.scale.linear()
            .domain([this.axes.y2.ticks[0], this.axes.y1.ticks[this.axes.y2.ticks.length-1]])
            .range([this.view.cliparea.height, 0]);
    }

    // Render axes and labels
    if (this.axes.x.render){
        this.state.x_axis = d3.svg.axis()
            .scale(this.state.x_scale)
            .orient("bottom")
            .tickValues(this.axes.x.ticks)
            .tickFormat(function(d) { return LocusZoom.formatMegabase(d); });
        this.svg.selectAll("g .lz-x.lz-axis").call(this.state.x_axis);
        if (this.axes.x.label != null){
            var x_label = this.axes.x.label;
            if (typeof this.axes.x.label == "function"){
                x_label = this.axes.x.label();
            }
            if (this.svg.select("text.lz-x.lz-axis.lz-label")[0][0] == null){
                this.svg.select("g .lz-x.lz-axis").append("text")
                    .attr("class", "lz-x lz-axis lz-label")
                    .attr("text-anchor", "middle")
                    .attr("x", this.view.cliparea.width / 2)
                    .attr("y", 33);
            }
            this.svg.select("text.lz-x.lz-axis.lz-label").text(x_label);
        }
    }

    if (this.axes.y1.render){
        this.state.y1_axis = d3.svg.axis().scale(this.state.y1_scale)
            .orient("left").tickValues(this.axes.y1.ticks);
        this.svg.selectAll("g .lz-y.lz-y1.lz-axis").call(this.state.y1_axis);
        if (this.axes.y1.label != null){
            var y1_label = this.axes.y1.label;
            if (typeof this.axes.y1.label == "function"){
                y1_label = this.axes.y1.label();
            }
            if (this.svg.select("text.lz-y1.lz-axis.lz-label")[0][0] == null){
                this.svg.select("g .lz-y1.lz-axis").append("text")
                    .attr("class", "lz-y1 lz-axis lz-label")
                    .attr("text-anchor", "middle")
                    .attr("transform", "rotate(-90 " + -28 + "," + (this.view.cliparea.height / 2) + ")")
                    .attr("x", -28)
                    .attr("y", this.view.cliparea.height / 2);
            }
            this.svg.select("text.lz-y1.lz-axis.lz-label").text(y1_label);
        }
    }

    if (this.axes.y2.render){
        this.state.y2_axis  = d3.svg.axis().scale(this.state.y2_scale)
            .orient("left").tickValues(this.axes.y2.ticks);
        this.svg.selectAll("g .lz-y.lz-y2.lz-axis").call(this.state.y2_axis);
    }

    // Render data layers by z-index
    for (var z_index in this.data_layer_ids_by_z_index){
        if (this.data_layer_ids_by_z_index.hasOwnProperty(z_index)){
            this._data_layers[this.data_layer_ids_by_z_index[z_index]].prerender().render();
        }
    }

    return this;

    // Set zoom
    /*
    this.view.zoom = d3.behavior.zoom()
        .scaleExtent([1, 1])
        .x(this.view.xscale)
        .on("zoom", function() {
            svg.select(".datum").attr("d", line)
            console.log("zooming");
        });
    this.svg.call(this.view.zoom);
    */

    // Set drag
    /*
    this.drag = d3.behavior.drag()
        .on("drag", function() {
            var stage = d3.select("#"+this.id+" g.stage");
            var transform = d3.transform(stage.attr("transform"));
            transform.translate[0] += d3.event.dx;
            stage.attr("transform", transform.toString());
        }).on("dragend", function() {
            // mapTo new values
        });
    this.svg.call(this.drag);
    */

};

/*****************
  Positions Panel
*/

LocusZoom.PositionsPanel = function(){

    LocusZoom.Panel.apply(this, arguments);
    this.id = "positions";

    this.axes.x.render = true;
    this.axes.x.label = function(){
        return "Chromosome " + this.parent.state.chr + " (Mb)";
    }.bind(this);

    this.axes.y1.render = true;
    this.axes.y1.label = "-log10 p-value";

    this.xExtent = function(){
        return d3.extent(this._data_layers.positions.data, function(d) { return +d.position; } );
    };

    this.y1Extent = function(){
        return d3.extent(this._data_layers.positions.data, function(d) { return +d.log10pval * 1.05; } );
    };

    return this;
};

LocusZoom.PositionsPanel.prototype = new LocusZoom.Panel();

/*************
  Genes Panel
*/

LocusZoom.GenesPanel = function(){

    LocusZoom.Panel.apply(this, arguments);
    this.id = "genes";

    this.xExtent = function(){
        return d3.extent([this.parent.state.start, this.parent.state.end]);
    };

    return this;
};

LocusZoom.GenesPanel.prototype = new LocusZoom.Panel();
<commit_msg>replace Promise with Q for cross-browser compatibility<commit_after>/* global LocusZoom,d3 */
/* eslint-env browser */
/* eslint-disable no-console */

"use strict";

/**

  LocusZoom.Panel Class

  A panel is an abstract class representing a subdivision of the LocusZoom stage
  to display a distinct data representation

*/

LocusZoom.Panel = function() {

    this.id     = null;
    this.parent = null;
    this.svg    = null;

    this.view = {
        width:  0,
        height: 0,
        origin: { x: 0, y: 0 },
        margin: { top: 0, right: 0, bottom: 0, left: 0 },
        cliparea: {
            width: 0,
            height: 0,
            origin: { x: 0, y: 0 }
        }
    };

    this.state = {};

    this._data_layers = {};
    this.data_layer_ids_by_z_index = [];
    this.data_promises = [];

    this.axes = {
        x:  { render:        false,
              ticks:         [],
              label:         null },
        y1: { render:        false,
              data_layer_id: null,
              ticks:         [],
              label:         null },
        y2: { render:        false,
              data_layer_id: null,
              ticks:         [],
              label:         null }
    };

    this.xExtent  = null;
    this.y1Extent = null;
    this.y2Extent = null;

    this.renderData = function(){};

    this.getBaseId = function(){
        return this.parent.id + "." + this.id;
    };

    return this;

};

LocusZoom.Panel.prototype.setDimensions = function(width, height){
    if (typeof width  !== "undefined"){ this.view.width  = +width;  }
    if (typeof height !== "undefined"){ this.view.height = +height; }
    this.view.cliparea.width = this.view.width - (this.view.margin.left + this.view.margin.right);
    this.view.cliparea.height = this.view.height - (this.view.margin.top + this.view.margin.bottom);
    return this;
};

LocusZoom.Panel.prototype.setOrigin = function(x, y){
    if (typeof x !== "undefined"){ this.view.origin.x = +x; }
    if (typeof y !== "undefined"){ this.view.origin.y = +y; }
    return this;
};

LocusZoom.Panel.prototype.setMargin = function(top, right, bottom, left){
    if (typeof top    !== "undefined"){ this.view.margin.top    = +top;    }
    if (typeof right  !== "undefined"){ this.view.margin.right  = +right;  }
    if (typeof bottom !== "undefined"){ this.view.margin.bottom = +bottom; }
    if (typeof left   !== "undefined"){ this.view.margin.left   = +left;   }
    this.view.cliparea.width = this.view.width - (this.view.margin.left + this.view.margin.right);
    this.view.cliparea.height = this.view.height - (this.view.margin.top + this.view.margin.bottom);
    this.view.cliparea.origin.x = this.view.margin.left;
    this.view.cliparea.origin.y = this.view.margin.top;
    return this;
};

// Initialize a panel
LocusZoom.Panel.prototype.initialize = function(){

    // Append a container group element to house the main panel group element and the clip path
    var container = this.parent.svg.append("g")
        .attr("id", this.getBaseId() + ".panel_container")
        .attr("transform", "translate(" + this.view.origin.x +  "," + this.view.origin.y + ")");

    // Append clip path to the parent svg element
    container.append("clipPath")
        .attr("id", this.getBaseId() + ".clip")
        .append("rect")
        .attr("width", this.view.width)
        .attr("height", this.view.height);

    // Append svg group for rendering all panel child elements, clipped by the clip path
    this.svg = container.append("g")
        .attr("id", this.getBaseId() + ".panel")
        .attr("clip-path", "url(#" + this.getBaseId() + ".clip)");

    // Initialize child Data Layers
    for (var id in this._data_layers){
        this._data_layers[id].initialize();
    }

    // Initialize Axes
    if (this.axes.x.render){
        this.state.x_scale = d3.scale.linear().domain([0,1]).range([0, this.view.cliparea.width]);
        this.state.x_axis  = d3.svg.axis().scale(this.state.x_scale).orient("bottom");
        this.svg.append("g")
            .attr("class", "lz-x lz-axis")
            .attr("transform", "translate(" + this.view.margin.left + "," + (this.view.height - this.view.margin.bottom) + ")")
            .call(this.state.x_axis);
    }
    if (this.axes.y1.render){
        this.state.y1_scale = d3.scale.linear().domain([0,1]).range([this.view.cliparea.height, 0]).nice();
        this.state.y1_axis  = d3.svg.axis().scale(this.state.y1_scale).orient("left");
        this.svg.append("g")
            .attr("class", "lz-y lz-y1 lz-axis")
            .attr("transform", "translate(" + this.view.margin.left + "," + this.view.margin.top + ")")
            .call(this.state.y1_axis);
    }
    if (this.axes.y2.render){
        this.state.y2_scale = d3.scale.linear().domain([0,1]).range([this.view.cliparea.height, 0]).nice();
        this.state.y2_axis  = d3.svg.axis().scale(this.state.y2_scale).orient("right");
        this.svg.append("g")
            .attr("class", "lz-y lz-y2 lz-axis")
            .attr("transform", "translate(" + (this.view.width - this.view.margin.right) + "," + this.view.margin.top + ")")
            .call(this.state.y2_axis);
    }

    return this;

};

// Create a new data layer by data layer class
LocusZoom.Panel.prototype.addDataLayer = function(DataLayerClass){
    if (typeof DataLayerClass !== "function"){
        return false;
    }
    var data_layer = new DataLayerClass();
    data_layer.parent = this;
    this._data_layers[data_layer.id] = data_layer;
    this.data_layer_ids_by_z_index.push(data_layer.id);
    return this._data_layers[data_layer.id];
};

// Re-Map a panel to new positions according to the parent instance's state
LocusZoom.Panel.prototype.reMap = function(){
    this.data_promises = [];
    // Trigger reMap on each Data Layer
    for (var id in this._data_layers){
        this.data_promises.push(this._data_layers[id].reMap());
    }
    // When all finished trigger a render
    Q.all(this.data_promises).then(function(){
        this.render();
    }.bind(this));
    return this;
};

// Render a given panel
LocusZoom.Panel.prototype.render = function(){

    // Generate extents and scales.
    if (typeof this.xExtent == "function"){
        this.state.x_extent = this.xExtent();
        this.axes.x.ticks = LocusZoom.prettyTicks(this.state.x_extent, this.view.cliparea.width/120, true);
        this.state.x_scale = d3.scale.linear()
            .domain([this.state.x_extent[0], this.state.x_extent[1]])
            .range([0, this.view.cliparea.width]);
    }
    // Pad out y scales for pretty ticks, regardless of axis rendering
    if (typeof this.y1Extent == "function"){
        this.state.y1_extent = this.y1Extent();
        this.axes.y1.ticks = LocusZoom.prettyTicks(this.state.y1_extent);
        this.state.y1_scale = d3.scale.linear()
            .domain([this.axes.y1.ticks[0], this.axes.y1.ticks[this.axes.y1.ticks.length-1]])
            .range([this.view.cliparea.height, 0]);
    }
    if (typeof this.y2Extent == "function"){
        this.state.y2_extent = this.y2Extent();
        this.axes.y2.ticks = LocusZoom.prettyTicks(this.state.y2_extent);
        this.state.y2_scale = d3.scale.linear()
            .domain([this.axes.y2.ticks[0], this.axes.y1.ticks[this.axes.y2.ticks.length-1]])
            .range([this.view.cliparea.height, 0]);
    }

    // Render axes and labels
    if (this.axes.x.render){
        this.state.x_axis = d3.svg.axis()
            .scale(this.state.x_scale)
            .orient("bottom")
            .tickValues(this.axes.x.ticks)
            .tickFormat(function(d) { return LocusZoom.formatMegabase(d); });
        this.svg.selectAll("g .lz-x.lz-axis").call(this.state.x_axis);
        if (this.axes.x.label != null){
            var x_label = this.axes.x.label;
            if (typeof this.axes.x.label == "function"){
                x_label = this.axes.x.label();
            }
            if (this.svg.select("text.lz-x.lz-axis.lz-label")[0][0] == null){
                this.svg.select("g .lz-x.lz-axis").append("text")
                    .attr("class", "lz-x lz-axis lz-label")
                    .attr("text-anchor", "middle")
                    .attr("x", this.view.cliparea.width / 2)
                    .attr("y", 33);
            }
            this.svg.select("text.lz-x.lz-axis.lz-label").text(x_label);
        }
    }

    if (this.axes.y1.render){
        this.state.y1_axis = d3.svg.axis().scale(this.state.y1_scale)
            .orient("left").tickValues(this.axes.y1.ticks);
        this.svg.selectAll("g .lz-y.lz-y1.lz-axis").call(this.state.y1_axis);
        if (this.axes.y1.label != null){
            var y1_label = this.axes.y1.label;
            if (typeof this.axes.y1.label == "function"){
                y1_label = this.axes.y1.label();
            }
            if (this.svg.select("text.lz-y1.lz-axis.lz-label")[0][0] == null){
                this.svg.select("g .lz-y1.lz-axis").append("text")
                    .attr("class", "lz-y1 lz-axis lz-label")
                    .attr("text-anchor", "middle")
                    .attr("transform", "rotate(-90 " + -28 + "," + (this.view.cliparea.height / 2) + ")")
                    .attr("x", -28)
                    .attr("y", this.view.cliparea.height / 2);
            }
            this.svg.select("text.lz-y1.lz-axis.lz-label").text(y1_label);
        }
    }

    if (this.axes.y2.render){
        this.state.y2_axis  = d3.svg.axis().scale(this.state.y2_scale)
            .orient("left").tickValues(this.axes.y2.ticks);
        this.svg.selectAll("g .lz-y.lz-y2.lz-axis").call(this.state.y2_axis);
    }

    // Render data layers by z-index
    for (var z_index in this.data_layer_ids_by_z_index){
        if (this.data_layer_ids_by_z_index.hasOwnProperty(z_index)){
            this._data_layers[this.data_layer_ids_by_z_index[z_index]].prerender().render();
        }
    }

    return this;

    // Set zoom
    /*
    this.view.zoom = d3.behavior.zoom()
        .scaleExtent([1, 1])
        .x(this.view.xscale)
        .on("zoom", function() {
            svg.select(".datum").attr("d", line)
            console.log("zooming");
        });
    this.svg.call(this.view.zoom);
    */

    // Set drag
    /*
    this.drag = d3.behavior.drag()
        .on("drag", function() {
            var stage = d3.select("#"+this.id+" g.stage");
            var transform = d3.transform(stage.attr("transform"));
            transform.translate[0] += d3.event.dx;
            stage.attr("transform", transform.toString());
        }).on("dragend", function() {
            // mapTo new values
        });
    this.svg.call(this.drag);
    */

};

/*****************
  Positions Panel
*/

LocusZoom.PositionsPanel = function(){

    LocusZoom.Panel.apply(this, arguments);
    this.id = "positions";

    this.axes.x.render = true;
    this.axes.x.label = function(){
        return "Chromosome " + this.parent.state.chr + " (Mb)";
    }.bind(this);

    this.axes.y1.render = true;
    this.axes.y1.label = "-log10 p-value";

    this.xExtent = function(){
        return d3.extent(this._data_layers.positions.data, function(d) { return +d.position; } );
    };

    this.y1Extent = function(){
        return d3.extent(this._data_layers.positions.data, function(d) { return +d.log10pval * 1.05; } );
    };

    return this;
};

LocusZoom.PositionsPanel.prototype = new LocusZoom.Panel();

/*************
  Genes Panel
*/

LocusZoom.GenesPanel = function(){

    LocusZoom.Panel.apply(this, arguments);
    this.id = "genes";

    this.xExtent = function(){
        return d3.extent([this.parent.state.start, this.parent.state.end]);
    };

    return this;
};

LocusZoom.GenesPanel.prototype = new LocusZoom.Panel();
<|endoftext|>


<commit_before>var filepath = 'config/customcolors.json';
var customColors = {};
var fs = require('fs');
var request = require('request');
var path = require('path');

function load () {
        fs.readFile(filepath, 'utf8', function (err, file) {
                if (err) return;
                customColors = JSON.parse(file);
        });
}
load();

/*function logMoney(message) {
       if (!message) return;
       var file = path.join(__dirname, '../logs/money.txt');
       var date = "[" + new Date().toUTCString() + "] ";
       var msg = message + "\n";
       fs.appendFile(file, date + msg);
}*/

function updateColor() {
        fs.writeFileSync(filepath, JSON.stringify(customColors));

        var newCss = '/* COLORS START */\n';

        for (var name in customColors) {
                newCss += generateCSS(name, customColors[name]);
        }
        newCss += '/* COLORS END */\n';

        var file = fs.readFileSync('config/custom.css', 'utf8').split('\n');
        if (~file.indexOf('/* COLORS START */')) file.splice(file.indexOf('/* COLORS START */'), (file.indexOf('/* COLORS END */') - file.indexOf('/* COLORS START */')) + 1);
        fs.writeFileSync('config/custom.css', file.join('\n') + newCss);
        request('http://play.pokemonshowdown.com/customcss.php?server=skypillar&invalidate', function callback(error, res, body) {
                if (error) return console.log('updateColor error: ' + error);
        });
}
global.updateColor = updateColor;

function generateCSS(name, color) {
        var css = '';
        var rooms = [];
        name = toId(name);
        for (var room in Rooms.rooms) {
                if (Rooms.rooms[room].id === 'global' || Rooms.rooms[room].type !== 'chat' || Rooms.rooms[room].isPersonal) continue;
                rooms.push('#' + Rooms.rooms[room].id + '-userlist-user-' + name + ' strong em');
                rooms.push('#' + Rooms.rooms[room].id + '-userlist-user-' + name + ' strong');
                rooms.push('#' + Rooms.rooms[room].id + '-userlist-user-' + name + ' span');
        }
        css = rooms.join(', ');
        css += '{\ncolor: ' + color + ' !important;\n}\n';
        css += '.chat.chatmessage-' + name + ' strong {\n';
        css += 'color: ' + color + ' !important;\n}\n';
        return css;
}

exports.commands = {
        customcolor: function (target, room, user) {
                if (!this.can('hotpatch')) return false;
                target = target.split(',');
                for (var u in target) target[u] = target[u].trim();
                if (!target[1]) return this.parse('/help customcolor');
                if (toId(target[0]).length > 19) return this.errorReply("Usernames are not this long...");
                if (target[1] === 'delete') {
                        if (!customColors[toId(target[0])]) return this.errorReply('/customcolor - ' + target[0] + ' does not have a custom color.');
                        delete customColors[toId(target[0])];
                        updateColor();
                        this.sendReply("You removed " + target[0] + "'s custom color.");
                        if (Users(target[0]) && Users(target[0]).connected) Users(target[0]).popup(user.name + " removed your custom color.");
                        return;
                }

                this.sendReply("|raw|You have given " + Tools.escapeHTML(target[0]) + " a custom color.");
                //logMoney(user.name + " le ha asignado un color personalizado a " + target[0] + ". (Color: " + target[1] + ").");
                customColors[toId(target[0])] = target[1];
                updateColor();
        },
        customcolorhelp: ["Commands Include:",
                                "/customcolor [user], [hex] - Gives [user] a custom color of [hex]",
                                "/customcolor [user], delete - Deletes a user's custom color"],

        cp: 'colorpreview',
        colorpreview: function (target, room, user) {
                if (!this.canBroadcast()) return;
                target = target.split(',');
                for (var u in target) target[u] = target[u].trim();
                if (!target[1]) return this.parse('/help colorpreview');
                return this.sendReplyBox('' + Tools.escapeHTML(target[0]) + '');
        },
        colorpreviewhelp: ["Usage: /colorpreview [user], [color] - Previews what that username looks like with [color] as the color."],
};

/* Pokemon Showdown hashColor function
 * This gives the color of a username
 * based on the userid.
*/

var MD5 = require('MD5');
var colorCache = {};

// hashColor function
function hashColor(name) {
        name = toId(name);
        if (customColors[name]) return customColors[name];
        if (colorCache[name]) return colorCache[name];
        var hash = MD5(name);
        var H = parseInt(hash.substr(4, 4), 16) % 360; // 0 to 360
        var S = parseInt(hash.substr(0, 4), 16) % 50 + 40; // 40 to 89
        var L = Math.floor(parseInt(hash.substr(8, 4), 16) % 20 + 30); // 30 to 49
        var C = (100 - Math.abs(2 * L - 100)) * S / 100 / 100;
        var X = C * (1 - Math.abs((H / 60) % 2 - 1));
        var m = L / 100 - C / 2;

        var R1, G1, B1;
        switch (Math.floor(H / 60)) {
                case 1: R1 = X; G1 = C; B1 = 0; break;
                case 2: R1 = 0; G1 = C; B1 = X; break;
                case 3: R1 = 0; G1 = X; B1 = C; break;
                case 4: R1 = X; G1 = 0; B1 = C; break;
                case 5: R1 = C; G1 = 0; B1 = X; break;
                case 0: default: R1 = C; G1 = X; B1 = 0; break;
        }
        var lum = (R1 + m) * 0.2126 + (G1 + m) * 0.7152 + (B1 + m) * 0.0722; // 0.05 (dark blue) to 0.93 (yellow)
        var HLmod = (lum - 0.5) * -100; // -43 (yellow) to 45 (dark blue)
        if (HLmod > 12) HLmod -= 12;
        else if (HLmod < -10) HLmod = (HLmod + 10) * 2 / 3;
        else HLmod = 0;

        L += HLmod;
        var Smod = 10 - Math.abs(50 - L);
        if (HLmod > 15) Smod += (HLmod - 15) / 2;
        S -= Smod;

        var rgb = hslToRgb(H, S, L);
        colorCache[name] = "#" + rgbToHex(rgb.r, rgb.g, rgb.b);
        return colorCache[name];
}
global.hashColorWithCustoms = hashColor;

function hslToRgb(h, s, l) {
        var r, g, b, m, c, x;
        if (!isFinite(h)) h = 0;
        if (!isFinite(s)) s = 0;
        if (!isFinite(l)) l = 0;
        h /= 60;
        if (h < 0) h = 6 - (-h % 6);
        h %= 6;
        s = Math.max(0, Math.min(1, s / 100));
        l = Math.max(0, Math.min(1, l / 100));
        c = (1 - Math.abs((2 * l) - 1)) * s;
        x = c * (1 - Math.abs((h % 2) - 1));
        if (h < 1) {
                r = c;
                g = x;
                b = 0;
        } else if (h < 2) {
                r = x;
                g = c;
                b = 0;
        } else if (h < 3) {
                r = 0;
                g = c;
                b = x;
        } else if (h < 4) {
                r = 0;
                g = x;
                b = c;
        } else if (h < 5) {
                r = x;
                g = 0;
                b = c;
        } else {
                r = c;
                g = 0;
                b = x;
        }
        m = l - c / 2;
        r = Math.round((r + m) * 255);
        g = Math.round((g + m) * 255);
        b = Math.round((b + m) * 255);
        return {
                r: r,
                g: g,
                b: b,
        };
}

function rgbToHex(R, G, B) {
        return toHex(R) + toHex(G) + toHex(B);
}

function toHex(N) {
        if (N == null) return "00";
        N = parseInt(N);
        if (N == 0 || isNaN(N)) return "00";
        N = Math.max(0, N);
        N = Math.min(N, 255);
        N = Math.round(N);
        return "0123456789ABCDEF".charAt((N - N % 16) / 16) + "0123456789ABCDEF".charAt(N % 16);
}
<commit_msg>Update hashcolor.js<commit_after>/**
 * Hashcolor file.
 *
 * Credits go to:
 * - panpawn and jd
 */

'use strict';

let fs = require('fs');
let path = require('path');
let https = require('https');
let request = require('request');

let customColors = {};
const FILE_PATH = 'config/customcolors.json';

function load () {
        fs.readFile(FILE_PATH, 'utf8', (err, file) => {
                if (err) return;
                customColors = JSON.parse(file);
        });
}
load();

/*function logMoney(message) {
       if (!message) return;
       var file = path.join(__dirname, '../logs/money.txt');
       var date = "[" + new Date().toUTCString() + "] ";
       var msg = message + "\n";
       fs.appendFile(file, date + msg);
}*/

function getCSS() {
        let options = {
                host: 'play.pokemonshowdown.com',
                port: 80,
                path: '/customcss.php?server=spacialgaze',
                method: 'GET',
        };
        https.get(options);
}
SG.loadCSS = getCSS;

function updateColor() {
        fs.writeFileSync(FILE_PATH, JSON.stringify(customColors));

        let newCss = '/* COLORS START */\n';

        for (let name in customColors) {
                newCss += generateCSS(toId(name), customColors[name]);
        }
        newCss += '/* COLORS END */\n';

        let file = fs.readFileSync('config/custom.css', 'utf8').split('\n');
        if (~file.indexOf('/* COLORS START */')) file.splice(file.indexOf('/* COLORS START */'), (file.indexOf('/* COLORS END */') - file.indexOf('/* COLORS START */')) + 1);
        fs.writeFileSync('config/custom.css', file.join('\n') + newCss);

        getCSS();
}
SG.updateColor = updateColor;

function generateCSS(name, color) {
        let css = '';
        let rooms = [];
        Rooms.rooms.forEach(curRoom => {
                if (curRoom.id === 'global' || curRoom.type !== 'chat' || curRoom.isPersonal) continue;
                rooms.push('#' + curRoom.id + '-userlist-user-' + name + ' strong em');
                rooms.push('#' + curRoom.id + '-userlist-user-' + name + ' strong');
                rooms.push('#' + curRoom.id + '-userlist-user-' + name + ' span');
        });
        css = rooms.join(', ');
        css += '{\ncolor: ' + color + ' !important;\n}\n';
        css += '.chat.chatmessage-' + name + ' strong {\n';
        css += 'color: ' + color + ' !important;\n}\n';
        return css;
}

exports.commands = {
        customcolor: function (target, room, user) {
                if (!this.can('hotpatch')) return false;
                target = target.split(',').map(param => param.trim());
                if (target.length !== 2) return this.parse('/help customcolor');
                let targetUser = target[0];
                let option = target[1];
                if (toId(targetUser).length > 18) return this.errorReply("Usernames cannot exceed 18 characters.");
                if (option === 'delete') {
                        if (!customColors[toId(targetUser)]) return this.errorReply('/customcolor - ' + targetUser + ' does not have a custom color.');
                        delete customColors[toId(targetUser)];
                        updateColor();
                        this.sendReply("You removed " + targetUser + "'s custom color.");
                        if (Users(targetUser) && Users(targetUser).connected) Users(targetUser).popup(user.name + " removed your custom color.");
                        return;
                }

                if (option.charAt(0) !== '#') return this.errorReply("The color needs to be a hex starting with '#'.");
                this.sendReply("|raw|You have given " + Tools.escapeHTML(targetUser) + " a custom color.");
                // logMoney(user.name + " le ha asignado un color personalizado a " + target[0] + ". (Color: " + target[1] + ").");
                customColors[toId(targetUser)] = option;
                updateColor();
        },
        customcolorhelp: ["Commands Include:",
                "/customcolor [user], [hex] - Gives [user] a custom color of [hex]",
                "/customcolor [user], delete - Deletes a user's custom color"],

        cp: 'colorpreview',
        colorpreview: function (target, room, user) {
                if (!this.canBroadcast()) return;
                target = target.split(',').map(param => param.trim());
                if (target.length !== 2) return this.parse('/help colorpreview');
                return this.sendReplyBox('' + Tools.escapeHTML(target[0]) + '');
        },
        colorpreviewhelp: ["Usage: /colorpreview [user], [color] - Previews what that username looks like with [color] as the color."],
};

/* Pokemon Showdown hashColor function
 * This gives the color of a username
 * based on the userid.
*/

let MD5 = require('MD5');
let colorCache = {};

// hashColor function
function hashColor(name) {
        name = toId(name);
        if (customColors[name]) return customColors[name];
        if (colorCache[name]) return colorCache[name];
        let hash = MD5(name);
        let H = parseInt(hash.substr(4, 4), 16) % 360; // 0 to 360
        let S = parseInt(hash.substr(0, 4), 16) % 50 + 40; // 40 to 89
        let L = Math.floor(parseInt(hash.substr(8, 4), 16) % 20 + 30); // 30 to 49
        let C = (100 - Math.abs(2 * L - 100)) * S / 100 / 100;
        let X = C * (1 - Math.abs((H / 60) % 2 - 1));
        let m = L / 100 - C / 2;

        let R1, G1, B1;
        switch (Math.floor(H / 60)) {
                case 1: R1 = X; G1 = C; B1 = 0; break;
                case 2: R1 = 0; G1 = C; B1 = X; break;
                case 3: R1 = 0; G1 = X; B1 = C; break;
                case 4: R1 = X; G1 = 0; B1 = C; break;
                case 5: R1 = C; G1 = 0; B1 = X; break;
                case 0: default: R1 = C; G1 = X; B1 = 0; break;
        }
        let lum = (R1 + m) * 0.2126 + (G1 + m) * 0.7152 + (B1 + m) * 0.0722; // 0.05 (dark blue) to 0.93 (yellow)
        let HLmod = (lum - 0.5) * -100; // -43 (yellow) to 45 (dark blue)
        if (HLmod > 12) HLmod -= 12;
        else if (HLmod < -10) HLmod = (HLmod + 10) * 2 / 3;
        else HLmod = 0;

        L += HLmod;
        let Smod = 10 - Math.abs(50 - L);
        if (HLmod > 15) Smod += (HLmod - 15) / 2;
        S -= Smod;

        let rgb = hslToRgb(H, S, L);
        colorCache[name] = "#" + rgbToHex(rgb.r, rgb.g, rgb.b);
        return colorCache[name];
}
global.hashColorWithCustoms = hashColor;

function hslToRgb(h, s, l) {
        let r, g, b, m, c, x;
        if (!isFinite(h)) h = 0;
        if (!isFinite(s)) s = 0;
        if (!isFinite(l)) l = 0;
        h /= 60;
        if (h < 0) h = 6 - (-h % 6);
        h %= 6;
        s = Math.max(0, Math.min(1, s / 100));
        l = Math.max(0, Math.min(1, l / 100));
        c = (1 - Math.abs((2 * l) - 1)) * s;
        x = c * (1 - Math.abs((h % 2) - 1));
        if (h < 1) {
                r = c;
                g = x;
                b = 0;
        } else if (h < 2) {
                r = x;
                g = c;
                b = 0;
        } else if (h < 3) {
                r = 0;
                g = c;
                b = x;
        } else if (h < 4) {
                r = 0;
                g = x;
                b = c;
        } else if (h < 5) {
                r = x;
                g = 0;
                b = c;
        } else {
                r = c;
                g = 0;
                b = x;
        }
        m = l - c / 2;
        r = Math.round((r + m) * 255);
        g = Math.round((g + m) * 255);
        b = Math.round((b + m) * 255);
        return {
                r: r,
                g: g,
                b: b,
        };
}

function rgbToHex(R, G, B) {
        return toHex(R) + toHex(G) + toHex(B);
}

function toHex(N) {
        if (N == null) return "00";
        N = parseInt(N);
        if (N == 0 || isNaN(N)) return "00";
        N = Math.max(0, N);
        N = Math.min(N, 255);
        N = Math.round(N);
        return "0123456789ABCDEF".charAt((N - N % 16) / 16) + "0123456789ABCDEF".charAt(N % 16);
}
<|endoftext|>


<commit_before>import purify from 'purify-css';
import { ConcatSource } from 'webpack-sources';
import * as parse from './parse';
import * as search from './search';
import validateOptions from './validate-options';
import schema from './schema';

module.exports = function PurifyPlugin(options) {
  return {
    apply(compiler) {
      const validation = validateOptions(
        schema({
          entry: compiler.options.entry
        }),
        options
      );

      if (!validation.isValid) {
        throw new Error(validation.error);
      }

      compiler.plugin('this-compilation', (compilation) => {
        const entryPaths = parse.entryPaths(options.paths);

        // Output debug information through a callback pattern
        // to avoid unnecessary processing
        const output = options.verbose ?
          messageCb => console.info(...messageCb()) :
          () => {};

        compilation.plugin('additional-assets', (cb) => {
          // Go through chunks and purify as configured
          compilation.chunks.forEach(
            ({ name: chunkName, modules }) => {
              const assetsToPurify = search.assets(
                compilation.assets, options.styleExtensions
              ).filter(
                asset => asset.name.indexOf(chunkName) >= 0
              );

              output(() => [
                'Assets to purify:',
                assetsToPurify.map(({ name }) => name).join(', ')
              ]);

              assetsToPurify.forEach(({ name, asset }) => {
                const filesToSearch = parse.entries(entryPaths, chunkName).concat(
                  search.files(
                    modules, options.moduleExtensions || [], file => file.resource
                  )
                );

                output(() => [
                  'Files to search for used rules:',
                  filesToSearch.join(', ')
                ]);

                // Compile through Purify and attach to output.
                // This loses sourcemaps should there be any!
                compilation.assets[name] = new ConcatSource(
                  purify(
                    filesToSearch,
                    asset.source(),
                    {
                      info: options.verbose,
                      minify: options.minimize,
                      ...options.purifyOptions
                    }
                  )
                );
              });
            }
          );

          cb();
        });
      });
    }
  };
};
<commit_msg>Fix chunk file match dependency on [name]<commit_after>import purify from 'purify-css';
import { ConcatSource } from 'webpack-sources';
import * as parse from './parse';
import * as search from './search';
import validateOptions from './validate-options';
import schema from './schema';

module.exports = function PurifyPlugin(options) {
  return {
    apply(compiler) {
      const validation = validateOptions(
        schema({
          entry: compiler.options.entry
        }),
        options
      );

      if (!validation.isValid) {
        throw new Error(validation.error);
      }

      compiler.plugin('this-compilation', (compilation) => {
        const entryPaths = parse.entryPaths(options.paths);

        // Output debug information through a callback pattern
        // to avoid unnecessary processing
        const output = options.verbose ?
          messageCb => console.info(...messageCb()) :
          () => {};

        compilation.plugin('additional-assets', (cb) => {
          // Go through chunks and purify as configured
          compilation.chunks.forEach(
            ({ name: chunkName, files, modules }) => {
              const assetsToPurify = search.assets(
                compilation.assets, options.styleExtensions
              ).filter(
                asset => files.indexOf(asset.name) >= 0
              );

              output(() => [
                'Assets to purify:',
                assetsToPurify.map(({ name }) => name).join(', ')
              ]);

              assetsToPurify.forEach(({ name, asset }) => {
                const filesToSearch = parse.entries(entryPaths, chunkName).concat(
                  search.files(
                    modules, options.moduleExtensions || [], file => file.resource
                  )
                );

                output(() => [
                  'Files to search for used rules:',
                  filesToSearch.join(', ')
                ]);

                // Compile through Purify and attach to output.
                // This loses sourcemaps should there be any!
                compilation.assets[name] = new ConcatSource(
                  purify(
                    filesToSearch,
                    asset.source(),
                    {
                      info: options.verbose,
                      minify: options.minimize,
                      ...options.purifyOptions
                    }
                  )
                );
              });
            }
          );

          cb();
        });
      });
    }
  };
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Cucumber pimper
// @namespace    http://tampermonkey.net/
// @version      3.4
// @description  Pimp cucumber reports
// @author       mquiron, mcormier, nguillet, shenault, marobert
// @match        https://jenkins.omnimed.com/*job/*/cucumber-html-reports/*overview-tags.html
// @grant        none
// ==/UserScript==
$(document).ready(function () {
	$("<style type='text/css'> .cukeMoc { background-color: black !important; color: white !important; } </style>").appendTo("head");
	$("<style type='text/css'> .cukeNic { background-color: red !important; color: white !important; } </style>").appendTo("head");
	$("<style type='text/css'> .cukeVal { background-color: blue !important; color: white !important; } </style>").appendTo("head");
	$("<style type='text/css'> .cukeMad { background-color: green !important; color: white !important; } </style>").appendTo("head");
	$("<style type='text/css'> .cukeAll { background-color: grey !important; color: white !important; } </style>").appendTo("head");
});

function colorCucumberTagForQA(tag, qa) {
	if ($('.tagname > a:contains(' + tag + ')').length !== 0) {
		$('.tagname > a:contains(' + tag + ')').removeClass('cukeVal', 'cukeMad', 'cukeNic', 'cukeMoc');
		$('.tagname > a:contains(' + tag + ')').addClass('cuke' + qa);
	} else {
		console.warn('Cucumber tag ' + tag + ' does not exists');
	}
}

function colorCucumberTags() {
	var qa = '';

	//Val
	qa = 'Val';
	//----global---- //doit etre avant tous les tags specifiques des autres QA
	colorCucumberTagForQA('@Dossier', qa);
	//----global---- //
	colorCucumberTagForQA('Antecedent', qa);
	colorCucumberTagForQA('AviseurHpn', qa);
	colorCucumberTagForQA('Cnesst', qa);
	colorCucumberTagForQA('Contexte', qa);
	colorCucumberTagForQA('@DsqSh', qa);
	colorCucumberTagForQA('MaladieChronique', qa);
	colorCucumberTagForQA('Note', qa);
	colorCucumberTagForQA('@OCAngular', qa);
	colorCucumberTagForQA('Outil', qa);
	colorCucumberTagForQA('Probleme', qa);
	colorCucumberTagForQA('Dictionnaire', qa);
	colorCucumberTagForQA('Programme', qa);
	//----Securite----
	colorCucumberTagForQA('@Droit', qa);
	colorCucumberTagForQA('Consentement', qa);
	colorCucumberTagForQA('Mandat', qa);
	//----Securite----
	colorCucumberTagForQA('Vitaux', qa);

	//Mad (jay et Marc)
	qa = 'Mad'
	colorCucumberTagForQA('@Aide', qa);
	colorCucumberTagForQA('@AdministrationActivite', qa);
	colorCucumberTagForQA('@AdministrationStatut', qa);
	colorCucumberTagForQA('@CentreAdmin', qa);
	colorCucumberTagForQA('@Contact', qa);
	colorCucumberTagForQA('@Notification', qa);
	colorCucumberTagForQA('@RendezVous', qa);
	colorCucumberTagForQA('SalleAttente', qa);
	colorCucumberTagForQA('@RecherchePatient', qa);

	//Nic
	qa = 'Nic';
	colorCucumberTagForQA('@DsqAcces', qa);
	colorCucumberTagForQA('@DsqSqii', qa);
	colorCucumberTagForQA('@DsqSqil', qa);
	//----Introduction----
	colorCucumberTagForQA('@Compte', qa);
	colorCucumberTagForQA('@Nouvelle', qa);
	colorCucumberTagForQA('@MenuOmnimed', qa);
	colorCucumberTagForQA('@ProfilUtilisateur', qa);
	//----Introduction----
	colorCucumberTagForQA('Requete', qa);
	//----Resultat----
	colorCucumberTagForQA('@DossierResultat', qa);
	colorCucumberTagForQA('@DossierActionLogResultat', qa);
	colorCucumberTagForQA('@DroitResultat', qa);
	colorCucumberTagForQA('RevisionResultat', qa);
	//----Resultat----
	//----Tache----
	colorCucumberTagForQA('Tache', qa);
	colorCucumberTagForQA('Umf', qa);
	//----Tache----
	//----SessionOnimed----
	colorCucumberTagForQA('@Authentification', qa);
	colorCucumberTagForQA('@ExpirationSession', qa);
	//----SessionOnimed----

	//Moc
	qa = 'Moc';
	colorCucumberTagForQA('@DossierAllergie', qa);
	colorCucumberTagForQA('@DossierActionLogAllergie', qa);
	colorCucumberTagForQA('@DossierImmunisation', qa);
	colorCucumberTagForQA('@DsqSqim', qa);
	colorCucumberTagForQA('ActionLogImmunisation', qa);
	colorCucumberTagForQA('Medication', qa);

	//All
	qa = 'All'
	colorCucumberTagForQA('@CreationDonnee', qa);
	colorCucumberTagForQA('@Exemple', qa);
}

colorCucumberTags();
<commit_msg>[???] ajout de Videoconference dans le tempermonkey<commit_after>// ==UserScript==
// @name         Cucumber pimper
// @namespace    http://tampermonkey.net/
// @version      3.5
// @description  Pimp cucumber reports
// @author       mquiron, mcormier, nguillet, shenault, marobert
// @match        https://jenkins.omnimed.com/*job/*/cucumber-html-reports/*overview-tags.html
// @grant        none
// ==/UserScript==
$(document).ready(function () {
	$("<style type='text/css'> .cukeMoc { background-color: black !important; color: white !important; } </style>").appendTo("head");
	$("<style type='text/css'> .cukeNic { background-color: red !important; color: white !important; } </style>").appendTo("head");
	$("<style type='text/css'> .cukeVal { background-color: blue !important; color: white !important; } </style>").appendTo("head");
	$("<style type='text/css'> .cukeMad { background-color: green !important; color: white !important; } </style>").appendTo("head");
	$("<style type='text/css'> .cukeAll { background-color: grey !important; color: white !important; } </style>").appendTo("head");
});

function colorCucumberTagForQA(tag, qa) {
	if ($('.tagname > a:contains(' + tag + ')').length !== 0) {
		$('.tagname > a:contains(' + tag + ')').removeClass('cukeVal', 'cukeMad', 'cukeNic', 'cukeMoc');
		$('.tagname > a:contains(' + tag + ')').addClass('cuke' + qa);
	} else {
		console.warn('Cucumber tag ' + tag + ' does not exists');
	}
}

function colorCucumberTags() {
	var qa = '';

	//Val
	qa = 'Val';
	//----global---- //doit etre avant tous les tags specifiques des autres QA
	colorCucumberTagForQA('@Dossier', qa);
	//----global---- //
	colorCucumberTagForQA('Antecedent', qa);
	colorCucumberTagForQA('AviseurHpn', qa);
	colorCucumberTagForQA('Cnesst', qa);
	colorCucumberTagForQA('Contexte', qa);
	colorCucumberTagForQA('@DsqSh', qa);
	colorCucumberTagForQA('MaladieChronique', qa);
	colorCucumberTagForQA('Note', qa);
	colorCucumberTagForQA('Outil', qa);
	colorCucumberTagForQA('Probleme', qa);
	colorCucumberTagForQA('Dictionnaire', qa);
	colorCucumberTagForQA('Programme', qa);
	//----Securite----
	colorCucumberTagForQA('@Droit', qa);
	colorCucumberTagForQA('Consentement', qa);
	colorCucumberTagForQA('Mandat', qa);
	//----Securite----
	colorCucumberTagForQA('Vitaux', qa);

	//Mad (jay et Marc)
	qa = 'Mad'
	colorCucumberTagForQA('@Aide', qa);
	colorCucumberTagForQA('@AdministrationActivite', qa);
	colorCucumberTagForQA('@AdministrationStatut', qa);
	colorCucumberTagForQA('@CentreAdmin', qa);
	colorCucumberTagForQA('@Contact', qa);
	colorCucumberTagForQA('@RendezVous', qa);
	colorCucumberTagForQA('SalleAttente', qa);
	colorCucumberTagForQA('@Videoconference', qa);

	//Nic
	qa = 'Nic';
	colorCucumberTagForQA('@DsqAcces', qa);
	colorCucumberTagForQA('@DsqSqii', qa);
	colorCucumberTagForQA('@DsqSqil', qa);
	//----Introduction----
	colorCucumberTagForQA('@Nouvelle', qa);
	colorCucumberTagForQA('@MenuOmnimed', qa);
	colorCucumberTagForQA('@ProfilUtilisateur', qa);
	//----Introduction----
	colorCucumberTagForQA('Requete', qa);
	//----Resultat----
	colorCucumberTagForQA('@DossierResultat', qa);
	colorCucumberTagForQA('@DossierActionLogResultat', qa);
	colorCucumberTagForQA('@DroitResultat', qa);
	colorCucumberTagForQA('RevisionResultat', qa);
	//----Resultat----
	//----Tache----
	colorCucumberTagForQA('Tache', qa);
	colorCucumberTagForQA('Umf', qa);
	//----Tache----
	//----SessionOnimed----
	colorCucumberTagForQA('@Authentification', qa);
	colorCucumberTagForQA('@ExpirationSession', qa);
	//----SessionOnimed----

	//Moc
	qa = 'Moc';
	colorCucumberTagForQA('@DossierAllergie', qa);
	colorCucumberTagForQA('@DossierActionLogAllergie', qa);
	colorCucumberTagForQA('@DossierImmunisation', qa);
	colorCucumberTagForQA('@DsqSqim', qa);
	colorCucumberTagForQA('ActionLogImmunisation', qa);
	colorCucumberTagForQA('Medication', qa);

	//All
	qa = 'All'
	colorCucumberTagForQA('@CreationDonnee', qa);
}

colorCucumberTags();
<|endoftext|>


<commit_before>/**
 * angular-poller
 *
 * @description
 * Angular poller service. It uses a timer and sends requests every few seconds to
 * keep the client synced with the server.
 *
 * @version v0.3.2
 * @link http://github.com/emmaguo/angular-poller
 * @license MIT
 *
 * @example
 * Simple example:
 *      var myPoller = poller.get(target);
 *      myPoller.promise.then(null, null, callback);
 *
 * Advanced example:
 *      var myPoller = poller.get(target, {
 *          action: 'query',
 *          argumentsArray: [
 *              {
 *                  verb: 'greet',
 *                  salutation: 'Hello'
 *              }
 *          ],
 *          delay: 6000,
 *          smart: true,
 *          catchError: true
 *      });
 *      myPoller.promise.then(null, null, callback);
 */

(function (window, angular, undefined) {

    'use strict';

    angular.module('emguo.poller', [])

        .constant('pollerConfig', {
            stopOnRouteChange: false,
            stopOnStateChange: false,
            resetOnRouteChange: false,
            resetOnStateChange: false,
            neverOverwrite: false
        })

        .run(function ($rootScope, poller, pollerConfig) {

            /**
             * Automatically stop or reset all pollers before route change ($routeProvider) or state change ($stateProvider).
             */
            if (pollerConfig.stopOnRouteChange) {
                $rootScope.$on('$routeChangeStart', function () {
                    poller.stopAll();
                });
            }

            if (pollerConfig.stopOnStateChange) {
                $rootScope.$on('$stateChangeStart', function () {
                    poller.stopAll();
                });
            }

            if (pollerConfig.resetOnRouteChange) {
                $rootScope.$on('$routeChangeStart', function () {
                    poller.reset();
                });
            }

            if (pollerConfig.resetOnStateChange) {
                $rootScope.$on('$stateChangeStart', function () {
                    poller.reset();
                });
            }
        })

        .factory('poller', function ($interval, $q, $http, pollerConfig) {

            var pollers = [], // Poller registry

                defaults = {
                    action: 'get',
                    argumentsArray: [],
                    delay: 5000,
                    smart: false,
                    catchError: false
                },

                /**
                 * Poller model:
                 *  - target (can be $resource object, or Restangular object, or $http url)
                 *  - action
                 *  - argumentsArray
                 *  - delay
                 *  - smart (indicates whether poller should only send new request if the previous one is resolved)
                 *  - catchError (indicates whether poller should get notified of error responses)
                 *  - promise
                 *  - interval
                 *
                 * @param target
                 * @param options
                 */
                Poller = function (target, options) {

                    this.target = target;
                    this.set(options);
                },

                /**
                 * Find poller by target in poller registry if pollerConfig.neverOverwrite is set to false (default).
                 * Otherwise return null to prevent overwriting existing pollers.
                 *
                 * @param target
                 * @returns {object}
                 */
                findPoller = function (target) {

                    var poller = null;

                    if (!pollerConfig.neverOverwrite) {
                        angular.forEach(pollers, function (item) {
                            if (angular.equals(item.target, target)) {
                                poller = item;
                            }
                        });
                    }

                    return poller;
                };

            angular.extend(Poller.prototype, {

                /**
                 * Set poller action, argumentsArray, delay, smart and catchError flags.
                 *
                 * If options.action is defined, then set poller action to options.action,
                 * else if poller.action is undefined, then set it to defaults.action,
                 * else do nothing. The same goes for poller.argumentsArray, poller.delay, poller.smart and poller.catchError.
                 *
                 * @param options
                 */
                set: function (options) {

                    angular.forEach(['action', 'argumentsArray', 'delay', 'smart', 'catchError'], function (prop) {
                        if (options && options[prop]) {
                            this[prop] = options[prop];
                        } else if (!this[prop]) {
                            this[prop] = defaults[prop];
                        }
                    }, this);
                },

                /**
                 * Start poller service.
                 */
                start: function () {

                    var target = this.target,
                        action = this.action,
                        argumentsArray = this.argumentsArray.slice(0),
                        delay = this.delay,
                        smart = this.smart,
                        catchError = this.catchError,
                        self = this,
                        current,
                        timestamp;

                    this.deferred = this.deferred || $q.defer();

                    /**
                     * $resource: typeof target === 'function'
                     * Restangular: typeof target === 'object'
                     * $http: typeof target === 'string'
                     */
                    if (typeof target === 'string') {

                        /**
                         * Update argumentsArray and target for target[action].apply(self, argumentsArray).
                         *
                         * @example
                         * $http.get(url, [config])
                         * $http.post(url, data, [config])
                         */
                        argumentsArray.unshift(target);
                        target = $http;
                    }

                    function tick() {

                        // If smart flag is true, then only send new request if the previous one is resolved.
                        if (!smart || !angular.isDefined(current) || current.$resolved) {

                            timestamp = new Date();
                            current = target[action].apply(self, argumentsArray);
                            current.$resolved = false;

                            /**
                             * $resource: current.$promise.then
                             * Restangular: current.then
                             * $http: current.then
                             */
                            (current.$promise || current).then(function (result) {

                                current.$resolved = true;

                                // Ignore success response if request is sent before poller is stopped.
                                if (angular.isUndefined(self.stopTimestamp) || timestamp >= self.stopTimestamp) {
                                    self.deferred.notify(result);
                                }

                            }, function (error) {

                                current.$resolved = true;

                                // Send error response if catchError flag is true and request is sent before poller is stopped
                                if (catchError && (angular.isUndefined(self.stopTimestamp) || timestamp >= self.stopTimestamp)) {
                                    self.deferred.notify(error);
                                }
                            });
                        }
                    }

                    tick();
                    this.interval = $interval(tick, delay);
                    this.promise = this.deferred.promise;
                },

                /**
                 * Stop poller service if it is running.
                 */
                stop: function () {

                    if (angular.isDefined(this.interval)) {
                        $interval.cancel(this.interval);
                        this.interval = undefined;
                        this.stopTimestamp = new Date();
                    }
                },

                /**
                 * Restart poller service.
                 */
                restart: function () {
                    this.stop();
                    this.start();
                }
            });

            return {

                /**
                 * Return a singleton instance of a poller. If poller does not exist, then register and
                 * start it. Otherwise return it and restart it if necessary.
                 *
                 * @param target
                 * @param options
                 * @returns {object}
                 */
                get: function (target, options) {

                    var poller = findPoller(target);

                    if (!poller) {

                        poller = new Poller(target, options);
                        pollers.push(poller);
                        poller.start();

                    } else {

                        poller.set(options);
                        poller.restart();
                    }

                    return poller;
                },

                /**
                 * Total number of pollers in poller registry.
                 *
                 * @returns {number}
                 */
                size: function () {
                    return pollers.length;
                },

                /**
                 * Stop all poller services.
                 */
                stopAll: function () {
                    angular.forEach(pollers, function (p) {
                        p.stop();
                    });
                },

                /**
                 * Restart all poller services.
                 */
                restartAll: function () {
                    angular.forEach(pollers, function (p) {
                        p.restart();
                    });
                },

                /**
                 * Stop and remove all poller services
                 */
                reset: function () {
                    this.stopAll();
                    pollers = [];
                }
            };
        }
    );
})(window, window.angular);<commit_msg>Using inline annotations for dependency injection<commit_after>/**
 * angular-poller
 *
 * @description
 * Angular poller service. It uses a timer and sends requests every few seconds to
 * keep the client synced with the server.
 *
 * @version v0.3.2
 * @link http://github.com/emmaguo/angular-poller
 * @license MIT
 *
 * @example
 * Simple example:
 *      var myPoller = poller.get(target);
 *      myPoller.promise.then(null, null, callback);
 *
 * Advanced example:
 *      var myPoller = poller.get(target, {
 *          action: 'query',
 *          argumentsArray: [
 *              {
 *                  verb: 'greet',
 *                  salutation: 'Hello'
 *              }
 *          ],
 *          delay: 6000,
 *          smart: true,
 *          catchError: true
 *      });
 *      myPoller.promise.then(null, null, callback);
 */

(function (window, angular, undefined) {

    'use strict';

    angular.module('emguo.poller', [])

        .constant('pollerConfig', {
            stopOnRouteChange: false,
            stopOnStateChange: false,
            resetOnRouteChange: false,
            resetOnStateChange: false,
            neverOverwrite: false
        })

        .run(['$rootScope', 'poller', 'pollerConfig', function ($rootScope, poller, pollerConfig) {

            /**
             * Automatically stop or reset all pollers before route change ($routeProvider) or state change ($stateProvider).
             */
            if (pollerConfig.stopOnRouteChange) {
                $rootScope.$on('$routeChangeStart', function () {
                    poller.stopAll();
                });
            }

            if (pollerConfig.stopOnStateChange) {
                $rootScope.$on('$stateChangeStart', function () {
                    poller.stopAll();
                });
            }

            if (pollerConfig.resetOnRouteChange) {
                $rootScope.$on('$routeChangeStart', function () {
                    poller.reset();
                });
            }

            if (pollerConfig.resetOnStateChange) {
                $rootScope.$on('$stateChangeStart', function () {
                    poller.reset();
                });
            }
        }])

        .factory('poller', ['$interval', '$q', '$http', 'pollerConfig', function ($interval, $q, $http, pollerConfig) {

            var pollers = [], // Poller registry

                defaults = {
                    action: 'get',
                    argumentsArray: [],
                    delay: 5000,
                    smart: false,
                    catchError: false
                },

                /**
                 * Poller model:
                 *  - target (can be $resource object, or Restangular object, or $http url)
                 *  - action
                 *  - argumentsArray
                 *  - delay
                 *  - smart (indicates whether poller should only send new request if the previous one is resolved)
                 *  - catchError (indicates whether poller should get notified of error responses)
                 *  - promise
                 *  - interval
                 *
                 * @param target
                 * @param options
                 */
                Poller = function (target, options) {

                    this.target = target;
                    this.set(options);
                },

                /**
                 * Find poller by target in poller registry if pollerConfig.neverOverwrite is set to false (default).
                 * Otherwise return null to prevent overwriting existing pollers.
                 *
                 * @param target
                 * @returns {object}
                 */
                findPoller = function (target) {

                    var poller = null;

                    if (!pollerConfig.neverOverwrite) {
                        angular.forEach(pollers, function (item) {
                            if (angular.equals(item.target, target)) {
                                poller = item;
                            }
                        });
                    }

                    return poller;
                };

            angular.extend(Poller.prototype, {

                /**
                 * Set poller action, argumentsArray, delay, smart and catchError flags.
                 *
                 * If options.action is defined, then set poller action to options.action,
                 * else if poller.action is undefined, then set it to defaults.action,
                 * else do nothing. The same goes for poller.argumentsArray, poller.delay, poller.smart and poller.catchError.
                 *
                 * @param options
                 */
                set: function (options) {

                    angular.forEach(['action', 'argumentsArray', 'delay', 'smart', 'catchError'], function (prop) {
                        if (options && options[prop]) {
                            this[prop] = options[prop];
                        } else if (!this[prop]) {
                            this[prop] = defaults[prop];
                        }
                    }, this);
                },

                /**
                 * Start poller service.
                 */
                start: function () {

                    var target = this.target,
                        action = this.action,
                        argumentsArray = this.argumentsArray.slice(0),
                        delay = this.delay,
                        smart = this.smart,
                        catchError = this.catchError,
                        self = this,
                        current,
                        timestamp;

                    this.deferred = this.deferred || $q.defer();

                    /**
                     * $resource: typeof target === 'function'
                     * Restangular: typeof target === 'object'
                     * $http: typeof target === 'string'
                     */
                    if (typeof target === 'string') {

                        /**
                         * Update argumentsArray and target for target[action].apply(self, argumentsArray).
                         *
                         * @example
                         * $http.get(url, [config])
                         * $http.post(url, data, [config])
                         */
                        argumentsArray.unshift(target);
                        target = $http;
                    }

                    function tick() {

                        // If smart flag is true, then only send new request if the previous one is resolved.
                        if (!smart || !angular.isDefined(current) || current.$resolved) {

                            timestamp = new Date();
                            current = target[action].apply(self, argumentsArray);
                            current.$resolved = false;

                            /**
                             * $resource: current.$promise.then
                             * Restangular: current.then
                             * $http: current.then
                             */
                            (current.$promise || current).then(function (result) {

                                current.$resolved = true;

                                // Ignore success response if request is sent before poller is stopped.
                                if (angular.isUndefined(self.stopTimestamp) || timestamp >= self.stopTimestamp) {
                                    self.deferred.notify(result);
                                }

                            }, function (error) {

                                current.$resolved = true;

                                // Send error response if catchError flag is true and request is sent before poller is stopped
                                if (catchError && (angular.isUndefined(self.stopTimestamp) || timestamp >= self.stopTimestamp)) {
                                    self.deferred.notify(error);
                                }
                            });
                        }
                    }

                    tick();
                    this.interval = $interval(tick, delay);
                    this.promise = this.deferred.promise;
                },

                /**
                 * Stop poller service if it is running.
                 */
                stop: function () {

                    if (angular.isDefined(this.interval)) {
                        $interval.cancel(this.interval);
                        this.interval = undefined;
                        this.stopTimestamp = new Date();
                    }
                },

                /**
                 * Restart poller service.
                 */
                restart: function () {
                    this.stop();
                    this.start();
                }
            });

            return {

                /**
                 * Return a singleton instance of a poller. If poller does not exist, then register and
                 * start it. Otherwise return it and restart it if necessary.
                 *
                 * @param target
                 * @param options
                 * @returns {object}
                 */
                get: function (target, options) {

                    var poller = findPoller(target);

                    if (!poller) {

                        poller = new Poller(target, options);
                        pollers.push(poller);
                        poller.start();

                    } else {

                        poller.set(options);
                        poller.restart();
                    }

                    return poller;
                },

                /**
                 * Total number of pollers in poller registry.
                 *
                 * @returns {number}
                 */
                size: function () {
                    return pollers.length;
                },

                /**
                 * Stop all poller services.
                 */
                stopAll: function () {
                    angular.forEach(pollers, function (p) {
                        p.stop();
                    });
                },

                /**
                 * Restart all poller services.
                 */
                restartAll: function () {
                    angular.forEach(pollers, function (p) {
                        p.restart();
                    });
                },

                /**
                 * Stop and remove all poller services
                 */
                reset: function () {
                    this.stopAll();
                    pollers = [];
                }
            };
        }]
    );
})(window, window.angular);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import _ from 'lodash';

import Title from '../Title';
import { Button } from '../Form';

import api from '../../utils/api';

import './Observations.css';

class Observations extends Component {
  constructor(...props) {
    super(...props);

    this.state = {
      observations: [],
    };
  }

  componentDidMount() {
    api.get('/observations')
      .then(({ data }) => this.setState({ observations: data }));
  }

  vote(value) {
    const observation = _.last(this.state.observations);

    this.setState({
      observations: [..._.dropRight(this.state.observations)],
    });

    api.post('/votes', {
      body: {
        observation_id: observation.id,
        value,
      },
    });
  }

  render() {
    const observation = _.last(this.state.observations);

    return (

        <Title name="Observations" />
        {observation && (

              <img src={`${process.env.REACT_APP_API_URL}/observations/${observation.id}/picture`} alt="Observation" />

            <Button onClick={() => this.vote(1)}>UP</Button>
            <Button onClick={() => this.vote(0)}>SKIP</Button>
            <Button onClick={() => this.vote(-1)}>DOWN</Button>

        )}

    );
  }
}
export default Observations;
<commit_msg>make UP and DOWN using a circle button<commit_after>import React, { Component } from 'react';
import _ from 'lodash';

import Title from '../Title';
import { Button } from '../Form';

import api from '../../utils/api';

import './Observations.css';

class Observations extends Component {
  constructor(...props) {
    super(...props);

    this.state = {
      observations: [],
    };
  }

  componentDidMount() {
    api.get('/observations')
      .then(({ data }) => this.setState({ observations: data }));
  }

  vote(value) {
    const observation = _.last(this.state.observations);

    this.setState({
      observations: [..._.dropRight(this.state.observations)],
    });

    api.post('/votes', {
      body: {
        observation_id: observation.id,
        value,
      },
    });
  }

  render() {
    const observation = _.last(this.state.observations);

    return (

        <Title name="Observations" />
        {observation && (

              <img src={`${process.env.REACT_APP_API_URL}/observations/${observation.id}/picture`} alt="Observation" />

              <Button onClick={() => this.vote(1)} circle>UP</Button>
              <Button onClick={() => this.vote(0)} >SKIP</Button>
              <Button onClick={() => this.vote(-1)} circle>DOWN</Button>

        )}

    );
  }
}
export default Observations;
<|endoftext|>