<commit_before>'use strict';

const Joi = require('joi');
const pick = require('lodash/pick');
const parseQuery = require('../../util/parseQuery');
const validateJoiSchema = require('../../util/validateJoiSchema');

function buildMatchQueries(params) {
    if (!params.text) {
        return [];
    }

    return [
        // Partial match using edge-ngram
        {
            multi_match: {
                query: params.text,
                operator: 'and',
                fields: [
                    'package.name.edge_ngram^4',
                    'package.description.edge_ngram',
                    'package.keywords.edge_ngram^2',
                ],
                type: 'phrase',
                slop: 3,
                boost: 3,
            },
        },

        // Normal term match with an english stemmer
        {
            multi_match: {
                query: params.text,
                operator: 'and',
                fields: [
                    'package.name.english_docs^4',
                    'package.description.english_docs',
                    'package.keywords.english_docs^2',
                ],
                type: 'cross_fields',
                boost: 3,
            },
        },

        // Normal term match with a more aggressive english stemmer (not so important)
        {
            multi_match: {
                query: params.text,
                operator: 'and',
                fields: [
                    'package.name.english_aggressive_docs^4',
                    'package.description.english_aggressive_docs',
                    'package.keywords.english_aggressive_docs^2',
                ],
                type: 'cross_fields',
            },
        },
    ];
}

function buildFilterQuery(params) {
    const filters = {
        must: [],
        mustNot: [],
    };

    if (params.author) {
        filters.must.push({
            or: [
                { term: { 'package.author.name': params.author } },
                { term: { 'package.author.username': params.author } },
                { term: { 'package.author.email': params.author } },
            ],
        });
    }

    if (params.maintainer) {
        filters.must.push({
            or: [
                { term: { 'package.maintainers.username': params.maintainer } },
                { term: { 'package.maintainers.email': params.maintainer } },
            ],
        });
    }

    if (params.keywords) {
        if (params.keywords.include) {
            filters.must.push({
                terms: { 'package.keywords.raw': params.keywords.include },  // Operator is OR
            });
        }
        if (params.keywords.exclude) {
            filters.mustNot.push({
                terms: { 'package.keywords.raw': params.keywords.exclude },
            });
        }
    }

    if (params.is) {
        filters.must.push({
            and: params.is.map((is) => ({
                exists: { field: `flags.${is}` },
            })),
        });
    }

    if (params.not) {
        filters.mustNot.push({
            or: params.not.map((not) => ({
                exists: { field: `flags.${not}` },
            })),
        });
    }

    return filters;
}

function buildScriptScore(params) {
    let script = '(doc["score.detail.popularity"].value * popularityWeight + ' +
        'doc["score.detail.quality"].value * qualityWeight + ' +
        'doc["score.detail.maintenance"].value * maintenanceWeight)';

    if (params.boostExact) {
        script = `doc["package.name.raw"].value.equals(text) ? 100000 + ${script} : _score * pow(${script}, scoreEffect)`;
    }

    return {
        lang: 'groovy',
        script,
        params: {
            text: params.text || '',
            scoreEffect: params.scoreEffect,
            qualityWeight: params.qualityWeight,
            popularityWeight: params.popularityWeight,
            maintenanceWeight: params.maintenanceWeight,
        },
    };
}

function fetchResults(params, esClient) {
    /* eslint camelcase: 0 */
    const matchQueries = buildMatchQueries(params);
    const filterQuery = buildFilterQuery(params);

    // Need to use Promise.resolve because Elasticsearch does not use native Promise
    return Promise.resolve(esClient.search({
        index: 'npms-current',
        type: 'score',
        body: {
            size: params.size,
            from: params.from,
            query: {
                function_score: {
                    boost_mode: 'replace',
                    query: {
                        bool: {
                            must: filterQuery.must,
                            must_not: filterQuery.mustNot,
                            should: matchQueries,
                            minimum_should_match: 1,
                        },
                    },
                    script_score: buildScriptScore(params),
                },
            },
        },
    }))
    .then((res) => ({
        total: res.hits.total,
        results: res.hits.hits.map((hit) => {
            // We can't use _fields in the query because the JSON properties order get messed up,
            // see https://github.com/elastic/elasticsearch/issues/17639
            // So we filter the source fields manually with pick().. this is not ideal since there's payload
            // navigating through the network that we do not use, but it's definitively better than having order messed up
            const result = pick(hit._source, 'package', 'flags', 'score');

            result.searchScore = hit._score;

            return result;
        }),
    }));
}

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

module.exports = (router, esClient) => {
    /**
     * @api {get} /search Perform a search query
     * @apiName ExecuteSearchQuery
     * @apiGroup Search
     * @apiVersion 2.0.0
     *
     * @apiParam {string} q         The query with support for filters and other modifiers
     * @apiParam {string} [from=0]  The offset in which to start searching from
     * @apiParam {string} [size=25] The total number of results to return
     *
     * @apiDescription
     *
     * Besides normal text, `q` supports qualifiers to express filters and other modifiers:
     * - `author:sindresorhus`: Show/filter results in which `sindresorhus` is the author
     * - `maintainer:sindresorhus`: Show/filter results in which `sindresorhus` is qualifier as a maintainer
     * - `keywords:gulpplugin`: Show/filter results that have `gulpplugin` in the keywords (separate multiple keywords with commas)
     * - `not:deprecated`: Exclude deprecated packages from the results
     * - `not:unstable`: Exclude packages whose version is `< 1.0.0`
     * - `not:insecure`: Exclude packages that are insecure or have vulnerable dependencies (as per [nsp](https://nodesecurity.io/))
     * - `is:deprecated`: Show/filter is deprecated packages (unstable and insecure are available too)
     * - `boost-exact:false`: Do not boost exact matches, defaults to `true`
     * - `score-effect:14`: Set the effect that package scores have for the final search score, defaults to `15.3`
     * - `quality-weight:1`: Set the weight that quality has for the each package score, defaults to `1.95`
     * - `popularity-weight:1`: Set the weight that popularity has for the each package score, defaults to `3.3`
     * - `maintenance-weight:1`: Set the weight that the quality has for the each package score, defaults to `2.05`
     *
     * @apiSuccess (Each result has) {object} package     The package data which contains the name, version and other useful information
     * @apiSuccess (Each result has) {object} flags       The package flags (deprecated, unstable, insecure)
     * @apiSuccess (Each result has) {object} score       The package score
     * @apiSuccess (Each result has) {number} searchScore The computed search score (from Elasticsearch)
     *
     * @apiSuccessExample {json} Response
     *     {
     *       "total": 251,
     *       "results": [
     *         {
     *           "package": { "name": "cross-spawn-async", "version": "2.2.4", ... },
     *           "flags": { "deprecated": "Use cross-spawn instead.." },
     *           "score": { "final": 0.89, "detail": { "quality": 0.99, "popularity": 0.77, ... } },
     *           "searchScore": 0.0021
     *         },
     *         ...
     *       ]
     *     }
     *
     * @apiExample {curl} Usage
     *     curl "https://api.npms.io/v2/search?q=cross+spawn"
     *
     * @apiExample {curl} With qualifiers usage
     *     curl "https://api.npms.io/v2/search?q=cross+spawn+not:deprecated,insecure"
     *     curl "https://api.npms.io/v2/search?q=sass+keywords:gulpplugin"
     */
    const queryQuerySchema = Joi.object({
        q: Joi.string().trim().min(1).lowercase(),
        from: Joi.number().min(0).default(0),
        size: Joi.number().min(1).max(250).default(25),
    }).required();

    router.get('/search',
        function * (next) {
            this.validated = validateJoiSchema(queryQuerySchema, this.request.query);
            yield next;
        },
        function * () {
            // Parse query and generate search params
            const params = Object.assign(parseQuery(this.validated.q), { from: this.validated.from, size: this.validated.size });

            this.log.debug({ params }, 'Got search params, will now fetch results');

            // Finally fetch the results from Elasticsearch
            this.body = yield fetchResults(params, esClient);
        });
};
<commit_msg>Update api docs.<commit_after>'use strict';

const Joi = require('joi');
const pick = require('lodash/pick');
const parseQuery = require('../../util/parseQuery');
const validateJoiSchema = require('../../util/validateJoiSchema');

function buildMatchQueries(params) {
    if (!params.text) {
        return [];
    }

    return [
        // Partial match using edge-ngram
        {
            multi_match: {
                query: params.text,
                operator: 'and',
                fields: [
                    'package.name.edge_ngram^4',
                    'package.description.edge_ngram',
                    'package.keywords.edge_ngram^2',
                ],
                type: 'phrase',
                slop: 3,
                boost: 3,
            },
        },

        // Normal term match with an english stemmer
        {
            multi_match: {
                query: params.text,
                operator: 'and',
                fields: [
                    'package.name.english_docs^4',
                    'package.description.english_docs',
                    'package.keywords.english_docs^2',
                ],
                type: 'cross_fields',
                boost: 3,
            },
        },

        // Normal term match with a more aggressive english stemmer (not so important)
        {
            multi_match: {
                query: params.text,
                operator: 'and',
                fields: [
                    'package.name.english_aggressive_docs^4',
                    'package.description.english_aggressive_docs',
                    'package.keywords.english_aggressive_docs^2',
                ],
                type: 'cross_fields',
            },
        },
    ];
}

function buildFilterQuery(params) {
    const filters = {
        must: [],
        mustNot: [],
    };

    if (params.author) {
        filters.must.push({
            or: [
                { term: { 'package.author.name': params.author } },
                { term: { 'package.author.username': params.author } },
                { term: { 'package.author.email': params.author } },
            ],
        });
    }

    if (params.maintainer) {
        filters.must.push({
            or: [
                { term: { 'package.maintainers.username': params.maintainer } },
                { term: { 'package.maintainers.email': params.maintainer } },
            ],
        });
    }

    if (params.keywords) {
        if (params.keywords.include) {
            filters.must.push({
                terms: { 'package.keywords.raw': params.keywords.include },  // Operator is OR
            });
        }
        if (params.keywords.exclude) {
            filters.mustNot.push({
                terms: { 'package.keywords.raw': params.keywords.exclude },
            });
        }
    }

    if (params.is) {
        filters.must.push({
            and: params.is.map((is) => ({
                exists: { field: `flags.${is}` },
            })),
        });
    }

    if (params.not) {
        filters.mustNot.push({
            or: params.not.map((not) => ({
                exists: { field: `flags.${not}` },
            })),
        });
    }

    return filters;
}

