<commit_before>var View = require('./view');
var template = require('./templates/oncovis');
var ControlsView = require("../views/oncovis_controls");
var SelectorsView = require("../views/oncovis_selectors");
var GeneListView = require("../views/genelist_view");
var ALL_COLUMNS = "All Columns";

module.exports = View.extend({
    template:template,
    className:"row-fluid",
    clusterProperty: null,
    rowLabels:[],

    initialize:function (options) {
        _.extend(this, options);
        _.bindAll(this, 'renderGraph', 'initControls', 'onNewRows');

        this.storageKeys = {
            cluster: "oncovis_view." + this.model.get("dataset_id") + ".cluster_property",
            rows: "oncovis_view." + this.model.get("dataset_id") + ".row_labels"
        };

        this.clusterProperty = localStorage.getItem(this.storageKeys.cluster);

        var localRows = localStorage.getItem(this.storageKeys.rows);
        if (localRows && localRows.length) this.rowLabels = localRows.split(",");

        this.model.on("load", this.renderGraph);
    },

    afterRender:function () {
        new GeneListView({ $el: this.$el }).on("genelist-selected", this.onNewRows);
    },

    initSelectors: function() {
        var cluster = this.clusterProperty;
        if (cluster && cluster == ALL_COLUMNS) cluster = null;
        this.$el.find('.selected-cluster').html(cluster);

        var selectorView = new SelectorsView({
            model: this.model,
            cluster: cluster,
            rows: this.rowLabels
        });
        this.$el.find('.selector-modal').html(selectorView.render().el);

        var _this = this;
        selectorView.on("selected", function(data) {
            _this.clusterProperty = data.cluster || ALL_COLUMNS;
            _this.rowLabels = data.rows;

            localStorage.setItem(_this.storageKeys.cluster, _this.clusterProperty);
            localStorage.setItem(_this.storageKeys.rows, _this.rowLabels.join(","));

            _this.$el.find('.selected-cluster').html(data.cluster);
            _this.$el.find('.selector-modal').modal("hide");
            _this.model.trigger("load");
        });

        if (_.isEmpty(this.rowLabels)) {
            this.rowLabels = _.first(this.model.get("ROWS"), 50);
        }
    },

    getColumnModel:function () {
        var _this = this;
        var unsorted_columns = [];
        var cluster_property = this.clusterProperty || ALL_COLUMNS;
        if (cluster_property == ALL_COLUMNS) {
            _.each(this.model.get("COLUMNS"), function (column_name, col_idx) {
                var column = { "name":column_name.trim(), "cluster":ALL_COLUMNS, "values":[] };
                _.each(_this.rowLabels, function (row_label) {
                    var row_idx = _this.model.get("ROWS").indexOf(row_label);
                    column.values.push(_this.model.get("DATA")[row_idx][col_idx].trim().toLowerCase());
                });
                unsorted_columns.push(column);
            });
        } else {
            _.each(this.model.get("COLUMNS"), function (column_name, col_idx) {
                var cluster_idx = _this.model.get("ROWS").indexOf(cluster_property);
                var cluster_value = _this.model.get("DATA")[cluster_idx][col_idx].trim();
                var column = { "name":column_name.trim(), "cluster":cluster_value, "values":[cluster_value] };
                _.each(_this.rowLabels, function (row_label) {
                    var row_idx = _this.model.get("ROWS").indexOf(row_label);
                    column.values.push(_this.model.get("DATA")[row_idx][col_idx].trim().toLowerCase());
                });
                unsorted_columns.push(column);
            });
        }

        var sorted_columns = _.sortBy(unsorted_columns, "values");
        var grouped_columns = _.groupBy(sorted_columns, "cluster");

        var columns_by_cluster = {};
        _.each(grouped_columns, function (values, key) {
            columns_by_cluster[key] = [];
            _.each(values, function (value) {
                columns_by_cluster[key].push(value.name);
            })
        });
        return columns_by_cluster;
    },

    renderGraph:function () {
        this.initControls();
        this.initSelectors();

        if (!this.rowLabels || !this.rowLabels.length) {
            this.$el.find('.selector-modal').modal("show");
            return;
        }

        var columns_by_cluster = this.getColumnModel();
        var data = {};
        var _this = this;
        _.each(this.rowLabels, function (rowLabel) {
            var row_idx = _this.model.get("ROWS").indexOf(rowLabel);
            var categories = _.uniq(_this.model.get("DATA")[row_idx]);
            var numberOfCategories = (categories.length < 3) ? 3 : categories.length;

            var colorscales = function (cell) {
                return colorbrewer.YlOrBr[numberOfCategories][categories.indexOf(cell)];
            };
            if (numberOfCategories > 7) {
                var colorscaleFn = d3.scale.ordinal().domain(categories)
                    .range(d3.range(categories.length)
                    .map(d3.scale.linear().domain([0, categories.length - 1])
                    .range(["yellow", "green"])
                    .interpolate(d3.interpolateLab)));
                colorscales = function (cell) {
                    return colorscaleFn(categories.indexOf(cell));
                }
            }

            _.each(_this.model.get("DATA")[row_idx], function (cell, cellIdx) {
                cell = cell.trim();
                var columnLabel = _this.model.get("COLUMNS")[cellIdx].trim();
                if (!data[columnLabel]) data[columnLabel] = {};
                data[columnLabel][rowLabel] = { "value":cell, "row":rowLabel, "colorscale":colorscales(cell), "label":columnLabel + "\n" + rowLabel + "\n" + cell };
            });
        });

        var optns = {
            plot_width:1500,
            plot_height:700,
            highlight_fill:colorbrewer.RdYlGn[3][2],
            color_fn:function (d) {
                return d ? d.colorscale : "white";
            },
            columns_by_cluster:columns_by_cluster,
            cluster_labels:_.keys(columns_by_cluster),
            row_labels:this.rowLabels
        };

        this.$el.find(".oncovis-container").oncovis(data, _.extend(optns, this.controls.initialValue()));
    },

    initControls:function () {
        this.controls = new ControlsView();
        this.$el.find('.controls-modal').html(this.controls.render().el);

        var oncovis_container = this.$el.find(".oncovis-container");
        this.controls.on("updated", function(dim) {
            oncovis_container.oncovis("update", dim);
        });
    },

    onNewRows:function (genelist) {
        if (genelist && genelist.values) {
            var _this = this;
            _.defer(function () {
                _this.rowLabels = _.filter(_this.model.get("ROWS"), function (row) {
                    return _.any(genelist.values, function (gene) {
                        return (row.toLowerCase().indexOf(gene.toLowerCase()) >= 0);
                    });
                });
                _this.model.trigger('load');
            });
        }
    }
});
<commit_msg>changed first 50 rows to check if less than 50 rows<commit_after>var View = require('./view');
var template = require('./templates/oncovis');
var ControlsView = require("../views/oncovis_controls");
var SelectorsView = require("../views/oncovis_selectors");
var GeneListView = require("../views/genelist_view");
var ALL_COLUMNS = "All Columns";

module.exports = View.extend({
    template:template,
    className:"row-fluid",
    clusterProperty: null,
    rowLabels:[],

    initialize:function (options) {
        _.extend(this, options);
        _.bindAll(this, 'renderGraph', 'initControls', 'onNewRows');

        this.storageKeys = {
            cluster: "oncovis_view." + this.model.get("dataset_id") + ".cluster_property",
            rows: "oncovis_view." + this.model.get("dataset_id") + ".row_labels"
        };

        this.clusterProperty = localStorage.getItem(this.storageKeys.cluster);

        var localRows = localStorage.getItem(this.storageKeys.rows);
        if (localRows && localRows.length) this.rowLabels = localRows.split(",");

        this.model.on("load", this.renderGraph);
    },

    afterRender:function () {
        new GeneListView({ $el: this.$el }).on("genelist-selected", this.onNewRows);
    },

    initSelectors: function() {
        var cluster = this.clusterProperty;
        if (cluster && cluster == ALL_COLUMNS) cluster = null;
        this.$el.find('.selected-cluster').html(cluster);

        var selectorView = new SelectorsView({
            model: this.model,
            cluster: cluster,
            rows: this.rowLabels
        });
        this.$el.find('.selector-modal').html(selectorView.render().el);

        var _this = this;
        selectorView.on("selected", function(data) {
            _this.clusterProperty = data.cluster || ALL_COLUMNS;
            _this.rowLabels = data.rows;

            localStorage.setItem(_this.storageKeys.cluster, _this.clusterProperty);
            localStorage.setItem(_this.storageKeys.rows, _this.rowLabels.join(","));

            _this.$el.find('.selected-cluster').html(data.cluster);
            _this.$el.find('.selector-modal').modal("hide");
            _this.model.trigger("load");
        });

        if (_.isEmpty(this.rowLabels)) {
            var rows = this.model.get("ROWS");
            this.rowLabels = _.first(rows, (rows.length < 50) ? rows.length : 50);
        }
    },

    getColumnModel:function () {
        var _this = this;
        var unsorted_columns = [];
        var cluster_property = this.clusterProperty || ALL_COLUMNS;
        if (cluster_property == ALL_COLUMNS) {
            _.each(this.model.get("COLUMNS"), function (column_name, col_idx) {
                var column = { "name":column_name.trim(), "cluster":ALL_COLUMNS, "values":[] };
                _.each(_this.rowLabels, function (row_label) {
                    var row_idx = _this.model.get("ROWS").indexOf(row_label);
                    column.values.push(_this.model.get("DATA")[row_idx][col_idx].trim().toLowerCase());
                });
                unsorted_columns.push(column);
            });
        } else {
            _.each(this.model.get("COLUMNS"), function (column_name, col_idx) {
                var cluster_idx = _this.model.get("ROWS").indexOf(cluster_property);
                var cluster_value = _this.model.get("DATA")[cluster_idx][col_idx].trim();
                var column = { "name":column_name.trim(), "cluster":cluster_value, "values":[cluster_value] };
                _.each(_this.rowLabels, function (row_label) {
                    var row_idx = _this.model.get("ROWS").indexOf(row_label);
                    column.values.push(_this.model.get("DATA")[row_idx][col_idx].trim().toLowerCase());
                });
                unsorted_columns.push(column);
            });
        }

        var sorted_columns = _.sortBy(unsorted_columns, "values");
        var grouped_columns = _.groupBy(sorted_columns, "cluster");

        var columns_by_cluster = {};
        _.each(grouped_columns, function (values, key) {
            columns_by_cluster[key] = [];
            _.each(values, function (value) {
                columns_by_cluster[key].push(value.name);
            })
        });
        return columns_by_cluster;
    },

    renderGraph:function () {
        this.initControls();
        this.initSelectors();

        if (!this.rowLabels || !this.rowLabels.length) {
            this.$el.find('.selector-modal').modal("show");
            return;
        }

        var columns_by_cluster = this.getColumnModel();
        var data = {};
        var _this = this;
        _.each(this.rowLabels, function (rowLabel) {
            var row_idx = _this.model.get("ROWS").indexOf(rowLabel);
            var categories = _.uniq(_this.model.get("DATA")[row_idx]);
            var numberOfCategories = (categories.length < 3) ? 3 : categories.length;

            var colorscales = function (cell) {
                return colorbrewer.YlOrBr[numberOfCategories][categories.indexOf(cell)];
            };
            if (numberOfCategories > 7) {
                var colorscaleFn = d3.scale.ordinal().domain(categories)
                    .range(d3.range(categories.length)
                    .map(d3.scale.linear().domain([0, categories.length - 1])
                    .range(["yellow", "green"])
                    .interpolate(d3.interpolateLab)));
                colorscales = function (cell) {
                    return colorscaleFn(categories.indexOf(cell));
                }
            }

            _.each(_this.model.get("DATA")[row_idx], function (cell, cellIdx) {
                cell = cell.trim();
                var columnLabel = _this.model.get("COLUMNS")[cellIdx].trim();
                if (!data[columnLabel]) data[columnLabel] = {};
                data[columnLabel][rowLabel] = { "value":cell, "row":rowLabel, "colorscale":colorscales(cell), "label":columnLabel + "\n" + rowLabel + "\n" + cell };
            });
        });

        var optns = {
            plot_width:1500,
            plot_height:700,
            highlight_fill:colorbrewer.RdYlGn[3][2],
            color_fn:function (d) {
                return d ? d.colorscale : "white";
            },
            columns_by_cluster:columns_by_cluster,
            cluster_labels:_.keys(columns_by_cluster),
            row_labels:this.rowLabels
        };

        this.$el.find(".oncovis-container").oncovis(data, _.extend(optns, this.controls.initialValue()));
    },

    initControls:function () {
        this.controls = new ControlsView();
        this.$el.find('.controls-modal').html(this.controls.render().el);

        var oncovis_container = this.$el.find(".oncovis-container");
        this.controls.on("updated", function(dim) {
            oncovis_container.oncovis("update", dim);
        });
    },

    onNewRows:function (genelist) {
        if (genelist && genelist.values) {
            var _this = this;
            _.defer(function () {
                _this.rowLabels = _.filter(_this.model.get("ROWS"), function (row) {
                    return _.any(genelist.values, function (gene) {
                        return (row.toLowerCase().indexOf(gene.toLowerCase()) >= 0);
                    });
                });
                _this.model.trigger('load');
            });
        }
    }
});
<|endoftext|>


