<commit_before>/* global lib, XMLHttpRequest */

'use strict'

const utils = require('../utils')
const logger = require('../logger')

require('httpurl')

let jsonpCnt = 0
const ERROR_STATE = -1

const TYPE_JSON = 'application/json;charset=UTF-8'
const TYPE_FORM = 'application/x-www-form-urlencoded'

const REG_FORM = /^(?:[^&=]+=[^&=]+)(?:&[^&=]+=[^&=]+)*$/

function _jsonp (config, callback, progressCallback) {
  const cbName = 'jsonp_' + (++jsonpCnt)
  let url

  if (!config.url) {
    logger.error('config.url should be set in _jsonp for \'fetch\' API.')
  }

  global[cbName] = (function (cb) {
    return function (response) {
      callback(response)
      delete global[cb]
    }
  })(cbName)

  const script = document.createElement('script')
  try {
    url = lib.httpurl(config.url)
  }
  catch (err) {
    logger.error('invalid config.url in _jsonp for \'fetch\' API: '
      + config.url)
  }
  url.params.callback = cbName
  script.type = 'text/javascript'
  script.src = url.toString()
  // script.onerror is not working on IE or safari.
  // but they are not considered here.
  script.onerror = (function (cb) {
    return function (err) {
      logger.error('unexpected error in _jsonp for \'fetch\' API', err)
      callback(err)
      delete global[cb]
    }
  })(cbName)
  const head = document.getElementsByTagName('head')[0]
  head.insertBefore(script, null)
}

function _xhr (config, callback, progressCallback) {
  const xhr = new XMLHttpRequest()
  xhr.responseType = config.type
  xhr.open(config.method, config.url, true)

  const headers = config.headers || {}
  for (const k in headers) {
    xhr.setRequestHeader(k, headers[k])
  }

  xhr.onload = function (res) {
    callback({
      status: xhr.status,
      ok: xhr.status >= 200 && xhr.status < 300,
      statusText: xhr.statusText,
      data: xhr.response,
      headers: xhr.getAllResponseHeaders().split('\n')
        .reduce(function (obj, headerStr) {
          const headerArr = headerStr.match(/(.+): (.+)/)
          if (headerArr) {
            obj[headerArr[1]] = headerArr[2]
          }
          return obj
        }, {})
    })
  }

  if (progressCallback) {
    xhr.onprogress = function (e) {
      progressCallback({
        readyState: xhr.readyState,
        status: xhr.status,
        length: e.loaded,
        total: e.total,
        statusText: xhr.statusText,
        headers: xhr.getAllResponseHeaders().split('\n')
          .reduce(function (obj, headerStr) {
            const headerArr = headerStr.match(/(.+): (.+)/)
            if (headerArr) {
              obj[headerArr[1]] = headerArr[2]
            }
            return obj
          }, {})
      })
    }
  }

  xhr.onerror = function (err) {
    logger.error('unexpected error in _xhr for \'fetch\' API', err)
    callback({
      status: ERROR_STATE,
      ok: false,
      statusText: '',
      data: '',
      headers: {}
    })
  }

  xhr.send(config.body)
}

const stream = {

  /**
   * sendHttp
   * @deprecated
   * Note: This API is deprecated. Please use stream.fetch instead.
   * send a http request through XHR.
   * @deprecated
   * @param  {obj} params
   *  - method: 'GET' | 'POST',
   *  - url: url requested
   * @param  {string} callbackId
   */
  sendHttp: function (param, callbackId) {
    if (typeof param === 'string') {
      try {
        param = JSON.parse(param)
      }
      catch (e) {
        return
      }
    }
    if (typeof param !== 'object' || !param.url) {
      return logger.error(
        'invalid config or invalid config.url for sendHttp API')
    }

    const sender = this.sender
    const method = param.method || 'GET'
    const xhr = new XMLHttpRequest()
    xhr.open(method, param.url, true)
    xhr.onload = function () {
      sender.performCallback(callbackId, this.responseText)
    }
    xhr.onerror = function (error) {
      return logger.error('unexpected error in sendHttp API', error)
      // sender.performCallback(
      //   callbackId,
      //   new Error('unexpected error in sendHttp API')
      // )
    }
    xhr.send()
  },

  /**
   * fetch
   * use stream.fetch to request for a json file, a plain text file or
   * a arraybuffer for a file stream. (You can use Blob and FileReader
   * API implemented by most modern browsers to read a arraybuffer.)
   * @param  {object} options config options
   *   - method {string} 'GET' | 'POST'
   *   - headers {obj}
   *   - url {string}
   *   - mode {string} 'cors' | 'no-cors' | 'same-origin' | 'navigate'
   *   - body
   *   - type {string} 'json' | 'jsonp' | 'text'
   * @param  {string} callbackId
   * @param  {string} progressCallbackId
   */
  fetch: function (options, callbackId, progressCallbackId) {
    const DEFAULT_METHOD = 'GET'
    const DEFAULT_MODE = 'cors'
    const DEFAULT_TYPE = 'text'

    const methodOptions = ['GET', 'POST']
    const modeOptions = ['cors', 'no-cors', 'same-origin', 'navigate']
    const typeOptions = ['text', 'json', 'jsonp', 'arraybuffer']

    // const fallback = false  // fallback from 'fetch' API to XHR.
    const sender = this.sender

    const config = utils.extend({}, options)

    // validate options.method
    if (typeof config.method === 'undefined') {
      config.method = DEFAULT_METHOD
      logger.warn('options.method for \'fetch\' API has been set to '
        + 'default value \'' + config.method + '\'')
    }
    else if (methodOptions.indexOf((config.method + '')
        .toUpperCase()) === -1) {
      return logger.error('options.method \''
        + config.method
        + '\' for \'fetch\' API should be one of '
        + methodOptions + '.')
    }

    // validate options.url
    if (!config.url) {
      return logger.error('options.url should be set for \'fetch\' API.')
    }

    // validate options.mode
    if (typeof config.mode === 'undefined') {
      config.mode = DEFAULT_MODE
    }
    else if (modeOptions.indexOf((config.mode + '').toLowerCase()) === -1) {
      return logger.error('options.mode \''
        + config.mode
        + '\' for \'fetch\' API should be one of '
        + modeOptions + '.')
    }

    // validate options.type
    if (typeof config.type === 'undefined') {
      config.type = DEFAULT_TYPE
      logger.warn('options.type for \'fetch\' API has been set to '
        + 'default value \'' + config.type + '\'.')
    }
    else if (typeOptions.indexOf((config.type + '').toLowerCase()) === -1) {
      return logger.error('options.type \''
          + config.type
          + '\' for \'fetch\' API should be one of '
          + typeOptions + '.')
    }

    // validate options.headers
    config.headers = config.headers || {}
    if (!utils.isPlainObject(config.headers)) {
      return logger.error('options.headers should be a plain object')
    }

    // validate options.body
    const body = config.body
    if (!config.headers['Content-Type'] && body) {
      if (utils.isPlainObject(body)) {
        // is a json data
        try {
          config.body = JSON.stringify(body)
          config.headers['Content-Type'] = TYPE_JSON
        } catch (e) {}
      } else if (utils.getType(body) === 'string' && body.match(REG_FORM)) {
        // is form-data
        config.body = encodeURI(body)
        config.headers['Content-Type'] = TYPE_FORM
      }
    }

    const _callArgs = [config, function (res) {
      sender.performCallback(callbackId, res)
    }]
    if (progressCallbackId) {
      _callArgs.push(function (res) {
        // Set 'keepAlive' to true for sending continuous callbacks
        sender.performCallback(progressCallbackId, res, true)
      })
    }

    if (config.type === 'jsonp') {
      _jsonp.apply(this, _callArgs)
    }
    else {
      _xhr.apply(this, _callArgs)
    }
  }

}

stream._meta = {
  stream: [{
    name: 'sendHttp',
    args: ['object', 'function']
  }, {
    name: 'fetch',
    args: ['object', 'function', 'function']
  }]
}

module.exports = stream
<commit_msg>* [html5] fix lint<commit_after>/* global lib, XMLHttpRequest */

'use strict'

const utils = require('../utils')
const logger = require('../logger')

require('httpurl')

let jsonpCnt = 0
const ERROR_STATE = -1

const TYPE_JSON = 'application/json;charset=UTF-8'
const TYPE_FORM = 'application/x-www-form-urlencoded'

const REG_FORM = /^(?:[^&=]+=[^&=]+)(?:&[^&=]+=[^&=]+)*$/

function _jsonp (config, callback, progressCallback) {
  const cbName = 'jsonp_' + (++jsonpCnt)
  let url

  if (!config.url) {
    logger.error('config.url should be set in _jsonp for \'fetch\' API.')
  }

  global[cbName] = (function (cb) {
    return function (response) {
      callback(response)
      delete global[cb]
    }
  })(cbName)

  const script = document.createElement('script')
  try {
    url = lib.httpurl(config.url)
  }
  catch (err) {
    logger.error('invalid config.url in _jsonp for \'fetch\' API: '
      + config.url)
  }
  url.params.callback = cbName
  script.type = 'text/javascript'
  script.src = url.toString()
  // script.onerror is not working on IE or safari.
  // but they are not considered here.
  script.onerror = (function (cb) {
    return function (err) {
      logger.error('unexpected error in _jsonp for \'fetch\' API', err)
      callback(err)
      delete global[cb]
    }
  })(cbName)
  const head = document.getElementsByTagName('head')[0]
  head.insertBefore(script, null)
}

function _xhr (config, callback, progressCallback) {
  const xhr = new XMLHttpRequest()
  xhr.responseType = config.type
  xhr.open(config.method, config.url, true)

  const headers = config.headers || {}
  for (const k in headers) {
    xhr.setRequestHeader(k, headers[k])
  }

  xhr.onload = function (res) {
    callback({
      status: xhr.status,
      ok: xhr.status >= 200 && xhr.status < 300,
      statusText: xhr.statusText,
      data: xhr.response,
      headers: xhr.getAllResponseHeaders().split('\n')
        .reduce(function (obj, headerStr) {
          const headerArr = headerStr.match(/(.+): (.+)/)
          if (headerArr) {
            obj[headerArr[1]] = headerArr[2]
          }
          return obj
        }, {})
    })
  }

  if (progressCallback) {
    xhr.onprogress = function (e) {
      progressCallback({
        readyState: xhr.readyState,
        status: xhr.status,
        length: e.loaded,
        total: e.total,
        statusText: xhr.statusText,
        headers: xhr.getAllResponseHeaders().split('\n')
          .reduce(function (obj, headerStr) {
            const headerArr = headerStr.match(/(.+): (.+)/)
            if (headerArr) {
              obj[headerArr[1]] = headerArr[2]
            }
            return obj
          }, {})
      })
    }
  }

  xhr.onerror = function (err) {
    logger.error('unexpected error in _xhr for \'fetch\' API', err)
    callback({
      status: ERROR_STATE,
      ok: false,
      statusText: '',
      data: '',
      headers: {}
    })
  }

  xhr.send(config.body)
}