function buildScriptScore(params) {
    let script = '(doc["score.detail.popularity"].value * popularityWeight + ' +
        'doc["score.detail.quality"].value * qualityWeight + ' +
        'doc["score.detail.maintenance"].value * maintenanceWeight)';

    if (params.boostExact) {
        script = `doc["package.name.raw"].value.equals(text) ? 100000 + ${script} : _score * pow(${script}, scoreEffect)`;
    }

    return {
        lang: 'groovy',
        script,
        params: {
            text: params.text || '',
            scoreEffect: params.scoreEffect,
            qualityWeight: params.qualityWeight,
            popularityWeight: params.popularityWeight,
            maintenanceWeight: params.maintenanceWeight,
        },
    };
}

function fetchResults(params, esClient) {
    /* eslint camelcase: 0 */
    const matchQueries = buildMatchQueries(params);
    const filterQuery = buildFilterQuery(params);

    // Need to use Promise.resolve because Elasticsearch does not use native Promise
    return Promise.resolve(esClient.search({
        index: 'npms-current',
        type: 'score',
        body: {
            size: params.size,
            from: params.from,
            query: {
                function_score: {
                    boost_mode: 'replace',
                    query: {
                        bool: {
                            must: filterQuery.must,
                            must_not: filterQuery.mustNot,
                            should: matchQueries,
                            minimum_should_match: 1,
                        },
                    },
                    script_score: buildScriptScore(params),
                },
            },
        },
    }))
    .then((res) => ({
        total: res.hits.total,
        results: res.hits.hits.map((hit) => {
            // We can't use _fields in the query because the JSON properties order get messed up,
            // see https://github.com/elastic/elasticsearch/issues/17639
            // So we filter the source fields manually with pick().. this is not ideal since there's payload
            // navigating through the network that we do not use, but it's definitively better than having order messed up
            const result = pick(hit._source, 'package', 'flags', 'score');

            result.searchScore = hit._score;

            return result;
        }),
    }));
}

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

module.exports = (router, esClient) => {
    /**
     * @api {get} /search Perform a search query
     * @apiName ExecuteSearchQuery
     * @apiGroup Search
     * @apiVersion 2.0.0
     *
     * @apiParam {string} q         The query with support for filters and other modifiers
     * @apiParam {string} [from=0]  The offset in which to start searching from
     * @apiParam {string} [size=25] The total number of results to return
     *
     * @apiDescription
     *
     * Besides normal text, `q` supports qualifiers to express filters and other modifiers:
     * - `author:sindresorhus`: Show/filter results in which `sindresorhus` is the author
     * - `maintainer:sindresorhus`: Show/filter results in which `sindresorhus` is qualifier as a maintainer
     * - `keywords:gulpplugin`: Show/filter results that have `gulpplugin` in the keywords
     *                          (separate multiple keywords with commas, you may also exclude keywords e.g.: -framework)
     * - `not:deprecated`: Exclude deprecated packages from the results
     * - `not:unstable`: Exclude packages whose version is `< 1.0.0`
     * - `not:insecure`: Exclude packages that are insecure or have vulnerable dependencies (as per [nsp](https://nodesecurity.io/))
     * - `is:deprecated`: Show/filter is deprecated packages
     * - `is:unstable`: Show/filter packages whose version is `< 1.0.0`
     * - `is:insecure`: Show/filter packages that are insecure or have vulnerable dependencies (as per [nsp](https://nodesecurity.io/))
     * - `boost-exact:false`: Do not boost exact matches, defaults to `true`
     * - `score-effect:14`: Set the effect that package scores have for the final search score, defaults to `15.3`
     * - `quality-weight:1`: Set the weight that quality has for the each package score, defaults to `1.95`
     * - `popularity-weight:1`: Set the weight that popularity has for the each package score, defaults to `3.3`
     * - `maintenance-weight:1`: Set the weight that the quality has for the each package score, defaults to `2.05`
     *
     * @apiSuccess (Each result has) {object} package     The package data which contains the name, version and other useful information
     * @apiSuccess (Each result has) {object} flags       The package flags (deprecated, unstable, insecure)
     * @apiSuccess (Each result has) {object} score       The package score
     * @apiSuccess (Each result has) {number} searchScore The computed search score (from Elasticsearch)
     *
     * @apiSuccessExample {json} Response
     *     {
     *       "total": 251,
     *       "results": [
     *         {
     *           "package": { "name": "cross-spawn-async", "version": "2.2.4", ... },
     *           "flags": { "deprecated": "Use cross-spawn instead.." },
     *           "score": { "final": 0.89, "detail": { "quality": 0.99, "popularity": 0.77, ... } },
     *           "searchScore": 0.0021
     *         },
     *         ...
     *       ]
     *     }
     *
     * @apiExample {curl} Usage
     *     curl "https://api.npms.io/v2/search?q=cross+spawn"
     *
     * @apiExample {curl} With qualifiers usage
     *     curl "https://api.npms.io/v2/search?q=cross+spawn+not:deprecated,insecure"
     *     curl "https://api.npms.io/v2/search?q=sass+keywords:gulpplugin"
     */
    const queryQuerySchema = Joi.object({
        q: Joi.string().trim().min(1).lowercase(),
        from: Joi.number().min(0).default(0),
        size: Joi.number().min(1).max(250).default(25),
    }).required();

    router.get('/search',
        function * (next) {
            this.validated = validateJoiSchema(queryQuerySchema, this.request.query);
            yield next;
        },
        function * () {
            // Parse query and generate search params
            const params = Object.assign(parseQuery(this.validated.q), { from: this.validated.from, size: this.validated.size });

            this.log.debug({ params }, 'Got search params, will now fetch results');

            // Finally fetch the results from Elasticsearch
            this.body = yield fetchResults(params, esClient);
        });
};
<|endoftext|>


<commit_before>function Application (cb) {
  this._logger = function () {};
  this._app    = function () { return {}; };

  cb.call(this);
}

Application.prototype.init = function () {
  this._app = this._app();
};

Application.prototype.setLogger = function (logger) {
  this._logger = logger || function () {};
};

Application.prototype.setApp = function (app) {
  this._app = app || function () {};
};

Application.prototype.log = function () {
  this._logger.apply(this._logger, arguments);
};

Application.prototype.serve = function (port) {
  this._app.listen(port, function () {
    this.log('Server listening on port ' + port);
  }.bind(this));
};

// var app = require('../app');
// app.set('port', cli.port);

// console.log(app.get('env'));

// var server = app.listen(app.get('port'), function() {
//   debug('Server listening on port ' + server.address().port);
// });

module.exports = Application;
<commit_msg>Get rid of old code (unused code that got abstracted).<commit_after>function Application (cb) {
  this._logger = function () {};
  this._app    = function () { return {}; };

  cb.call(this);
}

Application.prototype.init = function () {
  this._app = this._app();
};

Application.prototype.setLogger = function (logger) {
  this._logger = logger || function () {};
};

Application.prototype.setApp = function (app) {
  this._app = app || function () {};
};

Application.prototype.log = function () {
  this._logger.apply(this._logger, arguments);
};

Application.prototype.serve = function (port) {
  this._app.listen(port, function () {
    this.log('Server listening on port ' + port);
  }.bind(this));
};

module.exports = Application;
<|endoftext|>