<commit_before>/* eslint react/jsx-closing-bracket-location: 0 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {fetchCommits} from '../../redux/actions/actionsCommits';
import {fetchGlobalStats} from '../../redux/actions/actionsStats';
import {GlobalTotal} from '../../base/GlobalTotal';
import {GlobalDate} from '../../base/GlobalDate';
import {ChartCommitsByHour} from '../../charts/ChartCommitsByHour';
import {ChartCommitsByMinute} from '../../charts/ChartCommitsByMinute';
import {ChartCommitsBySecond} from '../../charts/ChartCommitsBySecond';
import {ChartCommitsByTimezone} from '../../charts/ChartCommitsByTimezone';
import {ChartCommitsByWeekday} from '../../charts/ChartCommitsByWeekday';
import {ChartCommitsByDayInTheMonth} from '../../charts/ChartCommitsByDayInTheMonth';
import {ChartCommitsByMonth} from '../../charts/ChartCommitsByMonth';
import {ChartCommitsByYear} from '../../charts/ChartCommitsByYear';
import {ChartCommitsByDay} from '../../charts/ChartCommitsByDay';
import {ChartCumulativeLinesOfCode} from '../../charts/ChartCumulativeLinesOfCode';
import {ChartImpact} from '../../charts/ChartImpact';
import {ChartNrFilesChanged} from '../../charts/ChartNrFilesChanged';
import {
  arrayByKey,
  arrayMaxMin
} from '../../helpers/oxo';

class GlobalStats extends Component {
  componentWillMount() {
    const {commits} = this.props;
    // When accessing the page directly for the first time, the 'commits' & 'stats'
    // arrays are defined, but empty. In those cases we should fetch the data. This
    // check also prevents a new fetch in case they already are defined and have data.
    if (typeof commits !== 'undefined' && commits !== null && commits.length === 0) {
      this.props.dispatch(fetchCommits());
    }
    // if (typeof stats.commits !== 'undefined' && stats.commits !== null && stats.commits.length === 0) {
    this.props.dispatch(fetchGlobalStats());
    // }
  }
  render() {
    const {commits} = this.props;
    // api/key/impact/max
    const impactCommitMax = arrayMaxMin(
      arrayByKey(commits, 'impact'), 'max'
    );
    // api/key/impact/min
    const impactCommitMin = arrayMaxMin(
      arrayByKey(commits, 'impact'), 'min'
    );
    // api/key/files_changed/min
    const filesChangedMax = arrayMaxMin(
      arrayByKey(commits, 'files_changed'), 'max'
    );
    const {
      contributors,
      repositories,
      lines,
      fileChanges,
      commitsWithoutFileChanges,
      commitsWithoutImpact,
      commitsImpactGtThousand,
      commitsOnWeekend,
      daysActive,
      commitDateFirst,
      commitDateLast,
      daysSinceFirstCommit,
      daysSinceLastCommit,
      staleness,
      commitsPerDay,
      commitsPerContributor
    } = this.props.stats;
    return (

          <GlobalTotal
            total={this.props.stats.commits}
            detail="Commits"
            color="green"
          />
          <GlobalTotal
            total={contributors}
            detail="Contributors"
            color="teal"
          />
          <GlobalTotal
            total={repositories}
            detail="Repositories"
            color="purple"
          />
          <GlobalTotal
            total={lines}
            detail="Lines of Code"
            color="cyan"
          />
          <GlobalTotal
            total={fileChanges}
            detail="File Changes"
            color="orange"
          />
          <GlobalTotal
            total={commitsWithoutFileChanges}
            detail="Commits w/o File Changes"
            color="violet"
          />
          <GlobalTotal
            total={commitsWithoutImpact}
            detail="Commits w/o Impact"
            color="deepPink"
          />
          <GlobalTotal
            total={commitsImpactGtThousand}
            detail="Commits w/ Impact > 1000"
            color="red"
          />
          <GlobalTotal
            total={commitsOnWeekend}
            detail="Commits on weekends"
            color="gold"
          />
          <GlobalTotal
            total={filesChangedMax}
            detail="Max. number of files changed on a single commit"
            color="magenta"
          />
          <GlobalTotal
            total={impactCommitMax}
            detail="Commit with highest Impact"
            color="maroon"
          />
          <GlobalTotal
            total={impactCommitMin}
            detail="Commit with lowest Impact"
            color="lime"
          />
          <GlobalTotal
            total={daysActive}
            detail="Number of days between first and last commits"
            color="orange"
          />
          <GlobalDate
            date={commitDateFirst}
            detail="Date of first commit"
            color="cyan"
          />
          <GlobalDate
            date={commitDateLast}
            detail="Date of last commit"
            color="magenta"
          />
          <GlobalTotal
            total={daysSinceFirstCommit}
            detail="Days since first commit"
            color="gold"
          />
          <GlobalTotal
            total={daysSinceLastCommit}
            detail="Days since last commit"
            color="purple"
          />
          <GlobalTotal
            total={staleness}
            detail="Overall staleness"
            color="teal"
          />
          <GlobalTotal
            total={commitsPerDay}
            detail="Average commits per day"
            color="lime"
          />
          <GlobalTotal
            total={commitsPerContributor}
            detail="Average commits per contributor"
            color="maroon"
          />

        <ChartCommitsByHour commits={commits}/>
        <ChartCommitsByMinute commits={commits}/>
        <ChartCommitsBySecond commits={commits}/>
        <ChartCommitsByTimezone commits={commits}/>
        <ChartCommitsByWeekday commits={commits}/>
        <ChartCommitsByDayInTheMonth commits={commits}/>
        <ChartCommitsByMonth commits={commits}/>
        <ChartCommitsByYear commits={commits}/>
        <ChartCommitsByDay commits={commits}/>
        <ChartCumulativeLinesOfCode commits={commits}/>
        <ChartImpact commits={commits}/>
        <ChartNrFilesChanged commits={commits}/>

    );
  }
}

GlobalStats.propTypes = {
  commits: PropTypes.array,
  dispatch: PropTypes.func,
  stats: PropTypes.object,
  contributors: PropTypes.string,
  repositories: PropTypes.string,
  lines: PropTypes.string,
  fileChanges: PropTypes.string,
  commitsWithoutFileChanges: PropTypes.string,
  commitsWithoutImpact: PropTypes.string,
  commitsImpactGtThousand: PropTypes.string,
  commitsOnWeekend: PropTypes.string,
  daysActive: PropTypes.string,
  commitDateFirst: PropTypes.string,
  commitDateLast: PropTypes.string,
  daysSinceFirstCommit: PropTypes.string,
  daysSinceLastCommit: PropTypes.string,
  staleness: PropTypes.string,
  commitsPerDay: PropTypes.string,
  commitsPerContributor: PropTypes.string
};

export default connect(store => {
  return {
    commits: store.commits.commits,
    stats: store.stats.stats
  };
})(GlobalStats);
<commit_msg>Add new totals based on a gist made two years ago<commit_after>/* eslint react/jsx-closing-bracket-location: 0 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {fetchCommits} from '../../redux/actions/actionsCommits';
import {fetchGlobalStats} from '../../redux/actions/actionsStats';
import {GlobalTotal} from '../../base/GlobalTotal';
import {GlobalDate} from '../../base/GlobalDate';
import {ChartCommitsByHour} from '../../charts/ChartCommitsByHour';
import {ChartCommitsByMinute} from '../../charts/ChartCommitsByMinute';
import {ChartCommitsBySecond} from '../../charts/ChartCommitsBySecond';
import {ChartCommitsByTimezone} from '../../charts/ChartCommitsByTimezone';
import {ChartCommitsByWeekday} from '../../charts/ChartCommitsByWeekday';
import {ChartCommitsByDayInTheMonth} from '../../charts/ChartCommitsByDayInTheMonth';
import {ChartCommitsByMonth} from '../../charts/ChartCommitsByMonth';
import {ChartCommitsByYear} from '../../charts/ChartCommitsByYear';
import {ChartCommitsByDay} from '../../charts/ChartCommitsByDay';
import {ChartCumulativeLinesOfCode} from '../../charts/ChartCumulativeLinesOfCode';
import {ChartImpact} from '../../charts/ChartImpact';
import {ChartNrFilesChanged} from '../../charts/ChartNrFilesChanged';
import {
  arrayByKey,
  arrayMaxMin
} from '../../helpers/oxo';

class GlobalStats extends Component {
  componentWillMount() {
    const {commits} = this.props;
    // When accessing the page directly for the first time, the 'commits' & 'stats'
    // arrays are defined, but empty. In those cases we should fetch the data. This
    // check also prevents a new fetch in case they already are defined and have data.
    if (typeof commits !== 'undefined' && commits !== null && commits.length === 0) {
      this.props.dispatch(fetchCommits());
    }
    // if (typeof stats.commits !== 'undefined' && stats.commits !== null && stats.commits.length === 0) {
    this.props.dispatch(fetchGlobalStats());
    // }
  }
  render() {
    const {commits} = this.props;
    // api/key/impact/max
    const impactCommitMax = arrayMaxMin(
      arrayByKey(commits, 'impact'), 'max'
    );
    // api/key/impact/min
    const impactCommitMin = arrayMaxMin(
      arrayByKey(commits, 'impact'), 'min'
    );
    // api/key/files_changed/min
    const filesChangedMax = arrayMaxMin(
      arrayByKey(commits, 'files_changed'), 'max'
    );
    const {
      contributors,
      repositories,
      lines,
      fileChanges,
      commitsWithoutFileChanges,
      commitsWithoutImpact,
      commitsImpactGtThousand,
      commitsOnWeekend,
      daysActive,
      commitDateFirst,
      commitDateLast,
      daysSinceFirstCommit,
      daysSinceLastCommit,
      staleness,
      // commitsPerDay,
      commitsPerContributor
    } = this.props.stats;
    return (

          <GlobalTotal
            total={this.props.stats.commits}
            detail="Commits"
            color="green"
          />
          <GlobalTotal
            total={contributors}
            detail="Contributors"
            color="teal"
          />
          <GlobalTotal
            total={repositories}
            detail="Repositories"
            color="purple"
          />
          <GlobalTotal
            total={lines}
            detail="Lines of Code"
            color="cyan"
          />
          <GlobalTotal
            total={fileChanges}
            detail="File Changes"
            color="orange"
          />
          <GlobalTotal
            total={commitsWithoutFileChanges}
            detail="Commits w/o File Changes"
            color="violet"
          />
          <GlobalTotal
            total={commitsWithoutImpact}
            detail="Commits w/o Impact"
            color="deepPink"
          />
          <GlobalTotal
            total={commitsImpactGtThousand}
            detail="Commits w/ Impact > 1000"
            color="red"
          />
          <GlobalTotal
            total={daysActive}
            detail="Active Days (Days between first and last commits)"
            color="orange"
          />
          <GlobalTotal
            total={daysSinceFirstCommit}
            detail="Days since first commit"
            color="gold"
          />
          <GlobalTotal
            total={daysSinceLastCommit}
            detail="Days since last commit"
            color="purple"
          />
          <GlobalDate
            date={commitDateFirst}
            detail="Date of first commit"
            color="cyan"
          />
          <GlobalDate
            date={commitDateLast}
            detail="Date of last commit"
            color="magenta"
          />
          <GlobalTotal
            total={impactCommitMax}
            detail="Commit with highest Impact"
            color="maroon"
          />
          <GlobalTotal
            total={impactCommitMin}
            detail="Commit with lowest Impact"
            color="lime"
          />
          <GlobalTotal
            // total={commitsPerDay} // <= wrong, must be corrected or removed at API's end
            total={this.props.stats.commits / daysActive}
            detail="Commits per day"
            color="lime"
          />
          <GlobalTotal
            total={lines / daysActive}
            detail="Lines of code per day"
            color="pink"
          />
          <GlobalTotal
            total={commitsPerContributor}
            detail="Commits per contributor"
            color="maroon"
          />
          <GlobalTotal
            total={lines / contributors}
            detail="Code Weight (Lines of code per contributor)"
            color="pink"
          />
          <GlobalTotal
            total={this.props.stats.commits / repositories}
            detail="Commits per repository"
            color="pink"
          />
          <GlobalTotal
            total={contributors / repositories}
            detail="Contributors per repository"
            color="pink"
          />
          <GlobalTotal
            total={lines / repositories}
            detail="Lines of code per repository"
            color="pink"
          />
          <GlobalTotal
            total={commitsOnWeekend}
            detail="Commits on weekends"
            color="gold"
          />
          <GlobalTotal
            total={filesChangedMax}
            detail="Max. number of files changed on a single commit"
            color="magenta"
          />
          <GlobalTotal
            total={staleness}
            detail="Overall staleness"
            color="teal"
          />

        <ChartCommitsByHour commits={commits}/>
        <ChartCommitsByMinute commits={commits}/>
        <ChartCommitsBySecond commits={commits}/>
        <ChartCommitsByTimezone commits={commits}/>
        <ChartCommitsByWeekday commits={commits}/>
        <ChartCommitsByDayInTheMonth commits={commits}/>
        <ChartCommitsByMonth commits={commits}/>
        <ChartCommitsByYear commits={commits}/>
        <ChartCommitsByDay commits={commits}/>
        <ChartCumulativeLinesOfCode commits={commits}/>
        <ChartImpact commits={commits}/>
        <ChartNrFilesChanged commits={commits}/>

    );
  }
}

GlobalStats.propTypes = {
  commits: PropTypes.array,
  dispatch: PropTypes.func,
  stats: PropTypes.object,
  contributors: PropTypes.string,
  repositories: PropTypes.string,
  lines: PropTypes.string,
  fileChanges: PropTypes.string,
  commitsWithoutFileChanges: PropTypes.string,
  commitsWithoutImpact: PropTypes.string,
  commitsImpactGtThousand: PropTypes.string,
  commitsOnWeekend: PropTypes.string,
  daysActive: PropTypes.string,
  commitDateFirst: PropTypes.string,
  commitDateLast: PropTypes.string,
  daysSinceFirstCommit: PropTypes.string,
  daysSinceLastCommit: PropTypes.string,
  staleness: PropTypes.string,
  // commitsPerDay: PropTypes.string,
  commitsPerContributor: PropTypes.string
};

export default connect(store => {
  return {
    commits: store.commits.commits,
    stats: store.stats.stats
  };
})(GlobalStats);
<|endoftext|>


<commit_before>define([
  'angular',
  'app',
  'lodash',
  'components/timeSeries',
  'kbn',
  'components/panelmeta',
  './singleStatPanel',
],
function (angular, app, _, TimeSeries, kbn, PanelMeta) {
  'use strict';

  var module = angular.module('grafana.panels.singlestat');
  app.useModule(module);

  module.directive('grafanaPanelSinglestat', function() {
    return {
      controller: 'SingleStatCtrl',
      templateUrl: 'app/panels/singlestat/module.html',
    };
  });

  module.controller('SingleStatCtrl', function($scope, panelSrv, panelHelper) {

    $scope.panelMeta = new PanelMeta({
      panelName: 'Singlestat',
      editIcon:  "fa fa-dashboard",
      fullscreen: true,
      metricsEditor: true
    });

    $scope.fontSizes = ['20%', '30%','50%','70%','80%','100%', '110%', '120%', '150%', '170%', '200%'];

    $scope.panelMeta.addEditorTab('Options', 'app/panels/singlestat/editor.html');
    $scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');

    // Set and populate defaults
    var _d = {
      links: [],
      maxDataPoints: 100,
      interval: null,
      targets: [{}],
      cacheTimeout: null,
      format: 'none',
      prefix: '',
      postfix: '',
      nullText: null,
      valueMaps: [
        { value: 'null', op: '=', text: 'N/A' }
      ],
      nullPointMode: 'connected',
      valueName: 'avg',
      prefixFontSize: '50%',
      valueFontSize: '80%',
      postfixFontSize: '50%',
      thresholds: '',
      colorBackground: false,
      colorValue: false,
      colors: ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
      sparkline: {
        show: false,
        full: false,
        lineColor: 'rgb(31, 120, 193)',
        fillColor: 'rgba(31, 118, 189, 0.18)',
      }
    };

    _.defaults($scope.panel, _d);
    $scope.unitFormats = kbn.getUnitFormats();

    $scope.setUnitFormat = function(subItem) {
      $scope.panel.format = subItem.value;
      $scope.render();
    };

    $scope.init = function() {
      panelSrv.init($scope);
    };

    $scope.refreshData = function(datasource) {
      panelHelper.updateTimeRange($scope);

      return panelHelper.issueMetricQuery($scope, datasource)
        .then($scope.dataHandler)
        .then(null, function() {
          $scope.render();
        });
    };

    $scope.loadSnapshot = function(snapshotData) {
      panelHelper.updateTimeRange($scope);
      $scope.dataHandler(snapshotData);
    };

    $scope.dataHandler = function(results) {
      $scope.series = _.map(results.data, $scope.seriesHandler);
      $scope.render();
    };

    $scope.seriesHandler = function(seriesData) {
      var series = new TimeSeries({
        datapoints: seriesData.datapoints,
        alias: seriesData.target,
      });

      series.flotpairs = series.getFlotPairs($scope.panel.nullPointMode);

      return series;
    };

    $scope.setColoring = function(options) {
      if (options.background) {
        $scope.panel.colorValue = false;
        $scope.panel.colors = ['rgba(71, 212, 59, 0.4)', 'rgba(245, 150, 40, 0.73)', 'rgba(225, 40, 40, 0.59)'];
      }
      else {
        $scope.panel.colorBackground = false;
        $scope.panel.colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)'];
      }
      $scope.render();
    };

    $scope.invertColorOrder = function() {
      var tmp = $scope.panel.colors[0];
      $scope.panel.colors[0] = $scope.panel.colors[2];
      $scope.panel.colors[2] = tmp;
      $scope.render();
    };

    $scope.getDecimalsForValue = function(value) {
      if ($scope.panel.decimals) {
        return { decimals: $scope.panel.decimals, scaledDecimals: null };
      }

      var delta = value / 2;
      var dec = -Math.floor(Math.log(delta) / Math.LN10);

      var magn = Math.pow(10, -dec),
          norm = delta / magn, // norm is between 1.0 and 10.0
          size;

      if (norm < 1.5) {
        size = 1;
      } else if (norm < 3) {
        size = 2;
        // special case for 2.5, requires an extra decimal
        if (norm > 2.25) {
          size = 2.5;
          ++dec;
        }
      } else if (norm < 7.5) {
        size = 5;
      } else {
        size = 10;
      }

      size *= magn;

      // reduce starting decimals if not needed
      if (Math.floor(value) === value) { dec = 0; }

      var result = {};
      result.decimals = Math.max(0, dec);
      result.scaledDecimals = result.decimals - Math.floor(Math.log(size) / Math.LN10) + 2;

      return result;
    };

    $scope.render = function() {
      var data = {};

      if (!$scope.series || $scope.series.length === 0) {
        data.flotpairs = [];
        data.mainValue = Number.NaN;
        data.mainValueFormated = $scope.getFormatedValue(null);
      }
      else {
        var series = $scope.series[0];
        data.mainValue = series.stats[$scope.panel.valueName];
        data.mainValueFormated = $scope.getFormatedValue(data.mainValue);
        data.flotpairs = series.flotpairs;
      }

      data.thresholds = $scope.panel.thresholds.split(',').map(function(strVale) {
        return Number(strVale.trim());
      });

      data.colorMap = $scope.panel.colors;

      $scope.data = data;
      $scope.$broadcast('render');
    };

    $scope.getFormatedValue = function(mainValue) {

      // first check value to text mappings
      for(var i = 0; i < $scope.panel.valueMaps.length; i++) {
        var map = $scope.panel.valueMaps[i];
        // special null case
        if (map.value === 'null') {
          if (mainValue === null || mainValue === void 0) {
            return map.text;
          }
          continue;
        }
        // value/number to text mapping
        var value = parseFloat(map.value);
        if (value === mainValue) {
          return map.text;
        }
      }

      if (mainValue === null || mainValue === void 0) {
        return "no value";
      }

      var decimalInfo = $scope.getDecimalsForValue(mainValue);
      var formatFunc = kbn.valueFormats[$scope.panel.format];
      return formatFunc(mainValue, decimalInfo.decimals, decimalInfo.scaledDecimals);
    };

    $scope.removeValueMap = function(map) {
      var index = _.indexOf($scope.panel.valueMaps, map);
      $scope.panel.valueMaps.splice(index, 1);
      $scope.render();
    };

    $scope.addValueMap = function() {
      $scope.panel.valueMaps.push({value: '', op: '=', text: '' });
    };

    $scope.init();
  });
});
<commit_msg>Singlestat panel: Fixed error handling, when query fail do not show last value, Fixes #1647<commit_after>define([
  'angular',
  'app',
  'lodash',
  'components/timeSeries',
  'kbn',
  'components/panelmeta',
  './singleStatPanel',
],
function (angular, app, _, TimeSeries, kbn, PanelMeta) {
  'use strict';

  var module = angular.module('grafana.panels.singlestat');
  app.useModule(module);

  module.directive('grafanaPanelSinglestat', function() {
    return {
      controller: 'SingleStatCtrl',
      templateUrl: 'app/panels/singlestat/module.html',
    };
  });

  module.controller('SingleStatCtrl', function($scope, panelSrv, panelHelper) {

    $scope.panelMeta = new PanelMeta({
      panelName: 'Singlestat',
      editIcon:  "fa fa-dashboard",
      fullscreen: true,
      metricsEditor: true
    });

    $scope.fontSizes = ['20%', '30%','50%','70%','80%','100%', '110%', '120%', '150%', '170%', '200%'];

    $scope.panelMeta.addEditorTab('Options', 'app/panels/singlestat/editor.html');
    $scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');

    // Set and populate defaults
    var _d = {
      links: [],
      maxDataPoints: 100,
      interval: null,
      targets: [{}],
      cacheTimeout: null,
      format: 'none',
      prefix: '',
      postfix: '',
      nullText: null,
      valueMaps: [
        { value: 'null', op: '=', text: 'N/A' }
      ],
      nullPointMode: 'connected',
      valueName: 'avg',
      prefixFontSize: '50%',
      valueFontSize: '80%',
      postfixFontSize: '50%',
      thresholds: '',
      colorBackground: false,
      colorValue: false,
      colors: ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
      sparkline: {
        show: false,
        full: false,
        lineColor: 'rgb(31, 120, 193)',
        fillColor: 'rgba(31, 118, 189, 0.18)',
      }
    };

    _.defaults($scope.panel, _d);
    $scope.unitFormats = kbn.getUnitFormats();

    $scope.setUnitFormat = function(subItem) {
      $scope.panel.format = subItem.value;
      $scope.render();
    };

    $scope.init = function() {
      panelSrv.init($scope);
    };

    $scope.refreshData = function(datasource) {
      panelHelper.updateTimeRange($scope);

      return panelHelper.issueMetricQuery($scope, datasource)
        .then($scope.dataHandler, function(err) {
          $scope.series = [];
          $scope.render();
          throw err;
        });
    };

    $scope.loadSnapshot = function(snapshotData) {
      panelHelper.updateTimeRange($scope);
      $scope.dataHandler(snapshotData);
    };

    $scope.dataHandler = function(results) {
      $scope.series = _.map(results.data, $scope.seriesHandler);
      $scope.render();
    };

    $scope.seriesHandler = function(seriesData) {
      var series = new TimeSeries({
        datapoints: seriesData.datapoints,
        alias: seriesData.target,
      });

      series.flotpairs = series.getFlotPairs($scope.panel.nullPointMode);

      return series;
    };

    $scope.setColoring = function(options) {
      if (options.background) {
        $scope.panel.colorValue = false;
        $scope.panel.colors = ['rgba(71, 212, 59, 0.4)', 'rgba(245, 150, 40, 0.73)', 'rgba(225, 40, 40, 0.59)'];
      }
      else {
        $scope.panel.colorBackground = false;
        $scope.panel.colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)'];
      }
      $scope.render();
    };

    $scope.invertColorOrder = function() {
      var tmp = $scope.panel.colors[0];
      $scope.panel.colors[0] = $scope.panel.colors[2];
      $scope.panel.colors[2] = tmp;
      $scope.render();
    };

    $scope.getDecimalsForValue = function(value) {
      if ($scope.panel.decimals) {
        return { decimals: $scope.panel.decimals, scaledDecimals: null };
      }

      var delta = value / 2;
      var dec = -Math.floor(Math.log(delta) / Math.LN10);

      var magn = Math.pow(10, -dec),
          norm = delta / magn, // norm is between 1.0 and 10.0
          size;

      if (norm < 1.5) {
        size = 1;
      } else if (norm < 3) {
        size = 2;
        // special case for 2.5, requires an extra decimal
        if (norm > 2.25) {
          size = 2.5;
          ++dec;
        }
      } else if (norm < 7.5) {
        size = 5;
      } else {
        size = 10;
      }

      size *= magn;

      // reduce starting decimals if not needed
      if (Math.floor(value) === value) { dec = 0; }

      var result = {};
      result.decimals = Math.max(0, dec);
      result.scaledDecimals = result.decimals - Math.floor(Math.log(size) / Math.LN10) + 2;

      return result;
    };

    $scope.render = function() {
      var data = {};

      if (!$scope.series || $scope.series.length === 0) {
        data.flotpairs = [];
        data.mainValue = Number.NaN;
        data.mainValueFormated = $scope.getFormatedValue(null);
      }
      else {
        var series = $scope.series[0];
        data.mainValue = series.stats[$scope.panel.valueName];
        data.mainValueFormated = $scope.getFormatedValue(data.mainValue);
        data.flotpairs = series.flotpairs;
      }

      data.thresholds = $scope.panel.thresholds.split(',').map(function(strVale) {
        return Number(strVale.trim());
      });

      data.colorMap = $scope.panel.colors;

      $scope.data = data;
      $scope.$broadcast('render');
    };

    $scope.getFormatedValue = function(mainValue) {

      // first check value to text mappings
      for(var i = 0; i < $scope.panel.valueMaps.length; i++) {
        var map = $scope.panel.valueMaps[i];
        // special null case
        if (map.value === 'null') {
          if (mainValue === null || mainValue === void 0) {
            return map.text;
          }
          continue;
        }
        // value/number to text mapping
        var value = parseFloat(map.value);
        if (value === mainValue) {
          return map.text;
        }
      }

      if (mainValue === null || mainValue === void 0) {
        return "no value";
      }

      var decimalInfo = $scope.getDecimalsForValue(mainValue);
      var formatFunc = kbn.valueFormats[$scope.panel.format];
      return formatFunc(mainValue, decimalInfo.decimals, decimalInfo.scaledDecimals);
    };

    $scope.removeValueMap = function(map) {
      var index = _.indexOf($scope.panel.valueMaps, map);
      $scope.panel.valueMaps.splice(index, 1);
      $scope.render();
    };

    $scope.addValueMap = function() {
      $scope.panel.valueMaps.push({value: '', op: '=', text: '' });
    };

    $scope.init();
  });
});
<|endoftext|>


<commit_before>/**
* Popover View Usage Example
* This is a block helper so it can be used like so:
*
*    {{#view App.PopoverView title="Test Title"}}
*      Hover over me.
*

*        This is the contention popover content. View Id: {{view.elementId}}
*

*  {{/view}}
*
* You may also specify the parameter dataTrigger as being 'hover', 'click' is default:
* {{#view App.PopoverView title="Test Title" dataTrigger="hover"}}
*
*/