const stream = {

  /**
   * sendHttp
   * @deprecated
   * Note: This API is deprecated. Please use stream.fetch instead.
   * send a http request through XHR.
   * @deprecated
   * @param  {obj} params
   *  - method: 'GET' | 'POST',
   *  - url: url requested
   * @param  {string} callbackId
   */
  sendHttp: function (param, callbackId) {
    if (typeof param === 'string') {
      try {
        param = JSON.parse(param)
      }
      catch (e) {
        return
      }
    }
    if (typeof param !== 'object' || !param.url) {
      return logger.error(
        'invalid config or invalid config.url for sendHttp API')
    }

    const sender = this.sender
    const method = param.method || 'GET'
    const xhr = new XMLHttpRequest()
    xhr.open(method, param.url, true)
    xhr.onload = function () {
      sender.performCallback(callbackId, this.responseText)
    }
    xhr.onerror = function (error) {
      return logger.error('unexpected error in sendHttp API', error)
      // sender.performCallback(
      //   callbackId,
      //   new Error('unexpected error in sendHttp API')
      // )
    }
    xhr.send()
  },

  /**
   * fetch
   * use stream.fetch to request for a json file, a plain text file or
   * a arraybuffer for a file stream. (You can use Blob and FileReader
   * API implemented by most modern browsers to read a arraybuffer.)
   * @param  {object} options config options
   *   - method {string} 'GET' | 'POST'
   *   - headers {obj}
   *   - url {string}
   *   - mode {string} 'cors' | 'no-cors' | 'same-origin' | 'navigate'
   *   - body
   *   - type {string} 'json' | 'jsonp' | 'text'
   * @param  {string} callbackId
   * @param  {string} progressCallbackId
   */
  fetch: function (options, callbackId, progressCallbackId) {
    const DEFAULT_METHOD = 'GET'
    const DEFAULT_MODE = 'cors'
    const DEFAULT_TYPE = 'text'

    const methodOptions = ['GET', 'POST']
    const modeOptions = ['cors', 'no-cors', 'same-origin', 'navigate']
    const typeOptions = ['text', 'json', 'jsonp', 'arraybuffer']

    // const fallback = false  // fallback from 'fetch' API to XHR.
    const sender = this.sender

    const config = utils.extend({}, options)

    // validate options.method
    if (typeof config.method === 'undefined') {
      config.method = DEFAULT_METHOD
      logger.warn('options.method for \'fetch\' API has been set to '
        + 'default value \'' + config.method + '\'')
    }
    else if (methodOptions.indexOf((config.method + '')
        .toUpperCase()) === -1) {
      return logger.error('options.method \''
        + config.method
        + '\' for \'fetch\' API should be one of '
        + methodOptions + '.')
    }

    // validate options.url
    if (!config.url) {
      return logger.error('options.url should be set for \'fetch\' API.')
    }

    // validate options.mode
    if (typeof config.mode === 'undefined') {
      config.mode = DEFAULT_MODE
    }
    else if (modeOptions.indexOf((config.mode + '').toLowerCase()) === -1) {
      return logger.error('options.mode \''
        + config.mode
        + '\' for \'fetch\' API should be one of '
        + modeOptions + '.')
    }

    // validate options.type
    if (typeof config.type === 'undefined') {
      config.type = DEFAULT_TYPE
      logger.warn('options.type for \'fetch\' API has been set to '
        + 'default value \'' + config.type + '\'.')
    }
    else if (typeOptions.indexOf((config.type + '').toLowerCase()) === -1) {
      return logger.error('options.type \''
          + config.type
          + '\' for \'fetch\' API should be one of '
          + typeOptions + '.')
    }

    // validate options.headers
    config.headers = config.headers || {}
    if (!utils.isPlainObject(config.headers)) {
      return logger.error('options.headers should be a plain object')
    }

    // validate options.body
    const body = config.body
    if (!config.headers['Content-Type'] && body) {
      if (utils.isPlainObject(body)) {
        // is a json data
        try {
          config.body = JSON.stringify(body)
          config.headers['Content-Type'] = TYPE_JSON
        }
        catch (e) {}
      }
      else if (utils.getType(body) === 'string' && body.match(REG_FORM)) {
        // is form-data
        config.body = encodeURI(body)
        config.headers['Content-Type'] = TYPE_FORM
      }
    }

    const _callArgs = [config, function (res) {
      sender.performCallback(callbackId, res)
    }]
    if (progressCallbackId) {
      _callArgs.push(function (res) {
        // Set 'keepAlive' to true for sending continuous callbacks
        sender.performCallback(progressCallbackId, res, true)
      })
    }

    if (config.type === 'jsonp') {
      _jsonp.apply(this, _callArgs)
    }
    else {
      _xhr.apply(this, _callArgs)
    }
  }

}

stream._meta = {
  stream: [{
    name: 'sendHttp',
    args: ['object', 'function']
  }, {
    name: 'fetch',
    args: ['object', 'function', 'function']
  }]
}

module.exports = stream
<|endoftext|>


<commit_before>/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Definitions for the JSON specification.
 * @see http://www.json.org/json2.js.
 * @externs
 */

var JSON = {};

/**
 * @param {string} jsonStr The string to parse.
 * @param {(function(string, *) : *)=} opt_reviver
 * @return {*} The JSON object.
 */
JSON.parse = function(jsonStr, opt_reviver) {};

/**
 * @param {*} jsonObj Input object.
 * @param {(Array.<string>|(function(string, *) : *)|null)=} opt_replacer
 * @param {(number|string)=} opt_space
 * @return {string} json string which represents jsonObj.
 */
JSON.stringify = function(jsonObj, opt_replacer, opt_space) {};
<commit_msg><commit_after>/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Definitions for the JSON specification.
 * @see http://www.json.org/json2.js.
 * @externs
 */

var JSON = {};

/**
 * @param {string} jsonStr The string to parse.
 * @param {(function(string, *) : *)=} opt_reviver
 * @return {*} The JSON object.
 */
JSON.parse = function(jsonStr, opt_reviver) {};

/**
 * @param {*} jsonObj Input object.
 * @param {(Array.<string>|(function(string, *) : *)|null)=} opt_replacer
 * @param {(number|string)=} opt_space
 * @return {string} json string which represents jsonObj.
 */
JSON.stringify = function(jsonObj, opt_replacer, opt_space) {};

/**
 * As per EcmaScript 5, 15.12.3.
 * @param {string=} opt_key The JSON key for this object.
 * @return {string} The string representation of the object.
 */
Object.prototype.toJSON = function(key) {};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { FormattedDate, FormattedRelative } from 'react-intl';

import './MessageList.scss';
import MessageGroup from './MessageGroup';
import { diffDays } from '../helpers/dateHelpers';
import { propMessageDateGroup } from './messageGroupHelpers';

export default class MessageDateGroup extends Component {
  static propTypes = {
    model: propMessageDateGroup.isRequired,
  };

  renderDay() {
    if (diffDays(new Date(), this.props.model.day) < 2) {
      return (
        <FormattedRelative
          value={this.props.model.day}
          units="day"
        />
      );
    }

    return (
      <FormattedDate
        value={this.props.model.day}
        year="numeric"
        month="long"
        day="numeric"
      />
    );
  }

  render() {
    const day = this.renderDay();
    return (

              {day}

        {this.props.model.messages.map((userGroup, i) => (
          <MessageGroup
            key={[userGroup.key, i]}
            model={userGroup.messages}
          />
        ))}

    );
  }
}
<commit_msg>Reduce date size<commit_after>import React, { Component } from 'react';
import { FormattedDate, FormattedRelative } from 'react-intl';

import './MessageList.scss';
import MessageGroup from './MessageGroup';
import { diffDays } from '../helpers/dateHelpers';
import { propMessageDateGroup } from './messageGroupHelpers';

export default class MessageDateGroup extends Component {
  static propTypes = {
    model: propMessageDateGroup.isRequired,
  };

  renderDay() {
    if (diffDays(new Date(), this.props.model.day) < 2) {
      return (
        <FormattedRelative
          value={this.props.model.day}
          units="day"
        />
      );
    }

    return (
      <FormattedDate
        value={this.props.model.day}
        year="numeric"
        month="long"
        day="numeric"
      />
    );
  }

  render() {
    const day = this.renderDay();
    return (

              {day}

        {this.props.model.messages.map((userGroup, i) => (
          <MessageGroup
            key={[userGroup.key, i]}
            model={userGroup.messages}
          />
        ))}

    );
  }
}
<|endoftext|>


