<commit_before>
'use strict';

// must have dl, with:
//  dts containing "This Version", "Latest Version", "Previous Version" in that order
//  this version is http://www.w3.org/TR/2013/WD-shortname-2013MMDD/
//  latest version is http://www.w3.org/TR/shortname/
//  h2 date and this version date must match
//  dt for editor or author

var Request = require('request')
,   Promise = require('promise');

exports.name = "headers.dl";

exports.check = function (sr, done) {

    // Pseudo-constants:
    var EDITORS_DRAFT = /Latest\ editor's\ draft/i;

    var $dl = sr.$("body div.head dl").first()
    ,   prevRequired = sr.config.previousVersion
    ,   rescinds = sr.config.rescinds
    ,   subType = sr.config.submissionType
    ,   topLevel = "TR"
    ,   thisURI = ''
    ,   previousURI = ''
    ,   latestURI = ''
    ,   err = function (str, extra) {
            sr.error(exports.name, str, extra);
        }
    ;

    var fetch = function(uri) {
      return new Promise(function (resolve, reject) {
        Request.get(uri, {}, function (error, response, body) {
          if (error) {
            reject(new Error('Fetching ' + uri + ' triggered a network error: ' + error.message));
          }
          else if (response.statusCode !== 200) {
            reject(new Error('Fetching ' + uri + ' triggered and HTTP error: code ' + response.statusCode));
          }
          else resolve(body);
        });
      });
    };

    if (subType === "member") topLevel = "Submission";
    else if (subType === "team") topLevel = "TeamSubmission";

    var extractHeaders = function (dl) {
      var dts = {};
      dl.find("dt").each(function (idx) {
        var $dt = sr.$(this)
        ,   txt = sr.norm($dt.text())
                      .replace(":", "")
                      .toLowerCase()
                      .replace("published ", "")
        ,   $dd = $dt.next('dd')
        ,   key = null
        ;
        if (!$dd) return err("no-dd", { dt: txt });
        if (txt === "this version") key = "This";
        else if (txt === "latest version") key = "Latest";
        else if (/^previous version(?:s)?$/.test(txt)) key = "Previous";
        else if (/^rescinds this recommendation?$/.test(txt)) key = "Rescinds";
        if (EDITORS_DRAFT.test(txt) && $dd.find('a')) sr.metadata('editorsDraft', $dd.find('a').attr('href').trim());
        if (key) dts[key] = { pos: idx, el: $dt, dd: $dd };
      });
      return dts;
    };

    var dts = extractHeaders($dl);
    if (!dts.This) err("this-version");
    if (!dts.Latest) err("latest-version");
    if (prevRequired && !dts.Previous) err("previous-version");
    if (!prevRequired && dts.Previous) sr.warning(exports.name, "previous-not-needed");
    if (rescinds && !dts.Rescinds) err("rescinds");
    if (!rescinds && dts.Rescinds) sr.warning(exports.name, "rescinds-not-needed");

    if (dts.This && dts.Latest && dts.This.pos > dts.Latest.pos) err("this-latest-order");
    if (dts.Latest && dts.Previous && dts.Latest.pos > dts.Previous.pos) err("latest-previous-order");
    if (dts.Latest && dts.Rescinds && dts.Latest.pos > dts.Rescinds.pos) err("latest-rescinds-order");

    var shortname;
    if (dts.This) {
        var $linkThis = dts.This.dd.find("a").first();
        if (!$linkThis
            || !$linkThis.length
            || $linkThis.attr("href").trim() !== $linkThis.text().trim()
           ) err("this-link");

        var vThisRex = "^http:\\/\\/www\\.w3\\.org\\/" +
                       topLevel +
                       "\\/(\\d{4})\\/" +
                       (sr.config.status || "[A-Z]+") +
                       "-(.+)-(\\d{4})(\\d\\d)(\\d\\d)\\/?$";
        var matches = ($linkThis.attr("href") || "").trim().match(new RegExp(vThisRex))
        ,   docDate = sr.getDocumentDate()
        ;
        if (matches) {
            thisURI = matches[0];
            sr.metadata('thisVersion', matches[0]);
            var year = matches[1] * 1
            ,   year2 = matches[3] * 1
            ,   month = matches[4] * 1
            ,   day = matches[5] * 1
            ;
            shortname = matches[2];
            if (docDate) {
                if (year !== docDate.getFullYear() ||
                    year2 !== docDate.getFullYear() ||
                    month - 1 !== docDate.getMonth() ||
                    day !== docDate.getDate()
                   ) err("this-date");
            }
            else sr.warning(exports.name, "no-date");
        }
        else err("this-syntax");
    }

    if (dts.Latest) {
        var $linkLate = dts.Latest.dd.find("a").first();
        if (!$linkLate
            || !$linkLate.length
            || $linkLate.attr("href").trim() !== $linkLate.text().trim()
           ) err("latest-link");

        var lateRex = "^https?:\\/\\/www\\.w3\\.org\\/" + topLevel + "\\/(.+?)\\/?$"
        ,   matches = ($linkLate.attr("href") || "").trim().match(new RegExp(lateRex));
        if (matches) {
            var sn = matches[1];
            latestURI = $linkLate.text();
            sr.metadata('latestVersion', $linkLate.text().trim());
            if (sn !== shortname) err("this-latest-shortname");
        }
        else err("latest-syntax");
    }

    if (dts.Previous) {
        var $linkPrev = dts.Previous.dd.find("a").first();
        if (!$linkPrev
            || !$linkPrev.length
            || $linkPrev.attr("href").trim() !== $linkPrev.text().trim()
           ) err("previous-link");

        var prevRex = "^https?:\\/\\/www\\.w3\\.org\\/" + topLevel + "\\/\\d{4}\\/[A-Z]+-(.+)-\\d{8}\\/?$"
        ,   matches = ($linkPrev.attr("href") || "").trim().match(new RegExp(prevRex))
        ;
        if (matches) {
            var sn = matches[1];
            previousURI = $linkPrev.text();
            sr.metadata('previousVersion', $linkPrev.text().trim());
            if (sn !== shortname) err("this-previous-shortname");
        }
        else err("previous-syntax");
    }

    if (dts.Rescinds) {
        var $linkResc = dts.Rescinds.dd.find("a").first();
        if (!$linkResc || !$linkResc.length || $linkResc.attr("href") !== $linkResc.text()) err("rescinds-link");

        var matches = ($linkResc.attr("href") || "").trim().match(/^https?:\/\/www\.w3\.org\/TR\/\d{4}\/REC-(.+)-\d{8}\/?$/);
        if (matches) {
            var sn = matches[1];
            if (sn !== shortname) err("this-rescinds-shortname");
        }
        else err("rescinds-syntax");
    }

    if (thisURI && previousURI && thisURI.toLowerCase() === previousURI.toLowerCase()) {
      err('same-this-and-previous');
    }

    if (!previousURI || !latestURI || previousURI.toLowerCase() === latestURI.toLowerCase()) {
      done();
    }
    else {
      Promise.all([fetch(previousURI), fetch(latestURI)]).then(function (bodies) {
        if (!bodies || 2 !== bodies.length) {
          err('cant-retrieve');
        }
        else if (bodies[0] !== bodies[1]) {
          // check same day publication
          var $         = require("whacko").load(bodies[1])
          ,   $latestDl = $("body div.head dl").first()
          ,   latestDts = extractHeaders($latestDl);
          if (latestDts.This &&
              latestDts.This.dd.find("a").first().attr("href") === thisURI &&
              latestDts.Previous &&
              latestDts.Previous.dd.find("a").first().attr("href") === previousURI) {
            sr.warning(exports.name, 'same-day-publication');
          } else {
            err('latest-is-not-previous');
          }
        }
        done();
      }, function() {
        err('cant-retrieve');
        done();
      }
    );
  }

};
<commit_msg>Latest version description term can be different for multi level specifications. Fix #328<commit_after>
'use strict';

// must have dl, with:
//  dts containing "This Version", "Latest Version", "Previous Version" in that order
//  this version is http://www.w3.org/TR/2013/WD-shortname-2013MMDD/
//  latest version is http://www.w3.org/TR/shortname/
//  h2 date and this version date must match
//  dt for editor or author

var Request = require('request')
,   Promise = require('promise');

exports.name = "headers.dl";