App.PopoverView = Ember.View.extend({
  classNames: ['inline-block', 'tooltip-container', 'popover-container'],
  classNameBindings: ['customId'],
  tagName: 'div',
  attributeBindings: ['title', 'dataTrigger:data-trigger', 'dataHtml:data-html','dataSelector:data-selector', 'dataContainer:data-container', 'dataPlacement:data-placement', 'dataContent:data-content', 'displayFlag', 'trigger', 'dataToggle:data-toggle'],
  toggle: false,
  dataTrigger: 'click',
  popoverContent: function() {
    var self = this;
    var $content = $('.' + self.get('customId') + ' > ' + '.popover-content');
    return $content.html();
/*
      return function() {
        var $content = $('#' + self.get('elementId') + ' > ' + '.popover-content');
        console.log('content.html', $content.html());
        return $content.html();
      }
*/
  }.property('customId', 'toggle'),
  popoverArguments: function() {
    return {
      container: 'body',
      html: true,
      trigger: 'manual',
      content: this.get('popoverContent'),
      template: '

 <button type="button" class="close">×</button>

'
    }
  }.property('popoverContent', 'customId'),
  mouseEnter: function (event) {
    //hide all other popovers
    $(".popover").remove();
    this.set('toggle', true);
    $('.' + this.get('customId')).popover(this.get('popoverArguments')).popover('show');

    $('.popover-close').on('click', function (e) {
      $(".popover").remove();
    });

    $('.popover-close').on('mouseleave', function (e) {
      $(".popover").remove();
    });
  },
  reloadObserver: function(event) {
    if (this.get('toggle')) {
      Ember.run.scheduleOnce('afterRender', this, function() {
        $('.' + this.get('customId')).popover(this.get('popoverArguments')).popover('show');
      });
    }
  }.observes('controller.vcpus'),
  init: function() {
    this.set('customId', App.uuid());
    var self = this;

    Ember.run.schedule('afterRender', this, function() {
      $('body').on('click', function (e) {
        if (!$(e.target).hasClass('popover-content') && !($(e.target).parents().hasClass('popover-content')) ) {
          $('.' + self.get('customId')).popover(self.get('popoverArguments')).popover('hide');
        }
      });
    });

    this._super();
  }
});
<commit_msg>Correct event binding from popover-close to popover-content<commit_after>/**
* Popover View Usage Example
* This is a block helper so it can be used like so:
*
*    {{#view App.PopoverView title="Test Title"}}
*      Hover over me.
*

*        This is the contention popover content. View Id: {{view.elementId}}
*

*  {{/view}}
*
* You may also specify the parameter dataTrigger as being 'hover', 'click' is default:
* {{#view App.PopoverView title="Test Title" dataTrigger="hover"}}
*
*/