<commit_before>window.GraphView = Backbone.View.extend({

    tagName: 'div',
	className: 'graph-view',

    events: {
    },

    initialize: function(options) {
	    this.template = _.template(tpl.get('graph'));
		this.vent = options.vent;
		$(window).bind("resize", _.bind(this.resize, this));

		_.bindAll(this, "drawGraph");
		this.vent.bind("drawGraph", this.drawGraph);

		this.collections = {};
		this.seriesData = [];
		this.graphData = [];
    },

    render: function() {
		$(this.el).html(this.template());
        return this;
    },

	addCollection: function(id, collection)
	{
		var self = this;
		this.collections[id] = collection;
		this.collections[id].bind('reset', this.reset, this);
		this.collections[id].bind('add', this.addOne, this);
		this.addCollectionToGraph(this.collections[id]);
	},

	addCollectionToGraph: function(collection)
	{
		var self = this;

		var currCollection = collection.collectionId;

		//console.log(collection);

		collection.each(function(model) {
			self.addOne(model, currCollection);
		});

		this.graphData.sort(function(a, b){
		 return a.epoch-b.epoch
		});
	},

	resize: function()
	{
		//Replace with a graph update when Rickshaw.js is updated
		this.drawGraph();
	},

	updateGraph: function()
	{
		this.graph.update();
	},

	drawGraph: function()
	{
		// $.each(this.graphData, function(key, val) {
		// 	console.log(val.date);
		// });

		this.seriesData.push(this.graphData);

		var self = this;
		this.$('#chart').empty();
		this.$('#legendContainer').empty();
		this.$('#legend').empty();
		this.$('#smoother').empty();

		this.graph = new Rickshaw.Graph( {
			element: $('#chart').get(0),
			width: $('#graphContainer').width(),
			height: 300,
			renderer: 'area',
			series: [
				{
					color: "steelblue",
					data: this.seriesData[0],
					name: 'Earthquakes'
				}
			]
		} );

		var hoverDetail = new Rickshaw.Graph.HoverDetail( {
			graph: this.graph
		});

		var yAxis = new Rickshaw.Graph.Axis.Y({
		    graph: this.graph,
		    tickFormat: Rickshaw.Fixtures.Number.formatKMBT
		});

		yAxis.render();

		var time = new Rickshaw.Fixtures.Time();
		var years = time.unit('year');
		var xAxis = new Rickshaw.Graph.Axis.Time({
				    graph: this.graph,
				    timeUnit: years
				});

				xAxis.render();

		var slider = new Rickshaw.Graph.RangeSlider( {
			graph: this.graph,
			element: $('#slider')
		});

		var controls = new RenderControls( {
			element: $('#side_panel').get(0),
			graph: this.graph
		} );

		this.graph.render();

		this.$('#slider').css('margin-left',7)
		this.$('#slider').width($('#graphContainer').width() - 30);
	},

    addOne: function(model, pointCollectionId) {
		var self = this;

		//Prep point for graph
		var collectionId = pointCollectionId;
		var name = model.get('name');

		var location = model.attributes.loc;
		var lon = location[0];
		var lat = location[1];

		var val = model.attributes.val;

		var colorlow = model.attributes.colorlow;
		var colorhigh = model.attributes.colorhigh;
		var date = model.attributes.date;

		//Set min/max values
		var maxVal = this.collections[collectionId].maxVal;
		var minVal = this.collections[collectionId].minVal;

		normVal = val/maxVal;

		epoch = new Date(date).getTime()/1000;

		var data = { x: Number(epoch), y: Number(normVal), date: date, color:this};
		//Need to pull color from params
		//console.log(this.collections[collectionId]);

		console.log('--- data');
		console.log(data);
		this.graphData.push(data);
    },

	reset: function(model) {
		//this.removeCollectionFromMap(model);
		if(model.length > 0)
			console.log('add collection to graph: reset')
			//this.addCollectionToMap(this.collections[model.collectionId]);
	},
});<commit_msg>Updates to graph view<commit_after>window.GraphView = Backbone.View.extend({

    tagName: 'div',
	className: 'graph-view',

    events: {
    },

    initialize: function(options) {
	    this.template = _.template(tpl.get('graph'));
		this.vent = options.vent;
		$(window).bind("resize", _.bind(this.resize, this));

		_.bindAll(this, "drawGraph");
		this.vent.bind("drawGraph", this.drawGraph);

		this.collections = {};
		this.seriesData = [];
		this.graphData = [];
    },

    render: function() {
		$(this.el).html(this.template());
        return this;
    },

	addCollection: function(id, collection)
	{
		var self = this;
		this.collections[id] = collection;
		this.collections[id].bind('reset', this.reset, this);
		this.collections[id].bind('add', this.addOne, this);
		this.addCollectionToGraph(this.collections[id]);
	},

	addCollectionToGraph: function(collection)
	{
		var self = this;

		var currCollection = collection.collectionId;

		//console.log(collection);

		collection.each(function(model) {
			self.addOne(model, currCollection);
		});

		this.graphData.sort(function(a, b){
		 return a.epoch-b.epoch
		});
	},

	resize: function()
	{
		//Replace with a graph update when Rickshaw.js is updated
		this.drawGraph();
	},

	updateGraph: function()
	{
		this.graph.update();
	},

	drawGraph: function()
	{
		// $.each(this.graphData, function(key, val) {
		// 	console.log(val.date);
		// });

		this.seriesData.push(this.graphData);

		var self = this;
		this.$('#chart').empty();
		this.$('#legendContainer').empty();
		this.$('#legend').empty();
		this.$('#smoother').empty();

		this.graph = new Rickshaw.Graph( {
			element: $('#chart').get(0),
			width: $('#graphContainer').width(),
			height: 300,
			renderer: 'area',
			series: [
				{
					color: "steelblue",
					data: this.seriesData[0],
					name: 'Earthquakes'
				}
			]
		} );

		var hoverDetail = new Rickshaw.Graph.HoverDetail( {
			graph: this.graph
		});

		var yAxis = new Rickshaw.Graph.Axis.Y({
		    graph: this.graph,
		    tickFormat: Rickshaw.Fixtures.Number.formatKMBT
		});

		yAxis.render();

		var time = new Rickshaw.Fixtures.Time();
		var years = time.unit('year');
		var xAxis = new Rickshaw.Graph.Axis.Time({
				    graph: this.graph,
				    timeUnit: years
				});

				xAxis.render();

		var slider = new Rickshaw.Graph.RangeSlider( {
			graph: this.graph,
			element: $('#slider')
		});

		var controls = new RenderControls( {
			element: $('#side_panel').get(0),
			graph: this.graph
		} );

		this.graph.render();

		this.$('#slider').css('margin-left',7)
		this.$('#slider').width($('#graphContainer').width() - 30);
	},

    addOne: function(model, pointCollectionId) {
		var self = this;

		//Prep point for graph
		var collectionId = pointCollectionId;
		var name = model.get('name');

		var location = model.attributes.loc;
		var lon = location[0];
		var lat = location[1];

		var val = model.attributes.val;

		var colorlow = model.attributes.colorlow;
		var colorhigh = model.attributes.colorhigh;
		var date = model.attributes.date;

		//console.log(date);
		var d = Date.parse(model.attributes.date);

		//console.log(model);

		//Set min/max values
		var maxVal = this.collections[collectionId].maxVal;
		var minVal = this.collections[collectionId].minVal;

		normVal = val/maxVal;

		epoch = new Date(date).getTime()/1000;

		var data = { x: Number(epoch), y: Number(normVal), date: date, color:this};
		//Need to pull color from params

		//this.graphData.push(data);
    },

	reset: function(model) {
		//this.removeCollectionFromMap(model);
		if(model.length > 0)
			console.log('add collection to graph: reset')
			//this.addCollectionToMap(this.collections[model.collectionId]);
	},
});<|endoftext|>


<commit_before>import logger from 'chayns-logger';
import htmlToElement from 'html-to-element';
import { chaynsInfo, setSelectedTapp } from '../chayns-info';
import { resetCallback } from '../json-chayns-call/calls/access-token-status-change';
import FloatingButton from '../ui/floating-button';
import WaitCursor from '../ui/wait-cursor';
import { getUrlParameters } from '../utils/url-parameter';
import { parameterStringToObject } from '../utils/convert';
import ConsoleLogger from '../utils/console-logger';

const loggerLoadTappById = new ConsoleLogger('loadTappById(custom-tapp.js)');
const loggerLoadTapp = new ConsoleLogger('loadTapp(custom-tapp.js)');

const $bodyContent = document.querySelector('.body-content');

/**
 * Loads Tapp by TappId.
 * @param {Number} tappId
 */
export default function loadTappById(tappId) {
    FloatingButton.hide();
    WaitCursor.hide();

    const tapp = getTappById(tappId);
    if (tapp) {
        setSelectedTapp(tapp);
        resetCallback();
        loadTapp(tapp.id, setUrlParams(tapp.url), tapp.postTobitAccessToken);
    } else {
        logger.warning({
            message: 'no tapp found',
            customNumber: tappId,
            fileName: 'custom-tapp.js',
            section: 'loadTapp'
        });
        loggerLoadTappById.warn('No Tapp found!');
    }
}

/**
 * Returns the tapp to tappId
 * @param tappId
 * @returns {*}
 */
export function getTappById(tappId) {
    return chaynsInfo.Tapps.find(tapp => tapp.id === tappId) || null;
}

/**
 * replaces url parameters with chayns env, removes double params, removes empty params, adds non system urlParameter from cnrt
 * @param {string} url
 * @returns {string} url
 */