exports.check = function (sr, done) {

    // Pseudo-constants:
    var EDITORS_DRAFT = /Latest\ editor's\ draft/i;

    var $dl = sr.$("body div.head dl").first()
    ,   prevRequired = sr.config.previousVersion
    ,   rescinds = sr.config.rescinds
    ,   subType = sr.config.submissionType
    ,   topLevel = "TR"
    ,   thisURI = ''
    ,   previousURI = ''
    ,   latestURI = ''
    ,   err = function (str, extra) {
            sr.error(exports.name, str, extra);
        }
    ;

    var fetch = function(uri) {
      return new Promise(function (resolve, reject) {
        Request.get(uri, {}, function (error, response, body) {
          if (error) {
            reject(new Error('Fetching ' + uri + ' triggered a network error: ' + error.message));
          }
          else if (response.statusCode !== 200) {
            reject(new Error('Fetching ' + uri + ' triggered and HTTP error: code ' + response.statusCode));
          }
          else resolve(body);
        });
      });
    };

    if (subType === "member") topLevel = "Submission";
    else if (subType === "team") topLevel = "TeamSubmission";

    var extractHeaders = function (dl) {
      var dts = {};
      dl.find("dt").each(function (idx) {
        var $dt = sr.$(this)
        ,   txt = sr.norm($dt.text())
                      .replace(":", "")
                      .toLowerCase()
                      .replace("published ", "")
        ,   $dd = $dt.next('dd')
        ,   key = null
        ;
        if (!$dd) return err("no-dd", { dt: txt });
        if (txt === "this version") key = "This";
        else if (txt.lastIndexOf("latest version", 0) === 0) key = "Latest";
        else if (/^previous version(?:s)?$/.test(txt)) key = "Previous";
        else if (/^rescinds this recommendation?$/.test(txt)) key = "Rescinds";
        if (EDITORS_DRAFT.test(txt) && $dd.find('a')) sr.metadata('editorsDraft', $dd.find('a').attr('href').trim());
        if (key) dts[key] = { pos: idx, el: $dt, dd: $dd };
      });
      return dts;
    };

    var dts = extractHeaders($dl);
    if (!dts.This) err("this-version");
    if (!dts.Latest) err("latest-version");
    if (prevRequired && !dts.Previous) err("previous-version");
    if (!prevRequired && dts.Previous) sr.warning(exports.name, "previous-not-needed");
    if (rescinds && !dts.Rescinds) err("rescinds");
    if (!rescinds && dts.Rescinds) sr.warning(exports.name, "rescinds-not-needed");

    if (dts.This && dts.Latest && dts.This.pos > dts.Latest.pos) err("this-latest-order");
    if (dts.Latest && dts.Previous && dts.Latest.pos > dts.Previous.pos) err("latest-previous-order");
    if (dts.Latest && dts.Rescinds && dts.Latest.pos > dts.Rescinds.pos) err("latest-rescinds-order");

    var shortname;
    if (dts.This) {
        var $linkThis = dts.This.dd.find("a").first();
        if (!$linkThis
            || !$linkThis.length
            || $linkThis.attr("href").trim() !== $linkThis.text().trim()
           ) err("this-link");

        var vThisRex = "^http:\\/\\/www\\.w3\\.org\\/" +
                       topLevel +
                       "\\/(\\d{4})\\/" +
                       (sr.config.status || "[A-Z]+") +
                       "-(.+)-(\\d{4})(\\d\\d)(\\d\\d)\\/?$";
        var matches = ($linkThis.attr("href") || "").trim().match(new RegExp(vThisRex))
        ,   docDate = sr.getDocumentDate()
        ;
        if (matches) {
            thisURI = matches[0];
            sr.metadata('thisVersion', matches[0]);
            var year = matches[1] * 1
            ,   year2 = matches[3] * 1
            ,   month = matches[4] * 1
            ,   day = matches[5] * 1
            ;
            shortname = matches[2];
            if (docDate) {
                if (year !== docDate.getFullYear() ||
                    year2 !== docDate.getFullYear() ||
                    month - 1 !== docDate.getMonth() ||
                    day !== docDate.getDate()
                   ) err("this-date");
            }
            else sr.warning(exports.name, "no-date");
        }
        else err("this-syntax");
    }

    if (dts.Latest) {
        var $linkLate = dts.Latest.dd.find("a").first();
        if (!$linkLate
            || !$linkLate.length
            || $linkLate.attr("href").trim() !== $linkLate.text().trim()
           ) err("latest-link");

        var lateRex = "^https?:\\/\\/www\\.w3\\.org\\/" + topLevel + "\\/(.+?)\\/?$"
        ,   matches = ($linkLate.attr("href") || "").trim().match(new RegExp(lateRex));
        if (matches) {
            var sn = matches[1];
            latestURI = $linkLate.text();
            sr.metadata('latestVersion', $linkLate.text().trim());
            if (sn !== shortname) err("this-latest-shortname");
        }
        else err("latest-syntax");
    }

    if (dts.Previous) {
        var $linkPrev = dts.Previous.dd.find("a").first();
        if (!$linkPrev
            || !$linkPrev.length
            || $linkPrev.attr("href").trim() !== $linkPrev.text().trim()
           ) err("previous-link");

        var prevRex = "^https?:\\/\\/www\\.w3\\.org\\/" + topLevel + "\\/\\d{4}\\/[A-Z]+-(.+)-\\d{8}\\/?$"
        ,   matches = ($linkPrev.attr("href") || "").trim().match(new RegExp(prevRex))
        ;
        if (matches) {
            var sn = matches[1];
            previousURI = $linkPrev.text();
            sr.metadata('previousVersion', $linkPrev.text().trim());
            if (sn !== shortname) err("this-previous-shortname");
        }
        else err("previous-syntax");
    }

    if (dts.Rescinds) {
        var $linkResc = dts.Rescinds.dd.find("a").first();
        if (!$linkResc || !$linkResc.length || $linkResc.attr("href") !== $linkResc.text()) err("rescinds-link");

        var matches = ($linkResc.attr("href") || "").trim().match(/^https?:\/\/www\.w3\.org\/TR\/\d{4}\/REC-(.+)-\d{8}\/?$/);
        if (matches) {
            var sn = matches[1];
            if (sn !== shortname) err("this-rescinds-shortname");
        }
        else err("rescinds-syntax");
    }

    if (thisURI && previousURI && thisURI.toLowerCase() === previousURI.toLowerCase()) {
      err('same-this-and-previous');
    }

    if (!previousURI || !latestURI || previousURI.toLowerCase() === latestURI.toLowerCase()) {
      done();
    }
    else {
      Promise.all([fetch(previousURI), fetch(latestURI)]).then(function (bodies) {
        if (!bodies || 2 !== bodies.length) {
          err('cant-retrieve');
        }
        else if (bodies[0] !== bodies[1]) {
          // check same day publication
          var $         = require("whacko").load(bodies[1])
          ,   $latestDl = $("body div.head dl").first()
          ,   latestDts = extractHeaders($latestDl);
          if (latestDts.This &&
              latestDts.This.dd.find("a").first().attr("href") === thisURI &&
              latestDts.Previous &&
              latestDts.Previous.dd.find("a").first().attr("href") === previousURI) {
            sr.warning(exports.name, 'same-day-publication');
          } else {
            err('latest-is-not-previous');
          }
        }
        done();
      }, function() {
        err('cant-retrieve');
        done();
      }
    );
  }

};
<|endoftext|>


<commit_before>'use strict';

var lazyReq = require('lazy-req')(require);
var request = lazyReq('request-promise');
var through = require('through2').obj;
var spawn = require('child_process').spawn;
var path = require('path');
var is = require('is_js');
var del = lazyReq('del');
var minimatch = lazyReq('minimatch');

module.exports = function (gulp, gutil) {
  var ENDPOINT_PATTERN_MAP = {
    'skins/images': ['**/skins/**/images/**'],
    skins: ['**/skins/**'],
    quilts: ['**/quilts/**'],
    layouts: ['**/layouts/**'],
    lang: ['**/lang/**'],
    components: ['**/components/**'],
    scripts: ['**/*.{js,tpl}', '**/sdk.conf.json']
  };

  var server;
  var error = false;
  try {
    server = require('../lib/server.js')(gulp, gutil);
    if (server.serverUrl() === undefined) {
      gutil.log(gutil.colors.red('A server URL is required in your configuration. ' +
        'Please use template.server.conf.json to create server.conf.json.'));
      error = true;
    }
    if (server.sandboxPluginDir() === undefined) {
      gutil.log(gutil.colors.red('A sandboxPluginDir is required in your configuration. ' +
        'Please use template.server.conf.json to create server.conf.json.'));
      error = true;
    }
  } catch (err) {
    gutil.log(gutil.colors.red(err.message));
    error = true;
  }
  if (error) {
    process.exit(1);
  }

  function createReloadQuery(path) {
    var query = {};
    var found = false;

    Object.keys(ENDPOINT_PATTERN_MAP).forEach(function (key) {
      if (found) { return; };
      ENDPOINT_PATTERN_MAP[key].forEach(function (pattern) {
        if (minimatch()(path, pattern)) {
          query[key] = found = true;
        }
      });
    });

    if (!found) {
      query.all = true;
    }

    return query;
  }

  function refreshPlugin(reload) {
    return request()({
      url: server.serverUrl() + server.pluginReloadUrl(),
      qs: reload.all ? { all: true } : reload,
      json: true
    }).then(function (res) {
      if (res.reloaded) {
        gutil.log(gutil.colors.green('Plugin cache cleared for [' + res.reloaded + '] assets, app is READY!'));
      } else {
        gutil.log(gutil.colors.red('Failed to reload plugin. ' + res));
      }
    }).catch(function (e) {
      gutil.log(gutil.colors.red('Failed to reload plugin, please make sure your server.conf.json is configured' +
          'properly, the "phase" config for your community is set to "dev", and your community is started.'));
    });
  }

  function deletePlugin() {
    return del()([server.sandboxPluginDir() + '/res', server.sandboxPluginDir() + '/web'], { force: true });
  }

  function syncPlugin() {
    return new Promise(function (resolve, reject) {
      spawn('rsync', ['-r', 'plugin/', server.sandboxPluginDir()], {
        cwd: './',
        stdio: ['pipe', 'ignore', 'inherit']
      }).on('close', function (code) {
        if (code === 0) {
          resolve();
        } else {
          gutil.log(gutil.colors.red('Failed to upload files'));
          reject();
        }
      });
    });
  }

  return {
    deletePlugin: deletePlugin,
    syncPlugin: syncPlugin,
    refreshPlugin: refreshPlugin,
    createReloadQuery: createReloadQuery
  };
};
<commit_msg>[space]<commit_after>'use strict';

var lazyReq = require('lazy-req')(require);
var request = lazyReq('request-promise');
var through = require('through2').obj;
var spawn = require('child_process').spawn;
var path = require('path');
var is = require('is_js');
var del = lazyReq('del');
var minimatch = lazyReq('minimatch');

module.exports = function (gulp, gutil) {
  var ENDPOINT_PATTERN_MAP = {
    'skins/images': ['**/skins/**/images/**'],
    skins: ['**/skins/**'],
    quilts: ['**/quilts/**'],
    layouts: ['**/layouts/**'],
    lang: ['**/lang/**'],
    components: ['**/components/**'],
    scripts: ['**/*.{js,tpl}', '**/sdk.conf.json']
  };

  var server;
  var error = false;
  try {
    server = require('../lib/server.js')(gulp, gutil);
    if (server.serverUrl() === undefined) {
      gutil.log(gutil.colors.red('A server URL is required in your configuration. ' +
        'Please use template.server.conf.json to create server.conf.json.'));
      error = true;
    }
    if (server.sandboxPluginDir() === undefined) {
      gutil.log(gutil.colors.red('A sandboxPluginDir is required in your configuration. ' +
        'Please use template.server.conf.json to create server.conf.json.'));
      error = true;
    }
  } catch (err) {
    gutil.log(gutil.colors.red(err.message));
    error = true;
  }
  if (error) {
    process.exit(1);
  }

  function createReloadQuery(path) {
    var query = {};
    var found = false;

    Object.keys(ENDPOINT_PATTERN_MAP).forEach(function (key) {
      if (found) { return; };
      ENDPOINT_PATTERN_MAP[key].forEach(function (pattern) {
        if (minimatch()(path, pattern)) {
          query[key] = found = true;
        }
      });
    });

    if (!found) {
      query.all = true;
    }

    return query;
  }

  function refreshPlugin(reload) {
    return request()({
      url: server.serverUrl() + server.pluginReloadUrl(),
      qs: reload.all ? { all: true } : reload,
      json: true
    }).then(function (res) {
      if (res.reloaded) {
        gutil.log(gutil.colors.green('Plugin cache cleared for [' + res.reloaded + '] assets, app is READY!'));
      } else {
        gutil.log(gutil.colors.red('Failed to reload plugin. ' + res));
      }
    }).catch(function (e) {
      gutil.log(gutil.colors.red('Failed to reload plugin, please make sure your server.conf.json is configured ' +
          'properly, the "phase" config for your community is set to "dev", and your community is started.'));
    });
  }

  function deletePlugin() {
    return del()([server.sandboxPluginDir() + '/res', server.sandboxPluginDir() + '/web'], { force: true });
  }

  function syncPlugin() {
    return new Promise(function (resolve, reject) {
      spawn('rsync', ['-r', 'plugin/', server.sandboxPluginDir()], {
        cwd: './',
        stdio: ['pipe', 'ignore', 'inherit']
      }).on('close', function (code) {
        if (code === 0) {
          resolve();
        } else {
          gutil.log(gutil.colors.red('Failed to upload files'));
          reject();
        }
      });
    });
  }

  return {
    deletePlugin: deletePlugin,
    syncPlugin: syncPlugin,
    refreshPlugin: refreshPlugin,
    createReloadQuery: createReloadQuery
  };
};
<|endoftext|>