App.PopoverView = Ember.View.extend({
  classNames: ['inline-block', 'tooltip-container', 'popover-container'],
  classNameBindings: ['customId'],
  tagName: 'div',
  attributeBindings: ['title', 'dataTrigger:data-trigger', 'dataHtml:data-html','dataSelector:data-selector', 'dataContainer:data-container', 'dataPlacement:data-placement', 'dataContent:data-content', 'displayFlag', 'trigger', 'dataToggle:data-toggle'],
  toggle: false,
  dataTrigger: 'click',
  popoverContent: function() {
    var self = this;
    var $content = $('.' + self.get('customId') + ' > ' + '.popover-content');
    return $content.html();
/*
      return function() {
        var $content = $('#' + self.get('elementId') + ' > ' + '.popover-content');
        console.log('content.html', $content.html());
        return $content.html();
      }
*/
  }.property('customId', 'toggle'),
  popoverArguments: function() {
    return {
      container: 'body',
      html: true,
      trigger: 'manual',
      content: this.get('popoverContent'),
      template: '

 <button type="button" class="close">×</button>

'
    }
  }.property('popoverContent', 'customId'),
  mouseEnter: function (event) {
    //hide all other popovers
    $(".popover").remove();
    this.set('toggle', true);
    $('.' + this.get('customId')).popover(this.get('popoverArguments')).popover('show');

    $('.popover-close').on('click', function (e) {
      $(".popover").remove();
    });

    $('.popover-content').on('mouseleave', function (e) {
      $(".popover").remove();
    });
  },
  reloadObserver: function(event) {
    if (this.get('toggle')) {
      Ember.run.scheduleOnce('afterRender', this, function() {
        $('.' + this.get('customId')).popover(this.get('popoverArguments')).popover('show');
      });
    }
  }.observes('controller.vcpus'),
  init: function() {
    this.set('customId', App.uuid());
    var self = this;

    Ember.run.schedule('afterRender', this, function() {
      $('body').on('click', function (e) {
        if (!$(e.target).hasClass('popover-content') && !($(e.target).parents().hasClass('popover-content')) ) {
          $('.' + self.get('customId')).popover(self.get('popoverArguments')).popover('hide');
        }
      });
    });

    this._super();
  }
});
<|endoftext|>