function setUrlParams(url) {
    url = url.replace(/##apname##/ig, chaynsInfo.LocationName);
    url = url.replace(/##siteid##/ig, chaynsInfo.SiteID);
    url = url.replace(/##os##/ig, 'chaynsnet-runtime');
    url = url.replace(/##version##/ig, chaynsInfo.getGlobalData().AppInfo.Version);
    url = url.replace(/##colormode##/ig, chaynsInfo.ColorMode.toString());
    url = url.replace(/##color##/ig, chaynsInfo.Color.replace('#', ''));
    url = url.replace(/##adminmode##/ig, (chaynsInfo.AdminMode ? 1 : 0).toString());
    url = url.replace(/##tobituserid##/ig, chaynsInfo.User.ID.toString());

    if (chaynsInfo.User !== undefined && chaynsInfo.User.ID !== '' && chaynsInfo.User.ID > 0) {
        url = url.replace(/##firstname##/ig, chaynsInfo.User.FirstName);
        url = url.replace(/##lastname##/ig, chaynsInfo.User.LastName);
    }

    url = url.replace(/##.*?##/g, ''); // removes unused parameters

    const urlParam = Object.assign(getUrlParameters(false), parameterStringToObject(url));

    const paramString = Object.keys(urlParam).map(key => (urlParam[key] !== undefined ? `${key}=${urlParam[key]}` : key));
    const timeStamp = url.match(/(?:_=)\b(\d*)/i);

    return `${url.split('?')[0]}?${paramString.join('&')}${(!timeStamp) ? `&_=${Date.now()}` : ''}`;
}

/**
 * loads an url by tapp id and creates the iframe
 * @param {number} tappId
 * @param {string} tappUrl
 * @param {boolean} postTobitAccessToken
 */
function loadTapp(tappId, tappUrl, postTobitAccessToken) {
    if (typeof tappId !== 'number') {
        tappId = parseInt(tappId, 10);
        if (Number.isNaN(tappId)) {
            loggerLoadTapp.error('TappId is not a number');
            return;
        }
    }
    if (!tappUrl || typeof tappUrl !== 'string') {
        loggerLoadTapp.error('TappUrl is not a string');
        return;
    }

    const $input = htmlToElement(`<input id="ActiveTappID" name="ActiveTappID" type="hidden" value="${tappId}">`);

    const $form = htmlToElement(`<form action="${tappUrl}" target="TappIframe" method="get" id="TobitAccessTokenForm"></form>`);
    if (postTobitAccessToken && chaynsInfo.User.TobitAccessToken) {
        $form.setAttribute('method', 'post');
        const $hiddenField = document.createElement('input');
        $hiddenField.setAttribute('type', 'hidden');
        $hiddenField.setAttribute('name', 'TobitAccessToken');
        $hiddenField.setAttribute('value', chaynsInfo.User.TobitAccessToken);
        $form.appendChild($hiddenField);
    }

    const parameter = parameterStringToObject(tappUrl);
    for (const key of Object.keys(parameter)) {
        $form.appendChild(htmlToElement(`<input name="${key}" value="${parameter[key]}" type="hidden">`));
    }

    const $iframe = htmlToElement('');
    $iframe.style.height = `${(window.innerHeight - document.body.getBoundingClientRect().top) + document.body.scrollTop}px`;

    if (chaynsInfo.IsMobile) {
        $iframe.setAttribute('style', 'margin-top: -10px !important;');
    }

    if (chaynsInfo.ExclusiveMode || chaynsInfo.fullSizeMode) {
        $bodyContent.classList.add('body-content--exclusive-view');
    } else {
        $bodyContent.classList.remove('body-content--exclusive-view');
    }

    $bodyContent.innerHTML = '';
    $bodyContent.appendChild($input);
    $bodyContent.appendChild($form);
    $bodyContent.appendChild($iframe);

    if ($form.length > 0) {
        $form.submit();
    }
}
<commit_msg>Add contentWidth-parameter in postTobitAccessToken<commit_after>import logger from 'chayns-logger';
import htmlToElement from 'html-to-element';
import { chaynsInfo, setSelectedTapp } from '../chayns-info';
import { resetCallback } from '../json-chayns-call/calls/access-token-status-change';
import FloatingButton from '../ui/floating-button';
import WaitCursor from '../ui/wait-cursor';
import { getUrlParameters } from '../utils/url-parameter';
import { parameterStringToObject } from '../utils/convert';
import ConsoleLogger from '../utils/console-logger';

const loggerLoadTappById = new ConsoleLogger('loadTappById(custom-tapp.js)');
const loggerLoadTapp = new ConsoleLogger('loadTapp(custom-tapp.js)');

const $bodyContent = document.querySelector('.body-content');

/**
 * Loads Tapp by TappId.
 * @param {Number} tappId
 */
export default function loadTappById(tappId) {
    FloatingButton.hide();
    WaitCursor.hide();

    const tapp = getTappById(tappId);
    if (tapp) {
        setSelectedTapp(tapp);
        resetCallback();
        loadTapp(tapp.id, setUrlParams(tapp.url), tapp.postTobitAccessToken);
    } else {
        logger.warning({
            message: 'no tapp found',
            customNumber: tappId,
            fileName: 'custom-tapp.js',
            section: 'loadTapp'
        });
        loggerLoadTappById.warn('No Tapp found!');
    }
}

/**
 * Returns the tapp to tappId
 * @param tappId
 * @returns {*}
 */
export function getTappById(tappId) {
    return chaynsInfo.Tapps.find(tapp => tapp.id === tappId) || null;
}

/**
 * replaces url parameters with chayns env, removes double params, removes empty params, adds non system urlParameter from cnrt
 * @param {string} url
 * @returns {string} url
 */
function setUrlParams(url) {
    url = url.replace(/##apname##/ig, chaynsInfo.LocationName);
    url = url.replace(/##siteid##/ig, chaynsInfo.SiteID);
    url = url.replace(/##os##/ig, 'chaynsnet-runtime');
    url = url.replace(/##version##/ig, chaynsInfo.getGlobalData().AppInfo.Version);
    url = url.replace(/##colormode##/ig, chaynsInfo.ColorMode.toString());
    url = url.replace(/##color##/ig, chaynsInfo.Color.replace('#', ''));
    url = url.replace(/##adminmode##/ig, (chaynsInfo.AdminMode ? 1 : 0).toString());
    url = url.replace(/##tobituserid##/ig, chaynsInfo.User.ID.toString());

    if (chaynsInfo.User !== undefined && chaynsInfo.User.ID !== '' && chaynsInfo.User.ID > 0) {
        url = url.replace(/##firstname##/ig, chaynsInfo.User.FirstName);
        url = url.replace(/##lastname##/ig, chaynsInfo.User.LastName);
    }

    url = url.replace(/##.*?##/g, ''); // removes unused parameters

    const urlParam = Object.assign(getUrlParameters(false), parameterStringToObject(url));

    const paramString = Object.keys(urlParam).map(key => (urlParam[key] !== undefined ? `${key}=${urlParam[key]}` : key));
    const timeStamp = url.match(/(?:_=)\b(\d*)/i);

    return `${url.split('?')[0]}?${paramString.join('&')}${(!timeStamp) ? `&_=${Date.now()}` : ''}`;
}

/**
 * loads an url by tapp id and creates the iframe
 * @param {number} tappId
 * @param {string} tappUrl
 * @param {boolean} postTobitAccessToken
 */
function loadTapp(tappId, tappUrl, postTobitAccessToken) {
    if (typeof tappId !== 'number') {
        tappId = parseInt(tappId, 10);
        if (Number.isNaN(tappId)) {
            loggerLoadTapp.error('TappId is not a number');
            return;
        }
    }
    if (!tappUrl || typeof tappUrl !== 'string') {
        loggerLoadTapp.error('TappUrl is not a string');
        return;
    }

    const $input = htmlToElement(`<input id="ActiveTappID" name="ActiveTappID" type="hidden" value="${tappId}">`);

    const $form = htmlToElement(`<form action="${tappUrl}" target="TappIframe" method="get" id="TobitAccessTokenForm"></form>`);
    if (postTobitAccessToken && chaynsInfo.User.TobitAccessToken) {
        $form.setAttribute('method', 'post');
        const $hiddenField = document.createElement('input');
        $hiddenField.setAttribute('type', 'hidden');
        $hiddenField.setAttribute('name', 'TobitAccessToken');
        $hiddenField.setAttribute('value', chaynsInfo.User.TobitAccessToken);
        $form.appendChild($hiddenField);
    }

    const parameter = parameterStringToObject(tappUrl);
    for (const key of Object.keys(parameter)) {
        $form.appendChild(htmlToElement(`<input name="${key}" value="${parameter[key]}" type="hidden">`));
    }

    const $iframe = htmlToElement('');
    $iframe.style.height = `${(window.innerHeight - document.body.getBoundingClientRect().top) + document.body.scrollTop}px`;

    if (chaynsInfo.IsMobile) {
        $iframe.setAttribute('style', 'margin-top: -10px !important;');
    }

    if (chaynsInfo.ExclusiveMode || chaynsInfo.fullSizeMode) {
        $bodyContent.classList.add('body-content--exclusive-view');
    } else {
        $bodyContent.classList.remove('body-content--exclusive-view');
    }
    $form.action = `${$form.action}&contentWidth=${$bodyContent.offsetWidth}`;

    $bodyContent.innerHTML = '';
    $bodyContent.appendChild($input);
    $bodyContent.appendChild($form);
    $bodyContent.appendChild($iframe);

    if ($form.length > 0) {
        $form.submit();
    }
}
<|endoftext|>


<commit_before>(function (angular, _, $, TL) {
  'use strict';

  function CartController($scope, $timeout, cart) {
    var vm = this;
    vm.show = false;
    vm.projects = [];
    vm.remote = [];
    vm.count = 0;
    vm.collapsed = {};
    vm.term = '';

    $scope.$on('cart.update', function () {
      getCart(false);
    });

    function getCart(collapse) {
      cart.all()
        .then(function (data) {
          vm.count = 0;
          vm.projects = data.projects;
          vm.remote = data.remote;
          _.each(vm.projects, function (p) {
            vm.count += p.samples.length;
            // Sort the samples by created date.
            p.samples.sort(function (a, b) {
              return b.createdDate -a.createdDate > 0;
            });
            if (collapse) {
              vm.collapsed[p.id] = true;
            }
          });
          vm.count += vm.getRemoteCount();
          if (collapse) {
            vm.collapsed.remote = true;
          }
        });
    }

    vm.getRemoteCount = function () {
      return Object.keys(vm.remote).length;
    };

    getCart(true);
  }

  /**
   * Controller for functions on the cart slider
   * @param CartService The cart service to communicate with the server
   */
  function CartSliderController(CartService, $uibModal) {
    var vm = this;

    vm.clear = function () {
      CartService.clear();
    };

    vm.removeProject = function (projectId) {
      CartService.removeProject(projectId);
    };

    vm.removeRemoteSamples = function () {
      CartService.removeRemoteSamples();
    };

    vm.removeRemoteSample = function (sampleUrl) {
      CartService.removeRemoteSample(sampleUrl);
    };

    vm.removeSample = function (projectId, sampleId) {
      CartService.removeSample(projectId, sampleId);
    };

    vm.exportToGalaxy = function () {
      CartService.all()
        .then(function (data) {
          if (data !== null) {
            var firstProjID = data.projects[0].id;

            $uibModal.open({
              templateUrl: TL.BASE_URL + 'cart/template/galaxy/project/' + firstProjID,
              controller: 'GalaxyDialogCtrl as gCtrl',
              resolve: {
                openedByCart: function () {
                  return true;
                },
                multiProject: function () {
                  return (data.length > 1);
                }
              }
            });
          }
        });
    };
  }

  function CartDirective() {
    return {
      restrict: 'E',
      templateUrl: '/cart.html',
      replace: true,
      controllerAs: 'cart',
      controller: ['$scope', '$timeout', 'CartService', CartController]
    };
  }

  function CartService(scope, $http, notifications) {
    var svc = this,
      urls = {
        all: TL.BASE_URL + 'cart',
        add: TL.BASE_URL + 'cart/add/samples',
        addRemote: TL.BASE_URL + 'cart/add/samples/remote',
        removeRemote: TL.BASE_URL + 'cart/remove/samples/remote',
        project: TL.BASE_URL + 'cart/project/'
      };

    svc.all = function () {
      return $http.get(urls.all)
        .then(function (response) {
          if (response.data) {
            return {projects: response.data.projects, remote: response.data.remote};
          } else {
            return [];
          }
        });
    };

    svc.add = function (projectId, samples) {
      return $http.post(urls.add, {projectId: projectId, sampleIds: samples})
          .then(function(result) {
            scope.$emit('cart.update');
            notifications.show({msg: result.data.message});
          });
    };

    svc.clear = function () {
      //fire a DELETE to the server on the cart then broadcast the cart update event
      return $http.delete(urls.all).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

    svc.removeProject = function (projectId) {
      return $http.delete(urls.project + projectId).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

    svc.removeSample = function (projectId, sampleId) {
      return $http.delete(urls.project + projectId + '/samples/' + sampleId).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

    svc.removeRemoteSamples = function () {
      return $http.delete(urls.removeRemote).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

    svc.removeRemoteSample = function (sampleURL) {
      return $http.post(urls.removeRemote, {sampleURL: sampleURL}).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

  }

  function GalaxyExportService(CartService, $http) {
    var svc = this,
      samples = [];

    function addSampleFile(sampleName, sampleFilePath) {
      var sample = _.find(samples, function (sampleItr) {
        return (sampleItr.name === sampleName);
      });
      if (typeof sample === 'undefined') {
        sample = {
          'name': sampleName,
          '_links': {'self': {'href': ''}}, //expected by the tool
          '_embedded': {'sample_files': []}
        };
        samples.push(sample);
      }
      sample._embedded.sample_files.push({'_links': {'self': {'href': sampleFilePath}}});
    }

    function getSampleFormEntities(args) {
      var defaults = {
          addtohistory: false,
          makepairedcollection: false
        },
        p = _.extend({}, defaults, args),
        params = {
        '_embedded': {
          'library': {'name': p.name},
          'user': {'email': p.email},
          'addtohistory': p.addtohistory,
          'makepairedcollection': p.makepairedcollection,
          'oauth2': {
            'code': p.authToken,
            'redirect': p.redirectURI
          },
          'samples': samples
        }
      };
      return [{
        'name': 'json_params',
        'value': JSON.stringify(params)
      }];
    }

    svc.exportFromProjSampPage = function (args, ids) {
      // Need to get an actual list of samples from the server from their ids.
      return $http.get(PAGE.urls.samples.idList + "?" + $.param({sampleIds: ids}))
        .then(function (result) {
          _.each(samples, function (sample) {
              addSampleFile(sample.sample.label, sample.href);
          });
          return getSampleFormEntities(args);
        });
    };

    svc.exportFromCart = function (args) {
      return CartService.all()
        .then(function (data) {
          var projects = data.projects;
          _.each(projects, function (project) {
            var samples = project.samples;
            _.each(samples, function (sample) {
              addSampleFile(sample.label, sample.href);
            });
          });
          return getSampleFormEntities(args);
        });
    };
  }

  function GalaxyDialogCtrl($uibModalInstance, $timeout, $scope, CartService, GalaxyExportService, openedByCart, multiProject, sampleIds) {
    var vm = this;
    vm.addtohistory=true;
    vm.makepairedcollection=true;
    vm.showOauthIframe = false;
    vm.showEmailLibInput = true;
    vm.redirectURI = TL.BASE_URL + 'galaxy/auth_code';

    vm.upload = function () {
      vm.makeOauth2AuthRequest(TL.galaxyClientID);
      vm.showEmailLibInput = false;
      vm.showOauthIframe = true;
    };

    vm.makeOauth2AuthRequest = function (clientID) {
      var request = buildOauth2Request(clientID, 'code', 'read', vm.redirectURI);
      vm.iframeSrc = TL.BASE_URL + 'api/oauth/authorize' + request;
    };

    function buildOauth2Request(clientID, responseType, scope, redirectURI) {
      return '?&client_id=' + clientID + '&response_type=' + responseType + '&scope=' + scope + '&redirect_uri=' + redirectURI;
    }

    $scope.$on('galaxyAuthCode', function (e, authToken) {

      if (authToken) {
        vm.uploading = true;

        vm.showOauthIframe = false;
        vm.showEmailLibInput = true;

        if (openedByCart) {
          GalaxyExportService.exportFromCart({name: vm.name, email: vm.email, addtohistory: vm.addtohistory, makepairedcollection: vm.makepairedcollection, authToken: authToken, redirectURI: vm.redirectURI}).then(sendSampleForm);
        } else {
          sendSampleForm(GalaxyExportService.exportFromProjSampPage({name: vm.name, email: vm.email, addtohistory: vm.addtohistory, makepairedcollection: vm.makepairedcollection, authToken: authToken, redirectURI: vm.redirectURI}, sampleIds));
        }
      }
    });

    function sendSampleForm(sampleFormEntities) {
      vm.sampleFormEntities = sampleFormEntities;

      if (openedByCart) {
        CartService.clear();
      }

      //$timeout is necessary because it adds a new event to the browser event queue,
      //allowing the full form to be generated before it is submitted.

      //Two timeouts are required now--this is starting to look like a real hack.
      $timeout(function () {
        $timeout(function () {
          document.getElementById('galSubFrm').submit();
          vm.close();
        });
      });
    }

    vm.setName = function (name, orgName) {
      if (multiProject) {
        vm.name = orgName;
      } else {
        vm.name = name;
      }
    };
    vm.setEmail = function (email) {
      vm.email = email;
    };
    vm.close = function () {
      $uibModalInstance.close();
    };

  }

  /**
   * @name cartFilter
   * @desc Filters the list of projects in the cart based on the term provided in the search input.
   * @type {Filter}
   */
  function CartFilter() {
    /**
     * @param list - list to filter
     * @param term - search term to use to filter the list.
     */
    return function (list, term) {
      //filter each element in the collection
      return _.filter(list, function (item) {
        //if we have a project, check for how many samples we have left
        if (item.samples) {
          return filterList(item.samples, term).length > 0;
        }
        //if we have an individual sample, filter it
        return filterSample(item, term);

      });
    };

    function filterList(samples, term) {
      return _.filter(samples, function (s) {
        return filterSample(s, term);
      });
    }

    function filterSample(item, term) {
      term = term.toLowerCase();
      return item.label.toLowerCase().indexOf(term) > -1;
    }

  }

  angular
    .module('irida.cart', ["irida.notifications"])
    .service('CartService', ['$rootScope', '$http', "notifications", CartService])
    .controller('CartSliderController', ['CartService', '$uibModal', CartSliderController])
    .controller('GalaxyDialogCtrl', ['$uibModalInstance', '$timeout', '$scope', 'CartService', 'GalaxyExportService', 'openedByCart', 'multiProject', 'sampleIds', GalaxyDialogCtrl])
    .service('GalaxyExportService', ['CartService', '$http', GalaxyExportService])
    .directive('cart', [CartDirective])
    .filter('cartFilter', [CartFilter])
  ;
})(window.angular, window._, window.jQuery, window.TL);
<commit_msg>Fix missing sampleIds[]<commit_after>(function (angular, _, $, TL) {
  'use strict';

  function CartController($scope, $timeout, cart) {
    var vm = this;
    vm.show = false;
    vm.projects = [];
    vm.remote = [];
    vm.count = 0;
    vm.collapsed = {};
    vm.term = '';

    $scope.$on('cart.update', function () {
      getCart(false);
    });

    function getCart(collapse) {
      cart.all()
        .then(function (data) {
          vm.count = 0;
          vm.projects = data.projects;
          vm.remote = data.remote;
          _.each(vm.projects, function (p) {
            vm.count += p.samples.length;
            // Sort the samples by created date.
            p.samples.sort(function (a, b) {
              return b.createdDate -a.createdDate > 0;
            });
            if (collapse) {
              vm.collapsed[p.id] = true;
            }
          });
          vm.count += vm.getRemoteCount();
          if (collapse) {
            vm.collapsed.remote = true;
          }
        });
    }

    vm.getRemoteCount = function () {
      return Object.keys(vm.remote).length;
    };

    getCart(true);
  }

  /**
   * Controller for functions on the cart slider
   * @param CartService The cart service to communicate with the server
   */
  function CartSliderController(CartService, $uibModal) {
    var vm = this;

    vm.clear = function () {
      CartService.clear();
    };

    vm.removeProject = function (projectId) {
      CartService.removeProject(projectId);
    };

    vm.removeRemoteSamples = function () {
      CartService.removeRemoteSamples();
    };

    vm.removeRemoteSample = function (sampleUrl) {
      CartService.removeRemoteSample(sampleUrl);
    };

    vm.removeSample = function (projectId, sampleId) {
      CartService.removeSample(projectId, sampleId);
    };

    vm.exportToGalaxy = function () {
      CartService.all()
        .then(function (data) {
          if (data !== null) {
            var firstProjID = data.projects[0].id;

            $uibModal.open({
              templateUrl: TL.BASE_URL + 'cart/template/galaxy/project/' + firstProjID,
              controller: 'GalaxyDialogCtrl as gCtrl',
              resolve: {
                openedByCart: function () {
                  return true;
                },
                multiProject: function () {
                  return (data.length > 1);
                }
              }
            });
          }
        });
    };
  }

  function CartDirective() {
    return {
      restrict: 'E',
      templateUrl: '/cart.html',
      replace: true,
      controllerAs: 'cart',
      controller: ['$scope', '$timeout', 'CartService', CartController]
    };
  }

  function CartService(scope, $http, notifications) {
    var svc = this,
      urls = {
        all: TL.BASE_URL + 'cart',
        add: TL.BASE_URL + 'cart/add/samples',
        addRemote: TL.BASE_URL + 'cart/add/samples/remote',
        removeRemote: TL.BASE_URL + 'cart/remove/samples/remote',
        project: TL.BASE_URL + 'cart/project/'
      };

    svc.all = function () {
      return $http.get(urls.all)
        .then(function (response) {
          if (response.data) {
            return {projects: response.data.projects, remote: response.data.remote};
          } else {
            return [];
          }
        });
    };

    svc.add = function (projectId, samples) {
      return $http.post(urls.add, {projectId: projectId, sampleIds: samples})
          .then(function(result) {
            scope.$emit('cart.update');
            notifications.show({msg: result.data.message});
          });
    };

    svc.clear = function () {
      //fire a DELETE to the server on the cart then broadcast the cart update event
      return $http.delete(urls.all).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

    svc.removeProject = function (projectId) {
      return $http.delete(urls.project + projectId).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

    svc.removeSample = function (projectId, sampleId) {
      return $http.delete(urls.project + projectId + '/samples/' + sampleId).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

    svc.removeRemoteSamples = function () {
      return $http.delete(urls.removeRemote).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

    svc.removeRemoteSample = function (sampleURL) {
      return $http.post(urls.removeRemote, {sampleURL: sampleURL}).then(function () {
        scope.$broadcast('cart.update', {});
      });
    };

  }

  function GalaxyExportService(CartService, $http) {
    var svc = this,
      samples = [];

    function addSampleFile(sampleName, sampleFilePath) {
      var sample = _.find(samples, function (sampleItr) {
        return (sampleItr.name === sampleName);
      });
      if (typeof sample === 'undefined') {
        sample = {
          'name': sampleName,
          '_links': {'self': {'href': ''}}, //expected by the tool
          '_embedded': {'sample_files': []}
        };
        samples.push(sample);
      }
      sample._embedded.sample_files.push({'_links': {'self': {'href': sampleFilePath}}});
    }

    function getSampleFormEntities(args) {
      var defaults = {
          addtohistory: false,
          makepairedcollection: false
        },
        p = _.extend({}, defaults, args),
        params = {
        '_embedded': {
          'library': {'name': p.name},
          'user': {'email': p.email},
          'addtohistory': p.addtohistory,
          'makepairedcollection': p.makepairedcollection,
          'oauth2': {
            'code': p.authToken,
            'redirect': p.redirectURI
          },
          'samples': samples
        }
      };
      return [{
        'name': 'json_params',
        'value': JSON.stringify(params)
      }];
    }

    svc.exportFromProjSampPage = function (args, ids) {
      // Need to get an actual list of samples from the server from their ids.
      return $http.get(PAGE.urls.samples.idList + "?" + $.param({"sampleIds[]": ids}))
        .then(function (result) {
          _.each(samples, function (sample) {
              addSampleFile(sample.sample.label, sample.href);
          });
          return getSampleFormEntities(args);
        });
    };

    svc.exportFromCart = function (args) {
      return CartService.all()
        .then(function (data) {
          var projects = data.projects;
          _.each(projects, function (project) {
            var samples = project.samples;
            _.each(samples, function (sample) {
              addSampleFile(sample.label, sample.href);
            });
          });
          return getSampleFormEntities(args);
        });
    };
  }

  function GalaxyDialogCtrl($uibModalInstance, $timeout, $scope, CartService, GalaxyExportService, openedByCart, multiProject, sampleIds) {
    var vm = this;
    vm.addtohistory=true;
    vm.makepairedcollection=true;
    vm.showOauthIframe = false;
    vm.showEmailLibInput = true;
    vm.redirectURI = TL.BASE_URL + 'galaxy/auth_code';

    vm.upload = function () {
      vm.makeOauth2AuthRequest(TL.galaxyClientID);
      vm.showEmailLibInput = false;
      vm.showOauthIframe = true;
    };

    vm.makeOauth2AuthRequest = function (clientID) {
      var request = buildOauth2Request(clientID, 'code', 'read', vm.redirectURI);
      vm.iframeSrc = TL.BASE_URL + 'api/oauth/authorize' + request;
    };

    function buildOauth2Request(clientID, responseType, scope, redirectURI) {
      return '?&client_id=' + clientID + '&response_type=' + responseType + '&scope=' + scope + '&redirect_uri=' + redirectURI;
    }

    $scope.$on('galaxyAuthCode', function (e, authToken) {

      if (authToken) {
        vm.uploading = true;

        vm.showOauthIframe = false;
        vm.showEmailLibInput = true;

        if (openedByCart) {
          GalaxyExportService.exportFromCart({name: vm.name, email: vm.email, addtohistory: vm.addtohistory, makepairedcollection: vm.makepairedcollection, authToken: authToken, redirectURI: vm.redirectURI}).then(sendSampleForm);
        } else {
          sendSampleForm(GalaxyExportService.exportFromProjSampPage({name: vm.name, email: vm.email, addtohistory: vm.addtohistory, makepairedcollection: vm.makepairedcollection, authToken: authToken, redirectURI: vm.redirectURI}, sampleIds));
        }
      }
    });

    function sendSampleForm(sampleFormEntities) {
      vm.sampleFormEntities = sampleFormEntities;

      if (openedByCart) {
        CartService.clear();
      }

      //$timeout is necessary because it adds a new event to the browser event queue,
      //allowing the full form to be generated before it is submitted.

      //Two timeouts are required now--this is starting to look like a real hack.
      $timeout(function () {
        $timeout(function () {
          document.getElementById('galSubFrm').submit();
          vm.close();
        });
      });
    }

    vm.setName = function (name, orgName) {
      if (multiProject) {
        vm.name = orgName;
      } else {
        vm.name = name;
      }
    };
    vm.setEmail = function (email) {
      vm.email = email;
    };
    vm.close = function () {
      $uibModalInstance.close();
    };

  }

  /**
   * @name cartFilter
   * @desc Filters the list of projects in the cart based on the term provided in the search input.
   * @type {Filter}
   */
  function CartFilter() {
    /**
     * @param list - list to filter
     * @param term - search term to use to filter the list.
     */
    return function (list, term) {
      //filter each element in the collection
      return _.filter(list, function (item) {
        //if we have a project, check for how many samples we have left
        if (item.samples) {
          return filterList(item.samples, term).length > 0;
        }
        //if we have an individual sample, filter it
        return filterSample(item, term);

      });
    };

    function filterList(samples, term) {
      return _.filter(samples, function (s) {
        return filterSample(s, term);
      });
    }

    function filterSample(item, term) {
      term = term.toLowerCase();
      return item.label.toLowerCase().indexOf(term) > -1;
    }

  }

  angular
    .module('irida.cart', ["irida.notifications"])
    .service('CartService', ['$rootScope', '$http', "notifications", CartService])
    .controller('CartSliderController', ['CartService', '$uibModal', CartSliderController])
    .controller('GalaxyDialogCtrl', ['$uibModalInstance', '$timeout', '$scope', 'CartService', 'GalaxyExportService', 'openedByCart', 'multiProject', 'sampleIds', GalaxyDialogCtrl])
    .service('GalaxyExportService', ['CartService', '$http', GalaxyExportService])
    .directive('cart', [CartDirective])
    .filter('cartFilter', [CartFilter])
  ;
})(window.angular, window._, window.jQuery, window.TL);
<|endoftext|>


<commit_before>function API() {
  this.version = 0.5;
  this.preferences = SeleniumIDE.Preferences;
  this.id = null;
  this.code = {
    ideExtensions: [],
    userExtensions: [],
    formatters: []
  };
}

API.prototype._save = function () {
  if (this.id) { //Save only if ID has been set
    var found = false;
    var id = this.id;
    var plugins = JSON.parse(this.preferences.getString('pluginsData', '[]'));
    for (var i = 0; i < plugins.length; i++) {
      if (plugins[i].id == id) {
        plugins[i].installed = true;
        plugins[i].code = this.code;
        found = true;
        break;
      }
    }
    if (!found) {
      plugins.push({
        id: this.id,
        installed: true,
        code: this.code,
        options: {
          disabled: false,
          autoDisabled: false
        }
      });
    }
    this.preferences.save({pluginsData: JSON.stringify(plugins)}, 'pluginsData');
  }
};

// add our plugin to the main list of selenium plugins
API.prototype.addPlugin = function (id) {
  this.id = id;
  this._save();
};

//add the provided chrome url to the list of IDE extensions provided through plugins
//-- or not if it already exists
API.prototype.addPluginProvidedIdeExtension = function (url) {
  this.code.ideExtensions.push(url);
  this._save();
};

// add the provided chrome url to the list of user extensions provided through plugins
// -- or not if it already exists
API.prototype.addPluginProvidedUserExtension = function (js_url, xml_url) {
  this.code.userExtensions.push(js_url + ';' + xml_url);
  this._save();
};

// add the formatter at the provided chrome url to the list of other formatters provided by plugins
API.prototype.addPluginProvidedFormatter = function (id, name, url) {
  this.code.formatters.push(id + ";" + name + ";" + url);
  this._save();
};

// cleanup after ourselves
//
// this works because plugins re-register every time the browser restarts
function initializeSeIDEAPIObserver() {
  seIDEAPIObserver.register();
}

var seIDEAPIObserver = {
  _uninstall: false,
  observe: function (subject, topic, data) {
    if (topic == "quit-application-granted") {
      var branch = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.selenium-ide.");
      branch.clearUserPref("pluginProvidedIDEExtensions");
      branch.clearUserPref("pluginProvidedUserExtensions");
      branch.clearUserPref("pluginProvidedFormatters");
      branch.clearUserPref("plugins");
      //Clear the plugin code and leave the options intact as we want to honour it on next load
      if (branch.prefHasUserValue('pluginsData')) {
        var plugins = JSON.parse(branch.getCharPref('pluginsData'));
        for (var i = 0; i < plugins.length; i++) {
          plugins[i].installed = false;
          plugins[i].code = {
            ideExtensions: [],
            userExtensions: [],
            formatters: []
          };
        }
        branch.setCharPref('pluginsData', JSON.stringify(plugins));
      }
      this.unregister();
    }
  },
  register: function () {
    var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
    observerService.addObserver(this, "quit-application-granted", false);
  },
  unregister: function () {
    var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
    observerService.removeObserver(this, "quit-application-granted");
  }
};

//Make the cleanup run one time for each window instead of once for every plugin for every window
if (!window.registeredSEIDEAPIObserver) {
  window.addEventListener("load", initializeSeIDEAPIObserver, false);
  window.registeredSEIDEAPIObserver = true;
}
<commit_msg>Improved Selenium IDE plugin API documentation and added type for formatters<commit_after>function API() {
  this.version = 0.6;
  this.preferences = SeleniumIDE.Preferences;
  this.id = null;
  this.code = {
    ideExtensions: [],
    userExtensions: [],
    formatters: []
  };
}

/**
 * Registers a Selenium IDE plugin so that it can be managed by Selenium IDE
 * Calling this is mandatory or the plugin will not be loaded by Selenium IDE
 *
 * @param id - this is the plugin id (not the name) that you specify in install.rdf of your plugin
 */
API.prototype.addPlugin = function (id) {
  this.id = id;
  this._save();
};

/**
 * Request Selenium IDE to load the IDE extension provided by your plugin through its chrome url of
 * the IDE extensions
 * Don't forget to call the addPlugin function once for your plugin
 *
 * @param url - url to your bundled extension in the form of chrome://
 */
API.prototype.addPluginProvidedIdeExtension = function (url) {
  this.code.ideExtensions.push(url);
  this._save();
};

/**
 * Request Selenium IDE to load the user extension provided by your plugin through its chrome url of
 * the user extensions.
 * Don't forget to call the addPlugin function once for your plugin!
 *
 * @param js_url - url to your bundled extension in the form of chrome://
 * @param xml_url - url to your bundled companion xml in the form of chrome://
 */
API.prototype.addPluginProvidedUserExtension = function (js_url, xml_url) {
  this.code.userExtensions.push(js_url + ';' + xml_url);
  this._save();
};

/**
 * Request Selenium IDE to load the formatter provided by your plugin through its chrome url of
 * the formatter.
 * Don't forget to call the addPlugin function once for your plugin!
 *
 * @param id - an id for your formatter, used internally, a combination of numbers, letters, underscores and atleast one letter
 * @param name - the name shown to the users. It should have three parts like "language / test-framework / WebDriver or Remote Control"
 * @param url - url to your bundled formatter in the form of chrome://
 * @param type - optional, can be "webdriver" or "remotecontrol". Specifying the type
 * automatically provides the given formatter type so it does not have to be
 * loaded with subScriptLoader.loadSubScript() in your formatter.
 */
API.prototype.addPluginProvidedFormatter = function (id, name, url, type) {
  this.code.formatters.push(id + ";" + name + ";" + url + ";" + type);
  this._save();
};

//--------------------------------------------------------------------------
// End of Selenium IDE Public API.
// The following provides internal and cleanup stuff for the plugin system
//--------------------------------------------------------------------------

/**
 * Internal function. Do not use.
 *
 * @private
 */
API.prototype._save = function () {
  if (this.id) { //Save only if ID has been set
    var found = false;
    var id = this.id;
    var plugins = JSON.parse(this.preferences.getString('pluginsData', '[]'));
    for (var i = 0; i < plugins.length; i++) {
      if (plugins[i].id == id) {
        plugins[i].installed = true;
        plugins[i].code = this.code;
        found = true;
        break;
      }
    }
    if (!found) {
      plugins.push({
                     id: this.id,
                     installed: true,
                     code: this.code,
                     options: {
                       disabled: false,
                       autoDisabled: false
                     }
                   });
    }
    this.preferences.save({pluginsData: JSON.stringify(plugins)}, 'pluginsData');
  }
};

// this works because plugins re-register every time the browser restarts
function initializeSeIDEAPIObserver() {
  seIDEAPIObserver.register();
}

var seIDEAPIObserver = {
  _uninstall: false,
  observe: function (subject, topic, data) {
    if (topic == "quit-application-granted") {
      var branch = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.selenium-ide.");
      branch.clearUserPref("pluginProvidedIDEExtensions");
      branch.clearUserPref("pluginProvidedUserExtensions");
      branch.clearUserPref("pluginProvidedFormatters");
      branch.clearUserPref("plugins");
      //Clear the plugin code and leave the options intact as we want to honour it on next load
      if (branch.prefHasUserValue('pluginsData')) {
        var plugins = JSON.parse(branch.getCharPref('pluginsData'));
        for (var i = 0; i < plugins.length; i++) {
          plugins[i].installed = false;
          plugins[i].code = {
            ideExtensions: [],
            userExtensions: [],
            formatters: []
          };
        }
        branch.setCharPref('pluginsData', JSON.stringify(plugins));
      }
      this.unregister();
    }
  },
  register: function () {
    var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
    observerService.addObserver(this, "quit-application-granted", false);
  },
  unregister: function () {
    var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
    observerService.removeObserver(this, "quit-application-granted");
  }
};

//Make the cleanup run one time for each window instead of once for every plugin for every window
if (!window.registeredSEIDEAPIObserver) {
  window.addEventListener("load", initializeSeIDEAPIObserver, false);
  window.registeredSEIDEAPIObserver = true;
}
<|endoftext|>


<commit_before>(function (angular, page, notifications) {
  /**
   * Controller to download the analysis.
   * @constructor
   */
  function FileDownloadController() {
    var vm = this;

    vm.getZipFile = function (id) {
      var iFrameId = 'hiddenDownloader';
      var hiddenIFrame = document.getElementById(iFrameId);
      if (hiddenIFrame === null) {
        hiddenIFrame = document.createElement('iframe');
        hiddenIFrame.id = iFrameId;
        hiddenIFrame.style.display = 'none';
        document.body.appendChild(hiddenIFrame);
      }
      hiddenIFrame.src = page.URLS.download + id + '?dandelionAssetFilterState=false';
    };
  }

  /**
   * Service for Analysis
   * @param $http
   * @param $interval
   * @returns {AnalysisService}
   * @constructor
   */
  function AnalysisService($http) {
    var svc = this;

    /**
     * Call the server to get the status for the current analysis.
     * 'page.URLS.status' is on the `_base.html` page for the analysis.
     * @returns {*}
     * @private
     */
    function _getState() {
      return $http.get(page.URLS.status).then(function (data) {
        return data.data;
      });
    }

    /**
     * Get the results from a SISTR analysis to preview in the browser.
     */
    svc.getSistrResults = function() {
      return $http.get(page.URLS.sistr).then(function(result) {
        return result.data;
      });
    }

    /**
     * Exported function to call the server for information about the current analysis.
     * @param fn Callback function with how to handle the results.
     */
    svc.getAnalysisState = function (fn) {
      _getState().then(function (data) {
        fn(data);
      });
    };

    /**
     * Call the server to update the shared status of the current analysis.
     */
    svc.updateProjectShare = function(project, shared) {
      var data = {project: project, shared: shared};
      return $http.post(page.URLS.share, data).then(function(response) {
        return response.data;
      });
    };

    /**
     * Call the server to get the shared status of project
     */
    svc.getSharedProjects = function() {
      return $http.get(page.URLS.share).then(function(response) {
        return response.data;
      });
    };

    return svc;
  }

  function ProjectShareController(AnalysisService) {
    var vm = this;

    vm.projects = {};

    function initialize() {
      AnalysisService.getSharedProjects().then(function(response){
        vm.projects = response;
        console.log(vm.projects);
      });
    }

    vm.updateShared = function(project) {
      AnalysisService.updateProjectShare(project.project.identifier, project.shared).then(function(response) {
        notifications.show({text: response.message});
      });
    };

    initialize();
  }

  /**
   * Controls the state for the current analysis.
   * @param AnalysisService
   * @constructor
   */
  function StateController(AnalysisService) {
    var vm = this;
    vm.percentage = 0;

    /**
     * Initializes the sate of the analysis.
     */
    function initialize() {
      return AnalysisService.getAnalysisState(function (data) {
        vm.state = data.state;
        vm.stateLang = data.stateLang;
        vm.percentage = Math.round(parseFloat(data.percentComplete));
        vm.stateClass = _createClass(vm.state);
      });
    }

    /**
     * Dynamically creates the border color for the top of the sidebar depending on the state of the analysis.
     * @param state
     * @returns {string}
     * @private
     */
    function _createClass(state) {
      return 'analysis__alert--' + state.toLowerCase();
    }

    initialize();
  }

  function PreviewController() {
    var vm = this;
    vm.newick = page.NEWICK;
  }

  function SistrController(analysisService) {
    var vm = this;

    analysisService.getSistrResults().then(function(result) {
      if (result['parse_results_error']) {
        vm.parse_results_error = true;
      } else {
        var sample_information = {};
        sample_information['name'] = result['sample_name'];
        sample_information['qc_status'] = result['qc_status'];
        sample_information['qc_messages'] = result['qc_messages'].split("|");
        sample_information['qc_pass'] = (result['qc_status'] == 'PASS');
        sample_information['qc_warning'] = (result['qc_status'] == 'WARNING');
        sample_information['qc_fail'] = (result['qc_status'] == 'FAIL');

        var cgMLST_predictions = {};
        cgMLST_predictions['matching_alleles'] = result['cgmlst_matching_alleles']+'/330';
        cgMLST_predictions['percent_matching'] = parseFloat((1 - result['cgmlst_distance'])*100).toFixed(1)+"%";

        var mash_predictions = {};
        mash_predictions['distance'] = result['mash_distance'];

	vm.result = result;
        vm.sample_information = sample_information;
        vm.cgMLST_predictions = cgMLST_predictions;
        vm.mash_predictions = mash_predictions;
        vm.parse_results_error = result['parse_results_error'];
      }
    });
  }

  angular.module('irida.analysis', ['ui.router', 'subnav', 'phylocanvas'])
    .config(['$stateProvider', function ($stateProvider) {
      $stateProvider
        .state("preview", {
          url        : "/preview",
          templateUrl: "preview.html"
        })
        .state("sistr", {
          url: "/sistr",
          templateUrl: "sistr.html",
          controllerAs: "sistrCtrl",
          controller: ["AnalysisService", SistrController]
        })
        .state("inputs", {
          url        : "/inputs",
          templateUrl: "inputs.html"
        })
        .state("provenance", {
          url        : "/provenance",
          templateUrl: "provenance.html"
        })
        .state("share", {
          url        : "/share",
          templateUrl: "share.html"
        })
      ;
    }])
    .service('AnalysisService', ['$http', AnalysisService])
    .controller('FileDownloadController', [FileDownloadController])
    .controller('StateController', ['AnalysisService', StateController])
    .controller('PreviewController', [PreviewController])
    .controller('ProjectShareController', ['AnalysisService', ProjectShareController])
  ;
})(window.angular, window.PAGE, window.notifications);
<commit_msg>Don't need to avoid the dandelion filter.<commit_after>(function (angular, page, notifications) {
  /**
   * Controller to download the analysis.
   * @constructor
   */
  function FileDownloadController() {
    var vm = this;

    vm.getZipFile = function (id) {
      var iFrameId = 'hiddenDownloader';
      var hiddenIFrame = document.getElementById(iFrameId);
      if (hiddenIFrame === null) {
        hiddenIFrame = document.createElement('iframe');
        hiddenIFrame.id = iFrameId;
        hiddenIFrame.style.display = 'none';
        document.body.appendChild(hiddenIFrame);
      }
      hiddenIFrame.src = page.URLS.download + id
    };
  }

  /**
   * Service for Analysis
   * @param $http
   * @param $interval
   * @returns {AnalysisService}
   * @constructor
   */
  function AnalysisService($http) {
    var svc = this;

    /**
     * Call the server to get the status for the current analysis.
     * 'page.URLS.status' is on the `_base.html` page for the analysis.
     * @returns {*}
     * @private
     */
    function _getState() {
      return $http.get(page.URLS.status).then(function (data) {
        return data.data;
      });
    }

    /**
     * Get the results from a SISTR analysis to preview in the browser.
     */
    svc.getSistrResults = function() {
      return $http.get(page.URLS.sistr).then(function(result) {
        return result.data;
      });
    }

    /**
     * Exported function to call the server for information about the current analysis.
     * @param fn Callback function with how to handle the results.
     */
    svc.getAnalysisState = function (fn) {
      _getState().then(function (data) {
        fn(data);
      });
    };

    /**
     * Call the server to update the shared status of the current analysis.
     */
    svc.updateProjectShare = function(project, shared) {
      var data = {project: project, shared: shared};
      return $http.post(page.URLS.share, data).then(function(response) {
        return response.data;
      });
    };

    /**
     * Call the server to get the shared status of project
     */
    svc.getSharedProjects = function() {
      return $http.get(page.URLS.share).then(function(response) {
        return response.data;
      });
    };

    return svc;
  }

  function ProjectShareController(AnalysisService) {
    var vm = this;

    vm.projects = {};

    function initialize() {
      AnalysisService.getSharedProjects().then(function(response){
        vm.projects = response;
        console.log(vm.projects);
      });
    }

    vm.updateShared = function(project) {
      AnalysisService.updateProjectShare(project.project.identifier, project.shared).then(function(response) {
        notifications.show({text: response.message});
      });
    };

    initialize();
  }

  /**
   * Controls the state for the current analysis.
   * @param AnalysisService
   * @constructor
   */
  function StateController(AnalysisService) {
    var vm = this;
    vm.percentage = 0;

    /**
     * Initializes the sate of the analysis.
     */
    function initialize() {
      return AnalysisService.getAnalysisState(function (data) {
        vm.state = data.state;
        vm.stateLang = data.stateLang;
        vm.percentage = Math.round(parseFloat(data.percentComplete));
        vm.stateClass = _createClass(vm.state);
      });
    }

    /**
     * Dynamically creates the border color for the top of the sidebar depending on the state of the analysis.
     * @param state
     * @returns {string}
     * @private
     */
    function _createClass(state) {
      return 'analysis__alert--' + state.toLowerCase();
    }

    initialize();
  }

  function PreviewController() {
    var vm = this;
    vm.newick = page.NEWICK;
  }

  function SistrController(analysisService) {
    var vm = this;

    analysisService.getSistrResults().then(function(result) {
      if (result['parse_results_error']) {
        vm.parse_results_error = true;
      } else {
        var sample_information = {};
        sample_information['name'] = result['sample_name'];
        sample_information['qc_status'] = result['qc_status'];
        sample_information['qc_messages'] = result['qc_messages'].split("|");
        sample_information['qc_pass'] = (result['qc_status'] == 'PASS');
        sample_information['qc_warning'] = (result['qc_status'] == 'WARNING');
        sample_information['qc_fail'] = (result['qc_status'] == 'FAIL');

        var cgMLST_predictions = {};
        cgMLST_predictions['matching_alleles'] = result['cgmlst_matching_alleles']+'/330';
        cgMLST_predictions['percent_matching'] = parseFloat((1 - result['cgmlst_distance'])*100).toFixed(1)+"%";

        var mash_predictions = {};
        mash_predictions['distance'] = result['mash_distance'];

	vm.result = result;
        vm.sample_information = sample_information;
        vm.cgMLST_predictions = cgMLST_predictions;
        vm.mash_predictions = mash_predictions;
        vm.parse_results_error = result['parse_results_error'];
      }
    });
  }

  angular.module('irida.analysis', ['ui.router', 'subnav', 'phylocanvas'])
    .config(['$stateProvider', function ($stateProvider) {
      $stateProvider
        .state("preview", {
          url        : "/preview",
          templateUrl: "preview.html"
        })
        .state("sistr", {
          url: "/sistr",
          templateUrl: "sistr.html",
          controllerAs: "sistrCtrl",
          controller: ["AnalysisService", SistrController]
        })
        .state("inputs", {
          url        : "/inputs",
          templateUrl: "inputs.html"
        })
        .state("provenance", {
          url        : "/provenance",
          templateUrl: "provenance.html"
        })
        .state("share", {
          url        : "/share",
          templateUrl: "share.html"
        })
      ;
    }])
    .service('AnalysisService', ['$http', AnalysisService])
    .controller('FileDownloadController', [FileDownloadController])
    .controller('StateController', ['AnalysisService', StateController])
    .controller('PreviewController', [PreviewController])
    .controller('ProjectShareController', ['AnalysisService', ProjectShareController])
  ;
})(window.angular, window.PAGE, window.notifications);
<|endoftext|>


<commit_before>import browserify from 'browserify';
import watchify from 'watchify';
import browserSync from 'browser-sync';
import uglify from 'gulp-uglify';
import streamify from 'gulp-streamify';
import source from 'vinyl-source-stream';
import path from 'path';
import notify from 'gulp-notify';
import util from 'gulp-util';
import collapse from 'bundle-collapser/plugin';
import sourcemaps from 'gulp-sourcemaps';
import buffer from 'vinyl-buffer';

/**
 * Gulp task to run browserify over config.entryJs
 * @param  {object} config Global configuration
 * @return {function}        Function task
 */
export default function browserifyTask(userConfig) {
    const gulp = this.gulp;
    const config = userConfig || this.config;
    let onBundleError;
    if (config.notify.onError) {
        onBundleError = notify.onError('Browserify Error: <%= error.message %>');
    } else {
        onBundleError = (err) => {
            util.log(util.colors.red('Error'), err.message);
        };
    }

    /**
     * Function to run the Browserify Bundler over pipes
     * @param  {object} bundler Bundler object
     * @return {object} stream  Gulp stream
     */
    function browserifyBundle(bundler) {
        if (config.isProduction) {
            bundler.plugin(collapse);
        }

        let stream = bundler.bundle()
            .on('error', onBundleError)
            .pipe(source('index.js'));

        if (config.isProduction) {
            stream = stream.pipe(streamify(uglify()));
        } else {
            // source map external
            stream = stream.pipe(buffer())
                .pipe(sourcemaps.init({
                    loadMaps: true
                }))
                .pipe(sourcemaps.write('./', {
                    sourceRoot: '/'
                }));
        }

        stream = stream.pipe(gulp.dest(config.destPath));

        if (config.watch) {
            stream.pipe(browserSync.stream({once: true}));
        }

        if (config.notify.onUpdated) {
            return stream.pipe(notify('Browserify Bundle - Updated'));
        }

        return stream;
    }

    return () => {
        let bundler = browserify({
            entries: path.join(config.sourcePath, config.entryJs),
            debug: !(config.isProduction),
            transforms: config.browserify.transforms
        });

        config.browserify.transforms.forEach((elem) => {
            bundler = bundler.transform(elem);
        });

        config.browserify.plugins.forEach((elem) => {
            bundler = bundler.plugin(elem.module, elem.opts);
        });

        if (config.watch) {
            bundler = watchify(bundler);

            bundler.on('update', () => {
                browserifyBundle(bundler);
            });
        }

        return browserifyBundle(bundler);
    };
}
<commit_msg>minor change<commit_after>import browserify from 'browserify';
import watchify from 'watchify';
import browserSync from 'browser-sync';
import uglify from 'gulp-uglify';
import streamify from 'gulp-streamify';
import source from 'vinyl-source-stream';
import path from 'path';
import notify from 'gulp-notify';
import util from 'gulp-util';
import collapse from 'bundle-collapser/plugin';
import sourcemaps from 'gulp-sourcemaps';
import buffer from 'vinyl-buffer';

/**
 * Gulp task to run browserify over config.entryJs
 * @param  {object} config Global configuration
 * @return {function}        Function task
 */
export default function browserifyTask(userConfig) {
    const gulp = this.gulp;
    const config = userConfig || this.config;
    let onBundleError;
    if (config.notify.onError) {
        onBundleError = notify.onError('Browserify Error: <%= error.message %>');
    } else {
        onBundleError = (err) => {
            util.log(util.colors.red('Error'), err.message);
        };
    }

    /**
     * Function to run the Browserify Bundler over pipes
     * @param  {object} bundler Bundler object
     * @return {object} stream  Gulp stream
     */
    function browserifyBundle(bundler) {
        if (config.isProduction) {
            bundler.plugin(collapse);
        }

        let stream = bundler.bundle()
            .on('error', onBundleError)
            .pipe(source('index.js'));

        if (config.isProduction) {
            stream = stream.pipe(streamify(uglify()));
        } else {
            // source map external
            stream = stream.pipe(buffer())
                .pipe(sourcemaps.init({
                    loadMaps: true
                }))
                .pipe(sourcemaps.write('./', {
                    sourceRoot: '/'
                }));
        }

        stream = stream.pipe(gulp.dest(config.destPath));

        if (config.watch) {
            stream.pipe(browserSync.stream({once: true}));
        }

        if (config.notify.onUpdated) {
            return stream.pipe(notify('Browserify Bundle - Updated'));
        }

        return stream;
    }

    return () => {
        let bundler = browserify({
            entries: path.join(config.sourcePath, config.entryJs),
            debug: !(config.isProduction)
        });

        config.browserify.transforms.forEach((elem) => {
            bundler = bundler.transform(elem);
        });

        config.browserify.plugins.forEach((elem) => {
            bundler = bundler.plugin(elem.module, elem.opts);
        });

        if (config.watch) {
            bundler = watchify(bundler);

            bundler.on('update', () => {
                browserifyBundle(bundler);
            });
        }

        return browserifyBundle(bundler);
    };
}
<|endoftext|>


<commit_before>import jsonop from 'jsonop';
import winston from 'winston';
import Counter from '../../lib/counter';
import * as pg from '../../lib/pg';
import { TABLES, TYPES } from '../../lib/schema';
import queryHandler from './query';
import entityHandler from './entity';
import { bus, cache, config } from '../../core-server';
import * as Types from './../../models/models';
import './cache-updater';
const channel = 'heyneighbor';

const TYPE_SEGMENT = `case \
when tableoid = 'notes'::regclass then 'note' \
when tableoid = 'privs'::regclass then 'privs' \
when tableoid = 'roomrelations'::regclass then 'roomrels' \
when tableoid = 'rooms'::regclass then 'room' \
when tableoid = 'textrelations'::regclass then 'textrel' \
when tableoid = 'texts'::regclass then 'text' \
when tableoid = 'threadrelations'::regclass then 'threadrel' \
when tableoid = 'threads'::regclass then 'thread' \
when tableoid = 'topicrelations'::regclass then 'topicrel' \
when tableoid = 'topics'::regclass then 'topic' \
when tableoid = 'users'::regclass then 'user' \
end as type`;

function broadcast (entity) {
	pg.notify(config.connStr, channel, entity);
}

cache.onChange((changes) => {
	winston.info(changes);
	const cb = (key, range, err, results) => {
		if (err) {
			winston.error(err);
			return;
		}
		bus.emit('change', {
			knowledge: { [key]: [ range ] },
			indexes: { [key]: results },
			source: 'postgres'
		});
	};

	if (changes.queries) {
		for (const key in changes.queries) {
			if (key === 'entities') {
				const ids = Object.keys(changes.queries.entities),
					typeToEntities = {
						item: [],
						user: []
					};

				ids.forEach((id) => {
					const _split = id.split('_');
					let type;

					if (_split.length === 3) return;
					else if (_split.length === 2) return;
					else if (id.length >= 36) type = 'item';
					else type = 'user';
					typeToEntities[type].push(id);
				});

				for (const i in typeToEntities) {
					if (!typeToEntities[i].length) continue;

					pg.read(config.connStr, {
						$: `select *, ${TYPE_SEGMENT} from "${TABLES[TYPES[i]]}" where id in (&(ids))`,
						ids: typeToEntities[i]
					}, (err, r) => {
						if (err) {
							winston.error(err.message);
							return;
						}

						console.log(r);
						const state = {
							entities: {},
							source: 'postgres'
						};

						r.map((entity) => {
							state.entities[entity.id] = new Types[entity.type](entity);
						});

						const missingIds = r.map(item => item.id).filter(itemID => typeToEntities[i].indexOf(itemID) > -1);

						missingIds.forEach(id => {
							state.entities[id] = null;
						});
						winston.info(JSON.stringify(state));
						bus.emit('change', state);
					});
				}
			} else {
				for (const range of changes.queries[key]) {
					pg.read(
						config.connStr,
						queryHandler(cache.keyToSlice(key), range),
						cb.bind(null, key, range)
					);
				}
			}
		}
	}
});

pg.listen(config.connStr, channel, (payload) => {
	bus.emit('postchange', payload);
});

bus.on('change', (changes, next) => {
	const counter = new Counter();

	winston.info(changes);
	if (changes.source === 'postgres') {
		next();
		return;
	}

	if (changes.entities) {
		const sql = [];

		winston.info('Got few entities to update');
		for (const id in changes.entities) {
			sql.push(entityHandler(changes.entities[id]));
		}

		winston.info('sql', sql);
		counter.inc();
		pg.write(config.connStr, sql, (err, results) => {
			if (err) {
				counter.err(err);
				return;
			}

			winston.info('PgWrite Results', results[0].rows);
			results.forEach((result) => broadcast(result.rows[0]));
			counter.dec();
		});
	}

	if (changes.queries) {
		const response = changes.response = {},
			cb = (key, err, results) => {
				if (err) { jsonop(response, { state: { error: err } }); }
				jsonop(response, { indexes: { [key]: results } });
				counter.dec();
			},
			entityCallback = (err, result) => {
				if (err) { jsonop(response, { state: { error: err } }); }

				if (result && result.id) {
					response.entities = response.entities ? response.entities : {};
					response.entities[result.id] = result;
				}

				counter.dec();
			};

		for (const key in changes.queries) {
			if (key === 'entities') {
				counter.inc();
				for (const entity in changes.queries[key][entity]) {
					cache.getEntity(entity, entityCallback);
				}
			} else {
				for (const range of changes.queries[key]) {
					counter.inc();
					cache.query(key, range, cb.bind(null, key));
				}
			}
		}
	}

	counter.then(next);
});
<commit_msg>Fix changes fired for missing entities<commit_after>import jsonop from 'jsonop';
import winston from 'winston';
import Counter from '../../lib/counter';
import * as pg from '../../lib/pg';
import { TABLES, TYPES } from '../../lib/schema';
import queryHandler from './query';
import entityHandler from './entity';
import { bus, cache, config } from '../../core-server';
import * as Types from './../../models/models';
import './cache-updater';
const channel = 'heyneighbor';

const TYPE_SEGMENT = `case \
when tableoid = 'notes'::regclass then 'note' \
when tableoid = 'privs'::regclass then 'privs' \
when tableoid = 'roomrelations'::regclass then 'roomrels' \
when tableoid = 'rooms'::regclass then 'room' \
when tableoid = 'textrelations'::regclass then 'textrel' \
when tableoid = 'texts'::regclass then 'text' \
when tableoid = 'threadrelations'::regclass then 'threadrel' \
when tableoid = 'threads'::regclass then 'thread' \
when tableoid = 'topicrelations'::regclass then 'topicrel' \
when tableoid = 'topics'::regclass then 'topic' \
when tableoid = 'users'::regclass then 'user' \
end as type`;

function broadcast (entity) {
	pg.notify(config.connStr, channel, entity);
}

cache.onChange((changes) => {
	const cb = (key, range, err, results) => {
		if (err) {
			winston.error(err);
			return;
		}
		bus.emit('change', {
			knowledge: { [key]: [ range ] },
			indexes: { [key]: results },
			source: 'postgres'
		});
	};

	if (changes.queries) {
		for (const key in changes.queries) {
			if (key === 'entities') {
				const ids = Object.keys(changes.queries.entities),
					typeToEntities = {
						item: [],
						user: []
					};

				ids.forEach((id) => {
					const _split = id.split('_');
					let type;

					if (_split.length === 3) return;
					else if (_split.length === 2) return;
					else if (id.length >= 36) type = 'item';
					else type = 'user';
					typeToEntities[type].push(id);
				});

				// TODO: move to diff file.
				for (const i in typeToEntities) {
					if (!typeToEntities[i].length) continue;

					pg.read(config.connStr, {
						$: `select *, ${TYPE_SEGMENT} from "${TABLES[TYPES[i]]}" where id in (&(ids))`,
						ids: typeToEntities[i]
					}, (err, r) => {
						if (err) {
							winston.error(err.message);
							return;
						}

						const state = {
							entities: {},
							source: 'postgres'
						};

						r.map((entity) => {
							state.entities[entity.id] = new Types[entity.type](entity);
						});

						const missingIds = ids.map(item => item.id).filter(itemID => typeToEntities[i].indexOf(itemID) < 0);

						missingIds.forEach(id => {
							state.entities[id] = null;
						});
						bus.emit('change', state);
					});
				}
			} else {
				for (const range of changes.queries[key]) {
					pg.read(
						config.connStr,
						queryHandler(cache.keyToSlice(key), range),
						cb.bind(null, key, range)
					);
				}
			}
		}
	}
});

pg.listen(config.connStr, channel, (payload) => {
	bus.emit('postchange', payload);
});

bus.on('change', (changes, next) => {
	const counter = new Counter();

	if (changes.source === 'postgres') {
		next();
		return;
	}

	if (changes.entities) {
		const sql = [];

		for (const id in changes.entities) {
			sql.push(entityHandler(changes.entities[id]));
		}

		winston.info('sql', sql);
		counter.inc();
		pg.write(config.connStr, sql, (err, results) => {
			if (err) {
				counter.err(err);
				return;
			}

			winston.info('PgWrite Results', results[0].rows);
			results.forEach((result) => broadcast(result.rows[0]));
			counter.dec();
		});
	}

	if (changes.queries) {
		const response = changes.response = {},
			cb = (key, err, results) => {
				if (err) { jsonop(response, { state: { error: err } }); }
				jsonop(response, { indexes: { [key]: results } });
				counter.dec();
			},
			entityCallback = (err, result) => {
				if (err) { jsonop(response, { state: { error: err } }); }
				if (result && result.id) {
					response.entities = response.entities ? response.entities : {};
					response.entities[result.id] = result;
				}

				counter.dec();
			};

		for (const key in changes.queries) {
			if (key === 'entities') {
				for (const entity in changes.queries[key]) {
					counter.inc();
					cache.getEntity(entity, entityCallback);
				}
			} else {
				for (const range of changes.queries[key]) {
					counter.inc();
					cache.query(key, range, cb.bind(null, key));
				}
			}
		}
	}

	counter.then(next);
});
<|endoftext|>