<commit_before>// uniq :: TransformStream
// uniq function returns a transform stream
// that keeps only the unique values
// from the input stream
// and enqueues it on the output stream.
//

import Pipe from "@pipes/core/pipe";

export default function uniq() {
  let seen = new Set;

  return new Pipe( chunk => {

    // Check to see if chunk seen before
    if ( chunk !== void 0 && !seen.has( chunk ) ) {

      // Add to seen set and enqueue
      seen.add( chunk );
      return chunk;
    }
  });
}

// Browserify compat
if ( typeof module !== "undefined" )
  module.exports = uniq;

<commit_msg>Added flow types to uniq<commit_after>// @flow

// uniq :: TransformStream
// uniq function returns a transform stream
// that keeps only the unique values
// from the input stream
// and enqueues it on the output stream.
//

import type { ReadableWritable } from "@pipes/core/streams";

import Pipe from "@pipes/core/pipe";

export default function uniq(): ReadableWritable {
  let seen: Set<mixed> = new Set;

  return new Pipe( (chunk: ?mixed) => {

    // Check to see if chunk seen before
    if ( chunk !== void 0 && !seen.has( chunk ) ) {

      // Add to seen set and enqueue
      seen.add( chunk );
      return chunk;
    }
  });
}

// Browserify compat
if ( typeof module !== "undefined" )
  // $FlowFixMe
  module.exports = uniq;
<|endoftext|>


<commit_before>/*
 * The MIT License
 *
 * Copyright 2017 OnCore Consulting LLC, 2017
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
/*
 * Your about ViewModel code goes here
 */