<commit_before>import _ from 'lodash';
import bluebird from 'bluebird';

let stopUploading = false;

export default {
  list() {
    this.NewLibConnection
      .Hosting
      .please()
      .list()
      .ordering('desc')
      .then(this.completed)
      .catch(this.failure);
  },

  create(params) {
    this.NewLibConnection
      .Hosting
      .please()
      .create(params)
      .then((createdHosting) => {
        if (params.is_default) {
          return this.NewLibConnection
            .Hosting
            .please()
            .setDefault({ id: createdHosting.id })
            .then(this.completed)
            .catch(this.failure);
        }
        return this.completed(createdHosting);
      })
      .catch(this.failure);
  },

  update(id, params) {
    this.NewLibConnection
      .Hosting
      .please()
      .update({ id }, params)
      .then((updatedHosting) => {
        if (params.is_default) {
          return this.NewLibConnection
            .Hosting
            .please()
            .setDefault({ id: updatedHosting.id })
            .then(this.completed)
            .catch(this.failure);
        }
        return this.completed(updatedHosting);
      })
      .catch(this.failure);
  },

  remove(items) {
    const promises = _.map(items, (item) => this.NewLibConnection.Hosting.please().delete({ id: item.id }));

    this.Promise
      .all(promises)
      .then(this.completed)
      .catch(this.failure);
  },

  cancelUploading() {
    stopUploading = true;
  },

  uploadFiles(hostingId, files) {
    const all = this.NewLibConnection.HostingFile.please().all({ hostingId }, { ordering: 'desc' });

    all.on('stop', (fetchedFiles) => {
      bluebird.mapSeries(files, (file, currentFileIndex) => {
        const lastFileIndex = files.length - 1;
        const isFinished = currentFileIndex === lastFileIndex;
        const fileToUpdate = _.find(fetchedFiles, { path: file.path });
        const payload = { file: this.NewLibConnection.file(file), path: file.path };
        const errorCallback = ({ errors, message }) => {
          this.failure(
            {
              isFinished,
              currentFileIndex,
              lastFileIndex
            },
            {
              file,
              errors,
              message
            }
          );
        };

        if (stopUploading) {
          if (currentFileIndex === lastFileIndex) {
            stopUploading = false;
            return this.completed({
              isFinished: true,
              isCanceled: true
            });
          }
          return true;
        }

        if (fileToUpdate) {
          return this.NewLibConnection
            .HostingFile
            .please()
            .update({ id: fileToUpdate.id, hostingId }, payload)
            .then(() => this.completed({
              isFinished,
              currentFileIndex,
              lastFileIndex
            }))
            .catch(errorCallback);
        }

        return this.NewLibConnection
          .HostingFile
          .please()
          .upload({ hostingId }, payload)
          .then(() => this.completed({
            isFinished,
            currentFileIndex,
            lastFileIndex
          }))
          .catch(errorCallback);
      });
    });
  },

  listFiles(hostingId) {
    const data = {};
    const all = this.NewLibConnection.HostingFile.please().all({ hostingId }, { ordering: 'desc' });

    all.on('stop', (files) => {
      data.files = files;

      this.NewLibConnection
        .Hosting
        .please()
        .get({ id: hostingId })
        .then((hostingDetails) => {
          data.hostingDetails = hostingDetails;

          this.completed(data);
        })
        .catch(this.failure);
    });
  },

  removeFiles(files, hostingId) {
    const lastFileIndex = files.length - 1;

    bluebird.mapSeries(files, (file, currentFileIndex) => {
      const hasNextFile = files.length > currentFileIndex + 1;

      return this.NewLibConnection
        .HostingFile
        .please()
        .delete({ hostingId, id: file.id })
        .then(() => this.completed({
          isFinished: !hasNextFile,
          currentFileIndex,
          lastFileIndex
        }))
        .catch(this.failure);
    });
  },

  publish(id) {
    this.NewLibConnection
      .Hosting
      .please()
      .setDefault({ id })
      .then(this.completed)
      .catch(this.failure);
  }
};
<commit_msg>[DASH-2293] Fix cancel uploading action<commit_after>import _ from 'lodash';
import bluebird from 'bluebird';

let stopUploading = false;

export default {
  list() {
    this.NewLibConnection
      .Hosting
      .please()
      .list()
      .ordering('desc')
      .then(this.completed)
      .catch(this.failure);
  },

  create(params) {
    this.NewLibConnection
      .Hosting
      .please()
      .create(params)
      .then((createdHosting) => {
        if (params.is_default) {
          return this.NewLibConnection
            .Hosting
            .please()
            .setDefault({ id: createdHosting.id })
            .then(this.completed)
            .catch(this.failure);
        }
        return this.completed(createdHosting);
      })
      .catch(this.failure);
  },

  update(id, params) {
    this.NewLibConnection
      .Hosting
      .please()
      .update({ id }, params)
      .then((updatedHosting) => {
        if (params.is_default) {
          return this.NewLibConnection
            .Hosting
            .please()
            .setDefault({ id: updatedHosting.id })
            .then(this.completed)
            .catch(this.failure);
        }
        return this.completed(updatedHosting);
      })
      .catch(this.failure);
  },

  remove(items) {
    const promises = _.map(items, (item) => this.NewLibConnection.Hosting.please().delete({ id: item.id }));

    this.Promise
      .all(promises)
      .then(this.completed)
      .catch(this.failure);
  },

  cancelUploading() {
    stopUploading = true;
  },

  uploadFiles(hostingId, files) {
    const all = this.NewLibConnection.HostingFile.please().all({ hostingId }, { ordering: 'desc' });
    let cancelFileIndex = false;

    all.on('stop', (fetchedFiles) => {
      bluebird.mapSeries(files, (file, currentFileIndex) => {
        const lastFileIndex = files.length - 1;
        const isFinished = currentFileIndex === lastFileIndex;
        const fileToUpdate = _.find(fetchedFiles, { path: file.path });
        const payload = { file: this.NewLibConnection.file(file), path: file.path };
        const errorCallback = ({ errors, message }) => {
          this.failure(
            {
              isFinished,
              currentFileIndex,
              lastFileIndex
            },
            {
              file,
              errors,
              message
            }
          );
        };

        if (stopUploading) {
          if (currentFileIndex === lastFileIndex) {
            stopUploading = false;
            return this.completed({
              isFinished: true,
              isCanceled: true,
              currentFileIndex: cancelFileIndex,
              lastFileIndex: cancelFileIndex
            });
          }
          if (!cancelFileIndex) {
            cancelFileIndex = currentFileIndex;
          }
          return true;
        }

        if (fileToUpdate) {
          return this.NewLibConnection
            .HostingFile
            .please()
            .update({ id: fileToUpdate.id, hostingId }, payload)
            .then(() => this.completed({
              isFinished,
              currentFileIndex,
              lastFileIndex
            }))
            .catch(errorCallback);
        }

        return this.NewLibConnection
          .HostingFile
          .please()
          .upload({ hostingId }, payload)
          .then(() => this.completed({
            isFinished,
            currentFileIndex,
            lastFileIndex
          }))
          .catch(errorCallback);
      });
    });
  },

  listFiles(hostingId) {
    const data = {};
    const all = this.NewLibConnection.HostingFile.please().all({ hostingId }, { ordering: 'desc' });

    all.on('stop', (files) => {
      data.files = files;

      this.NewLibConnection
        .Hosting
        .please()
        .get({ id: hostingId })
        .then((hostingDetails) => {
          data.hostingDetails = hostingDetails;

          this.completed(data);
        })
        .catch(this.failure);
    });
  },

  removeFiles(files, hostingId) {
    const lastFileIndex = files.length - 1;

    bluebird.mapSeries(files, (file, currentFileIndex) => {
      const hasNextFile = files.length > currentFileIndex + 1;

      return this.NewLibConnection
        .HostingFile
        .please()
        .delete({ hostingId, id: file.id })
        .then(() => this.completed({
          isFinished: !hasNextFile,
          currentFileIndex,
          lastFileIndex
        }))
        .catch(this.failure);
    });
  },

  publish(id) {
    this.NewLibConnection
      .Hosting
      .please()
      .setDefault({ id })
      .then(this.completed)
      .catch(this.failure);
  }
};
<|endoftext|>


<commit_before>'use strict';

class BotPlug {
    constructor( bot ) {
        this.bot = bot;

        this.aliasList = {
            gustin : 'gust1n',
            sälen : 'theseal',
            jwilsson : 'mcgurk'
        };

        this.names = {};

        this.setupNameDetection();
    }