<commit_before>
  /**
   *  Date field -> Place to choose and edit date field
   *  - It accepts a model with {attribute: 'colum', value: '2013-02-12T12:19:58+01:00'}
   *  - It will create a new model to split this value into {day, month, year and time}
   *  var date = new cdb.admin.DateField({ model: model })
   */

  cdb.admin.DateField = cdb.admin.StringField.extend({

    className: 'field date',

    timezone: 2,

    default_options: {
      template_name: 'common/views/forms/date_field',
      label:          false,
      readOnly:       false
    },

    events: {
      'change input.time': '_onChange',
      'keyup input.time':  '_onKeyUp'
    },

    initialize: function() {
      _.defaults(this.options, this.default_options);

      _.bindAll(this, '_onChange', '_onKeyUp', '_onChangeModel');

      this.template_base = this.options.template_base ? _.template(this.options.template_base) : cdb.templates.getTemplate(this.options.template_name);

      // Get date
      var date = this._splitDate((this.model.get('value')));

      // Generate a new date Model (later it will be removed and destroyed)
      this.date_model = new cdb.core.Model(date);

      // Begins as valid
      this.valid = true;

      // Bind changes
      this.date_model.bind('change', this._onChangeModel);

      // On clean
      this.bind('clean', this._reClean);
    },

    render: function() {
      this.$el.html(this.template_base(_.extend(this.model.toJSON(), this.options)));

      // Apply views
      this._initViews();

      // Check readOnly and unbind all events
      if (this.options.readOnly) {
        this.undelegateEvents();
      }

      return this;
    },

    _initViews: function() {
      // Days spinner
      var days = this.days = new cdb.forms.Spinner({
        el: this.$el.find('div.day'),
        model:    this.date_model,
        disabled: this.options.readOnly,
        property: 'day',
        min:      1,
        max:      31,
        inc:      1,
        width:    15,
        noSlider: true,
        pattern:  /^([12]?\d{0,1}|3[01]{0,2})$/
      });
      this.addView(this.days);
      this.$("div.day").append(days.render());

      // Year spinner
      var years = this.years = new cdb.forms.Spinner({
        el: this.$el.find('div.year'),
        model:    this.date_model,
        disabled: this.options.readOnly,
        property: 'year',
        min:      1900,
        max:      2100,
        width:    28,
        noSlider: true,
        pattern:  /^([0-9]{0,4})$/
      });
      this.addView(this.years);
      this.$("div.year").append(years.render());

      // Month selector
      var months = this.months = new cdb.forms.Combo({
        el: this.$el.find('div.month'),
        model:      this.date_model,
        disabled:   this.options.readOnly,
        property:   'month',
        width:      '140px',
        extra:      [['January',1], ['February',2], ['March',3], ['April',4], ['May',5], ['June',6], ['July',7], ['August',8], ['September',9], ['October',10], ['November',11], ['December',12]]
      });
      this.addView(this.months);
      this.$("div.month").append(months.render());

      // Time input
      this.$('input.time').val(this.date_model.get('time'));
    },

    /**
     *  Split the date string
     */
    _splitDate: function(str) {
      var date = {};

      if (str=='') {
        date.day = 1;
        date.month = 1;
        date.year = 2012;
        date.time = '00:00:00';
      } else {
        try {
          var split_date_hour = str.split('T');
          if (split_date_hour.length>1) {
            var split_date = split_date_hour[0].split('-');
            date.time = split_date_hour[1].substr(0,8);
            date.day = parseInt(split_date[2]);
            date.month = parseInt(split_date[1]);
            date.year = parseInt(split_date[0]);
          } else {
            date.day = 1;
            date.month = 1;
            date.year = 2012;
            date.time = '00:00:00';
          }
        } catch (e) {
          date.day = 1;
          date.month = 1;
          date.year = 2012;
          date.time = '00:00:00';
        }
      }
      return date;
    },

    /**
     *  Get the date model and converts to date string
     */
    _toDate: function(date) {
      return date.year + "-" + date.month + "-" + date.day + "T" + date.time + "+0" + this.timezone + ":00"
    },

    /**
     *  Check if the time is well formed or not
     */
    _checkTime: function(time) {
      var pattern = /^([01]{1}[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;
      if (pattern.test(time)) {
        return true
      } else {
        return false
      }
    },

    // Events
    _onChange: function(e) {
      var time = this.$('input.time').val();

      if (this._checkTime(time)) {
        this.date_model.set('time', time);
      }
    },

    _onChangeModel: function(m) {
      this.model.set('value', this._toDate(this.date_model.toJSON()));
    },

    _onKeyDown: function() {},

    _onKeyUp: function(e) {
      var time = $(e.target).val();

      if (this._checkTime(time)) {

        if (e.keyCode === 13) {
          e.preventDefault();
          this._triggerEvent('ENTER');
          return false;
        }

        this.valid = true;
        this.date_model.set('time', time);
        $(e.target).removeClass("error");
      } else {
        this.valid = false;
        $(e.target).addClass("error");
      }
    },

    _reClean: function() {
      this.date_model.unbind('change');
      this.date_model.destroy();
    }
  })<commit_msg>date field save by default a date<commit_after>
  /**
   *  Date field -> Place to choose and edit date field
   *  - It accepts a model with {attribute: 'colum', value: '2013-02-12T12:19:58+01:00'}
   *  - It will create a new model to split this value into {day, month, year and time}
   *  var date = new cdb.admin.DateField({ model: model })
   */

  cdb.admin.DateField = cdb.admin.StringField.extend({

    className: 'field date',

    timezone: 2,

    default_options: {
      template_name: 'common/views/forms/date_field',
      label:          false,
      readOnly:       false
    },

    events: {
      'change input.time': '_onChange',
      'keyup input.time':  '_onKeyUp'
    },

    initialize: function() {
      _.defaults(this.options, this.default_options);

      _.bindAll(this, '_onChange', '_onKeyUp', '_onChangeModel');

      this.template_base = this.options.template_base ? _.template(this.options.template_base) : cdb.templates.getTemplate(this.options.template_name);

      // Get date
      var date = this._splitDate((this.model.get('value')));

      // Generate a new date Model (later it will be removed and destroyed)
      this.date_model = new cdb.core.Model();

      // Begins as valid
      this.valid = true;

      // Bind changes
      this.date_model.bind('change', this._onChangeModel);

      // Date model data set
      this.date_model.set(date);

      // On clean
      this.bind('clean', this._reClean);
    },

    render: function() {
      this.$el.html(this.template_base(_.extend(this.model.toJSON(), this.options)));

      // Apply views
      this._initViews();

      // Check readOnly and unbind all events
      if (this.options.readOnly) {
        this.undelegateEvents();
      }

      return this;
    },

    _initViews: function() {
      // Days spinner
      var days = this.days = new cdb.forms.Spinner({
        el: this.$el.find('div.day'),
        model:    this.date_model,
        disabled: this.options.readOnly,
        property: 'day',
        min:      1,
        max:      31,
        inc:      1,
        width:    15,
        noSlider: true,
        pattern:  /^([12]?\d{0,1}|3[01]{0,2})$/
      });
      this.addView(this.days);
      this.$("div.day").append(days.render());

      // Year spinner
      var years = this.years = new cdb.forms.Spinner({
        el: this.$el.find('div.year'),
        model:    this.date_model,
        disabled: this.options.readOnly,
        property: 'year',
        min:      1900,
        max:      2100,
        width:    28,
        noSlider: true,
        pattern:  /^([0-9]{0,4})$/
      });
      this.addView(this.years);
      this.$("div.year").append(years.render());

      // Month selector
      var months = this.months = new cdb.forms.Combo({
        el: this.$el.find('div.month'),
        model:      this.date_model,
        disabled:   this.options.readOnly,
        property:   'month',
        width:      '140px',
        extra:      [['January',1], ['February',2], ['March',3], ['April',4], ['May',5], ['June',6], ['July',7], ['August',8], ['September',9], ['October',10], ['November',11], ['December',12]]
      });
      this.addView(this.months);
      this.$("div.month").append(months.render());

      // Time input
      this.$('input.time').val(this.date_model.get('time'));
    },

    /**
     *  Split the date string
     */
    _splitDate: function(str) {
      var date = {};

      if (str=='') {
        date.day = 1;
        date.month = 1;
        date.year = 2012;
        date.time = '00:00:00';
      } else {
        try {
          var split_date_hour = str.split('T');
          if (split_date_hour.length>1) {
            var split_date = split_date_hour[0].split('-');
            date.time = split_date_hour[1].substr(0,8);
            date.day = parseInt(split_date[2]);
            date.month = parseInt(split_date[1]);
            date.year = parseInt(split_date[0]);
          } else {
            date.day = 1;
            date.month = 1;
            date.year = 2012;
            date.time = '00:00:00';
          }
        } catch (e) {
          date.day = 1;
          date.month = 1;
          date.year = 2012;
          date.time = '00:00:00';
        }
      }
      return date;
    },

    /**
     *  Get the date model and converts to date string
     */
    _toDate: function(date) {
      return date.year + "-" + date.month + "-" + date.day + "T" + date.time + "+0" + this.timezone + ":00"
    },

    /**
     *  Check if the time is well formed or not
     */
    _checkTime: function(time) {
      var pattern = /^([01]{1}[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;
      if (pattern.test(time)) {
        return true
      } else {
        return false
      }
    },

    // Events
    _onChange: function(e) {
      var time = this.$('input.time').val();

      if (this._checkTime(time)) {
        this.date_model.set('time', time);
      }
    },

    _onChangeModel: function(m) {
      this.model.set('value', this._toDate(this.date_model.toJSON()));
    },

    _onKeyDown: function() {},

    _onKeyUp: function(e) {
      var time = $(e.target).val();

      if (this._checkTime(time)) {

        if (e.keyCode === 13) {
          e.preventDefault();
          this._triggerEvent('ENTER');
          return false;
        }

        this.valid = true;
        this.date_model.set('time', time);
        $(e.target).removeClass("error");
      } else {
        this.valid = false;
        $(e.target).addClass("error");
      }
    },

    _reClean: function() {
      this.date_model.unbind('change');
      this.date_model.destroy();
    }
  })<|endoftext|>


<commit_before>'use strict';

/*
* The following copyright, license, and long comment were part of the original implementation available as part of [FreeBSD]{@link https://svnweb.freebsd.org/base/release/9.3.0/lib/msun/src/e_exp.c?view=markup}.
*
* The implementation follows the original, but has been modified for JavaScript.
*/

/*
* ====================================================
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
*
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/

// MODULES //

var isnan = require( '@stdlib/math/base/assert/is-nan' );
var trunc = require( '@stdlib/math/base/special/trunc' );
var NINF = require( '@stdlib/constants/math/float64-ninf' );
var PINF = require( '@stdlib/constants/math/float64-pinf' );
var expmulti = require( './expmulti.js' );

// VARIABLES //

var LN2_HI = 6.93147180369123816490e-01;
var LN2_LO = 1.90821492927058770002e-10;
var LOG2_E = 1.44269504088896338700e+00;
var OVERFLOW = 7.09782712893383973096e+02;
var UNDERFLOW = -7.45133219101941108420e+02;
var NEARZERO = 1.0 / (1 << 28); // 2^-28;
var NEG_NEARZERO = -NEARZERO;

// MAIN //

/**
* Evaluates the natural exponential function.
*
* #### Method
*
* 1. We reduce \\( x \\) to an \\( r \\) so that \\( |r| \leq 0.5 \cdot \ln(2) \approx 0.34658 \\). Given \\( x \\), we find an \\( r \\) and integer \\( k \\) such that
*
*   ```tex
*   \begin{align*}
*   x &= k \cdot \ln(2) + r \\
*   |r| &\leq 0.5 \cdot \ln(2)
*   \end{align*}
*   ```
*
*   <!-- <note> -->
*   \\( r \\) can be represented as \\( r = \mathrm{hi} - \mathrm{lo} \\) for better accuracy.
*   <!-- </note> -->
*
* 2. We approximate of \\( e^{r} \\) by a special rational function on the interval \\([0,0.34658]\\):
*
*   ```tex
*   \begin{align*}
*   R\left(r^2\right) &= r \cdot \frac{ e^{r}+1 }{ e^{r}-1 } \\
*   &= 2 + \frac{r^2}{6} - \frac{r^4}{360} + \ldots
*   \end{align*}
*   ```
*
*   We use a special Remes algorithm on \\([0,0.34658]\\) to generate a polynomial of degree \\(5\\) to approximate \\(R\\). The maximum error of this polynomial approximation is bounded by \\(2^{-59}\\). In other words,
*
*   ```tex
*   R(z) \sim 2 + P_1 z + P_2 z^2 + P_3 z^3 + P_4 z^4 + P_5 z^5
*   ```
*
*   where \\( z = r^2 \\) and
*
*   ```tex
*   \left|  2 + P_1 z + \ldots + P_5 z^5  - R(z) \right| \leq 2^{-59}
*   ```
*
*   <!-- <note> -->
*   The values of \\( P_1 \\) to \\( P_5 \\) are listed in the source code.
*   <!-- </note> -->
*   The computation of \\( e^{r} \\) thus becomes
*
*   ```tex
*   \begin{align*}
*   e^{r} &= 1 + \frac{2r}{R-r} \\
*           &= 1 + r + \frac{r \cdot R_1(r)}{2 - R_1(r)}\ \text{for better accuracy}
*   \end{align*}
*   ```
*
*   where
*
*   ```tex
*   R_1(r) = r - P_1\ r^2 + P_2\ r^4 + \ldots + P_5\ r^{10}
*   ```
*
* 3. We scale back to obtain \\( e^{x} \\). From step 1, we have
*
*   ```tex
*   e^{x} = 2^k e^{r}
*   ```
*
*
* #### Special Cases
*
* ```tex
* \begin{align*}
* e^\infty &= \infty \\
* e^{-\infty} &= 0 \\
* e^{\mathrm{NaN}} &= \mathrm{NaN} \\
* e^0 &= 1\ \mathrm{is\ exact\ for\ finite\ argument\ only}
* \end{align*}
* ```
*
* #### Notes
*
* - According to an error analysis, the error is always less than \\(1\\) ulp (unit in the last place).
* - For IEEE double,
*   * if \\(x > 7.09782712893383973096\mbox{e+}02\\), then \\(e^{x}\\) overflows
*   * if \\(x < -7.45133219101941108420\mbox{e+}02\\), then \\(e^{x}\\) underflows
* - The hexadecimal values included in the source code are the intended ones for the used constants. Decimal values may be used, provided that the compiler will convert from decimal to binary accurately enough to produce the intended hexadecimal values.
*
*
* @param {number} x - input value
* @returns {number} function value
*
* @example
* var v = exp( 4.0 );
* // returns ~54.5982
*
* @example
* var v = exp( -9.0 );
* // returns ~1.234e-4
*
* @example
* var v = exp( 0.0 );
* // returns 1.0
*
* @example
* var v = exp( NaN );
* // returns NaN
*/
function exp( x ) {
	var hi;
	var lo;
	var k;

	if ( isnan( x ) || x === PINF ) {
		return x;
	}
	if ( x === NINF ) {
		return 0.0;
	}
	if ( x > OVERFLOW ) {
		return PINF;
	}
	if ( x < UNDERFLOW ) {
		return 0.0;
	}
	if (
		x > NEG_NEARZERO &&
		x < NEARZERO
	) {
		return 1.0 + x;
	}
	// Reduce and compute `r = hi - lo` for extra precision.
	if ( x < 0.0 ) {
		k = trunc( (LOG2_E*x) - 0.5 );
	} else {
		k = trunc( (LOG2_E*x) + 0.5 );
	}
	hi = x - (k*LN2_HI);
	lo = k * LN2_LO;

	return expmulti( hi, lo, k );
} // end FUNCTION exp()

// EXPORTS //

module.exports = exp;
<commit_msg>Update formatting<commit_after>'use strict';

/*
* The following copyright, license, and long comment were part of the original implementation available as part of [FreeBSD]{@link https://svnweb.freebsd.org/base/release/9.3.0/lib/msun/src/e_exp.c?view=markup}.
*
* The implementation follows the original, but has been modified for JavaScript.
*/

/*
* ====================================================
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
*
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/

// MODULES //

var isnan = require( '@stdlib/math/base/assert/is-nan' );
var trunc = require( '@stdlib/math/base/special/trunc' );
var NINF = require( '@stdlib/constants/math/float64-ninf' );
var PINF = require( '@stdlib/constants/math/float64-pinf' );
var expmulti = require( './expmulti.js' );

// VARIABLES //

var LN2_HI = 6.93147180369123816490e-01;
var LN2_LO = 1.90821492927058770002e-10;
var LOG2_E = 1.44269504088896338700e+00;
var OVERFLOW = 7.09782712893383973096e+02;
var UNDERFLOW = -7.45133219101941108420e+02;
var NEARZERO = 1.0 / (1 << 28); // 2^-28;
var NEG_NEARZERO = -NEARZERO;

// MAIN //

/**
* Evaluates the natural exponential function.
*
* ## Method
*
* 1. We reduce \\( x \\) to an \\( r \\) so that \\( |r| \leq 0.5 \cdot \ln(2) \approx 0.34658 \\). Given \\( x \\), we find an \\( r \\) and integer \\( k \\) such that
*
*   ```tex
*   \begin{align*}
*   x &= k \cdot \ln(2) + r \\
*   |r| &\leq 0.5 \cdot \ln(2)
*   \end{align*}
*   ```
*
*   <!-- <note> -->
*
*   \\( r \\) can be represented as \\( r = \mathrm{hi} - \mathrm{lo} \\) for better accuracy.
*
*   <!-- </note> -->
*
* 2. We approximate of \\( e^{r} \\) by a special rational function on the interval \\([0,0.34658]\\):
*
*   ```tex
*   \begin{align*}
*   R\left(r^2\right) &= r \cdot \frac{ e^{r}+1 }{ e^{r}-1 } \\
*   &= 2 + \frac{r^2}{6} - \frac{r^4}{360} + \ldots
*   \end{align*}
*   ```
*
*   We use a special Remes algorithm on \\([0,0.34658]\\) to generate a polynomial of degree \\(5\\) to approximate \\(R\\). The maximum error of this polynomial approximation is bounded by \\(2^{-59}\\). In other words,
*
*   ```tex
*   R(z) \sim 2 + P_1 z + P_2 z^2 + P_3 z^3 + P_4 z^4 + P_5 z^5
*   ```
*
*   where \\( z = r^2 \\) and
*
*   ```tex
*   \left|  2 + P_1 z + \ldots + P_5 z^5  - R(z) \right| \leq 2^{-59}
*   ```
*
*   <!-- <note> -->
*
*   The values of \\( P_1 \\) to \\( P_5 \\) are listed in the source code.
*
*   <!-- </note> -->
*
*   The computation of \\( e^{r} \\) thus becomes
*
*   ```tex
*   \begin{align*}
*   e^{r} &= 1 + \frac{2r}{R-r} \\
*           &= 1 + r + \frac{r \cdot R_1(r)}{2 - R_1(r)}\ \text{for better accuracy}
*   \end{align*}
*   ```
*
*   where
*
*   ```tex
*   R_1(r) = r - P_1\ r^2 + P_2\ r^4 + \ldots + P_5\ r^{10}
*   ```
*
* 3. We scale back to obtain \\( e^{x} \\). From step 1, we have
*
*   ```tex
*   e^{x} = 2^k e^{r}
*   ```
*
*
* ## Special Cases
*
* ```tex
* \begin{align*}
* e^\infty &= \infty \\
* e^{-\infty} &= 0 \\
* e^{\mathrm{NaN}} &= \mathrm{NaN} \\
* e^0 &= 1\ \mathrm{is\ exact\ for\ finite\ argument\ only}
* \end{align*}
* ```
*
* ## Notes
*
* -   According to an error analysis, the error is always less than \\(1\\) ulp (unit in the last place).
*
* -   For an IEEE double,
*
*     -   if \\(x > 7.09782712893383973096\mbox{e+}02\\), then \\(e^{x}\\) overflows
*     -   if \\(x < -7.45133219101941108420\mbox{e+}02\\), then \\(e^{x}\\) underflows
*
* -   The hexadecimal values included in the source code are the intended ones for the used constants. Decimal values may be used, provided that the compiler will convert from decimal to binary accurately enough to produce the intended hexadecimal values.
*
*
* @param {number} x - input value
* @returns {number} function value
*
* @example
* var v = exp( 4.0 );
* // returns ~54.5982
*
* @example
* var v = exp( -9.0 );
* // returns ~1.234e-4
*
* @example
* var v = exp( 0.0 );
* // returns 1.0
*
* @example
* var v = exp( NaN );
* // returns NaN
*/
function exp( x ) {
	var hi;
	var lo;
	var k;

	if ( isnan( x ) || x === PINF ) {
		return x;
	}
	if ( x === NINF ) {
		return 0.0;
	}
	if ( x > OVERFLOW ) {
		return PINF;
	}
	if ( x < UNDERFLOW ) {
		return 0.0;
	}
	if (
		x > NEG_NEARZERO &&
		x < NEARZERO
	) {
		return 1.0 + x;
	}
	// Reduce and compute `r = hi - lo` for extra precision.
	if ( x < 0.0 ) {
		k = trunc( (LOG2_E*x) - 0.5 );
	} else {
		k = trunc( (LOG2_E*x) + 0.5 );
	}
	hi = x - (k*LN2_HI);
	lo = k * LN2_LO;

	return expmulti( hi, lo, k );
} // end FUNCTION exp()

// EXPORTS //

module.exports = exp;
<|endoftext|>


<commit_before>/* eslint-disable object-curly-newline, no-unused-vars */
'use strict';

// MODULES //

var tape = require( 'tape' );
var UINT32_MAX = require( '@stdlib/math/constants/uint32-max' );
var isArrayLike = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof isArrayLike, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function returns `true` if provided an array-like object', function test( t ) {
	var values;
	var i;

	values = [
		[],
		{ 'length': 10 },
		'beep',
		arguments
	];

	for ( i = 0; i < values.length; i++ ) {
		t.equal( isArrayLike( values[i] ), true, 'returns true when provided '+values[i] );
	}
	t.end();
});

tape( 'the function returns `false` if provided an array-like object whose length exceeds the maximum array length', function test( t ) {
	var o = { 'length': UINT32_MAX+1 };
	t.equal( isArrayLike( o ), false, 'returns false' );
	t.end();
});

tape( 'the function returns `false` if provided an array-like object whose length property is not an integer', function test( t ) {
	var o = { 'length': 3.14 };
	t.equal( isArrayLike( o ), false, 'returns false' );
	t.end();
});

tape( 'the function returns `false` if provided an array-like object whose length property is a negative integer', function test( t ) {
	var o = { 'length': -1 };
	t.equal( isArrayLike( o ), false, 'returns false' );
	t.end();
});

tape( 'the function returns `false` if not provided an array-like object', function test( t ) {
	var values;
	var i;

	values = [
		5,
		null,
		undefined,
		NaN,
		true,
		false,
		{},
		function boop( a, b, c ) {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.equal( isArrayLike( values[i] ), false, 'returns false when provided '+values[i] );
	}
	t.end();
});
<commit_msg>Fix test descriptions<commit_after>/* eslint-disable object-curly-newline, no-unused-vars */
'use strict';

// MODULES //

var tape = require( 'tape' );
var UINT32_MAX = require( '@stdlib/math/constants/uint32-max' );
var isArrayLike = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof isArrayLike, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function returns `true` if provided an array-like value', function test( t ) {
	var values;
	var i;

	values = [
		[],
		{ 'length': 10 },
		'beep',
		arguments
	];

	for ( i = 0; i < values.length; i++ ) {
		t.equal( isArrayLike( values[i] ), true, 'returns true when provided '+values[i] );
	}
	t.end();
});

tape( 'the function returns `false` if provided an array-like value whose length exceeds the maximum array length', function test( t ) {
	var o = { 'length': UINT32_MAX+1 };
	t.equal( isArrayLike( o ), false, 'returns false' );
	t.end();
});

tape( 'the function returns `false` if provided an array-like value whose length property is not an integer', function test( t ) {
	var o = { 'length': 3.14 };
	t.equal( isArrayLike( o ), false, 'returns false' );
	t.end();
});

tape( 'the function returns `false` if provided an array-like value whose length property is a negative integer', function test( t ) {
	var o = { 'length': -1 };
	t.equal( isArrayLike( o ), false, 'returns false' );
	t.end();
});

tape( 'the function returns `false` if not provided an array-like value', function test( t ) {
	var values;
	var i;

	values = [
		5,
		null,
		undefined,
		NaN,
		true,
		false,
		{},
		function boop( a, b, c ) {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.equal( isArrayLike( values[i] ), false, 'returns false when provided '+values[i] );
	}
	t.end();
});
<|endoftext|>


<commit_before>function FeedbackControl($scope, FeedbackControlService, FeedbackSignal, Template, FeedbackService) {

    var qs = (function(a) {
        if (a == "") return {};
        var b = {};
        for (var i = 0; i < a.length; ++i) {
            var p=a[i].split('=');
            if (p.length != 2) continue;
            b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
        }
        return b;
    })(window.location.search.substr(1).split('&'));

    var is_empty = function(obj) {
        return Object.keys(obj).length === 0;
    }

    var update_selected = function(action, id) {
        if (action == 'add' && $scope.selected.indexOf(id) == -1) {
            $scope.selected.push(id);
        }

        if (action == 'remove' && $scope.selected.indexOf(id) != -1) {
            $scope.selected.splice($scope.selected.indexOf(id), 1);
        }
    }

    var feedback_collect = function(n, mode, collect_type) {
        var me = n;

        var entity = $(".dashboard-feedback[feedback=" + me + "]");
        var entity_parent = entity.parents('.feedback-group');
        var score = entity.attr('score');
        var permission = entity.attr('permission');
        var catid = entity.attr('catid');

        if(
               (score >= 3 && permission == 1)
           || ((score >= 3 && permission == 0) && (mode == 'delete' || mode == 'restore' || mode == 'remove'))
           || ((score == 1 || score == 2) && (mode == 'delete' || mode == 'restore' || mode == 'remove'))
          )  {
            entity.hide();
            var child_count = entity_parent.children('.dashboard-feedback:visible');

            if(child_count.length == 0) {
                entity_parent.hide();
            }

            if(collect_type == 'feedid') {
                return me;
            } else {
                return catid;
            }
        }
    }

    var current_url = window.location.pathname;

    var url_params = function() {
        var prmstr = window.location.search.substr(1);
        var prmarr = prmstr.split ("&");
        var params = {};

        for ( var i = 0; i < prmarr.length; i++) {
            var tmparr = prmarr[i].split("=");
                params[tmparr[0]] = tmparr[1];
        }

        return params;
    }

    $scope.selected   = [];
    $scope.uri_params = [];
    var checkboxes = $(".feed-checkbox");

    $scope.status_select_value = 'none';
    $scope.date_filter     = (!is_empty(qs) && qs['date']) ? qs['date'] : 'none';
    $scope.priority_filter = (!is_empty(qs) && qs['priority']) ? qs['priority'] : 'none';
    $scope.status_filter   = (!is_empty(qs) && qs['status']) ? qs['status'] : 'none';
    $scope.rating_filter   = (!is_empty(qs) && qs['rating']) ? qs['rating'] : 'none';

    $scope.feedback_status = function($event) {
        var target = $($event.target);
        var feed = $.parseJSON(target.attr('data-feed'));

        if(current_url.match(/inbox\/all|deleted/g)) {
            var current = {
                id: feed.id
              , catid: Template.default_category_id
              , status: feed.status
              , origin: Template.current_inbox_state
            }
        }

        if(current_url.match(/published/g)) {
            var current = {
                id: feed.id
              , catid: Template.default_category_id
              , status: feed.status
              , origin: feed.origin
            }
        }

        if(current_url.match(/filed/g)) {
            var current = {
                id: feed.id
              , catid: feed.catid
              , status: feed.status
              , origin: Template.current_inbox_state
            }
        }

        var process = function() {
            FeedbackSignal.current_state(current);
            feed.origin = Template.current_inbox_state;
            FeedbackControlService.change_status(feed, true);
        }

        if(feed.status != "remove") {
            process();
        }else {
            if(confirm("Warning! You are about to permanently delete this feedback. There is no undo.")) {
                process();
            }
        }
    }

    $scope.flag_feedback = function($event) {
        var flag = $($event.target);
        var feed = $.parseJSON(flag.attr('data-feed'));

        var return_policy = flag.attr('return-policy') == true;

        var modfeed = {
            id: feed.id
          , catid: (current_url.match(/filed/g)) ? feed.catid : Template.default_category_id
          , status: (return_policy == true) ? feed.status : 'unflag'
          , origin: Template.current_inbox_state
        }

        FeedbackControlService.flag_feedback(modfeed);
    }

    $scope.update_selection = function($event, id) {
        var checkbox = $event.target;
        var action = (checkbox.checked ? 'add' : 'remove');
        update_selected(action, id);
    }

    $scope.change_value_status = function() {
        if( $('input[type=checkbox].feed-checkbox:checked').length > 0 ) {

            var selected = [];
            var catids = [];
            var ids = $scope.selected;
            var mode = $scope.status_select_value;
            var feed = {};

            //refactor this you lazy bastard
            if(mode == "remove") {
                if(confirm("Are you sure you want to permanently remove this feedback? There is no undo.")) {
                    for(var i=0; i < ids.length; ++i) {
                        selected.push(feedback_collect(ids[i], mode, 'feedid'));
                        catids.push(feedback_collect(ids[i], mode, 'catid'));
                    }
                } else {
                    $('input[type=checkbox].feed-checkbox:checked, .sorter-checkbox:checked').click();
                }
            } else {
                for(var i=0; i < ids.length; ++i) {
                    selected.push(feedback_collect(ids[i], mode, 'feedid'));
                    catids.push(feedback_collect(ids[i], mode, 'catid'));
                }
            }

            if(selected.length > 0) {
                if(current_url.match(/filed/g)) {
                    var feed = {
                        id: selected
                      , status: $scope.status_select_value
                      , catid:  catids
                      , origin: Template.current_inbox_state
                    }
                } else {
                    var feed = {
                        id: selected
                      , status: $scope.status_select_value
                      , catid: Template.default_category_id
                      , origin: Template.current_inbox_state
                    }
                }

                if(mode == "remove") {
                    FeedbackSignal.current_state(feed);
                    FeedbackControlService.change_status(feed, true);
                } else {
                    FeedbackSignal.current_state(feed);
                    FeedbackControlService.change_status(feed, true);
                }

                $(".checky-box-container").show();

            } else {
                if(mode != "remove") {
                    alert("Action is not allowed!");
                }
            }

            selected = [];
            $scope.selected = [];
            $scope.status_select_value = 'none';

        }
    }

    $scope.select_all = function($event) {

        var checkbox = $event.target;
        var action = (checkbox.checked ? 'add' : 'remove');

        for(var i=0; i < checkboxes.length; i++) {

            var entity = $(checkboxes[i]);
            var myparent = entity.parents('.dashboard-feedback');

            //if action is add then click on checkboxes if not click again to deselect
            if(action == "add") {
                if(!entity.is(":checked")) {
                    entity.click();
                }
            } else {
                entity.click();
            }

            update_selected(action, parseInt(entity.val(), 10));
        }
    }

    $scope.process_filter = function() {

        var data = {}
        if($scope.rating_filter != 'none') {
            data.rating = $scope.rating_filter;
        }

        if($scope.status_filter != 'none') {
            data.status = $scope.status_filter;
        }

        if($scope.priority_filter != 'none') {
            data.priority = $scope.priority_filter;
        }

        if($scope.date_filter != 'none') {
            data.date = $scope.date_filter;
        }

        var result = $.param(data);
        var params = url_params();
        var page = '';
        if('page' in params) { page = '&page=' + params.page; }
        var str = '?' + result + page;
        document.location.search = str;
    }

    $scope.fast_forward = function(email, feedid) {
        FeedbackService.send_fastforward(email, feedid);
    }

    $scope.$on('expungeFeedId', function() {
        FeedbackSignal.data.id = [];
        $scope.selected = [];
    })
}

function CheckyBox($scope, FeedbackSignal, FeedbackControlService) {

    $scope.status_selection;
    $scope.id;
    $scope.data;

    $scope.undo = function() {
        console.log($scope.data);
        FeedbackControlService.change_status($scope.data);
    }

    $scope.close = function() {
        location.reload();
    }

    $scope.$on('checkFeedbackStatus', function() {
        $scope.status_selection = FeedbackSignal.data.status;
        $scope.id = FeedbackSignal.data.id;
        $scope.data = FeedbackSignal.data;
    });
}
<commit_msg>atlasd<commit_after>function FeedbackControl($scope, FeedbackControlService, FeedbackSignal, Template, FeedbackService) {

    var qs = (function(a) {
        if (a == "") return {};
        var b = {};
        for (var i = 0; i < a.length; ++i) {
            var p=a[i].split('=');
            if (p.length != 2) continue;
            b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
        }
        return b;
    })(window.location.search.substr(1).split('&'));

    var is_empty = function(obj) {
        return Object.keys(obj).length === 0;
    }

    var update_selected = function(action, id) {
        if (action == 'add' && $scope.selected.indexOf(id) == -1) {
            $scope.selected.push(id);
        }

        if (action == 'remove' && $scope.selected.indexOf(id) != -1) {
            $scope.selected.splice($scope.selected.indexOf(id), 1);
        }
    }

    var feedback_collect = function(n, mode, collect_type) {
        var me = n;

        var entity = $(".dashboard-feedback[feedback=" + me + "]");
        var entity_parent = entity.parents('.feedback-group');
        var score = entity.attr('score');
        var permission = entity.attr('permission');
        var catid = entity.attr('catid');

        if(
               (score >= 3 && permission == 1)
           || ((score >= 3 && permission == 0) && (mode == 'delete' || mode == 'restore' || mode == 'remove'))
           || ((score == 1 || score == 2) && (mode == 'delete' || mode == 'restore' || mode == 'remove'))
          )  {
            entity.hide();
            var child_count = entity_parent.children('.dashboard-feedback:visible');

            if(child_count.length == 0) {
                entity_parent.hide();
            }

            if(collect_type == 'feedid') {
                return me;
            } else {
                return catid;
            }
        }
    }

    var current_url = window.location.pathname;

    var url_params = function() {
        var prmstr = window.location.search.substr(1);
        var prmarr = prmstr.split ("&");
        var params = {};

        for ( var i = 0; i < prmarr.length; i++) {
            var tmparr = prmarr[i].split("=");
                params[tmparr[0]] = tmparr[1];
        }

        return params;
    }

    $scope.selected   = [];
    $scope.uri_params = [];
    var checkboxes = $(".feed-checkbox");

    $scope.status_select_value = 'none';
    $scope.date_filter     = (!is_empty(qs) && qs['date']) ? qs['date'] : 'none';
    $scope.priority_filter = (!is_empty(qs) && qs['priority']) ? qs['priority'] : 'none';
    $scope.status_filter   = (!is_empty(qs) && qs['status']) ? qs['status'] : 'none';
    $scope.rating_filter   = (!is_empty(qs) && qs['rating']) ? qs['rating'] : 'none';

    $scope.feedback_status = function($event) {
        var target = $($event.target);
        var feed = $.parseJSON(target.attr('data-feed'));

        if(current_url.match(/inbox\/all|deleted/g)) {
            var current = {
                id: feed.id
              , catid: Template.default_category_id
              , status: feed.status
              , origin: Template.current_inbox_state
            }
        }

        if(current_url.match(/published/g)) {
            var current = {
                id: feed.id
              , catid: Template.default_category_id
              , status: feed.status
              , origin: feed.origin
            }
        }

        if(current_url.match(/filed/g)) {
            var current = {
                id: feed.id
              , catid: feed.catid
              , status: feed.status
              , origin: Template.current_inbox_state
            }
        }

        var process = function() {
            console.log(current);
            FeedbackSignal.current_state(current);
            feed.origin = Template.current_inbox_state;
            FeedbackControlService.change_status(feed, true);
        }

        if(feed.status != "remove") {
            process();
        }else {
            if(confirm("Warning! You are about to permanently delete this feedback. There is no undo.")) {
                process();
            }
        }
    }

    $scope.flag_feedback = function($event) {
        var flag = $($event.target);
        var feed = $.parseJSON(flag.attr('data-feed'));

        var return_policy = flag.attr('return-policy') == true;

        var modfeed = {
            id: feed.id
          , catid: (current_url.match(/filed/g)) ? feed.catid : Template.default_category_id
          , status: (return_policy == true) ? feed.status : 'unflag'
          , origin: Template.current_inbox_state
        }

        FeedbackControlService.flag_feedback(modfeed);
    }

    $scope.update_selection = function($event, id) {
        var checkbox = $event.target;
        var action = (checkbox.checked ? 'add' : 'remove');
        update_selected(action, id);
    }

    $scope.change_value_status = function() {
        if( $('input[type=checkbox].feed-checkbox:checked').length > 0 ) {

            var selected = [];
            var catids = [];
            var ids = $scope.selected;
            var mode = $scope.status_select_value;
            var feed = {};

            //refactor this you lazy bastard
            if(mode == "remove") {
                if(confirm("Are you sure you want to permanently remove this feedback? There is no undo.")) {
                    for(var i=0; i < ids.length; ++i) {
                        selected.push(feedback_collect(ids[i], mode, 'feedid'));
                        catids.push(feedback_collect(ids[i], mode, 'catid'));
                    }
                } else {
                    $('input[type=checkbox].feed-checkbox:checked, .sorter-checkbox:checked').click();
                }
            } else {
                for(var i=0; i < ids.length; ++i) {
                    selected.push(feedback_collect(ids[i], mode, 'feedid'));
                    catids.push(feedback_collect(ids[i], mode, 'catid'));
                }
            }

            if(selected.length > 0) {
                if(current_url.match(/filed/g)) {
                    var feed = {
                        id: selected
                      , status: $scope.status_select_value
                      , catid:  catids
                      , origin: Template.current_inbox_state
                    }
                } else {
                    var feed = {
                        id: selected
                      , status: $scope.status_select_value
                      , catid: Template.default_category_id
                      , origin: Template.current_inbox_state
                    }
                }

                if(mode == "remove") {
                    FeedbackSignal.current_state(feed);
                    FeedbackControlService.change_status(feed, true);
                } else {
                    FeedbackSignal.current_state(feed);
                    FeedbackControlService.change_status(feed, true);
                }

                $(".checky-box-container").show();

            } else {
                if(mode != "remove") {
                    alert("Action is not allowed!");
                }
            }

            selected = [];
            $scope.selected = [];
            $scope.status_select_value = 'none';

        }
    }

    $scope.select_all = function($event) {

        var checkbox = $event.target;
        var action = (checkbox.checked ? 'add' : 'remove');

        for(var i=0; i < checkboxes.length; i++) {

            var entity = $(checkboxes[i]);
            var myparent = entity.parents('.dashboard-feedback');

            //if action is add then click on checkboxes if not click again to deselect
            if(action == "add") {
                if(!entity.is(":checked")) {
                    entity.click();
                }
            } else {
                entity.click();
            }

            update_selected(action, parseInt(entity.val(), 10));
        }
    }

    $scope.process_filter = function() {

        var data = {}
        if($scope.rating_filter != 'none') {
            data.rating = $scope.rating_filter;
        }

        if($scope.status_filter != 'none') {
            data.status = $scope.status_filter;
        }

        if($scope.priority_filter != 'none') {
            data.priority = $scope.priority_filter;
        }

        if($scope.date_filter != 'none') {
            data.date = $scope.date_filter;
        }

        var result = $.param(data);
        var params = url_params();
        var page = '';
        if('page' in params) { page = '&page=' + params.page; }
        var str = '?' + result + page;
        document.location.search = str;
    }

    $scope.fast_forward = function(email, feedid) {
        FeedbackService.send_fastforward(email, feedid);
    }

    $scope.$on('expungeFeedId', function() {
        FeedbackSignal.data.id = [];
        $scope.selected = [];
    })
}

function CheckyBox($scope, FeedbackSignal, FeedbackControlService) {

    $scope.status_selection;
    $scope.id;
    $scope.data;

    $scope.undo = function() {
        console.log($scope.data);
        FeedbackControlService.change_status($scope.data);
    }

    $scope.close = function() {
        location.reload();
    }

    $scope.$on('checkFeedbackStatus', function() {
        $scope.status_selection = FeedbackSignal.data.status;
        $scope.id = FeedbackSignal.data.id;
        $scope.data = FeedbackSignal.data;
    });
}
<|endoftext|>


<commit_before>import determineCondition from '../utils/determineCondition';
import isSelector from '../utils/isSelector';

const convertStylesToArray = (obj, previousSelectors, recursiveOptions = {}) => {
  if(typeof obj !== 'object') return obj;
  const newObj = Object.entries(obj);
  return newObj.map(([key, value]) => {
    let selectors = [...previousSelectors];
    // All @-stuff from css, should go global.
    if(key.startsWith('@')) {
      selectors = [ key ];
    }

    let type = 'node';
    let condition = null;
    if(key.startsWith('_')) {
      type = 'mixin';
    }
    else if(Array.isArray(value)) {
      type = 'array';
      value = value.map((v, i) => {
        if(typeof v === 'object') {
          return convertStylesToArray(v, selectors);
        }
        return {
          type: 'node',
          selectors,
          append: true,
          key,
          value: v,
          condition,
        };
      })
    }
    else if(typeof value === 'object' && value){
      type = 'nested';
      // If media query, take current selector, and put it after the media query
      if(key.startsWith('@media')) {
        selectors.push(previousSelectors[previousSelectors.length - 1]);
      }
      else if(selectors[0].startsWith('@keyframes')) {
        if(!key.startsWith('@keyframes')){
          selectors.push(key);
        }
      }
      // CSS Selectors like "&:hover" etc.
      else if(isSelector(key)) {
        const currentSel = selectors[selectors.length - 1];
        if(currentSel !== '&' && isSelector(currentSel)) {
          // Support multi level , seperated deeper nesting.
          key = key.split(/,\ ?/g).map(keyS => {
            return currentSel.split(/,\ ?/g).map((currentS) => {
              return keyS.replace(/&/gi, currentS);
            }).join(', ');
          }).join(', ');
        }
        selectors[selectors.length - 1] = key;
      }
      // Else we assume this is prop based conditions
      else {
        // setting condition to determine if styles should be applied
        if(!recursiveOptions.disableProps) {
          condition = determineCondition(key);
          if(condition && recursiveOptions.__touchedConditionalProps) {
            recursiveOptions.__touchedConditionalProps[condition.key] = true;
          }
        }
      }
      value = convertStylesToArray(value, selectors, recursiveOptions);
    }

    return {
      type,
      key,
      value,
      selectors,
      condition,
    };
  })
}
export default convertStylesToArray;<commit_msg>added temporary warning<commit_after>import determineCondition from '../utils/determineCondition';
import isSelector from '../utils/isSelector';

const convertStylesToArray = (obj, previousSelectors, recursiveOptions = {}) => {
  if(typeof obj !== 'object') return obj;
  const newObj = Object.entries(obj);
  return newObj.map(([key, value]) => {
    let selectors = [...previousSelectors];
    // All @-stuff from css, should go global.
    if(key.startsWith('@')) {
      selectors = [ key ];
    }

    let type = 'node';
    let condition = null;
    if(key.startsWith('_')) {
      type = 'mixin';
    }
    else if(Array.isArray(value)) {
      type = 'array';
      value = value.map((v, i) => {
        if(typeof v === 'object') {
          return convertStylesToArray(v, selectors);
        }
        return {
          type: 'node',
          selectors,
          append: true,
          key,
          value: v,
          condition,
        };
      })
    }
    else if(typeof value === 'object' && value){
      type = 'nested';
      // If media query, take current selector, and put it after the media query
      if(key.startsWith('@media')) {
        selectors.push(previousSelectors[previousSelectors.length - 1]);
      }
      else if(selectors[0].startsWith('@keyframes')) {
        if(!key.startsWith('@keyframes')){
          selectors.push(key);
        }
      }
      // CSS Selectors like "&:hover" etc.
      else if(isSelector(key)) {
        const currentSel = selectors[selectors.length - 1];
        if(currentSel !== '&' && isSelector(currentSel)) {
          // Support multi level , seperated deeper nesting.
          console.warn('swiss temporary warning. check', currentSel, key, 'there might be breaking changes');
          key = key.split(/,\ ?/g).map(keyS => {
            return currentSel.split(/,\ ?/g).map((currentS) => {
              return keyS.replace(/&/gi, currentS);
            }).join(', ');
          }).join(', ');
        }
        selectors[selectors.length - 1] = key;
      }
      // Else we assume this is prop based conditions
      else {
        // setting condition to determine if styles should be applied
        if(!recursiveOptions.disableProps) {
          condition = determineCondition(key);
          if(condition && recursiveOptions.__touchedConditionalProps) {
            recursiveOptions.__touchedConditionalProps[condition.key] = true;
          }
        }
      }
      value = convertStylesToArray(value, selectors, recursiveOptions);
    }

    return {
      type,
      key,
      value,
      selectors,
      condition,
    };
  })
}
export default convertStylesToArray;<|endoftext|>


<commit_before>function FeedbackControl($scope, FeedbackControlService, FeedbackSignal, Template, FeedbackService) {

    var qs = (function(a) {
        if (a == "") return {};
        var b = {};
        for (var i = 0; i < a.length; ++i) {
            var p=a[i].split('=');
            if (p.length != 2) continue;
            b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
        }
        return b;
    })(window.location.search.substr(1).split('&'));

    var is_empty = function(obj) {
        return Object.keys(obj).length === 0;
    }

    var update_selected = function(action, id) {
        if (action == 'add' && $scope.selected.indexOf(id) == -1) {
            $scope.selected.push(id);
        }

        if (action == 'remove' && $scope.selected.indexOf(id) != -1) {
            $scope.selected.splice($scope.selected.indexOf(id), 1);
        }
    }

    var feedback_collect = function(n, mode, collect_type) {
        var me = n;

        var entity = $(".dashboard-feedback[feedback=" + me + "]");
        var entity_parent = entity.parents('.feedback-group');
        var score = entity.attr('score');
        var permission = entity.attr('permission');
        var catid = entity.attr('catid');

        if(
               (score >= 3 && permission == 1)
           || ((score >= 3 && permission == 0) && (mode == 'delete' || mode == 'restore' || mode == 'remove'))
           || ((score == 1 || score == 2) && (mode == 'delete' || mode == 'restore' || mode == 'remove'))
          )  {
            entity.hide();
            var child_count = entity_parent.children('.dashboard-feedback:visible');

            if(child_count.length == 0) {
                entity_parent.hide();
            }

            if(collect_type == 'feedid') {
                return me;
            } else {
                return catid;
            }
        }
    }

    var current_url = window.location.pathname;

    var insert_param = function(key, value) {

        var key = escape(key); value = escape(value);
        var kvp = document.location.search.substr(1).split('&');
        if (kvp == '') {
            document.location.search = '?' + key + '=' + value;
        } else {
            var i=kvp.length;
            var x;
            while(i--) {
                x = kvp[i].split('=');

                if (x[0]==key) {
                    x[1] = value;
                    kvp[i] = x.join('=');
                    break;
                }
            }

            if (i<0) {
                kvp[kvp.length] = [key,value].join('=');
            }

            //this will reload the page, it's likely better to store this until finished
            document.location.search = kvp.join('&');
        }
    }

    $scope.selected = [];
    var checkboxes = $(".feed-checkbox");

    $scope.status_select_value = 'none';
    $scope.date_filter     = (!is_empty(qs) && qs['date']) ? qs['date'] : 'none';
    $scope.priority_filter = (!is_empty(qs) && qs['priority']) ? qs['priority'] : 'none';
    $scope.status_filter   = (!is_empty(qs) && qs['status']) ? qs['status'] : 'none';
    $scope.rating_filter   = (!is_empty(qs) && qs['rating']) ? qs['rating'] : 'none';

    $scope.feedback_status = function($event) {

        var target = $($event.target);
        var feed = $.parseJSON(target.attr('data-feed'));

        if(current_url.match(/filed/g)) {
            var current = {
                id: feed.id
              , catid: feed.catid
              , status: feed.status
              , origin: Template.current_inbox_state
            }
        } else {
            var current = {
                id: feed.id
              , catid: Template.default_category_id
              , status: feed.status
              , origin: Template.current_inbox_state
            }
        }

        if(feed.status != "remove") {
            FeedbackSignal.current_state(current);
            feed.origin = Template.current_inbox_state;
            FeedbackControlService.change_status(feed, true);
        }else {
            if(confirm("Warning! You are about to permanently delete this feedback. There is no undo.")) {
                FeedbackSignal.current_state(current);
                feed.origin = Template.current_inbox_state;
                FeedbackControlService.change_status(feed, true);
            }
        }
    }

    $scope.flag_feedback = function($event) {
        var flag = $($event.target);
        var feed = $.parseJSON(flag.attr('data-feed'));

        var return_policy = flag.attr('return-policy') == true;

        var modfeed = {
            id: feed.id
          , catid: (current_url.match(/filed/g)) ? feed.catid : Template.default_category_id
          , status: (return_policy == true) ? feed.status : 'unflag'
          , origin: Template.current_inbox_state
        }

        FeedbackControlService.flag_feedback(modfeed);
    }

    $scope.update_selection = function($event, id) {
        var checkbox = $event.target;
        var action = (checkbox.checked ? 'add' : 'remove');
        update_selected(action, id);
    }

    $scope.change_value_status = function() {
        if( $('input[type=checkbox].feed-checkbox:checked').length > 0 ) {

            var selected = [];
            var catids = [];
            var ids = $scope.selected;
            var mode = $scope.status_select_value;
            var feed = {};

            if(mode == "remove") {
                if(confirm("Are you sure you want to permanently remove this feedback? There is no undo.")) {
                    for(var i=0; i < ids.length; ++i) {
                        selected.push(feedback_collect(ids[i], mode, 'feedid'));
                        catids.push(feedback_collect(ids[i], mode, 'catid'));
                    }
                } else {
                    $('input[type=checkbox].feed-checkbox:checked, .sorter-checkbox:checked').click();
                }
            } else {
                for(var i=0; i < ids.length; ++i) {
                    selected.push(feedback_collect(ids[i], mode, 'feedid'));
                    catids.push(feedback_collect(ids[i], mode, 'catid'));
                }
            }

            if(selected.length > 0) {
                if(current_url.match(/filed/g)) {
                    var feed = {
                        id: selected
                      , status: $scope.status_select_value
                      , catid:  catids
                      , origin: Template.current_inbox_state
                    }
                } else {
                    var feed = {
                        id: selected
                      , status: $scope.status_select_value
                      , catid: Template.default_category_id
                      , origin: Template.current_inbox_state
                    }
                }

                if(mode == "remove") {
                    FeedbackSignal.current_state(feed);
                    FeedbackControlService.change_status(feed, true);
                } else {
                    FeedbackSignal.current_state(feed);
                    FeedbackControlService.change_status(feed, true);
                }

                $(".checky-box-container").show();

            } else {
                if(mode != "remove") {
                    alert("Action is not allowed!");
                }
            }

            selected = [];
            $scope.selected = [];
            $scope.status_select_value = 'none';

        }
    }

    $scope.select_all = function($event) {

        var checkbox = $event.target;
        var action = (checkbox.checked ? 'add' : 'remove');

        for(var i=0; i < checkboxes.length; i++) {

            var entity = $(checkboxes[i]);
            var myparent = entity.parents('.dashboard-feedback');

            //if action is add then click on checkboxes if not click again to deselect
            if(action == "add") {
                if(!entity.is(":checked")) {
                    entity.click();
                }
            } else {
                entity.click();
            }

            update_selected(action, parseInt(entity.val(), 10));
        }
    }

    $scope.filter = function(filter_type) {
        if(filter_type == 'date') {
            if($scope.date_filter == 'none') {
                window.location = window.location.pathname;
            } else {
                insert_param('date', $scope.date_filter);
            }
        }

        if(filter_type == 'priority') {
            if($scope.priority_filter == 'none') {
                window.location = window.location.pathname;
            } else {
                insert_param('priority', $scope.priority_filter);
            }
        }

        if(filter_type == 'status') {
            if($scope.status_filter == 'none') {
                window.location = window.location.pathname;
            } else {
                insert_param('status', $scope.status_filter);
            }
        }

        if(filter_type == 'rating') {
            if($scope.rating_filter == 'none') {
                window.location = window.location.pathname;
            } else {
                insert_param('rating', $scope.rating_filter);
            }
        }
    }

    $scope.fast_forward = function(email, feedid) {
        FeedbackService.send_fastforward(email, feedid);
    }

    $scope.$on('expungeFeedId', function() {
        FeedbackSignal.data.id = [];
        $scope.selected = [];
    })
}

function CheckyBox($scope, FeedbackSignal, FeedbackControlService) {

    $scope.status_selection;
    var checkboxes = $(".feed-checkbox:not(:hidden)");

    $scope.undo = function() {
        FeedbackControlService.change_status(FeedbackSignal.data, false);
    }

    $scope.close = function() {
        location.reload();
    }

    $scope.$on('checkFeedbackStatus', function() {
        $scope.status_selection = FeedbackSignal.data.status;
        $scope.id = FeedbackSignal.data.id;
    });
}
<commit_msg>fixkgn<commit_after>function FeedbackControl($scope, FeedbackControlService, FeedbackSignal, Template, FeedbackService) {

    var qs = (function(a) {
        if (a == "") return {};
        var b = {};
        for (var i = 0; i < a.length; ++i) {
            var p=a[i].split('=');
            if (p.length != 2) continue;
            b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
        }
        return b;
    })(window.location.search.substr(1).split('&'));

    var is_empty = function(obj) {
        return Object.keys(obj).length === 0;
    }

    var update_selected = function(action, id) {
        if (action == 'add' && $scope.selected.indexOf(id) == -1) {
            $scope.selected.push(id);
        }

        if (action == 'remove' && $scope.selected.indexOf(id) != -1) {
            $scope.selected.splice($scope.selected.indexOf(id), 1);
        }
    }

    var feedback_collect = function(n, mode, collect_type) {
        var me = n;

        var entity = $(".dashboard-feedback[feedback=" + me + "]");
        var entity_parent = entity.parents('.feedback-group');
        var score = entity.attr('score');
        var permission = entity.attr('permission');
        var catid = entity.attr('catid');

        if(
               (score >= 3 && permission == 1)
           || ((score >= 3 && permission == 0) && (mode == 'delete' || mode == 'restore' || mode == 'remove'))
           || ((score == 1 || score == 2) && (mode == 'delete' || mode == 'restore' || mode == 'remove'))
          )  {
            entity.hide();
            var child_count = entity_parent.children('.dashboard-feedback:visible');

            if(child_count.length == 0) {
                entity_parent.hide();
            }

            if(collect_type == 'feedid') {
                return me;
            } else {
                return catid;
            }
        }
    }

    var current_url = window.location.pathname;

    var insert_param = function(key, value) {

        var key = escape(key); value = escape(value);
        var kvp = document.location.search.substr(1).split('&');
        if (kvp == '') {
            document.location.search = '?' + key + '=' + value;
        } else {
            var i=kvp.length;
            var x;
            while(i--) {
                x = kvp[i].split('=');

                if (x[0]==key) {
                    x[1] = value;
                    kvp[i] = x.join('=');
                    break;
                }
            }

            if (i<0) {
                kvp[kvp.length] = [key,value].join('=');
            }

            //this will reload the page, it's likely better to store this until finished
            document.location.search = kvp.join('&');
        }
    }

    $scope.selected = [];
    var checkboxes = $(".feed-checkbox");

    $scope.status_select_value = 'none';
    $scope.date_filter     = (!is_empty(qs) && qs['date']) ? qs['date'] : 'none';
    $scope.priority_filter = (!is_empty(qs) && qs['priority']) ? qs['priority'] : 'none';
    $scope.status_filter   = (!is_empty(qs) && qs['status']) ? qs['status'] : 'none';
    $scope.rating_filter   = (!is_empty(qs) && qs['rating']) ? qs['rating'] : 'none';

    $scope.feedback_status = function($event) {

        var target = $($event.target);
        var feed = $.parseJSON(target.attr('data-feed'));

        if(current_url.match(/filed/g)) {
            var current = {
                id: feed.id
              , catid: feed.catid
              , status: feed.status
              , origin: Template.current_inbox_state
            }
        } else {
            var current = {
                id: feed.id
              , catid: Template.default_category_id
              , status: feed.status
              , origin: Template.current_inbox_state
            }
        }

        console.log(current);

        if(feed.status != "remove") {
            FeedbackSignal.current_state(current);
            feed.origin = Template.current_inbox_state;
            FeedbackControlService.change_status(feed, true);
        }else {
            if(confirm("Warning! You are about to permanently delete this feedback. There is no undo.")) {
                FeedbackSignal.current_state(current);
                feed.origin = Template.current_inbox_state;
                FeedbackControlService.change_status(feed, true);
            }
        }
    }

    $scope.flag_feedback = function($event) {
        var flag = $($event.target);
        var feed = $.parseJSON(flag.attr('data-feed'));

        var return_policy = flag.attr('return-policy') == true;

        var modfeed = {
            id: feed.id
          , catid: (current_url.match(/filed/g)) ? feed.catid : Template.default_category_id
          , status: (return_policy == true) ? feed.status : 'unflag'
          , origin: Template.current_inbox_state
        }

        FeedbackControlService.flag_feedback(modfeed);
    }

    $scope.update_selection = function($event, id) {
        var checkbox = $event.target;
        var action = (checkbox.checked ? 'add' : 'remove');
        update_selected(action, id);
    }

    $scope.change_value_status = function() {
        if( $('input[type=checkbox].feed-checkbox:checked').length > 0 ) {

            var selected = [];
            var catids = [];
            var ids = $scope.selected;
            var mode = $scope.status_select_value;
            var feed = {};

            if(mode == "remove") {
                if(confirm("Are you sure you want to permanently remove this feedback? There is no undo.")) {
                    for(var i=0; i < ids.length; ++i) {
                        selected.push(feedback_collect(ids[i], mode, 'feedid'));
                        catids.push(feedback_collect(ids[i], mode, 'catid'));
                    }
                } else {
                    $('input[type=checkbox].feed-checkbox:checked, .sorter-checkbox:checked').click();
                }
            } else {
                for(var i=0; i < ids.length; ++i) {
                    selected.push(feedback_collect(ids[i], mode, 'feedid'));
                    catids.push(feedback_collect(ids[i], mode, 'catid'));
                }
            }

            if(selected.length > 0) {
                if(current_url.match(/filed/g)) {
                    var feed = {
                        id: selected
                      , status: $scope.status_select_value
                      , catid:  catids
                      , origin: Template.current_inbox_state
                    }
                } else {
                    var feed = {
                        id: selected
                      , status: $scope.status_select_value
                      , catid: Template.default_category_id
                      , origin: Template.current_inbox_state
                    }
                }

                if(mode == "remove") {
                    FeedbackSignal.current_state(feed);
                    FeedbackControlService.change_status(feed, true);
                } else {
                    FeedbackSignal.current_state(feed);
                    FeedbackControlService.change_status(feed, true);
                }

                $(".checky-box-container").show();

            } else {
                if(mode != "remove") {
                    alert("Action is not allowed!");
                }
            }

            selected = [];
            $scope.selected = [];
            $scope.status_select_value = 'none';

        }
    }

    $scope.select_all = function($event) {

        var checkbox = $event.target;
        var action = (checkbox.checked ? 'add' : 'remove');

        for(var i=0; i < checkboxes.length; i++) {

            var entity = $(checkboxes[i]);
            var myparent = entity.parents('.dashboard-feedback');

            //if action is add then click on checkboxes if not click again to deselect
            if(action == "add") {
                if(!entity.is(":checked")) {
                    entity.click();
                }
            } else {
                entity.click();
            }

            update_selected(action, parseInt(entity.val(), 10));
        }
    }

    $scope.filter = function(filter_type) {
        if(filter_type == 'date') {
            if($scope.date_filter == 'none') {
                window.location = window.location.pathname;
            } else {
                insert_param('date', $scope.date_filter);
            }
        }

        if(filter_type == 'priority') {
            if($scope.priority_filter == 'none') {
                window.location = window.location.pathname;
            } else {
                insert_param('priority', $scope.priority_filter);
            }
        }

        if(filter_type == 'status') {
            if($scope.status_filter == 'none') {
                window.location = window.location.pathname;
            } else {
                insert_param('status', $scope.status_filter);
            }
        }

        if(filter_type == 'rating') {
            if($scope.rating_filter == 'none') {
                window.location = window.location.pathname;
            } else {
                insert_param('rating', $scope.rating_filter);
            }
        }
    }

    $scope.fast_forward = function(email, feedid) {
        FeedbackService.send_fastforward(email, feedid);
    }

    $scope.$on('expungeFeedId', function() {
        FeedbackSignal.data.id = [];
        $scope.selected = [];
    })
}

function CheckyBox($scope, FeedbackSignal, FeedbackControlService) {

    $scope.status_selection;
    var checkboxes = $(".feed-checkbox:not(:hidden)");

    $scope.undo = function() {
        FeedbackControlService.change_status(FeedbackSignal.data, false);
    }

    $scope.close = function() {
        location.reload();
    }

    $scope.$on('checkFeedbackStatus', function() {
        $scope.status_selection = FeedbackSignal.data.status;
        $scope.id = FeedbackSignal.data.id;
    });
}
<|endoftext|>


<commit_before>var _ = require('underscore'),
	Hapi = require('hapi'),
	queryParser = require('./../query'),
	RSVP = require('rsvp');

var orm, serializer;

module.exports = function (ormModule, serializerModule) {
	orm = ormModule;
	serializer = serializerModule;

	return handler;
};

function handler (request, reply) {
	var modelSchema = orm.getSchema().getModel(request.params.model),
		primaryKey = request.params.id,
		model;

	// Make sure the model exists, throw 404 if not
	if ( ! modelSchema)
		return reply(Hapi.error.notFound());

	try {
		// Get the base model
		model = orm.factory(modelSchema.getName());

		// Load the model
		if (primaryKey !== '') {
			model.find(primaryKey).then(function (data) {
				if ( ! data)
					return RSVP.Promise.cast(reply(Hapi.error.notFound(error.message)));

				return RSVP.Promise.cast(data.preGetHook(request)).then(function (data) {
					reply(prettyJson(serializer.serialize(data))).type(serializer.type());
				}).then(function () {
					data.postGetHook(request);
				});
			}).catch(error);
		}
		else {
			// Parse the params
			queryParser(request.query, model);

			model.findAll().then(function (data) {
				var d = [],
					wrapper = {
						_embedded: {}
					};

				return RSVP.Promise.cast(data.preGetHook(request)).then(function () {
					data.forEach(function(value) {
						d.push(serializer.serialize(value));
					});

					wrapper._embedded[modelSchema.getPluralizedName()] = d;

					reply(prettyJson(wrapper)).type(serializer.type());

					data.postGetHook(request);
				});

			}, error).then(null, error);
		}
	}
	catch (err) {
		if (err.name === 'AssertionException')
			return reply(Hapi.error.notFound());
		else
			error(err);
	}

	function error (err) {
		console.error(err.message);
		console.error(err.stack);
		reply(err);
	}
}

function prettyJson(obj) {
	return JSON.stringify(obj, null, 4);
}<commit_msg>Fixed a bug introduced with adding hooks to the GET collection<commit_after>var _ = require('underscore'),
	Hapi = require('hapi'),
	queryParser = require('./../query'),
	RSVP = require('rsvp');

var orm, serializer;

module.exports = function (ormModule, serializerModule) {
	orm = ormModule;
	serializer = serializerModule;

	return handler;
};

function handler (request, reply) {
	var modelSchema = orm.getSchema().getModel(request.params.model),
		primaryKey = request.params.id,
		model;

	// Make sure the model exists, throw 404 if not
	if ( ! modelSchema)
		return reply(Hapi.error.notFound());

	try {
		// Get the base model
		model = orm.factory(modelSchema.getName());

		// Load the model
		if (primaryKey !== '') {
			model.find(primaryKey).then(function (data) {
				if ( ! data)
					return RSVP.Promise.cast(reply(Hapi.error.notFound(error.message)));

				return RSVP.Promise.cast(data.preGetHook(request)).then(function (data) {
					reply(prettyJson(serializer.serialize(data))).type(serializer.type());
				}).then(function () {
					data.postGetHook(request);
				});
			}).catch(error);
		}
		else {
			// Parse the params
			queryParser(request.query, model);

			model.findAll().then(function (data) {
				var d = [],
					wrapper = {
						_embedded: {}
					};

				data.forEach(function(value) {
					d.push(serializer.serialize(value));
				});

				wrapper._embedded[modelSchema.getPluralizedName()] = d;

				reply(prettyJson(wrapper)).type(serializer.type());
			}, error).then(null, error);
		}
	}
	catch (err) {
		if (err.name === 'AssertionException')
			return reply(Hapi.error.notFound());
		else
			error(err);
	}

	function error (err) {
		console.error(err.message);
		console.error(err.stack);
		reply(err);
	}
}

function prettyJson(obj) {
	return JSON.stringify(obj, null, 4);
}<|endoftext|>