define(['ojs/ojcore', 'knockout', 'data/data', 'ojs/ojrouter', 'ojs/ojknockout', 'promise', 'ojs/ojlistview', 'ojs/ojmodel', 'ojs/ojpagingcontrol', 'ojs/ojpagingcontrol-model'],
        function (oj, ko, data) {

            function CartViewModel() {
                var self = this;

                var serviceEndPoints = new ServiceEndPoints();
                self.createOrderServiceURL = serviceEndPoints.getEndPoint('createOrder');

                self.router = oj.Router.rootInstance;

                self.itemTotalPrice = ko.observable();
                self.shippingPrice = ko.observable();
                self.totalPrice = ko.observable();
                self.cart = ko.observableArray();
                self.listViewDataSource = null;
                self.cardViewDataSource = null;
                self.productLayoutType = ko.observable('productCardLayout');

                var lgQuery = oj.ResponsiveUtils.getFrameworkQuery(oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.LG_UP);
                var mdQuery = oj.ResponsiveUtils.getFrameworkQuery(oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.MD_UP);
                var smQuery = oj.ResponsiveUtils.getFrameworkQuery(oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.SM_UP);
                var smOnlyQuery = oj.ResponsiveUtils.getFrameworkQuery(oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.SM_ONLY);
                self.large = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(lgQuery);
                self.medium = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(mdQuery);
                self.small = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(smQuery);
                self.smallOnly = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(smOnlyQuery);

                // Below are a subset of the ViewModel methods invoked by the ojModule binding
                // Please reference the ojModule jsDoc for additionaly available methods.

                /**
                 * Optional ViewModel method invoked when this ViewModel is about to be
                 * used for the View transition.  The application can put data fetch logic
                 * here that can return a Promise which will delay the handleAttached function
                 * call below until the Promise is resolved.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @return {Promise|undefined} - If the callback returns a Promise, the next phase (attaching DOM) will be delayed until
                 * the promise is resolved
                 */
                self.handleActivated = function (info) {

                    if (sessionStorage.authenticated === "false")
                    {
                        return self.router.go('welcome');
                    }
                    if (sessionStorage.cartProducts !== "")
                    {
                        var sessionCart = JSON.parse(sessionStorage.cartProducts);

                        var tempItemTotalPrice = 0.0;
                        var tempShippingPrice = 25.00;
                        var tempTotalPrice = 0.00;

                        for (i = 0; i < sessionCart.length; i++)
                        {
                            tempItemTotalPrice += sessionCart[i].prdPrice;
                        }

                        self.itemTotalPrice("$" + tempItemTotalPrice.toFixed(2));
                        self.shippingPrice("$" + tempShippingPrice.toFixed(2));

                        tempTotalPrice = tempShippingPrice + tempItemTotalPrice;

                        self.totalPrice("$" + tempTotalPrice.toFixed(2));

                        sessionStorage.itemTotalPrice = self.itemTotalPrice();
                        sessionStorage.shippingPrice = self.shippingPrice();
                        sessionStorage.totalPrice = self.totalPrice();

                        self.cart(sessionCart);

                        self.listViewDataSource = ko.computed(function () {
                            return new oj.ArrayTableDataSource(self.cart(), {idAttribute: 'prdUid'});
                        });

                        self.cardViewDataSource = ko.computed(function () {
                            return new oj.PagingTableDataSource(self.listViewDataSource());
                        });

                    } else
                    {
                        self.itemTotalPrice("$0.00");
                        self.shippingPrice("$0.00");
                        self.totalPrice("$0.00");
                        sessionStorage.itemTotalPrice = self.itemTotalPrice();
                        sessionStorage.shippingPrice = self.shippingPrice();
                        sessionStorage.totalPrice = self.totalPrice();
                        self.cart = ko.observableArray([]);

                        self.listViewDataSource = ko.computed(function () {
                            return new oj.ArrayTableDataSource(self.cart(), {idAttribute: 'prdUid'});
                        });

                        self.cardViewDataSource = ko.computed(function () {
                            return new oj.PagingTableDataSource(self.listViewDataSource());
                        });
                    }
                };

                /**
                 * Optional ViewModel method invoked after the View is inserted into the
                 * document DOM.  The application can put logic that requires the DOM being
                 * attached here.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @param {boolean} info.fromCache - A boolean indicating whether the module was retrieved from cache.
                 */
                self.handleAttached = function (info) {
                    // Implement if needed
                };

                /**
                 * Optional ViewModel method invoked after the bindings are applied on this View.
                 * If the current View is retrieved from cache, the bindings will not be re-applied
                 * and this callback will not be invoked.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 */
                self.handleBindingsApplied = function (info) {
                    // Implement if needed
                };

                /*
                 * Optional ViewModel method invoked after the View is removed from the
                 * document DOM.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @param {Array} info.cachedNodes - An Array containing cached nodes for the View if the cache is enabled.
                 */
                self.handleDetached = function (info) {
                    // Implement if needed
                };

                /**
                 * Get the photo for the product.
                 *
                 * @param {type} product
                 * @returns {undefined}
                 */
                self.getPhoto = function (product) {
                    return ProductHelper.getPhoto(product);
                };

                self.cardLayoutHandler = function () {
                    self.productLayoutType('productCardLayout');
                };

                self.listLayoutHandler = function () {
                    self.productLayoutType('productListLayout');
                };

                /*
                 * Places the Order.
                 *
                 * @param {type} trackerObj
                 * @returns {Boolean}
                 */
                self.placeOrderClick = function (trackerObj)
                {
                    if (sessionStorage.partyUid !== "" && sessionStorage.cartProducts !== ""
                            && sessionStorage.authenticated !== "false")
                    {
                        var partyUid = sessionStorage.partyUid;

                        var sessionCart = JSON.parse(sessionStorage.cartProducts);

                        var order = {createUserId: partyUid, updateUserId: partyUid,
                            orderStatusCd: "SUBT",
                            partyUid: partyUid,
                            products: sessionCart};

                        // call our REST service
                        var OrderService = oj.Model.extend({
                            urlRoot: self.createOrderServiceURL
                        });

                        var orderService = new OrderService();

                        // execute REST createOrder operation
                        orderService.save(
                                order,
                                {
                                    success: function (myModel, response, options) {
                                        return self.router.go("orderConfirmation");
                                    },
                                    error: function (jqXHR, textStatus, errorThrown) {

                                        console.log("Unable to create the order: " + errorThrown);
                                    }
                                });
                    }

                };

                self.continueShoppingClick = function (data, event)
                {
                    return self.router.go("productSearch");
                };

// TODO: Do we want Enter key to do anything by default on Cart page?
                self.onEnter = function (data, event) {
                    if (event.keyCode === 13) {

                    }
                    return true;
                };

// TODO: Do we want to do anything when clicking on an item from the Cart?
                self.changeHandler = function (page, event) {
                    if (event.option === 'currentItem') {

                    }
                };

            }

            /*
             * Returns a constructor for the ViewModel so that the ViewModel is constrcuted
             * each time the view is displayed.  Return an instance of the ViewModel if
             * only one instance of the ViewModel is needed.
             */
            return new CartViewModel();
        }
);
<commit_msg>[#139507125] Fixed the order totals when more than one of a product is added to the cart.<commit_after>/*
 * The MIT License
 *
 * Copyright 2017 OnCore Consulting LLC, 2017
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
/*
 * Your about ViewModel code goes here
 */
define(['ojs/ojcore', 'knockout', 'data/data', 'ojs/ojrouter', 'ojs/ojknockout', 'promise', 'ojs/ojlistview', 'ojs/ojmodel', 'ojs/ojpagingcontrol', 'ojs/ojpagingcontrol-model'],
        function (oj, ko, data) {

            function CartViewModel() {
                var self = this;

                var serviceEndPoints = new ServiceEndPoints();
                self.createOrderServiceURL = serviceEndPoints.getEndPoint('createOrder');

                self.router = oj.Router.rootInstance;

                self.itemTotalPrice = ko.observable();
                self.shippingPrice = ko.observable();
                self.totalPrice = ko.observable();
                self.cart = ko.observableArray();
                self.listViewDataSource = null;
                self.cardViewDataSource = null;
                self.productLayoutType = ko.observable('productCardLayout');

                var lgQuery = oj.ResponsiveUtils.getFrameworkQuery(oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.LG_UP);
                var mdQuery = oj.ResponsiveUtils.getFrameworkQuery(oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.MD_UP);
                var smQuery = oj.ResponsiveUtils.getFrameworkQuery(oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.SM_UP);
                var smOnlyQuery = oj.ResponsiveUtils.getFrameworkQuery(oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.SM_ONLY);
                self.large = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(lgQuery);
                self.medium = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(mdQuery);
                self.small = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(smQuery);
                self.smallOnly = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(smOnlyQuery);

                // Below are a subset of the ViewModel methods invoked by the ojModule binding
                // Please reference the ojModule jsDoc for additionaly available methods.

                /**
                 * Optional ViewModel method invoked when this ViewModel is about to be
                 * used for the View transition.  The application can put data fetch logic
                 * here that can return a Promise which will delay the handleAttached function
                 * call below until the Promise is resolved.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @return {Promise|undefined} - If the callback returns a Promise, the next phase (attaching DOM) will be delayed until
                 * the promise is resolved
                 */
                self.handleActivated = function (info) {

                    if (sessionStorage.authenticated === "false")
                    {
                        return self.router.go('welcome');
                    }
                    if (sessionStorage.cartProducts !== "")
                    {
                        var sessionCart = JSON.parse(sessionStorage.cartProducts);

                        var tempItemTotalPrice = 0.0;
                        var tempShippingPrice = 25.00;
                        var tempTotalPrice = 0.00;

                        for (i = 0; i < sessionCart.length; i++)
                        {
                            tempItemTotalPrice += ( sessionCart[i].prdPrice * sessionCart[i].quantity );
                        }

                        self.itemTotalPrice("$" + tempItemTotalPrice.toFixed(2));
                        self.shippingPrice("$" + tempShippingPrice.toFixed(2));

                        tempTotalPrice = tempShippingPrice + tempItemTotalPrice;

                        self.totalPrice("$" + tempTotalPrice.toFixed(2));

                        sessionStorage.itemTotalPrice = self.itemTotalPrice();
                        sessionStorage.shippingPrice = self.shippingPrice();
                        sessionStorage.totalPrice = self.totalPrice();

                        self.cart(sessionCart);

                        self.listViewDataSource = ko.computed(function () {
                            return new oj.ArrayTableDataSource(self.cart(), {idAttribute: 'prdUid'});
                        });

                        self.cardViewDataSource = ko.computed(function () {
                            return new oj.PagingTableDataSource(self.listViewDataSource());
                        });

                    } else
                    {
                        self.itemTotalPrice("$0.00");
                        self.shippingPrice("$0.00");
                        self.totalPrice("$0.00");
                        sessionStorage.itemTotalPrice = self.itemTotalPrice();
                        sessionStorage.shippingPrice = self.shippingPrice();
                        sessionStorage.totalPrice = self.totalPrice();
                        self.cart = ko.observableArray([]);

                        self.listViewDataSource = ko.computed(function () {
                            return new oj.ArrayTableDataSource(self.cart(), {idAttribute: 'prdUid'});
                        });

                        self.cardViewDataSource = ko.computed(function () {
                            return new oj.PagingTableDataSource(self.listViewDataSource());
                        });
                    }
                };

                /**
                 * Optional ViewModel method invoked after the View is inserted into the
                 * document DOM.  The application can put logic that requires the DOM being
                 * attached here.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @param {boolean} info.fromCache - A boolean indicating whether the module was retrieved from cache.
                 */
                self.handleAttached = function (info) {
                    // Implement if needed
                };

                /**
                 * Optional ViewModel method invoked after the bindings are applied on this View.
                 * If the current View is retrieved from cache, the bindings will not be re-applied
                 * and this callback will not be invoked.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 */
                self.handleBindingsApplied = function (info) {
                    // Implement if needed
                };

                /*
                 * Optional ViewModel method invoked after the View is removed from the
                 * document DOM.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @param {Array} info.cachedNodes - An Array containing cached nodes for the View if the cache is enabled.
                 */
                self.handleDetached = function (info) {
                    // Implement if needed
                };

                /**
                 * Get the photo for the product.
                 *
                 * @param {type} product
                 * @returns {undefined}
                 */
                self.getPhoto = function (product) {
                    return ProductHelper.getPhoto(product);
                };

                self.cardLayoutHandler = function () {
                    self.productLayoutType('productCardLayout');
                };

                self.listLayoutHandler = function () {
                    self.productLayoutType('productListLayout');
                };

                /*
                 * Places the Order.
                 *
                 * @param {type} trackerObj
                 * @returns {Boolean}
                 */
                self.placeOrderClick = function (trackerObj)
                {
                    if (sessionStorage.partyUid !== "" && sessionStorage.cartProducts !== ""
                            && sessionStorage.authenticated !== "false")
                    {
                        var partyUid = sessionStorage.partyUid;

                        var sessionCart = JSON.parse(sessionStorage.cartProducts);

                        var order = {createUserId: partyUid, updateUserId: partyUid,
                            orderStatusCd: "SUBT",
                            partyUid: partyUid,
                            products: sessionCart};

                        // call our REST service
                        var OrderService = oj.Model.extend({
                            urlRoot: self.createOrderServiceURL
                        });

                        var orderService = new OrderService();

                        // execute REST createOrder operation
                        orderService.save(
                                order,
                                {
                                    success: function (myModel, response, options) {
                                        return self.router.go("orderConfirmation");
                                    },
                                    error: function (jqXHR, textStatus, errorThrown) {

                                        console.log("Unable to create the order: " + errorThrown);
                                    }
                                });
                    }

                };

                self.continueShoppingClick = function (data, event)
                {
                    return self.router.go("productSearch");
                };

// TODO: Do we want Enter key to do anything by default on Cart page?
                self.onEnter = function (data, event) {
                    if (event.keyCode === 13) {

                    }
                    return true;
                };

// TODO: Do we want to do anything when clicking on an item from the Cart?
                self.changeHandler = function (page, event) {
                    if (event.option === 'currentItem') {

                    }
                };

            }

            /*
             * Returns a constructor for the ViewModel so that the ViewModel is constrcuted
             * each time the view is displayed.  Return an instance of the ViewModel if
             * only one instance of the ViewModel is needed.
             */
            return new CartViewModel();
        }
);
<|endoftext|>


<commit_before>'use strict';

const qspToSbml = require('./qsp-to-sbml.json');

/**
 * Class describes compound phisical units.
 *
 */
module.exports = class Unit extends Array {
  /**
   * Serialize Unit object.
   *
   * @return {string} of format: 'mM2*L/mg/h2'
   */
  toString(){
    return this
      .map((item, i) => {
        let operator = (item.exponent<0)
          ? '/'
          : (i>0) ? '*' : ''; // no operator for first element

        let expAbs = Math.abs(item.exponent); // absolute value
        let exponent = (expAbs!==1)
          ? expAbs
          : '';

        return operator + item.kind + exponent;
      })
      .join('');
  }

  /**
   * Serialize unit-object to string.
   *
   * @return {string} of type 'mM2_L\__mg\__h2'
   */
  toHash(){
    return this
      .sort((x1, x2) => x1.kind > x2.kind ? -1 : 1)
      .map((item, i) => {
        let operator = (item.exponent<0)
          ? '__'
          : (i>0) ? '_' : ''; // no operator for first element

        let expAbs = Math.abs(item.exponent); // absolute value
        let exponent = (expAbs!==1)
          ? String(expAbs).replace('.', '_')
          : '';

        return operator + item.kind + exponent;
      })
      .join('');
  }

  /**
   * Serialize unit-object.
   *
   * @return {string} with TeX '\frac{mM^{2} \cdot L}{mg \cdot h^{2}}'
   */
  toTex(){
    let res = '';
    let numerator = this
      .filter((item) => item.exponent > 0)
      .map((item) => {
        let expAbs = Math.abs(item.exponent); // absolute value
        let exponent = (expAbs!==1)
          ? '^{' + expAbs + '}'
          : '';
        return item.kind + exponent;
      })
      .join(' \\cdot ');

    let denominator = this
      .filter((item) => item.exponent < 0)
      .map((item) => {
        let expAbs = Math.abs(item.exponent); // absolute value
        let exponent = (expAbs!==1)
          ? '^{' + expAbs + '}'
          : '';
        return item.kind + exponent;
      })
      .join(' \\cdot ');

    if(denominator!=='' && numerator!==''){ // \frac{num}{den}
      return '\\frac{' + numerator + '}{' + denominator + '}';
    }else if(denominator==='' && numerator!==''){ // num
      return numerator;
    }else if(denominator!=='' && numerator===''){ // \frac{1}{den}
      return '\\frac{1}{' + denominator + '}';
    }else{
      return ''; // unitless
    }
  }

  /**
   * Translate to SBML terms.
   *
   * @returns {Unit} Unit in SBML friendly format.
   */
  toRebaseUnits(transformator){ // TOFIX: not checked yet
    let sbmlUnit = [];
    this.forEach((parseUnit) => {
      transformator[parseUnit.kind].forEach((simpleUnit) => {
        sbmlUnit.push({
          kind: simpleUnit.kind,
          multiplier: simpleUnit.multiplier || 1,
          scale: simpleUnit.scale || 0,
          exponent: simpleUnit.exponent * parseUnit.exponent || parseUnit.exponent
        });
      });
    });

    return sbmlUnit
  }

  /**
   * Multiply two units.
   *
   * @param {Unit} unit - the second unit
   *
   * @returns {Unit} result of multiplying
   */
  multiply(unit) {
    return this.concat(unit);
  }

  /**
   * Divide two units.
   *
   * @param {Unit} unit - the second unit
   *
   * @returns {Unit} Result of division.
   */
  divide(unit) {
    let newUnit = unit.map((item) => {
      let current = Object.assign({}, item); // clone
      current.exponent *= -1;
      return current;
    });
    return this.concat(newUnit);
  }

  /**
   * Normalize units.
   *
   * @return {Unit} Simplified version of units.
   */
  simplify() {
    let listOfKind = [];
    let newUnit = new Unit();

    this.forEach(function(item) {
      let current = Object.assign({}, item),
        posElement = listOfKind.indexOf(current.kind);

      if (posElement !== -1) {
        current.exponent += newUnit[posElement].exponent;
        listOfKind.splice(posElement, 1);
        newUnit.splice(posElement, 1);
      }

      if (current.exponent !== 0) {
        listOfKind.push(current.kind);
        newUnit.push(current);
      }
    });

    if (newUnit.length === 0) {
      newUnit.push({
        kind: 'dl',
        exponent: 1,
        scale: 0,
        multiplier: 1
      });
    }

    return newUnit;
  }

  toXmlUnitDefinition(transformator, options={nameAsTex:false}){
    let units = this.toRebaseUnits(transformator);

    let listOfUnits = units
      .map((item) => {
        return `\n    <unit kind="${item.kind}" exponent="${item.exponent}" scale="${item.scale}" multiplier="${item.multiplier}"/>`;
      })
      .join('');

    let name = options.nameAsTex
      ? ` name="${this.toTex()}"`
      : ` name="${this.toString()}"`;
    let unitDefinition = `<unitDefinition id="${this.toHash()}"${name}>\n  <listOfUnits>`
      + listOfUnits
      + `\n  </listOfUnits>\n</unitDefinition>`;
    return unitDefinition;
  }

  /**
   * Creates XML representing unitDefinition as required in SBML L2.
   *
   * @returns {string} Unit definition in SBML format.
   */
  toSbmlUnitDefinition(options){
    return this.toXmlUnitDefinition(qspToSbml, options);
  }

  /**
   * toJSON - description
   *
   * @returns {string}  JSON
   */
  toJSON(){
    return JSON.stringify(this, null, 2)
  }
}
<commit_msg>fix toString and toRebase<commit_after>'use strict';

const qspToSbml = require('./qsp-to-sbml.json');

/**
 * Class describes compound phisical units.
 *
 */
module.exports = class Unit extends Array {
  /**
   * Serialize Unit object.
   *
   * @return {string} of format: 'mM2*L/mg/h2'
   */
  toString(){
    return this
      .map((item, i) => {
        let operator = (item.exponent<0)
          ? ( (i>0) ? '/' : '1/' ) // 1 for 1/L
          : ( (i>0) ? '*' : '' ); // no operator for first element

        let expAbs = Math.abs(item.exponent); // absolute value
        let exponent = (expAbs!==1)
          ? expAbs
          : '';

        return operator + item.kind + exponent;
      })
      .join('');
  }

  /**
   * Serialize unit-object to string.
   *
   * @return {string} of type 'mM2_L\__mg\__h2'
   */
  toHash(){
    return this
      .sort((x1, x2) => x1.kind > x2.kind ? -1 : 1)
      .map((item, i) => {
        let operator = (item.exponent<0)
          ? '__'
          : (i>0) ? '_' : ''; // no operator for first element

        let expAbs = Math.abs(item.exponent); // absolute value
        let exponent = (expAbs!==1)
          ? String(expAbs).replace('.', '_')
          : '';

        return operator + item.kind + exponent;
      })
      .join('');
  }

  /**
   * Serialize unit-object.
   *
   * @return {string} with TeX '\frac{mM^{2} \cdot L}{mg \cdot h^{2}}'
   */
  toTex(){
    let res = '';
    let numerator = this
      .filter((item) => item.exponent > 0)
      .map((item) => {
        let expAbs = Math.abs(item.exponent); // absolute value
        let exponent = (expAbs!==1)
          ? '^{' + expAbs + '}'
          : '';
        return item.kind + exponent;
      })
      .join(' \\cdot ');

    let denominator = this
      .filter((item) => item.exponent < 0)
      .map((item) => {
        let expAbs = Math.abs(item.exponent); // absolute value
        let exponent = (expAbs!==1)
          ? '^{' + expAbs + '}'
          : '';
        return item.kind + exponent;
      })
      .join(' \\cdot ');

    if(denominator!=='' && numerator!==''){ // \frac{num}{den}
      return '\\frac{' + numerator + '}{' + denominator + '}';
    }else if(denominator==='' && numerator!==''){ // num
      return numerator;
    }else if(denominator!=='' && numerator===''){ // \frac{1}{den}
      return '\\frac{1}{' + denominator + '}';
    }else{
      return ''; // unitless
    }
  }

  /**
   * Translate to SBML terms.
   *
   * @returns {Unit} Unit in SBML friendly format.
   */
  toRebaseUnits(transformator){ // TOFIX: not checked yet
    let sbmlUnit = new Unit();
    this.forEach((parseUnit) => {
      transformator[parseUnit.kind].forEach((simpleUnit) => {
        sbmlUnit.push({
          kind: simpleUnit.kind,
          multiplier: simpleUnit.multiplier || 1,
          scale: simpleUnit.scale || 0,
          exponent: simpleUnit.exponent * parseUnit.exponent || parseUnit.exponent
        });
      });
    });

    return sbmlUnit
  }

  /**
   * Multiply two units.
   *
   * @param {Unit} unit - the second unit
   *
   * @returns {Unit} result of multiplying
   */
  multiply(unit) {
    return this.concat(unit);
  }

  /**
   * Divide two units.
   *
   * @param {Unit} unit - the second unit
   *
   * @returns {Unit} Result of division.
   */
  divide(unit) {
    let newUnit = unit.map((item) => {
      let current = Object.assign({}, item); // clone
      current.exponent *= -1;
      return current;
    });
    return this.concat(newUnit);
  }

  /**
   * Normalize units.
   *
   * @return {Unit} Simplified version of units.
   */
  simplify() {
    let listOfKind = [];
    let newUnit = new Unit();

    this.forEach(function(item) {
      let current = Object.assign({}, item),
        posElement = listOfKind.indexOf(current.kind);

      if (posElement !== -1) {
        current.exponent += newUnit[posElement].exponent;
        listOfKind.splice(posElement, 1);
        newUnit.splice(posElement, 1);
      }

      if (current.exponent !== 0) {
        listOfKind.push(current.kind);
        newUnit.push(current);
      }
    });

    if (newUnit.length === 0) {
      newUnit.push({
        kind: 'dl',
        exponent: 1,
        scale: 0,
        multiplier: 1
      });
    }

    return newUnit;
  }

  toXmlUnitDefinition(transformator, options={nameAsTex:false}){
    let units = this.toRebaseUnits(transformator);

    let listOfUnits = units
      .map((item) => {
        return `\n    <unit kind="${item.kind}" exponent="${item.exponent}" scale="${item.scale}" multiplier="${item.multiplier}"/>`;
      })
      .join('');

    let name = options.nameAsTex
      ? ` name="${this.toTex()}"`
      : ` name="${this.toString()}"`;
    let unitDefinition = `<unitDefinition id="${this.toHash()}"${name}>\n  <listOfUnits>`
      + listOfUnits
      + `\n  </listOfUnits>\n</unitDefinition>`;
    return unitDefinition;
  }

  /**
   * Creates XML representing unitDefinition as required in SBML L2.
   *
   * @returns {string} Unit definition in SBML format.
   */
  toSbmlUnitDefinition(options){
    return this.toXmlUnitDefinition(qspToSbml, options);
  }

  /**
   * toJSON - description
   *
   * @returns {string}  JSON
   */
  toJSON(){
    return JSON.stringify(this, null, 2)
  }
}
<|endoftext|>


<commit_before> var mongoose         = require('mongoose'),
    Schema            = mongoose.Schema,
    ObjectId          = Schema.ObjectId,
    passgen           = require('passgen'),
    config            = require('config'),
    utils             = require('../utils'),
    url               = require('url'),
    http              = require('http'),
    async             = require('async'),
    InstanceInfo      = require('../schemas').InstanceInfo;

var InstanceSchema = new Schema({
    slug: {
        type:      String,
        lowercase: true,
        trim:      true,
        match:     /^[a-z][a-z0-9\-]{3,19}$/,
        validate:  [
            function( v, fn ) {
                // run on insert only, when we don't have an ID
                // FIXME - find better way to handle this and test
                if ( ! this.isNew ) return fn( true );

                this.collection.count(
                    { slug: v },
                    function (err, count) {
                        fn( count ? false : true );
                    }
                );
            },
            'slug_not_unique'
        ],
        unique:    true,
        required:  true,
    },
    created_date: { type: Date, 'default': Date.now },

    status: {
        type: String,
        required: true,
        'default': 'pending',
        'enum': [
            'pending',   // has not been activated yet - db does not exist
            'active',    // created and available
            'suspended', // blocked for some reason
            'archived',  // has been archived due to lack of use
        ],
    },

    email: {
        type: String,
        required: true,
        validate: [ utils.is_email, 'not_an_email' ]
    },

    // Initial info needed to set up the instance - should be cleared once
    // instance configured.
    setup_info: {
        // initial password for
        password_hash: {
            type: String,
        },
        confirmation_token: {
            type: String,
            'default': function () { return passgen.create(16); },
        }
    },

    // details - a hash that is created from values in the instance. Eg number of
    // entities stored, name and description. This is collected by a cron job and
    // used to provide information on the instance.

    info: [InstanceInfo],

    // domains - the domains that map to this instance. These are in addition to the
    // default popit domain.

}, { strict: true } );

InstanceSchema
  .virtual('base_url')
  .get(function () {
    return utils.instance_base_url_from_slug(this.slug);
  });

InstanceSchema.statics.sync = function(callback) {

  this
    .find({},  function (err, docs) {
			async.forEachSeries(
				docs,
				function (doc, cb){
          var instanceAPIURL = utils.instance_base_url_from_slug( doc.slug ) + '/api/v1/about/';
          http.get(url.parse(instanceAPIURL), function(res){
            var aboutJSON = '';
            res.on('data', function (chunk){
              aboutJSON += chunk;
            });
            res.on('end',function(){
              console.log(aboutJSON);
              var Info = mongoose.model('Info', InstanceInfo);
              var aboutObj = new Info( JSON.parse(aboutJSON).result );
              doc.info = [ aboutObj ];
              doc.save(function (err){
                if(err) throw err;
                cb();
              });
            });
          });
        },
				function (err) {
					if (err) throw err;
          callback();
				}
			);
    });
};

module.exports = InstanceSchema;
<commit_msg>Indentation fix<commit_after>var mongoose         = require('mongoose'),
Schema            = mongoose.Schema,
ObjectId          = Schema.ObjectId,
passgen           = require('passgen'),
config            = require('config'),
utils             = require('../utils'),
url               = require('url'),
http              = require('http'),
async             = require('async'),
InstanceInfo      = require('../schemas').InstanceInfo;

var InstanceSchema = new Schema({
  slug: {
    type:      String,
    lowercase: true,
    trim:      true,
    match:     /^[a-z][a-z0-9\-]{3,19}$/,
    validate:  [
    function( v, fn ) {
      // run on insert only, when we don't have an ID
      // FIXME - find better way to handle this and test
      if ( ! this.isNew ) return fn( true );

      this.collection.count(
      {
        slug: v
      },
      function (err, count) {
        fn( count ? false : true );
      }
      );
    },
    'slug_not_unique'
    ],
    unique:    true,
    required:  true,
  },
  created_date: {
    type: Date,
    'default': Date.now
  },

  status: {
    type: String,
    required: true,
    'default': 'pending',
    'enum': [
    'pending',   // has not been activated yet - db does not exist
    'active',    // created and available
    'suspended', // blocked for some reason
    'archived',  // has been archived due to lack of use
    ],
  },

  email: {
    type: String,
    required: true,
    validate: [ utils.is_email, 'not_an_email' ]
  },

  // Initial info needed to set up the instance - should be cleared once
  // instance configured.
  setup_info: {
    // initial password for
    password_hash: {
      type: String,
    },
    confirmation_token: {
      type: String,
      'default': function () {
        return passgen.create(16);
      },
    }
  },

  // details - a hash that is created from values in the instance. Eg number of
  // entities stored, name and description. This is collected by a cron job and
  // used to provide information on the instance.

  info: [InstanceInfo],

// domains - the domains that map to this instance. These are in addition to the
// default popit domain.

}, {
  strict: true
} );

InstanceSchema
  .virtual('base_url')
  .get(function () {
    return utils.instance_base_url_from_slug(this.slug);
  });

InstanceSchema.statics.sync = function(callback) {

  this
  .find({},  function (err, docs) {
    async.forEachSeries(
      docs,
      function (doc, cb){
        var instanceAPIURL = utils.instance_base_url_from_slug( doc.slug ) + '/api/v1/about/';
        http.get(url.parse(instanceAPIURL), function(res){
          var aboutJSON = '';
          res.on('data', function (chunk){
            aboutJSON += chunk;
          });
          res.on('end',function(){
            console.log(aboutJSON);
            var Info = mongoose.model('Info', InstanceInfo);
            var aboutObj = new Info( JSON.parse(aboutJSON).result );
            doc.info = [ aboutObj ];
            doc.save(function (err){
              if(err) throw err;
              cb();
            });
          });
        });
      },
      function (err) {
        if (err) throw err;
        callback();
      }
      );
  });
};

module.exports = InstanceSchema;
<|endoftext|>


<commit_before>var page = new WebPage(),
    address, output, div, i, pair;

// use named arguments
var args = {};
for(i = 0; i < phantom.args.length; i++) {
    pair = phantom.args[i].split(/=(.*)/);
    args[pair[0]] = pair[1];
}

if( args.url ) {
    args.url = decodeURIComponent(args.url);
}

console.log(JSON.stringify(args));

if( !args.url || !args.output ) {
    console.log('Usage: rasterize.js url=URL output=filename');
    phantom.exit();
}

page.onConsoleMessage = function (msg) {
    console.log("from page: " + msg);
};

page.open(args.url, function (status) {
    if(status !== 'success') {
        console.log('Unable to load:' + args.url);
        phantom.exit();
    }

    page.render(args.output);

    phantom.exit();
});

<commit_msg>force screenshot width<commit_after>var page = new WebPage(),
    address, output, div, i, pair;

// use named arguments
var args = {};
for(i = 0; i < phantom.args.length; i++) {
    pair = phantom.args[i].split(/=(.*)/);
    args[pair[0]] = pair[1];
}

if( args.url ) {
    args.url = decodeURIComponent(args.url);
}

console.log(JSON.stringify(args));

if( !args.url || !args.output ) {
    console.log('Usage: rasterize.js url=URL output=filename');
    phantom.exit();
}

page.onConsoleMessage = function (msg) {
    console.log("from page: " + msg);
};

page.open(args.url, function (status) {
    if(status !== 'success') {
        console.log('Unable to load:' + args.url);
        phantom.exit();
    }
    var height = page.evaluate(function () {
       return document.body.clientHeight;
    });
    page.viewportSize = {width: 1400, height: height};

    setTimeout(function() {
      page.render(args.output);
      phantom.exit();
    }, 0)
});

<|endoftext|>


<commit_before>(function () {
    var COUNTRY_CODES = {
        Ireland: "ie",
        Spain: "es",
        "United Kingdom": "gb",
        France: "fr",
        Germany: "de",
        Sweden: "se",
        Italy: "it",
        Greece: "gr",
        Iceland: "is",
        Portugal: "pt",
        Malta: "mt",
        Norway: "no",
        Brazil: "br",
        Argentina: "ar",
        Colombia: "co",
        Peru: "pe",
        Venezuela: "ve",
        Uruguay: "uy"
    };

    var IT_SKILLS = ['android', 'css', 'html5', 'mac', 'windows'];
    var IT_SKILLS_NAMES = ['Android', 'CSS', 'HTML 5', 'Mac', 'Windows'];

    var columnDefs = [
        {
            headerName: '', width: 70, checkboxSelection: true, suppressSorting: true,
            suppressMenu: true
        },
        {
            headerName: 'Employee',
            children: [
                {
                    headerName: "Name", field: "name",
                    width: 150
                },
                {
                    headerName: "Country", field: "country", width: 150,
                    cellRenderer: countryCellRenderer,
                    filterParams: {cellRenderer: countryCellRenderer, cellHeight: 20}
                },
            ]
        },
        {
            headerName: 'IT Skills',
            children: [
                {
                    headerName: "Skills", width: 125, suppressSorting: true,
                    cellRenderer: skillsCellRenderer, filter: SkillFilter
                },
                {
                    headerName: "Proficiency", field: "proficiency", filter: 'number',
                    width: 150, cellRenderer: percentCellRenderer, filter: ProficiencyFilter
                },
            ]
        },
        {
            headerName: 'Contact',
            children: [
                {headerName: "Mobile", field: "mobile", width: 180, filter: 'text'},
                {headerName: "Land-line", field: "landline", width: 180, filter: 'text'},
                {headerName: "Address", field: "address", width: 500, filter: 'text'}
            ]
        }
    ];

    var gridOptions = {
        columnDefs: columnDefs,
        rowSelection: 'multiple',
        enableColResize: true,
        enableSorting: true,
        enableFilter: true,
        enableRangeSelection: true,
        suppressRowClickSelection: true,
        animateRows: true,
        onModelUpdated: modelUpdated,
        debug: true
    };

    var btBringGridBack;
    var btDestroyGrid;

    // wait for the document to be loaded, otherwise
    // ag-Grid will not find the div in the document.
    document.addEventListener("DOMContentLoaded", function () {
        btBringGridBack = document.querySelector('#btBringGridBack');
        btDestroyGrid = document.querySelector('#btDestroyGrid');

        // this example is also used in the website landing page, where
        // we don't display the buttons, so we check for the buttons existance
        if (btBringGridBack) {
            btBringGridBack.addEventListener('click', onBtBringGridBack);
            btDestroyGrid.addEventListener('click', onBtDestroyGrid);
        }

        addQuickFilterListener();
        onBtBringGridBack();
    });

    function onBtBringGridBack() {
        var eGridDiv = document.querySelector('#bestHtml5Grid');
        new agGrid.Grid(eGridDiv, gridOptions);
        if (btBringGridBack) {
            btBringGridBack.disabled = true;
            btDestroyGrid.disabled = false;
        }
        // createRowData is available in data.js
        gridOptions.api.setRowData(createRowData());
    }

    function onBtDestroyGrid() {
        btBringGridBack.disabled = false;
        btDestroyGrid.disabled = true;
        gridOptions.api.destroy();
    }

    function addQuickFilterListener() {
        var eInput = document.querySelector('#quickFilterInput');
        eInput.addEventListener("input", function () {
            var text = eInput.value;
            gridOptions.api.setQuickFilter(text);
        });
    }

    function modelUpdated() {
        var model = gridOptions.api.getModel();
        var totalRows = model.getTopLevelNodes().length;
        var processedRows = model.getRowCount();
        var eSpan = document.querySelector('#rowCount');
        eSpan.innerHTML = processedRows.toLocaleString() + ' / ' + totalRows.toLocaleString();
    }

    function skillsCellRenderer(params) {
        var data = params.data;
        var skills = [];
        IT_SKILLS.forEach(function (skill) {
            if (data && data.skills[skill]) {
                skills.push('');
            }
        });
        return skills.join(' ');
    }

    function countryCellRenderer(params) {
        var flag = "";
        return flag + " " + params.value;
    }

    function createRandomPhoneNumber() {
        var result = '+';
        for (var i = 0; i < 12; i++) {
            result += Math.round(Math.random() * 10);
            if (i === 2 || i === 5 || i === 8) {
                result += ' ';
            }
        }
        return result;
    }

    function percentCellRenderer(params) {
        var value = params.value;

        var eDivPercentBar = document.createElement('div');
        eDivPercentBar.className = 'div-percent-bar';
        eDivPercentBar.style.width = value + '%';
        if (value < 20) {
            eDivPercentBar.style.backgroundColor = '#f44336';
        } else if (value < 60) {
            eDivPercentBar.style.backgroundColor = '#FF9100';
        } else {
            eDivPercentBar.style.backgroundColor = '#4CAF50';
        }

        var eValue = document.createElement('div');
        eValue.className = 'div-percent-value';
        eValue.innerHTML = value + '%';

        var eOuterDiv = document.createElement('div');
        eOuterDiv.className = 'div-outer-div';
        eOuterDiv.appendChild(eDivPercentBar);
        eOuterDiv.appendChild(eValue);

        return eOuterDiv;
    }

    var SKILL_TEMPLATE =
        '' +
        '  ' +
        '
SKILL_NAME
' +
        '
' +
        '      <input type="checkbox"/>' +
        '      ' +
        '
' +
        '  ' +
        '';

    var FILTER_TITLE =
        '
' +
        'TITLE_NAME' +
        '
';

    function SkillFilter() {
    }

    SkillFilter.prototype.init = function (params) {
        this.filterChangedCallback = params.filterChangedCallback;
        this.model = {
            android: false,
            css: false,
            html5: false,
            mac: false,
            windows: false
        };
    };

    SkillFilter.prototype.getModel = function () {

    };

    SkillFilter.prototype.setModel = function (model) {

    };

    SkillFilter.prototype.getGui = function () {
        var eGui = document.createElement('div');
        var eInstructions = document.createElement('div');
        eInstructions.innerHTML = FILTER_TITLE.replace('TITLE_NAME', 'Custom Skills Filter');
        eGui.appendChild(eInstructions);

        var that = this;

        IT_SKILLS.forEach(function (skill, index) {
            var skillName = IT_SKILLS_NAMES[index];
            var eSpan = document.createElement('span');
            var html = SKILL_TEMPLATE.replace("SKILL_NAME", skillName).replace("SKILL", skill);
            eSpan.innerHTML = html;

            var eCheckbox = eSpan.querySelector('input');
            eCheckbox.addEventListener('click', function () {
                that.model[skill] = eCheckbox.checked;
                that.filterChangedCallback();
            });

            eGui.appendChild(eSpan);
        });

        return eGui;
    };

    SkillFilter.prototype.doesFilterPass = function (params) {

        var rowSkills = params.data.skills;
        var model = this.model;
        var passed = true;

        IT_SKILLS.forEach(function (skill) {
            if (model[skill]) {
                if (!rowSkills[skill]) {
                    passed = false;
                }
            }
        });

        return passed;
    };

    SkillFilter.prototype.isFilterActive = function () {
        var model = this.model;
        var somethingSelected = model.android || model.css || model.html5 || model.mac || model.windows;
        return somethingSelected;
    };

    var PROFICIENCY_TEMPLATE =
        '' +
        '<input type="radio" name="RANDOM"/>' +
        'PROFICIENCY_NAME' +
        '';

    var PROFICIENCY_NONE = 'none';
    var PROFICIENCY_ABOVE40 = 'above40';
    var PROFICIENCY_ABOVE60 = 'above60';
    var PROFICIENCY_ABOVE80 = 'above80';

    var PROFICIENCY_NAMES = ['No Filter', 'Above 40%', 'Above 60%', 'Above 80%'];
    var PROFICIENCY_VALUES = [PROFICIENCY_NONE, PROFICIENCY_ABOVE40, PROFICIENCY_ABOVE60, PROFICIENCY_ABOVE80];

    function ProficiencyFilter() {
    }

    ProficiencyFilter.prototype.init = function (params) {
        this.filterChangedCallback = params.filterChangedCallback;
        this.selected = PROFICIENCY_NONE;
        this.valueGetter = params.valueGetter;
    };

    ProficiencyFilter.prototype.getModel = function () {

    };

    ProficiencyFilter.prototype.setModel = function (model) {

    };

    ProficiencyFilter.prototype.getGui = function () {
        var eGui = document.createElement('div');
        var eInstructions = document.createElement('div');
        eInstructions.innerHTML = FILTER_TITLE.replace('TITLE_NAME', 'Custom Proficiency Filter');
        eGui.appendChild(eInstructions);

        var random = '' + Math.random();

        var that = this;
        PROFICIENCY_NAMES.forEach(function (name, index) {
            var eFilter = document.createElement('div');
            var html = PROFICIENCY_TEMPLATE.replace('PROFICIENCY_NAME', name).replace('RANDOM', random);
            eFilter.innerHTML = html;
            var eRadio = eFilter.querySelector('input');
            if (index === 0) {
                eRadio.checked = true;
            }
            eGui.appendChild(eFilter);

            eRadio.addEventListener('click', function () {
                that.selected = PROFICIENCY_VALUES[index];
                that.filterChangedCallback();
            });
        });

        return eGui;
    };

    ProficiencyFilter.prototype.doesFilterPass = function (params) {

        var value = this.valueGetter(params);
        var valueAsNumber = parseFloat(value);

        switch (this.selected) {
            case PROFICIENCY_ABOVE40 :
                return valueAsNumber >= 40;
            case PROFICIENCY_ABOVE60 :
                return valueAsNumber >= 60;
            case PROFICIENCY_ABOVE80 :
                return valueAsNumber >= 80;
            default :
                return true;
        }

    };

    ProficiencyFilter.prototype.isFilterActive = function () {
        return this.selected !== PROFICIENCY_NONE;
    };
})();
<commit_msg>Fix custom filters<commit_after>(function () {
    var COUNTRY_CODES = {
        Ireland: "ie",
        Spain: "es",
        "United Kingdom": "gb",
        France: "fr",
        Germany: "de",
        Sweden: "se",
        Italy: "it",
        Greece: "gr",
        Iceland: "is",
        Portugal: "pt",
        Malta: "mt",
        Norway: "no",
        Brazil: "br",
        Argentina: "ar",
        Colombia: "co",
        Peru: "pe",
        Venezuela: "ve",
        Uruguay: "uy"
    };

    var IT_SKILLS = ['android', 'css', 'html5', 'mac', 'windows'];
    var IT_SKILLS_NAMES = ['Android', 'CSS', 'HTML 5', 'Mac', 'Windows'];

    var columnDefs = [
        {
            headerName: '', width: 70, checkboxSelection: true, suppressSorting: true,
            suppressMenu: true
        },
        {
            headerName: 'Employee',
            children: [
                {
                    headerName: "Name", field: "name",
                    width: 150
                },
                {
                    headerName: "Country", field: "country", width: 150,
                    cellRenderer: countryCellRenderer,
                    filterParams: {cellRenderer: countryCellRenderer, cellHeight: 20}
                },
            ]
        },
        {
            headerName: 'IT Skills',
            children: [
                {
                    headerName: "Skills", width: 125, suppressSorting: true,
                    cellRenderer: skillsCellRenderer, filter: SkillFilter
                },
                {
                    headerName: "Proficiency", field: "proficiency", filter: 'number',
                    width: 150, cellRenderer: percentCellRenderer, filter: ProficiencyFilter
                },
            ]
        },
        {
            headerName: 'Contact',
            children: [
                {headerName: "Mobile", field: "mobile", width: 180, filter: 'text'},
                {headerName: "Land-line", field: "landline", width: 180, filter: 'text'},
                {headerName: "Address", field: "address", width: 500, filter: 'text'}
            ]
        }
    ];

    var gridOptions = {
        columnDefs: columnDefs,
        rowSelection: 'multiple',
        enableColResize: true,
        enableSorting: true,
        enableFilter: true,
        enableRangeSelection: true,
        suppressRowClickSelection: true,
        animateRows: true,
        onModelUpdated: modelUpdated,
        debug: true
    };

    var btBringGridBack;
    var btDestroyGrid;

    // wait for the document to be loaded, otherwise
    // ag-Grid will not find the div in the document.
    document.addEventListener("DOMContentLoaded", function () {
        btBringGridBack = document.querySelector('#btBringGridBack');
        btDestroyGrid = document.querySelector('#btDestroyGrid');

        // this example is also used in the website landing page, where
        // we don't display the buttons, so we check for the buttons existance
        if (btBringGridBack) {
            btBringGridBack.addEventListener('click', onBtBringGridBack);
            btDestroyGrid.addEventListener('click', onBtDestroyGrid);
        }

        addQuickFilterListener();
        onBtBringGridBack();
    });

    function onBtBringGridBack() {
        var eGridDiv = document.querySelector('#bestHtml5Grid');
        new agGrid.Grid(eGridDiv, gridOptions);
        if (btBringGridBack) {
            btBringGridBack.disabled = true;
            btDestroyGrid.disabled = false;
        }
        // createRowData is available in data.js
        gridOptions.api.setRowData(createRowData());
    }

    function onBtDestroyGrid() {
        btBringGridBack.disabled = false;
        btDestroyGrid.disabled = true;
        gridOptions.api.destroy();
    }

    function addQuickFilterListener() {
        var eInput = document.querySelector('#quickFilterInput');
        eInput.addEventListener("input", function () {
            var text = eInput.value;
            gridOptions.api.setQuickFilter(text);
        });
    }

    function modelUpdated() {
        var model = gridOptions.api.getModel();
        var totalRows = model.getTopLevelNodes().length;
        var processedRows = model.getRowCount();
        var eSpan = document.querySelector('#rowCount');
        eSpan.innerHTML = processedRows.toLocaleString() + ' / ' + totalRows.toLocaleString();
    }

    function skillsCellRenderer(params) {
        var data = params.data;
        var skills = [];
        IT_SKILLS.forEach(function (skill) {
            if (data && data.skills[skill]) {
                skills.push('');
            }
        });
        return skills.join(' ');
    }

    function countryCellRenderer(params) {
        var flag = "";
        return flag + " " + params.value;
    }

    function createRandomPhoneNumber() {
        var result = '+';
        for (var i = 0; i < 12; i++) {
            result += Math.round(Math.random() * 10);
            if (i === 2 || i === 5 || i === 8) {
                result += ' ';
            }
        }
        return result;
    }

    function percentCellRenderer(params) {
        var value = params.value;

        var eDivPercentBar = document.createElement('div');
        eDivPercentBar.className = 'div-percent-bar';
        eDivPercentBar.style.width = value + '%';
        if (value < 20) {
            eDivPercentBar.style.backgroundColor = '#f44336';
        } else if (value < 60) {
            eDivPercentBar.style.backgroundColor = '#FF9100';
        } else {
            eDivPercentBar.style.backgroundColor = '#4CAF50';
        }

        var eValue = document.createElement('div');
        eValue.className = 'div-percent-value';
        eValue.innerHTML = value + '%';

        var eOuterDiv = document.createElement('div');
        eOuterDiv.className = 'div-outer-div';
        eOuterDiv.appendChild(eDivPercentBar);
        eOuterDiv.appendChild(eValue);

        return eOuterDiv;
    }

    var SKILL_TEMPLATE =
        '' +
        '  ' +
        '
SKILL_NAME
' +
        '
' +
        '      <input type="checkbox"/>' +
        '      ' +
        '
' +
        '  ' +
        '';

    var FILTER_TITLE =
        '
' +
        'TITLE_NAME' +
        '
';

    function SkillFilter() {
    }

    SkillFilter.prototype.init = function (params) {
        this.filterChangedCallback = params.filterChangedCallback;
        this.model = {
            android: false,
            css: false,
            html5: false,
            mac: false,
            windows: false
        };
    };

    SkillFilter.prototype.getModel = function () {

    };

    SkillFilter.prototype.setModel = function (model) {

    };

    SkillFilter.prototype.getGui = function () {
        var eGui = document.createElement('div');
        var eInstructions = document.createElement('div');
        eInstructions.innerHTML = FILTER_TITLE.replace('TITLE_NAME', 'Custom Skills Filter');
        eGui.appendChild(eInstructions);

        var that = this;

        IT_SKILLS.forEach(function (skill, index) {
            var skillName = IT_SKILLS_NAMES[index];
            var eSpan = document.createElement('span');
            var html = SKILL_TEMPLATE.replace("SKILL_NAME", skillName).replace("SKILL", skill);
            eSpan.innerHTML = html;

            var eCheckbox = eSpan.querySelector('input');
            eCheckbox.addEventListener('click', function () {
                that.model[skill] = eCheckbox.checked;
                that.filterChangedCallback();
            });

            eGui.appendChild(eSpan);
        });

        return eGui;
    };

    SkillFilter.prototype.doesFilterPass = function (params) {

        var rowSkills = params.data.skills;
        var model = this.model;
        var passed = true;

        IT_SKILLS.forEach(function (skill) {
            if (model[skill]) {
                if (!rowSkills[skill]) {
                    passed = false;
                }
            }
        });

        return passed;
    };

    SkillFilter.prototype.isFilterActive = function () {
        var model = this.model;
        var somethingSelected = model.android || model.css || model.html5 || model.mac || model.windows;
        return somethingSelected;
    };

    var PROFICIENCY_TEMPLATE =
        '' +
        '<input type="radio" name="RANDOM"/>' +
        'PROFICIENCY_NAME' +
        '';

    var PROFICIENCY_NONE = 'none';
    var PROFICIENCY_ABOVE40 = 'above40';
    var PROFICIENCY_ABOVE60 = 'above60';
    var PROFICIENCY_ABOVE80 = 'above80';

    var PROFICIENCY_NAMES = ['No Filter', 'Above 40%', 'Above 60%', 'Above 80%'];
    var PROFICIENCY_VALUES = [PROFICIENCY_NONE, PROFICIENCY_ABOVE40, PROFICIENCY_ABOVE60, PROFICIENCY_ABOVE80];

    function ProficiencyFilter() {
    }

    ProficiencyFilter.prototype.init = function (params) {
        this.filterChangedCallback = params.filterChangedCallback;
        this.selected = PROFICIENCY_NONE;
        this.valueGetter = params.valueGetter;
    };

    ProficiencyFilter.prototype.getModel = function () {

    };

    ProficiencyFilter.prototype.setModel = function (model) {

    };

    ProficiencyFilter.prototype.getGui = function () {
        var eGui = document.createElement('div');
        var eInstructions = document.createElement('div');
        eInstructions.innerHTML = FILTER_TITLE.replace('TITLE_NAME', 'Custom Proficiency Filter');
        eGui.appendChild(eInstructions);

        var random = '' + Math.random();

        var that = this;
        PROFICIENCY_NAMES.forEach(function (name, index) {
            var eFilter = document.createElement('div');
            var html = PROFICIENCY_TEMPLATE.replace('PROFICIENCY_NAME', name).replace('RANDOM', random);
            eFilter.innerHTML = html;
            var eRadio = eFilter.querySelector('input');
            if (index === 0) {
                eRadio.checked = true;
            }
            eGui.appendChild(eFilter);

            eRadio.addEventListener('click', function () {
                that.selected = PROFICIENCY_VALUES[index];
                that.filterChangedCallback();
            });
        });

        return eGui;
    };

    ProficiencyFilter.prototype.doesFilterPass = function (params) {

        var value = this.valueGetter(params);
        var valueAsNumber = parseFloat(value);

        switch (this.selected) {
            case PROFICIENCY_ABOVE40 :
                return valueAsNumber >= 40;
            case PROFICIENCY_ABOVE60 :
                return valueAsNumber >= 60;
            case PROFICIENCY_ABOVE80 :
                return valueAsNumber >= 80;
            default :
                return true;
        }

    };

    ProficiencyFilter.prototype.isFilterActive = function () {
        return this.selected !== PROFICIENCY_NONE;
    };
})();
<|endoftext|>


<commit_before>export function findNearestView(view, selector, predicate) {
  if (!view || !selector || view.matches("[data-jsua-app]")) return null;

  var matching = view.querySelector(selector);
  if (!matching) return findNearestView(view.parentElement, selector, predicate);

  if (predicate) {
    if (predicate(matching)) return matching;
    return findNearestView(view.parentElement, selector, predicate);
  }

  return matching;
}

export function findNearestAncestorView(view, selector) {
  if (!view || !selector || view.matches("[data-jsua-app]")) return null;
  var parent = view.parentElement;
  if (parent && parent.matches(selector)) return parent;
  return findNearestAncestorView(parent, selector);
}

export function buildFormData(submitView) {
  var formView = exports.findNearestAncestorView(submitView, "[data-lynx-hints~=form]");
  if (!formView) return null;

  var formData;

  if (submitView.formEnctype === "multipart/form-data") {
    formData = new FormData();
  } else {
    formData = new URLSearchParams();
  }

  var inputViews = formView.querySelectorAll("[data-lynx-input]:not([data-lynx-hints~=container])");

  Array.from(inputViews).forEach(function (inputView) {
    var inputValues = inputView.lynxGetValue();
    if (!Array.isArray(inputValues)) inputValues = [ inputValues ];

    inputValues.forEach(function (inputValue) {
      formData.append(inputView.getAttribute("data-lynx-input"), inputValue);
    });
  });

  return formData;
}
<commit_msg>findNearestView Should Check All Subviews<commit_after>export function findNearestView(view, selector, predicate) {
  if (!view || !selector || view.matches("[data-jsua-app]")) return null;

  var matches = Array.from(view.querySelectorAll(selector));
  if (matches.length === 0) return findNearestView(view.parentElement, selector, predicate);

  if (predicate) {
    let matching = matches.find(predicate);
    if (matching) return matching;
    return findNearestView(view.parentElement, selector, predicate);
  }

  return matches[0];
}

export function findNearestAncestorView(view, selector) {
  if (!view || !selector || view.matches("[data-jsua-app]")) return null;
  var parent = view.parentElement;
  if (parent && parent.matches(selector)) return parent;
  return findNearestAncestorView(parent, selector);
}

export function buildFormData(submitView) {
  var formView = exports.findNearestAncestorView(submitView, "[data-lynx-hints~=form]");
  if (!formView) return null;

  var formData;

  if (submitView.formEnctype === "multipart/form-data") {
    formData = new FormData();
  } else {
    formData = new URLSearchParams();
  }

  var inputViews = formView.querySelectorAll("[data-lynx-input]:not([data-lynx-hints~=container])");

  Array.from(inputViews).forEach(function (inputView) {
    var inputValues = inputView.lynxGetValue();
    if (!Array.isArray(inputValues)) inputValues = [ inputValues ];

    inputValues.forEach(function (inputValue) {
      formData.append(inputView.getAttribute("data-lynx-input"), inputValue);
    });
  });

  return formData;
}
<|endoftext|>


<commit_before>var SuperPipe = require('superpipe')

exports.initLocalService = SuperPipe
  .pipeline()
  // Gether service information
  .pipe('getEnvVariables')
  .pipe('getPackageJSON', 'packagePath', 'packageJSON')
  .pipe('getServiceInfo',
    ['packageJSON', 'service'],
    ['hasAsset', 'serviceName', 'serviceInfo', 'serviceVersion'])
  .pipe('prepareService', ['hasAsset', 'service'])
  // Setup web features
  .pipe('prepareFramework?',
    ['framework', 'setDep'],
    ['app', 'attachRoutes', 'attachLocalMiddlewares', 'startHttpServer', 'serveLocalAsset'])
  .pipe('setupAsset?', ['hasAsset', 'packageJSON'], ['asset', 'assetInfo'])
  .pipe('setupRoute?', ['route', 'page', 'pageApiBaseUrl'], 'routes')
  .pipe('setupUse?', 'use', 'uses')
  .pipe('setupMiddleware?', ['middleware', 'middlewareBaseUrl'], 'middlewares')
  // Start web server and attach request handlers
  .pipe('startWebServer?',
    ['port', 'host', 'serviceName', 'startHttpServer', 'setDep'],
    ['httpServer', 'httpPort', 'httpHost'])
  .pipe('serveLocalAsset?', ['asset', 'serviceName'])
  .pipe('attachRoutes?', ['routes', 'service'])
  .pipe('attachLocalMiddlewares?', ['middlewares', 'service'])
  // RPC features
  .pipe('setupRPC?', ['api', 'rpcType'], ['rpc', 'rpcApi'])
  .pipe('startRPCServer?', ['rpc', 'rpcPort', 'host', 'service', 'setDep', 'next'])
  .pipe('generateAnnouncement',
    ['assetInfo', 'routes', 'uses', 'middlewares', 'service',
      'httpPort', 'framework', 'rpcApi', 'rpcPort', 'rpcType', 'host'
    ], 'announcement')
  .pipe('announceService', ['serviceName', 'announcement'])
<commit_msg>Move `setupRPC` up.<commit_after>var SuperPipe = require('superpipe')

exports.initLocalService = SuperPipe
  .pipeline()
  // Gether service information
  .pipe('getEnvVariables')
  .pipe('getPackageJSON', 'packagePath', 'packageJSON')
  .pipe('getServiceInfo',
    ['packageJSON', 'service'],
    ['hasAsset', 'serviceName', 'serviceInfo', 'serviceVersion'])
  .pipe('prepareService', ['hasAsset', 'service'])
  // Setup web features
  .pipe('prepareFramework?',
    ['framework', 'setDep'],
    ['app', 'attachRoutes', 'attachLocalMiddlewares', 'startHttpServer', 'serveLocalAsset'])
  .pipe('setupAsset?', ['hasAsset', 'packageJSON'], ['asset', 'assetInfo'])
  .pipe('setupRoute?', ['route', 'page', 'pageApiBaseUrl'], 'routes')
  .pipe('setupUse?', 'use', 'uses')
  .pipe('setupMiddleware?', ['middleware', 'middlewareBaseUrl'], 'middlewares')
  // Setup RPC
  .pipe('setupRPC?', ['api', 'rpcType'], ['rpc', 'rpcApi'])
  // Start web server
  .pipe('startWebServer?',
    ['port', 'host', 'serviceName', 'startHttpServer', 'setDep'],
    ['httpServer', 'httpPort', 'httpHost'])
  // Attach request handlers and start RPC server
  .pipe('serveLocalAsset?', ['asset', 'serviceName'])
  .pipe('attachRoutes?', ['routes', 'service'])
  .pipe('attachLocalMiddlewares?', ['middlewares', 'service'])
  .pipe('startRPCServer?', ['rpc', 'rpcPort', 'host', 'service', 'setDep', 'next'])
  .pipe('generateAnnouncement',
    ['assetInfo', 'routes', 'uses', 'middlewares', 'service',
      'httpPort', 'framework', 'rpcApi', 'rpcPort', 'rpcType', 'host'
    ], 'announcement')
  .pipe('announceService', ['serviceName', 'announcement'])
<|endoftext|>


<commit_before>/**
 * Utility functions.
 */

export const isArray = Array.isArray;

export function isObject(obj) {
    return obj !== null && typeof obj === 'object';
}

export function forEach(collection, callback) {
    Object.keys(collection || {}).forEach(key => {
        callback.call(null, collection[key], key);
    });
}
<commit_msg>add findexIndex()<commit_after>/**
 * Utility functions.
 */

export const isArray = Array.isArray;

export function isObject(obj) {
    return obj !== null && typeof obj === 'object';
}

export function forEach(collection, callback) {
    Object.keys(collection || {}).forEach(key => {
        callback.call(null, collection[key], key);
    });
}

/**
 * Array.findIndex() polyfill.
 */
if (!Array.prototype.findIndex) {
    Object.defineProperty(Array.prototype, 'findIndex', {

        value(predicate) {

            if (this == null) {
                throw new TypeError('"this" is null or not defined');
            }

            if (typeof predicate !== 'function') {
                throw new TypeError('predicate must be a function');
            }

            var o = Object(this);
            var len = o.length >>> 0;
            var thisArg = arguments[1];
            var k = 0;

            while (k < len) {

                var kValue = o[k];

                if (predicate.call(thisArg, kValue, k, o)) {
                    return k;
                }

                k++;
            }

            return -1;
        }

    });
}
<|endoftext|>