    setupNameDetection(){
        this.bot.addListener( 'names', ( channel, nicks ) => {
            this.names[ channel ] = [];

            for( let name in nicks ){
                this.names[ channel ].push( name.toLowerCase() );
            }
        } );

        this.bot.addListener( 'join', ( channel, nick ) => {
            if( this.names[ channel ] ){
                this.names[ channel ].push( nick.toLowerCase() );
            }
        } );

        this.bot.addListener( 'quit', ( nick, reason, channels ) => {
            for( let i = 0; i < channels.length; i = i + 1 ){
                let channel = channels[ i ];

                if( this.names[ channel ] ){
                    this.names[ channel ].splice( this.names[ channel ].indexOf( nick ), 1 );
                }
            }
        } );

        this.bot.addListener( 'part', ( channel, nick ) => {
            if( this.names[ channel ] ){
                this.names[ channel ].splice( this.names[ channel ].indexOf( nick ), 1 );
            }
        } );

        this.bot.addListener( 'kick', ( channel, nick ) => {
            if( this.names[ channel ] ){
                this.names[ channel ].splice( this.names[ channel ].indexOf( nick ), 1 );
            }
        } );

        this.bot.addListener( 'kill', ( nick, reason, channels ) => {
            for( let i = 0; i < channels.length; i = i + 1 ){
                let channel = channels[ i ];

                if( this.names[ channel ] ){
                    this.names[ channel ].splice( this.names[ channel ].indexOf( nick ), 1 );
                }
            }
        } );

        this.bot.addListener( 'nick', ( oldnick, newnick, channels ) => {
            for( let i = 0; i < channels.length; i = i + 1 ){
                let channel = channels[ i ];

                if( this.names[ channel ] ){
                    this.names[ channel ][ this.names[ channel ].indexOf( oldnick ) ] = newnick.toLowerCase();
                }
            }
        } );
    }

    sendMessageToChannel( channel, message ) {
        this.bot.say( channel, message.trim() );
    }

    detectMessage( callback ){
        // callback gets called with nick, text, message
        for( let channel in this.bot.opt.channels ){
            if( this.bot.opt.channels.hasOwnProperty( channel ) ){
                this.bot.addListener( 'message' + this.bot.opt.channels[ channel ], callback );
            }
        }
    }

    detectMessageToUser( callback ){
        this.detectMessage( ( nick, text, message ) => {
            let usersInMessage = this.checkIfMessageToUser( nick, message.args[ 0 ], text );
            if( usersInMessage.length > 0 ){
                callback( usersInMessage, nick, text );
            }
        });
    }

    checkIfMessageToUser( from, channel, message ){
        let formattedMessage = message.toLowerCase();
        let namesInMessage = [];
        let formattedFrom = from.toLowerCase();
        let validNamesInMessage = [];

        // Add any user that might be in the channel
        for( let i = 0; i < this.names[ channel ].length; i = i + 1 ){
            if( formattedMessage.indexOf( this.names[ channel ][ i ] ) > -1 ){
                if( namesInMessage.indexOf( this.names[ channel ][ i ] ) === -1 ){
                    namesInMessage.push( this.names[ channel ][ i ] );
                }
            }
        }

        // Add some aliases
        for( let name in this.aliasList ){
            if( formattedMessage.indexOf( name ) !== -1 ){
                if( namesInMessage.indexOf( name ) === -1 ){
                    namesInMessage.push( this.aliasList[ name ] );
                }
            }
        }

        // Remove the sender if it's there
        for( let i = 0; i < namesInMessage.length; i = i + 1 ){
            if( namesInMessage[ i ] === formattedFrom ){
                console.log( 'Found a message from ' + from + ' with ' + from + ' in it, skipping that user.' );
            } else {
                validNamesInMessage.push( namesInMessage[ i ] );
            }
        }

        return validNamesInMessage;
    }
}

module.exports = BotPlug;
<commit_msg>Add method to send message to all channels<commit_after>'use strict';

class BotPlug {
    constructor( bot ) {
        this.bot = bot;

        this.aliasList = {
            gustin : 'gust1n',
            sälen : 'theseal',
            jwilsson : 'mcgurk'
        };

        this.names = {};

        this.setupNameDetection();
    }

    setupNameDetection(){
        this.bot.addListener( 'names', ( channel, nicks ) => {
            this.names[ channel ] = [];

            for( let name in nicks ){
                this.names[ channel ].push( name.toLowerCase() );
            }
        } );

        this.bot.addListener( 'join', ( channel, nick ) => {
            if( this.names[ channel ] ){
                this.names[ channel ].push( nick.toLowerCase() );
            }
        } );

        this.bot.addListener( 'quit', ( nick, reason, channels ) => {
            for( let i = 0; i < channels.length; i = i + 1 ){
                let channel = channels[ i ];

                if( this.names[ channel ] ){
                    this.names[ channel ].splice( this.names[ channel ].indexOf( nick ), 1 );
                }
            }
        } );

        this.bot.addListener( 'part', ( channel, nick ) => {
            if( this.names[ channel ] ){
                this.names[ channel ].splice( this.names[ channel ].indexOf( nick ), 1 );
            }
        } );

        this.bot.addListener( 'kick', ( channel, nick ) => {
            if( this.names[ channel ] ){
                this.names[ channel ].splice( this.names[ channel ].indexOf( nick ), 1 );
            }
        } );

        this.bot.addListener( 'kill', ( nick, reason, channels ) => {
            for( let i = 0; i < channels.length; i = i + 1 ){
                let channel = channels[ i ];

                if( this.names[ channel ] ){
                    this.names[ channel ].splice( this.names[ channel ].indexOf( nick ), 1 );
                }
            }
        } );

        this.bot.addListener( 'nick', ( oldnick, newnick, channels ) => {
            for( let i = 0; i < channels.length; i = i + 1 ){
                let channel = channels[ i ];

                if( this.names[ channel ] ){
                    this.names[ channel ][ this.names[ channel ].indexOf( oldnick ) ] = newnick.toLowerCase();
                }
            }
        } );
    }

    sendMessageToAllChannels( message ){
        for( let i = 0; i < this.bot.opt.channels.length; i = i + 1 ){
            this.sendMessageToChannel( this.bot.opt.channels[ i ], message );
        }
    }

    sendMessageToChannel( channel, message ) {
        this.bot.say( channel, message.trim() );
    }

    detectMessage( callback ){
        // callback gets called with nick, text, message
        for( let channel in this.bot.opt.channels ){
            if( this.bot.opt.channels.hasOwnProperty( channel ) ){
                this.bot.addListener( 'message' + this.bot.opt.channels[ channel ], callback );
            }
        }
    }

    detectMessageToUser( callback ){
        this.detectMessage( ( nick, text, message ) => {
            let usersInMessage = this.checkIfMessageToUser( nick, message.args[ 0 ], text );
            if( usersInMessage.length > 0 ){
                callback( usersInMessage, nick, text );
            }
        });
    }

    checkIfMessageToUser( from, channel, message ){
        let formattedMessage = message.toLowerCase();
        let namesInMessage = [];
        let formattedFrom = from.toLowerCase();
        let validNamesInMessage = [];

        // Add any user that might be in the channel
        for( let i = 0; i < this.names[ channel ].length; i = i + 1 ){
            if( formattedMessage.indexOf( this.names[ channel ][ i ] ) > -1 ){
                if( namesInMessage.indexOf( this.names[ channel ][ i ] ) === -1 ){
                    namesInMessage.push( this.names[ channel ][ i ] );
                }
            }
        }

        // Add some aliases
        for( let name in this.aliasList ){
            if( formattedMessage.indexOf( name ) !== -1 ){
                if( namesInMessage.indexOf( name ) === -1 ){
                    namesInMessage.push( this.aliasList[ name ] );
                }
            }
        }

        // Remove the sender if it's there
        for( let i = 0; i < namesInMessage.length; i = i + 1 ){
            if( namesInMessage[ i ] === formattedFrom ){
                console.log( 'Found a message from ' + from + ' with ' + from + ' in it, skipping that user.' );
            } else {
                validNamesInMessage.push( namesInMessage[ i ] );
            }
        }

        return validNamesInMessage;
    }
}

module.exports = BotPlug;
<|endoftext|>


<commit_before>
const { spawn } = require('child_process');
const moment = require('moment'); // require

// Helpers Container
let Helpers = {};

/**
 * Convert units to byte
 * @param {*} meminfo
 */
Helpers.unitConverter = (meminfo) => {
    const [value, unit] = meminfo;
    switch (unit) {
      case "EB":
        return 1024 * value;
      case "KB":
        return 1024 * value;
      case "MB":
        return 1000000 * value;
      case "GB":
        return 1000000000 * value;
      default:
        throw new Error("Cannot determine unit size");
    }
};

/**
 * Retrieve memory info from Slurm's seff plugin
 * @param {*} seffInfo
 */
Helpers.getSeffMem = (seffInfo) => {
  // Regular expression for Memory Utilized retrieval
  let seffParam = new RegExp(/[a-z A-Z]+(:) [0-9]+([.])[0-9]+ (EB|KB|MB|GB)/gi);

  let arrSeffInfo = seffInfo.split(/\n/);

  // Iterate the list of seff params and retrieve 'Memory Utilized' value
  let getMemInfo = arrSeffInfo.filter( val => {
    let searchMemInfo = seffParam.test(val);
    if (searchMemInfo === true) {
      return val;
    }
    return false;
  });

  let defaultMem = ['0.00', 'MB'];

  getMemInfo = getMemInfo.length !== 0 ? getMemInfo : null;

  // Separate the mem value and the unit then convert to bytes and return
  let splitMemInfo = getMemInfo !== null ? getMemInfo[0].split(":")[1].trim().split(" ", 2) : defaultMem;
  let memInfoInBytes = Helpers.unitConverter(splitMemInfo);
  splitMemInfo[1] = splitMemInfo[1].replace('MB', 'M');
  splitMemInfo[1] = splitMemInfo[1].replace('EB', 'K')
  splitMemInfo[1] = splitMemInfo[1].replace('GB', 'G')

  return {
    bytes: memInfoInBytes,
    raw: splitMemInfo.join("")
  };
};

Helpers.injectParams = async (responseObj) => {
  let result = [];
  let seffQueryPerJobId;
  return new Promise((resolve, reject) => {

     responseObj.forEach((obj) => {
      seffQueryPerJobId = spawn('seff', ['-j', obj._id]);

      seffQueryPerJobId.stdout.on('data', seffInfoStream => {
        obj.mem_bytes = Helpers.getSeffMem(`${seffInfoStream}`).bytes;
        obj.mem_used = Helpers.getSeffMem(`${seffInfoStream}`).raw;

        result.push(obj)
      });
    });

    seffQueryPerJobId.on('close', code => {
      resolve(result);
    });
  });
}

/**
 * Convert Epoch to unix timestamp
 * @param {*} value
 */
Helpers.toTimeStamp = (time) => {
    let dateObj = new Date(time);
    return dateObj.getTime();
};

/**
 * Check if a given item(Application name) exists among the list of applications fetched
 * and return its object information
 * @param {*} obj Object
 * @param {*} item String
 */
Helpers.checkIfAppExists = (obj, item) => {
  let result = {};

  let apps = obj.map((data) => {
    return data.Name;
  });

  let checker = apps.includes(item);

  result.appNames = apps;
  result.exists = checker;

  if (checker) {
    result.index = apps.indexOf(item);
    const { _id, Name } = obj[result.index];
    result.data = { _id, Name };
  }

  return result;
};

/**
 * pluralize words
 * @param {*} size Number
 * @param {*} word String
 */
Helpers.pluralize = (length, word) => {
  return (length > 1 || length == 0 ) ? ((length === 1) ? `${word}` : `${word}s`) : `${word}`;
};

/**
 * Get current timestamp
 */
Helpers.timestamp = () => {
  return moment().format('YYYY-MM-DD HH:mm:ss');;
}

/**
 * Increment time by seconds
 * @param {*} timestamp Date
 * @param {*} increment Milliseconds
 */
Helpers.fromDateTime = (timestamp, increment) => {
  const currentDate = timestamp + increment;
  const newDate = moment(currentDate).format('YYYY-MM-DD HH:mm:ss');
  return newDate;
};

/**
 *
 * @param {*} status String - sucess | error | process
 * @param {*} message String
 */
Helpers.console = (...data) => {
  let status = data[0];
  let message = data[1];

  const errorCode = '\x1b[31m%s\x1b[0m';
  const successCode = '\x1b[32m%s\x1b[0m';
  const processCode = '\x1b[34m%s\x1b[0m';
  const normalCode = '\x1b[35m%s\x1b[0m';

  let lCaseString = status.toLowerCase();

  switch(lCaseString){
    case 'success':
      console.log(successCode, '==>', message);
      break;
    case 'error':
      console.log(errorCode, '==>', message);
      break;
    case 'process':
      console.log(processCode, '==>', message);
      break;
    case 'normal':
      console.log(normalCode, '==>', message);
      break;
    default:
      console.log(message);
  }
  console.log('\x1b[0m');
};

Helpers.out = {
  error: (message) =>  Helpers.console('error', message),
  success: (message) => Helpers.console('success', message),
  process: (message) => Helpers.console('process', message),
  normal: (message) => Helpers.console('normal', message)
};

module.exports = Helpers;<commit_msg>Updated logs method in helper class<commit_after>
const { spawn } = require('child_process');
<<<<<<< HEAD
const moment = require('moment'); // require

// Helpers Container
let Helpers = {};
=======
const Helpers = {};
>>>>>>> codeRefactor

/**
 * Convert units to byte
 * @param {*} meminfo
 */
Helpers.unitConverter = (meminfo) => {
    const [value, unit] = meminfo;
    switch (unit) {
      case "EB":
        return 1024 * value;
      case "KB":
        return 1024 * value;
      case "MB":
        return 1000000 * value;
      case "GB":
        return 1000000000 * value;
      default:
        throw new Error("Cannot determine unit size");
    }
};

/**
 * Retrieve memory info from Slurm's seff plugin
 * @param {*} seffInfo
 */
Helpers.getSeffMem = (seffInfo) => {
  // Regular expression for Memory Utilized retrieval
  let seffParam = new RegExp(/[a-z A-Z]+(:) [0-9]+([.])[0-9]+ (EB|KB|MB|GB)/gi);

  let arrSeffInfo = seffInfo.split(/\n/);

  // Iterate the list of seff params and retrieve 'Memory Utilized' value
  let getMemInfo = arrSeffInfo.filter( val => {
    let searchMemInfo = seffParam.test(val);
    if (searchMemInfo === true) {
      return val;
    }
    return false;
  });

  let defaultMem = ['0.00', 'MB'];

  getMemInfo = getMemInfo.length !== 0 ? getMemInfo : null;

  // Separate the mem value and the unit then convert to bytes and return
  let splitMemInfo = getMemInfo !== null ? getMemInfo[0].split(":")[1].trim().split(" ", 2) : defaultMem;
  let memInfoInBytes = Helpers.unitConverter(splitMemInfo);
  splitMemInfo[1] = splitMemInfo[1].replace('MB', 'M');
  splitMemInfo[1] = splitMemInfo[1].replace('EB', 'K')
  splitMemInfo[1] = splitMemInfo[1].replace('GB', 'G')

  return {
    bytes: memInfoInBytes,
    raw: splitMemInfo.join("")
  };
};

Helpers.injectParams = async (responseObj) => {
  let result = [];
  let seffQueryPerJobId;
  return new Promise((resolve, reject) => {

     responseObj.forEach((obj) => {
      seffQueryPerJobId = spawn('seff', ['-j', obj._id]);

      seffQueryPerJobId.stdout.on('data', seffInfoStream => {
        obj.mem_bytes = Helpers.getSeffMem(`${seffInfoStream}`).bytes;
        obj.mem_used = Helpers.getSeffMem(`${seffInfoStream}`).raw;

        result.push(obj)
      });
    });

    seffQueryPerJobId.on('close', code => {
      resolve(result);
    });
  });
}

/**
 * Convert Epoch to unix timestamp
 * @param {*} value
 */
Helpers.toTimeStamp = (time) => {
    let dateObj = new Date(time);
    return dateObj.getTime();
};

/**
 * Check if a given item(Application name) exists among the list of applications fetched
 * and return its object information
 * @param {*} obj Object
 * @param {*} item String
 */
Helpers.checkIfAppExists = (obj, item) => {
  let result = {};

  let apps = obj.map((data) => {
    return data.Name;
  });

  let checker = apps.includes(item);

  result.appNames = apps;
  result.exists = checker;

  if (checker) {
    result.index = apps.indexOf(item);
    const { _id, Name } = obj[result.index];
    result.data = { _id, Name };
  }

  return result;
};

/**
 * pluralize words
 * @param {*} size Number
 * @param {*} word String
 */
Helpers.pluralize = (length, word) => {
  return (length > 1 || length == 0 ) ? ((length === 1) ? `${word}` : `${word}s`) : `${word}`;
};

/**
 * Get current timestamp
 */
Helpers.timestamp = () => {
  return moment().format('YYYY-MM-DD HH:mm:ss');;
}

/**
 * Increment time by seconds
 * @param {*} timestamp Date
 * @param {*} increment Milliseconds
 */
Helpers.fromDateTime = (timestamp, increment) => {
  const currentDate = timestamp + increment;
  const newDate = moment(currentDate).format('YYYY-MM-DD HH:mm:ss');
  return newDate;
};

/**
 *
 * @param {*} status String - sucess | error | process
 * @param {*} message String
 */
Helpers.console = (...data) => {
  let status = data[0];
  let message = data[1];

  const errorCode = '\x1b[31m%s\x1b[0m';
  const successCode = '\x1b[32m%s\x1b[0m';
  const processCode = '\x1b[34m%s\x1b[0m';
  const normalCode = '\x1b[35m%s\x1b[0m';

  let lCaseString = status.toLowerCase();

  switch(lCaseString){
    case 'success':
      console.log(successCode, '==>', message);
      break;
    case 'error':
      console.log(errorCode, '==>', message);
      break;
    case 'process':
      console.log(processCode, '==>', message);
      break;
    case 'normal':
      console.log(normalCode, '==>', message);
      break;
    default:
      console.log(message);
  }
  console.log('\x1b[0m');
};

Helpers.out = {
  error: (message) =>  Helpers.console('error', message),
  success: (message) => Helpers.console('success', message),
  process: (message) => Helpers.console('process', message),
  normal: (message) => Helpers.console('normal', message)
};

module.exports = Helpers;<|endoftext|>


<commit_before>const {createVariableRule} = require('./lib/variable-rules')

module.exports = createVariableRule('primer/borders', {
  border: {
    expects: 'a border variable',
    props: 'border{,-top,-right,-bottom,-left}',
    values: ['$border', 'none', '0'],
    components: ['border-width', 'border-style', 'border-color'],
    replacements: {
      // because shorthand border properties ¯\_(ツ)_/¯
      '$border-width $border-style $border-gray': '$border',
      '$border-width $border-gray $border-style': '$border',
      '$border-style $border-width $border-gray': '$border',
      '$border-style $border-gray $border-width': '$border',
      '$border-gray $border-width $border-style': '$border',
      '$border-gray $border-style $border-width': '$border',
      '$border-width $border-style $border-color': '$border',
      '$border-width $border-color $border-style': '$border',
      '$border-style $border-width $border-color': '$border',
      '$border-style $border-color $border-width': '$border',
      '$border-color $border-width $border-style': '$border',
      '$border-color $border-style $border-width': '$border'
    }
  },
  'border color': {
    expects: 'a border color variable',
    props: 'border{,-top,-right,-bottom,-left}-color',
    values: ['$border-*', 'transparent', 'currentColor'],
    replacements: {
      '$border-gray': '$border-color'
    }
  },
  'border style': {
    expects: 'a border style variable',
    props: 'border{,-top,-right,-bottom,-left}-style',
    values: ['$border-style', 'none']
  },
  'border width': {
    expects: 'a border width variable',
    props: 'border{,-top,-right,-bottom,-left}-width',
    values: ['$border-width*', '0']
  },
  'border radius': {
    expects: 'a border radius variable',
    props: 'border{,-{top,bottom}-{left,right}}-radius',
    values: ['$border-radius', '0', '50%', '100%']
  }
})
<commit_msg>nix 100% from border-radius values; suggest 50% instead<commit_after>const {createVariableRule} = require('./lib/variable-rules')

module.exports = createVariableRule('primer/borders', {
  border: {
    expects: 'a border variable',
    props: 'border{,-top,-right,-bottom,-left}',
    values: ['$border', 'none', '0'],
    components: ['border-width', 'border-style', 'border-color'],
    replacements: {
      // because shorthand border properties ¯\_(ツ)_/¯
      '$border-width $border-style $border-gray': '$border',
      '$border-width $border-gray $border-style': '$border',
      '$border-style $border-width $border-gray': '$border',
      '$border-style $border-gray $border-width': '$border',
      '$border-gray $border-width $border-style': '$border',
      '$border-gray $border-style $border-width': '$border',
      '$border-width $border-style $border-color': '$border',
      '$border-width $border-color $border-style': '$border',
      '$border-style $border-width $border-color': '$border',
      '$border-style $border-color $border-width': '$border',
      '$border-color $border-width $border-style': '$border',
      '$border-color $border-style $border-width': '$border'
    }
  },
  'border color': {
    expects: 'a border color variable',
    props: 'border{,-top,-right,-bottom,-left}-color',
    values: ['$border-*', 'transparent', 'currentColor'],
    replacements: {
      '$border-gray': '$border-color'
    }
  },
  'border style': {
    expects: 'a border style variable',
    props: 'border{,-top,-right,-bottom,-left}-style',
    values: ['$border-style', 'none']
  },
  'border width': {
    expects: 'a border width variable',
    props: 'border{,-top,-right,-bottom,-left}-width',
    values: ['$border-width*', '0']
  },
  'border radius': {
    expects: 'a border radius variable',
    props: 'border{,-{top,bottom}-{left,right}}-radius',
    values: ['$border-radius', '0', '50%', 'inherit'],
    replacements: {
      '100%': '50%'
    }
  }
})
<|endoftext|>


<commit_before>import { expect } from '../../spec_helper'
import { stubJSONStore } from '../../stubs'
import { sortCategories } from '../../../src/selectors'
import {
  loadCategoryPosts,
  loadDiscoverPosts,
  loadDiscoverUsers,
  getCategories,
} from '../../../src/actions/discover'
import {
  generateTabs,
  getStreamAction,
  shouldContainerUpdate,
} from '../../../src/containers/DiscoverContainer'

describe('DiscoverContainer', () => {
  context('#getStreamAction', () => {
    it('returns the correct stream action for featured and recommended', () => {
      const realAction = loadCategoryPosts()
      const featuredAction = getStreamAction('featured')
      const recommendedAction = getStreamAction('recommended')
      expect(featuredAction).to.deep.equal(realAction)
      expect(recommendedAction).to.deep.equal(realAction)
    })

    it('returns the correct stream action for recent', () => {
      const realAction = loadDiscoverPosts('recent')
      const testAction = getStreamAction('recent')
      expect(testAction).to.deep.equal(realAction)
    })

    it('returns the correct stream action for trending', () => {
      const realAction = loadDiscoverUsers('trending')
      const testAction = getStreamAction('trending')
      expect(testAction).to.deep.equal(realAction)
    })

    it('returns the correct stream action for all', () => {
      const realAction = getCategories()
      const testAction = getStreamAction('all')
      expect(testAction).to.deep.equal(realAction)
    })
  })

  context('#generateTabs', () => {
    it('returns the correct stream action for featured and recommended', () => {
      const json = stubJSONStore()
      const categories = json.categories
      const keys = Object.keys(categories)
      let primary = []
      let secondary = []
      let tertiary = []
      keys.forEach((key) => {
        const category = categories[key]
        switch (category.level) {
          case 'primary':
            primary.push(category)
            break
          case 'secondary':
            secondary.push(category)
            break
          case 'tertiary':
            tertiary.push(category)
            break
          default:
            break
        }
      })
      primary = primary.sort(sortCategories)
      secondary = secondary.sort(sortCategories)
      tertiary = tertiary.sort(sortCategories)
      const tabs = generateTabs(primary, secondary, tertiary)
      expect(tabs[0]).to.have.property('children', 'Featured')
      expect(tabs[0]).to.have.property('to', '/discover')
      expect(tabs[1]).to.have.property('children', 'Trending')
      expect(tabs[1]).to.have.property('to', '/discover/trending')
      expect(tabs[2]).to.have.property('children', 'Recent')
      expect(tabs[2]).to.have.property('to', '/discover/recent')
      expect(tabs[3]).to.have.property('kind', 'divider')
      expect(tabs[4]).to.have.property('children', 'Art')
      expect(tabs[4]).to.have.property('to', '/discover/art')
      expect(tabs[5]).to.have.property('children', 'Design')
      expect(tabs[5]).to.have.property('to', '/discover/design')
      expect(tabs[6]).to.have.property('children', 'Photography')
      expect(tabs[6]).to.have.property('to', '/discover/photography')
      expect(tabs[7]).to.have.property('children', 'Architecture')
      expect(tabs[7]).to.have.property('to', '/discover/architecture')
      expect(tabs[8]).to.have.property('children', 'Interviews')
      expect(tabs[8]).to.have.property('to', '/discover/interviews')
      expect(tabs[9]).to.have.property('children', 'Collage')
      expect(tabs[9]).to.have.property('to', '/discover/collage')
    })
  })
  context('#shouldSearchContainerUpdate', () => {
    it('returns the correct stream action for discover', () => {
      const thisProps = {
        coverDPI: 'xhdpi',
        isBeaconActive: true,
        isLoggedIn: true,
        location: 'location',
        params: 'Params',
        pageTitle: 'PageTitle',
        primary: ['primary0', 'primary1', 'primary2'],
        secondary: ['secondary0', 'secondary1', 'secondary2'],
        tertiary: ['tertiary0', 'tertiary1', 'tertiary2'],
      }
      const sameProps = {
        coverDPI: 'xhdpi',
        isBeaconActive: true,
        isLoggedIn: true,
        location: 'location',
        params: 'Params',
        pageTitle: 'PageTitle',
        primary: ['primary0', 'primary1', 'primary2'],
        secondary: ['secondary0', 'secondary1', 'secondary2'],
        tertiary: ['tertiary0', 'tertiary1', 'tertiary2'],
      }
      const nextProps = {
        coverDPI: 'xhdpi',
        isBeaconActive: false,
        isLoggedIn: true,
        location: 'location',
        params: 'Params2',
        pageTitle: 'PageTitle',
        primary: ['primary0', 'primary1', 'primary2'],
        secondary: ['secondary0', 'secondary1', 'secondary2'],
        tertiary: ['tertiary0', 'tertiary1', 'tertiary2'],
      }
      const lastProps = {
        coverDPI: 'xhdpi',
        isBeaconActive: false,
        isLoggedIn: true,
        location: 'location',
        params: 'Params2',
        pageTitle: 'PageTitle',
        primary: ['primary00', 'primary01', 'primary02'],
        secondary: ['secondary00', 'secondary01', 'secondary02'],
        tertiary: ['tertiary00', 'tertiary01', 'tertiary02'],
      }
      const shouldSameUpdate = shouldContainerUpdate(thisProps, sameProps)
      const shouldNextUpdate = shouldContainerUpdate(thisProps, nextProps)
      const shouldLastUpdate = shouldContainerUpdate(nextProps, lastProps)
      expect(shouldSameUpdate).to.be.false
      expect(shouldNextUpdate).to.be.true
      expect(shouldLastUpdate).to.be.true
    })
  })
})

<commit_msg>Update a test name<commit_after>import { expect } from '../../spec_helper'
import { stubJSONStore } from '../../stubs'
import { sortCategories } from '../../../src/selectors'
import {
  loadCategoryPosts,
  loadDiscoverPosts,
  loadDiscoverUsers,
  getCategories,
} from '../../../src/actions/discover'
import {
  generateTabs,
  getStreamAction,
  shouldContainerUpdate,
} from '../../../src/containers/DiscoverContainer'

describe('DiscoverContainer', () => {
  context('#getStreamAction', () => {
    it('returns the correct stream action for featured and recommended', () => {
      const realAction = loadCategoryPosts()
      const featuredAction = getStreamAction('featured')
      const recommendedAction = getStreamAction('recommended')
      expect(featuredAction).to.deep.equal(realAction)
      expect(recommendedAction).to.deep.equal(realAction)
    })

    it('returns the correct stream action for recent', () => {
      const realAction = loadDiscoverPosts('recent')
      const testAction = getStreamAction('recent')
      expect(testAction).to.deep.equal(realAction)
    })

    it('returns the correct stream action for trending', () => {
      const realAction = loadDiscoverUsers('trending')
      const testAction = getStreamAction('trending')
      expect(testAction).to.deep.equal(realAction)
    })

    it('returns the correct stream action for all', () => {
      const realAction = getCategories()
      const testAction = getStreamAction('all')
      expect(testAction).to.deep.equal(realAction)
    })
  })

  context('#generateTabs', () => {
    it('returns the correct stream action for featured and recommended', () => {
      const json = stubJSONStore()
      const categories = json.categories
      const keys = Object.keys(categories)
      let primary = []
      let secondary = []
      let tertiary = []
      keys.forEach((key) => {
        const category = categories[key]
        switch (category.level) {
          case 'primary':
            primary.push(category)
            break
          case 'secondary':
            secondary.push(category)
            break
          case 'tertiary':
            tertiary.push(category)
            break
          default:
            break
        }
      })
      primary = primary.sort(sortCategories)
      secondary = secondary.sort(sortCategories)
      tertiary = tertiary.sort(sortCategories)
      const tabs = generateTabs(primary, secondary, tertiary)
      expect(tabs[0]).to.have.property('children', 'Featured')
      expect(tabs[0]).to.have.property('to', '/discover')
      expect(tabs[1]).to.have.property('children', 'Trending')
      expect(tabs[1]).to.have.property('to', '/discover/trending')
      expect(tabs[2]).to.have.property('children', 'Recent')
      expect(tabs[2]).to.have.property('to', '/discover/recent')
      expect(tabs[3]).to.have.property('kind', 'divider')
      expect(tabs[4]).to.have.property('children', 'Art')
      expect(tabs[4]).to.have.property('to', '/discover/art')
      expect(tabs[5]).to.have.property('children', 'Design')
      expect(tabs[5]).to.have.property('to', '/discover/design')
      expect(tabs[6]).to.have.property('children', 'Photography')
      expect(tabs[6]).to.have.property('to', '/discover/photography')
      expect(tabs[7]).to.have.property('children', 'Architecture')
      expect(tabs[7]).to.have.property('to', '/discover/architecture')
      expect(tabs[8]).to.have.property('children', 'Interviews')
      expect(tabs[8]).to.have.property('to', '/discover/interviews')
      expect(tabs[9]).to.have.property('children', 'Collage')
      expect(tabs[9]).to.have.property('to', '/discover/collage')
    })
  })
  context('#shouldContainerUpdate', () => {
    it('returns the correct stream action for discover', () => {
      const thisProps = {
        coverDPI: 'xhdpi',
        isBeaconActive: true,
        isLoggedIn: true,
        location: 'location',
        params: 'Params',
        pageTitle: 'PageTitle',
        primary: ['primary0', 'primary1', 'primary2'],
        secondary: ['secondary0', 'secondary1', 'secondary2'],
        tertiary: ['tertiary0', 'tertiary1', 'tertiary2'],
      }
      const sameProps = {
        coverDPI: 'xhdpi',
        isBeaconActive: true,
        isLoggedIn: true,
        location: 'location',
        params: 'Params',
        pageTitle: 'PageTitle',
        primary: ['primary0', 'primary1', 'primary2'],
        secondary: ['secondary0', 'secondary1', 'secondary2'],
        tertiary: ['tertiary0', 'tertiary1', 'tertiary2'],
      }
      const nextProps = {
        coverDPI: 'xhdpi',
        isBeaconActive: false,
        isLoggedIn: true,
        location: 'location',
        params: 'Params2',
        pageTitle: 'PageTitle',
        primary: ['primary0', 'primary1', 'primary2'],
        secondary: ['secondary0', 'secondary1', 'secondary2'],
        tertiary: ['tertiary0', 'tertiary1', 'tertiary2'],
      }
      const lastProps = {
        coverDPI: 'xhdpi',
        isBeaconActive: false,
        isLoggedIn: true,
        location: 'location',
        params: 'Params2',
        pageTitle: 'PageTitle',
        primary: ['primary00', 'primary01', 'primary02'],
        secondary: ['secondary00', 'secondary01', 'secondary02'],
        tertiary: ['tertiary00', 'tertiary01', 'tertiary02'],
      }
      const shouldSameUpdate = shouldContainerUpdate(thisProps, sameProps)
      const shouldNextUpdate = shouldContainerUpdate(thisProps, nextProps)
      const shouldLastUpdate = shouldContainerUpdate(nextProps, lastProps)
      expect(shouldSameUpdate).to.be.false
      expect(shouldNextUpdate).to.be.true
      expect(shouldLastUpdate).to.be.true
    })
  })
})

<|endoftext|>