<commit_before>import {
  toSockjsUrl,
  toWebsocketUrl,
} from "./urls.js";
import "./sockjs-0.3.4.js";
import { StreamClientCommon } from "./common.js";

export class ClientStream extends StreamClientCommon {
  // @param url {String} URL to Meteor app
  //   "http://subdomain.meteor.com/" or "/" or
  //   "ddp+sockjs://foo-**.meteor.com/sockjs"
  constructor(url, options) {
    super(options);

    this._initCommon(this.options);

    //// Constants

    // how long between hearing heartbeat from the server until we declare
    // the connection dead. heartbeats come every 45s (stream_server.js)
    //
    // NOTE: this is a older timeout mechanism. We now send heartbeats at
    // the DDP level (https://github.com/meteor/meteor/pull/1865), and
    // expect those timeouts to kill a non-responsive connection before
    // this timeout fires. This is kept around for compatibility (when
    // talking to a server that doesn't support DDP heartbeats) and can be
    // removed later.
    this.HEARTBEAT_TIMEOUT = 100 * 1000;

    this.rawUrl = url;
    this.socket = null;
    this.lastError = null;

    this.heartbeatTimer = null;

    // Listen to global 'online' event if we are running in a browser.
    // (IE8 does not support addEventListener)
    if (typeof window !== 'undefined' && window.addEventListener)
      window.addEventListener(
        'online',
        this._online.bind(this),
        false /* useCapture. make FF3.6 happy. */
      );

    //// Kickoff!
    this._launchConnection();
  }

  // data is a utf8 string. Data sent while not connected is dropped on
  // the floor, and it is up the user of this API to retransmit lost
  // messages on 'reset'
  send(data) {
    if (this.currentStatus.connected) {
      this.socket.send(data);
    }
  }

  // Changes where this connection points
  _changeUrl(url) {
    this.rawUrl = url;
  }

  _connected() {
    if (this.connectionTimer) {
      clearTimeout(this.connectionTimer);
      this.connectionTimer = null;
    }

    if (this.currentStatus.connected) {
      // already connected. do nothing. this probably shouldn't happen.
      return;
    }

    // update status
    this.currentStatus.status = 'connected';
    this.currentStatus.connected = true;
    this.currentStatus.retryCount = 0;
    this.statusChanged();

    // fire resets. This must come after status change so that clients
    // can call send from within a reset callback.
    this.forEachCallback('reset', callback => {
      callback();
    });
  }

  _cleanup(maybeError) {
    this._clearConnectionAndHeartbeatTimers();
    if (this.socket) {
      this.socket.onmessage = this.socket.onclose = this.socket.onerror = this.socket.onheartbeat = () => {};
      this.socket.close();
      this.socket = null;
    }

    this.forEachCallback('disconnect', callback => {
      callback(maybeError);
    });
  }

  _clearConnectionAndHeartbeatTimers() {
    if (this.connectionTimer) {
      clearTimeout(this.connectionTimer);
      this.connectionTimer = null;
    }
    if (this.heartbeatTimer) {
      clearTimeout(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  _heartbeat_timeout() {
    console.log('Connection timeout. No sockjs heartbeat received.');
    this._lostConnection(new this.ConnectionError("Heartbeat timed out"));
  }

  _heartbeat_received() {
    // If we've already permanently shut down this stream, the timeout is
    // already cleared, and we don't need to set it again.
    if (this._forcedToDisconnect) return;
    if (this.heartbeatTimer) clearTimeout(this.heartbeatTimer);
    this.heartbeatTimer = setTimeout(
      this._heartbeat_timeout.bind(this),
      this.HEARTBEAT_TIMEOUT
    );
  }

  _sockjsProtocolsWhitelist() {
    // only allow polling protocols. no streaming.  streaming
    // makes safari spin.
    var protocolsWhitelist = [
      'xdr-polling',
      'xhr-polling',
      'iframe-xhr-polling',
      'jsonp-polling'
    ];

    // iOS 4 and 5 and below crash when using websockets over certain
    // proxies. this seems to be resolved with iOS 6. eg
    // https://github.com/LearnBoost/socket.io/issues/193#issuecomment-7308865.
    //
    // iOS <4 doesn't support websockets at all so sockjs will just
    // immediately fall back to http
    var noWebsockets =
      navigator &&
      /iPhone|iPad|iPod/.test(navigator.userAgent) &&
      /OS 4_|OS 5_/.test(navigator.userAgent);

    if (!noWebsockets)
      protocolsWhitelist = ['websocket'].concat(protocolsWhitelist);

    return protocolsWhitelist;
  }

  _launchConnection() {
    this._cleanup(); // cleanup the old socket, if there was one.

    var options = {
      protocols_whitelist: this._sockjsProtocolsWhitelist(),
      ...this.options._sockjsOptions
    };

    const hasSockJS = typeof SockJS === "function";

    this.socket = hasSockJS
      // Convert raw URL to SockJS URL each time we open a connection, so
      // that we can connect to random hostnames and get around browser
      // per-host connection limits.
      ? new SockJS(toSockjsUrl(this.rawUrl), undefined, options)
      : new WebSocket(toWebsocketUrl(this.rawUrl));

    this.socket.onopen = data => {
      this.lastError = null;
      this._connected();
    };

    this.socket.onmessage = data => {
      this.lastError = null;
      this._heartbeat_received();
      if (this.currentStatus.connected) {
        this.forEachCallback('message', callback => {
          callback(data.data);
        });
      }
    };

    this.socket.onclose = () => {
      Promise.resolve(
        // If the socket is closing because there was an error, and we
        // didn't load SockJS before, try loading it dynamically before
        // retrying the connection.
        this.lastError &&
        ! hasSockJS &&
        import("./sockjs-0.3.4.js")
      ).done(() => {
        this._lostConnection();
      });
    };

    this.socket.onerror = error => {
      const { lastError } = this;
      this.lastError = error;
      if (lastError) return;
      console.log(
        'stream error',
        error,
        new Date().toDateString()
      );
    };

    this.socket.onheartbeat = () => {
      this.lastError = null;
      this._heartbeat_received();
    };

    if (this.connectionTimer) clearTimeout(this.connectionTimer);
    this.connectionTimer = setTimeout(() => {
      this._lostConnection(
        new this.ConnectionError("DDP connection timed out")
      );
    }, this.CONNECT_TIMEOUT);
  }
}
<commit_msg>Exclude sockjs-0.3.4.js from JS bundle in modern browsers, again.<commit_after>import {
  toSockjsUrl,
  toWebsocketUrl,
} from "./urls.js";

import { StreamClientCommon } from "./common.js";

export class ClientStream extends StreamClientCommon {
  // @param url {String} URL to Meteor app
  //   "http://subdomain.meteor.com/" or "/" or
  //   "ddp+sockjs://foo-**.meteor.com/sockjs"
  constructor(url, options) {
    super(options);

    this._initCommon(this.options);

    //// Constants

    // how long between hearing heartbeat from the server until we declare
    // the connection dead. heartbeats come every 45s (stream_server.js)
    //
    // NOTE: this is a older timeout mechanism. We now send heartbeats at
    // the DDP level (https://github.com/meteor/meteor/pull/1865), and
    // expect those timeouts to kill a non-responsive connection before
    // this timeout fires. This is kept around for compatibility (when
    // talking to a server that doesn't support DDP heartbeats) and can be
    // removed later.
    this.HEARTBEAT_TIMEOUT = 100 * 1000;

    this.rawUrl = url;
    this.socket = null;
    this.lastError = null;

    this.heartbeatTimer = null;

    // Listen to global 'online' event if we are running in a browser.
    // (IE8 does not support addEventListener)
    if (typeof window !== 'undefined' && window.addEventListener)
      window.addEventListener(
        'online',
        this._online.bind(this),
        false /* useCapture. make FF3.6 happy. */
      );

    //// Kickoff!
    this._launchConnection();
  }

  // data is a utf8 string. Data sent while not connected is dropped on
  // the floor, and it is up the user of this API to retransmit lost
  // messages on 'reset'
  send(data) {
    if (this.currentStatus.connected) {
      this.socket.send(data);
    }
  }

  // Changes where this connection points
  _changeUrl(url) {
    this.rawUrl = url;
  }

  _connected() {
    if (this.connectionTimer) {
      clearTimeout(this.connectionTimer);
      this.connectionTimer = null;
    }

    if (this.currentStatus.connected) {
      // already connected. do nothing. this probably shouldn't happen.
      return;
    }

    // update status
    this.currentStatus.status = 'connected';
    this.currentStatus.connected = true;
    this.currentStatus.retryCount = 0;
    this.statusChanged();

    // fire resets. This must come after status change so that clients
    // can call send from within a reset callback.
    this.forEachCallback('reset', callback => {
      callback();
    });
  }

  _cleanup(maybeError) {
    this._clearConnectionAndHeartbeatTimers();
    if (this.socket) {
      this.socket.onmessage = this.socket.onclose = this.socket.onerror = this.socket.onheartbeat = () => {};
      this.socket.close();
      this.socket = null;
    }

    this.forEachCallback('disconnect', callback => {
      callback(maybeError);
    });
  }

  _clearConnectionAndHeartbeatTimers() {
    if (this.connectionTimer) {
      clearTimeout(this.connectionTimer);
      this.connectionTimer = null;
    }
    if (this.heartbeatTimer) {
      clearTimeout(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  _heartbeat_timeout() {
    console.log('Connection timeout. No sockjs heartbeat received.');
    this._lostConnection(new this.ConnectionError("Heartbeat timed out"));
  }

  _heartbeat_received() {
    // If we've already permanently shut down this stream, the timeout is
    // already cleared, and we don't need to set it again.
    if (this._forcedToDisconnect) return;
    if (this.heartbeatTimer) clearTimeout(this.heartbeatTimer);
    this.heartbeatTimer = setTimeout(
      this._heartbeat_timeout.bind(this),
      this.HEARTBEAT_TIMEOUT
    );
  }

  _sockjsProtocolsWhitelist() {
    // only allow polling protocols. no streaming.  streaming
    // makes safari spin.
    var protocolsWhitelist = [
      'xdr-polling',
      'xhr-polling',
      'iframe-xhr-polling',
      'jsonp-polling'
    ];

    // iOS 4 and 5 and below crash when using websockets over certain
    // proxies. this seems to be resolved with iOS 6. eg
    // https://github.com/LearnBoost/socket.io/issues/193#issuecomment-7308865.
    //
    // iOS <4 doesn't support websockets at all so sockjs will just
    // immediately fall back to http
    var noWebsockets =
      navigator &&
      /iPhone|iPad|iPod/.test(navigator.userAgent) &&
      /OS 4_|OS 5_/.test(navigator.userAgent);

    if (!noWebsockets)
      protocolsWhitelist = ['websocket'].concat(protocolsWhitelist);

    return protocolsWhitelist;
  }

  _launchConnection() {
    this._cleanup(); // cleanup the old socket, if there was one.

    var options = {
      protocols_whitelist: this._sockjsProtocolsWhitelist(),
      ...this.options._sockjsOptions
    };

    const hasSockJS = typeof SockJS === "function";

    this.socket = hasSockJS
      // Convert raw URL to SockJS URL each time we open a connection, so
      // that we can connect to random hostnames and get around browser
      // per-host connection limits.
      ? new SockJS(toSockjsUrl(this.rawUrl), undefined, options)
      : new WebSocket(toWebsocketUrl(this.rawUrl));

    this.socket.onopen = data => {
      this.lastError = null;
      this._connected();
    };

    this.socket.onmessage = data => {
      this.lastError = null;
      this._heartbeat_received();
      if (this.currentStatus.connected) {
        this.forEachCallback('message', callback => {
          callback(data.data);
        });
      }
    };

    this.socket.onclose = () => {
      Promise.resolve(
        // If the socket is closing because there was an error, and we
        // didn't load SockJS before, try loading it dynamically before
        // retrying the connection.
        this.lastError &&
        ! hasSockJS &&
        import("./sockjs-0.3.4.js")
      ).done(() => {
        this._lostConnection();
      });
    };

    this.socket.onerror = error => {
      const { lastError } = this;
      this.lastError = error;
      if (lastError) return;
      console.log(
        'stream error',
        error,
        new Date().toDateString()
      );
    };

    this.socket.onheartbeat = () => {
      this.lastError = null;
      this._heartbeat_received();
    };

    if (this.connectionTimer) clearTimeout(this.connectionTimer);
    this.connectionTimer = setTimeout(() => {
      this._lostConnection(
        new this.ConnectionError("DDP connection timed out")
      );
    }, this.CONNECT_TIMEOUT);
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import ReactAudioPlayer from 'react-audio-player';
import axios from "axios";

class availableDatalist extends React.Component {
   availableDatalist(props) {
    return(

{props.all_songs.map(c =>
c.name

c.album
 )}

    )

  }
}

class SongBoard extends React.Component {
getAllSongs() {
  axios
  .get("http://localhost:8000/song/")
  .then(response => {
    const songs = response.data.map(c => {
      return{
        name: c.name
        album: c.album
      };
    });

    const newState = Object.assign({}, this.state, {
          all_songs: songs
        });

    this.setState(newState);

  })
  .catch(error => console.log(error));
}

  render() {
    return(

            <button className="song">
              Song
            </button>
            <button className="album">
              Album
            </button>

          <availableDatalist songs={this.state.all_songs} />

    )
  }
}

class Player extends React.Component {
  render() {
    return(
      <ReactAudioPlayer
        src="my_audio_file.ogg"
        autoPlay
        controls
      />
    )
  }
}

class Site extends React.Component {
  render() {
    return (

          <Player />

          <SongBoard />

    )
  }
}

ReactDOM.render(
  <Site />,
  document.getElementById('root')
);
<commit_msg>reactplayer<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import ReactAudioPlayer from 'react-audio-player';
import axios from "axios";

class availableDatalist extends React.Component {
   availableDatalist(props) {
    return(

{props.all_songs.map(c =>

c.name

c.album

 )}

    )

  }
}

class SongBoard extends React.Component {
getAllSongs() {
  axios
  .get("http://localhost:8000/song/")
  .then(response => {
    const songs = response.data.map(c => {
      return{
        name: c.name
        album: c.album
      };
    });

    const newState = Object.assign({}, this.state, {
          all_songs: songs
        });

    this.setState(newState);

  })
  .catch(error => console.log(error));
}

  render() {
    return(

            <button className="song">
              Song
            </button>
            <button className="album">
              Album
            </button>

          <availableDatalist songs={this.state.all_songs} />

    )
  }
}

class Player extends React.Component {
  render() {
    return(
      <ReactAudioPlayer
        src="my_audio_file.ogg"
        autoPlay
        controls
      />
    )
  }
}

class Site extends React.Component {
  render() {
    return (

          <Player />

          <SongBoard />

    )
  }
}

ReactDOM.render(
  <Site />,
  document.getElementById('root')
);
<|endoftext|>


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

export default class Dashboard extends Component {
  render() {
    const loading = true;
    return  (

Dashboard

          {loading &&
Cargando ...
}

    )
  }
}<commit_msg>user selector in dashboard<commit_after>import React, {Component} from 'react'
import { renderAsyncSelect as AsyncSelect } from '../../shared/FormFields';
import { searchUsers } from 'services/selectHelpers'
import styled from 'styled-components';
import {connect} from 'react-redux'

const Header = styled.div`
  display: flex;
  justify-content: space-between;
  .select-icon {
    line-height: 60px;
    padding: 12px;
    padding-bottom: 0;
  }
  .select-container {
    min-width: 230px;
  }
`;

class Dashboard extends Component {
  state = {
    selectedUser: {}
  }
  componentWillReceiveProps(nextProps) {
    if(nextProps.selectedUser.value !== this.state.selectedUser.value) {
      this.setState({selectedUser: nextProps.selectedUser})
    }
  }
  render() {
    const loading = true;
    const searchInputProps = {
      value: this.state.selectedUser,
      onChange: (selectedUser) => this.setState({selectedUser})
    }
    return  (

Reportes

            {this.props.isAdmin && (
              <AsyncSelect
                name="user"
                icon="person"
                label="Usuario"
                className="select"
                placeholder="Escribe para buscar"
                loadOptions={searchUsers}
                input={searchInputProps}
                meta={{}}
              />
            )}

          {loading &&
Cargando ...
}

    )
  }
}

export default connect(
  (state, props) => {
    return {
      isAdmin: state.auth.roles.indexOf("ADMIN") !== -1,
      selectedUser: {
        label: state.auth.full_name,
        value: state.auth._id
      }
    }
  }
)(Dashboard)
<|endoftext|>


<commit_before><commit_msg>general updating 140<commit_after><|endoftext|>


<commit_before>import { reject, resolve } from 'rsvp';
import { ResolvedHandlerInfo } from './handler-info';
import { trigger, slice, log, promiseLabel } from './utils';

/**
  @private

  A Transition is a thennable (a promise-like object) that represents
  an attempt to transition to another route. It can be aborted, either
  explicitly via `abort` or by attempting another transition while a
  previous one is still underway. An aborted transition can also
  be `retry()`d later.
 */
function Transition(router, intent, state, error) {
  var transition = this;
  this.state = state || router.state;
  this.intent = intent;
  this.router = router;
  this.data = this.intent && this.intent.data || {};
  this.resolvedModels = {};
  this.queryParams = {};

  if (error) {
    this.promise = reject(error);
    return;
  }

  if (state) {
    this.params = state.params;
    this.queryParams = state.queryParams;

    var len = state.handlerInfos.length;
    if (len) {
      this.targetName = state.handlerInfos[state.handlerInfos.length-1].name;
    }

    for (var i = 0; i < len; ++i) {
      var handlerInfo = state.handlerInfos[i];
      if (!(handlerInfo instanceof ResolvedHandlerInfo)) {
        break;
      }
      this.pivotHandler = handlerInfo.handler;
    }

    this.sequence = Transition.currentSequence++;
    this.promise = state.resolve(router.async, checkForAbort, this)['catch'](function(result) {
      if (result.wasAborted) {
        throw logAbort(transition);
      } else {
        transition.trigger('error', result.error, transition, result.handlerWithError);
        transition.abort();
        throw result.error;
      }
    }, promiseLabel('Handle Abort'));
  } else {
    this.promise = resolve(this.state);
    this.params = {};
  }

  function checkForAbort() {
    if (transition.isAborted) {
      return reject(undefined, promiseLabel("Transition aborted - reject"));
    }
  }
}

Transition.currentSequence = 0;

Transition.prototype = {
  targetName: null,
  urlMethod: 'update',
  intent: null,
  params: null,
  pivotHandler: null,
  resolveIndex: 0,
  handlerInfos: null,
  resolvedModels: null,
  isActive: true,
  state: null,

  /**
    @public

    The Transition's internal promise. Calling `.then` on this property
    is that same as calling `.then` on the Transition object itself, but
    this property is exposed for when you want to pass around a
    Transition's promise, but not the Transition object itself, since
    Transition object can be externally `abort`ed, while the promise
    cannot.
   */
  promise: null,

  /**
    @public

    Custom state can be stored on a Transition's `data` object.
    This can be useful for decorating a Transition within an earlier
    hook and shared with a later hook. Properties set on `data` will
    be copied to new transitions generated by calling `retry` on this
    transition.
   */
  data: null,

  /**
    @public

    A standard promise hook that resolves if the transition
    succeeds and rejects if it fails/redirects/aborts.

    Forwards to the internal `promise` property which you can
    use in situations where you want to pass around a thennable,
    but not the Transition itself.

    @param {Function} success
    @param {Function} failure
   */
  then: function(success, failure) {
    return this.promise.then(success, failure);
  },

  /**
    @public

    Aborts the Transition. Note you can also implicitly abort a transition
    by initiating another transition while a previous one is underway.
   */
  abort: function() {
    if (this.isAborted) { return this; }
    log(this.router, this.sequence, this.targetName + ": transition was aborted");
    this.isAborted = true;
    this.isActive = false;
    this.router.activeTransition = null;
    return this;
  },

  /**
    @public

    Retries a previously-aborted transition (making sure to abort the
    transition if it's still active). Returns a new transition that
    represents the new attempt to transition.
   */
  retry: function() {
    // TODO: add tests for merged state retry()s
    this.abort();
    return this.router.transitionByIntent(this.intent, false);
  },

  /**
    @public

    Sets the URL-changing method to be employed at the end of a
    successful transition. By default, a new Transition will just
    use `updateURL`, but passing 'replace' to this method will
    cause the URL to update using 'replaceWith' instead. Omitting
    a parameter will disable the URL change, allowing for transitions
    that don't update the URL at completion (this is also used for
    handleURL, since the URL has already changed before the
    transition took place).

    @param {String} method the type of URL-changing method to use
      at the end of a transition. Accepted values are 'replace',
      falsy values, or any other non-falsy value (which is
      interpreted as an updateURL transition).

    @return {Transition} this transition
   */
  method: function(method) {
    this.urlMethod = method;
    return this;
  },

  /**
    @public

    Fires an event on the current list of resolved/resolving
    handlers within this transition. Useful for firing events
    on route hierarchies that haven't fully been entered yet.

    Note: This method is also aliased as `send`

    @param {Boolean} ignoreFailure the name of the event to fire
    @param {String} name the name of the event to fire
   */
  trigger: function (ignoreFailure) {
    var args = slice.call(arguments);
    if (typeof ignoreFailure === 'boolean') {
      args.shift();
    } else {
      // Throw errors on unhandled trigger events by default
      ignoreFailure = false;
    }
    trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args);
  },

  /**
    @public

    Transitions are aborted and their promises rejected
    when redirects occur; this method returns a promise
    that will follow any redirects that occur and fulfill
    with the value fulfilled by any redirecting transitions
    that occur.

    @return {Promise} a promise that fulfills with the same
      value that the final redirecting transition fulfills with
   */
  followRedirects: function() {
    var router = this.router;
    return this.promise['catch'](function(reason) {
      if (router.activeTransition) {
        return router.activeTransition.followRedirects();
      }
      throw reason;
    });
  },

  toString: function() {
    return "Transition (sequence " + this.sequence + ")";
  },

  /**
    @private
   */
  log: function(message) {
    log(this.router, this.sequence, message);
  }
};

// Alias 'trigger' as 'send'
Transition.prototype.send = Transition.prototype.trigger;

/**
  @private

  Logs and returns a TransitionAborted error.
 */
function logAbort(transition) {
  log(transition.router, transition.sequence, "detected abort.");
  return new TransitionAborted();
}

function TransitionAborted(message) {
  this.message = (message || "TransitionAborted");
  this.name = "TransitionAborted";
}

export { Transition, logAbort, TransitionAborted };
<commit_msg>Correct docs for Transition#trigger<commit_after>import { reject, resolve } from 'rsvp';
import { ResolvedHandlerInfo } from './handler-info';
import { trigger, slice, log, promiseLabel } from './utils';

/**
  @private

  A Transition is a thennable (a promise-like object) that represents
  an attempt to transition to another route. It can be aborted, either
  explicitly via `abort` or by attempting another transition while a
  previous one is still underway. An aborted transition can also
  be `retry()`d later.
 */
function Transition(router, intent, state, error) {
  var transition = this;
  this.state = state || router.state;
  this.intent = intent;
  this.router = router;
  this.data = this.intent && this.intent.data || {};
  this.resolvedModels = {};
  this.queryParams = {};

  if (error) {
    this.promise = reject(error);
    return;
  }

  if (state) {
    this.params = state.params;
    this.queryParams = state.queryParams;

    var len = state.handlerInfos.length;
    if (len) {
      this.targetName = state.handlerInfos[state.handlerInfos.length-1].name;
    }

    for (var i = 0; i < len; ++i) {
      var handlerInfo = state.handlerInfos[i];
      if (!(handlerInfo instanceof ResolvedHandlerInfo)) {
        break;
      }
      this.pivotHandler = handlerInfo.handler;
    }

    this.sequence = Transition.currentSequence++;
    this.promise = state.resolve(router.async, checkForAbort, this)['catch'](function(result) {
      if (result.wasAborted) {
        throw logAbort(transition);
      } else {
        transition.trigger('error', result.error, transition, result.handlerWithError);
        transition.abort();
        throw result.error;
      }
    }, promiseLabel('Handle Abort'));
  } else {
    this.promise = resolve(this.state);
    this.params = {};
  }

  function checkForAbort() {
    if (transition.isAborted) {
      return reject(undefined, promiseLabel("Transition aborted - reject"));
    }
  }
}

Transition.currentSequence = 0;

Transition.prototype = {
  targetName: null,
  urlMethod: 'update',
  intent: null,
  params: null,
  pivotHandler: null,
  resolveIndex: 0,
  handlerInfos: null,
  resolvedModels: null,
  isActive: true,
  state: null,

  /**
    @public

    The Transition's internal promise. Calling `.then` on this property
    is that same as calling `.then` on the Transition object itself, but
    this property is exposed for when you want to pass around a
    Transition's promise, but not the Transition object itself, since
    Transition object can be externally `abort`ed, while the promise
    cannot.
   */
  promise: null,

  /**
    @public

    Custom state can be stored on a Transition's `data` object.
    This can be useful for decorating a Transition within an earlier
    hook and shared with a later hook. Properties set on `data` will
    be copied to new transitions generated by calling `retry` on this
    transition.
   */
  data: null,

  /**
    @public

    A standard promise hook that resolves if the transition
    succeeds and rejects if it fails/redirects/aborts.

    Forwards to the internal `promise` property which you can
    use in situations where you want to pass around a thennable,
    but not the Transition itself.

    @param {Function} success
    @param {Function} failure
   */
  then: function(success, failure) {
    return this.promise.then(success, failure);
  },

  /**
    @public

    Aborts the Transition. Note you can also implicitly abort a transition
    by initiating another transition while a previous one is underway.
   */
  abort: function() {
    if (this.isAborted) { return this; }
    log(this.router, this.sequence, this.targetName + ": transition was aborted");
    this.isAborted = true;
    this.isActive = false;
    this.router.activeTransition = null;
    return this;
  },

  /**
    @public

    Retries a previously-aborted transition (making sure to abort the
    transition if it's still active). Returns a new transition that
    represents the new attempt to transition.
   */
  retry: function() {
    // TODO: add tests for merged state retry()s
    this.abort();
    return this.router.transitionByIntent(this.intent, false);
  },

  /**
    @public

    Sets the URL-changing method to be employed at the end of a
    successful transition. By default, a new Transition will just
    use `updateURL`, but passing 'replace' to this method will
    cause the URL to update using 'replaceWith' instead. Omitting
    a parameter will disable the URL change, allowing for transitions
    that don't update the URL at completion (this is also used for
    handleURL, since the URL has already changed before the
    transition took place).

    @param {String} method the type of URL-changing method to use
      at the end of a transition. Accepted values are 'replace',
      falsy values, or any other non-falsy value (which is
      interpreted as an updateURL transition).

    @return {Transition} this transition
   */
  method: function(method) {
    this.urlMethod = method;
    return this;
  },

  /**
    @public

    Fires an event on the current list of resolved/resolving
    handlers within this transition. Useful for firing events
    on route hierarchies that haven't fully been entered yet.

    Note: This method is also aliased as `send`

    @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error
    @param {String} name the name of the event to fire
   */
  trigger: function (ignoreFailure) {
    var args = slice.call(arguments);
    if (typeof ignoreFailure === 'boolean') {
      args.shift();
    } else {
      // Throw errors on unhandled trigger events by default
      ignoreFailure = false;
    }
    trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args);
  },

  /**
    @public

    Transitions are aborted and their promises rejected
    when redirects occur; this method returns a promise
    that will follow any redirects that occur and fulfill
    with the value fulfilled by any redirecting transitions
    that occur.

    @return {Promise} a promise that fulfills with the same
      value that the final redirecting transition fulfills with
   */
  followRedirects: function() {
    var router = this.router;
    return this.promise['catch'](function(reason) {
      if (router.activeTransition) {
        return router.activeTransition.followRedirects();
      }
      throw reason;
    });
  },

  toString: function() {
    return "Transition (sequence " + this.sequence + ")";
  },

  /**
    @private
   */
  log: function(message) {
    log(this.router, this.sequence, message);
  }
};

// Alias 'trigger' as 'send'
Transition.prototype.send = Transition.prototype.trigger;

/**
  @private

  Logs and returns a TransitionAborted error.
 */
function logAbort(transition) {
  log(transition.router, transition.sequence, "detected abort.");
  return new TransitionAborted();
}

function TransitionAborted(message) {
  this.message = (message || "TransitionAborted");
  this.name = "TransitionAborted";
}

export { Transition, logAbort, TransitionAborted };
<|endoftext|>


<commit_before>import {helper} from '@ember/component/helper';

export const AVAILABLE_EVENTS = [
    // GROUPNAME: Global
    {event: 'site.changed', name: 'Site changed (rebuild)', group: 'Global'},

    // GROUPNAME: Posts
    {event: 'post.added', name: 'Post created', group: 'Posts'},
    {event: 'post.deleted', name: 'Post deleted', group: 'Posts'},
    {event: 'post.edited', name: 'Post updated', group: 'Posts'},
    {event: 'post.published', name: 'Post published', group: 'Posts'},
    {event: 'post.published.edited', name: 'Published post updated', group: 'Posts'},
    {event: 'post.unpublished', name: 'Post unpublished', group: 'Posts'},
    {event: 'post.tag.attached', name: 'Tag added to post', group: 'Posts'},
    {event: 'post.tag.detached', name: 'Tag removed from post', group: 'Posts'},

    // GROUPNAME: Pages
    {event: 'page.added', name: 'Page created', group: 'Pages'},
    {event: 'page.deleted', name: 'Page deleted', group: 'Pages'},
    {event: 'page.edited', name: 'Page updated', group: 'Pages'},
    {event: 'page.published', name: 'Page published', group: 'Pages'},
    {event: 'page.published.edited', name: 'Published page updated', group: 'Pages'},
    {event: 'page.unpublished', name: 'Page unpublished', group: 'Pages'},
    {event: 'page.tag.attached', name: 'Tag added to page', group: 'Pages'},
    {event: 'page.tag.detached', name: 'Tag removed from page', group: 'Pages'},

    // GROUPNAME: Tags
    {event: 'tag.added', name: 'Tag created', group: 'Tags'},
    {event: 'tag.edited', name: 'Tag updated', group: 'Tags'},
    {event: 'tag.deleted', name: 'Tag deleted', group: 'Tags'}
];

export function eventName([event]/*, hash*/) {
    let match = AVAILABLE_EVENTS.findBy('event', event);

    return match ? match.name : event;
}

export default helper(eventName);
<commit_msg>Added "Member added" event to webhooks list (#1359)<commit_after>import {helper} from '@ember/component/helper';

export const AVAILABLE_EVENTS = [
    // GROUPNAME: Global
    {event: 'site.changed', name: 'Site changed (rebuild)', group: 'Global'},

    // GROUPNAME: Posts
    {event: 'post.added', name: 'Post created', group: 'Posts'},
    {event: 'post.deleted', name: 'Post deleted', group: 'Posts'},
    {event: 'post.edited', name: 'Post updated', group: 'Posts'},
    {event: 'post.published', name: 'Post published', group: 'Posts'},
    {event: 'post.published.edited', name: 'Published post updated', group: 'Posts'},
    {event: 'post.unpublished', name: 'Post unpublished', group: 'Posts'},
    {event: 'post.tag.attached', name: 'Tag added to post', group: 'Posts'},
    {event: 'post.tag.detached', name: 'Tag removed from post', group: 'Posts'},

    // GROUPNAME: Pages
    {event: 'page.added', name: 'Page created', group: 'Pages'},
    {event: 'page.deleted', name: 'Page deleted', group: 'Pages'},
    {event: 'page.edited', name: 'Page updated', group: 'Pages'},
    {event: 'page.published', name: 'Page published', group: 'Pages'},
    {event: 'page.published.edited', name: 'Published page updated', group: 'Pages'},
    {event: 'page.unpublished', name: 'Page unpublished', group: 'Pages'},
    {event: 'page.tag.attached', name: 'Tag added to page', group: 'Pages'},
    {event: 'page.tag.detached', name: 'Tag removed from page', group: 'Pages'},

    // GROUPNAME: Tags
    {event: 'tag.added', name: 'Tag created', group: 'Tags'},
    {event: 'tag.edited', name: 'Tag updated', group: 'Tags'},
    {event: 'tag.deleted', name: 'Tag deleted', group: 'Tags'},

    // GROUPNAME: Members
    {event: 'member.added', name: 'Member added', group: 'Members'}
    // TODO: enable once server-side payload is fixed
    // {event: 'member.deleted', name: 'Member deleted', group: 'Members'}
];

export function eventName([event]/*, hash*/) {
    let match = AVAILABLE_EVENTS.findBy('event', event);

    return match ? match.name : event;
}

export default helper(eventName);
<|endoftext|>


<commit_before>'use strict';

angular.module('pumprApp')
  .directive('documentForm',  ['agsServer', 'DocumentFactory', 'streetSearch', '$timeout', '$filter', '$http',
    function (agsServer, DocumentFactory, streetSearch, $timeout, $filter, $http) {
    return {
      restrict: 'E',
      transclude: true,
      scope: {
        project: '='
      },
      templateUrl: 'app/directives/documentForm/documentForm.html',
      link: function (scope) {
          //   scope.projects = [];
          //   var baseproject;
          //   scope.supportTables = [
          //     {
          //         name: 'engTypes',
          //         id: 'RPUD.ENGINEERINGFIRM',
          //         joinField: 'ENGID',
          //         addField: 'SIMPLIFIEDNAME',
          //     },
          //     {
          //         name: 'sheetTypes',
          //         id: 'RPUD.SHEETTYPES',
          //         joinField: 'SHEETTYPEID',
          //         addField: 'SHEETTYPE',
          //     },
          //     {
          //         name: 'docTypes',
          //         id: 'RPUD.DOCUMENTTYPES',
          //         joinField: 'DOCTYPEID',
          //         addField: 'DOCUMENTTYPE',
          //     }
          //    ];
          //
          //
          //    //Watch for change of project
          //   scope.project = undefined;
          //   scope.refresh = function (project){
          //   if (project !== undefined){
          //     scope.supportTables.forEach(function(table){
          //       var name = table.name;
          //
          //       var options = {
          //         layer: table.id,
          //         actions: 'query',
          //         params: {
          //           f: 'json',
          //           where: '1=1',
          //           outFields: '*',
          //           orderByFields: table.addField + ' ASC',
          //           returnGeometry: false
          //         }
          //       };
          //       agsServer.ptFs.request(options).then(function(d){
          //         table.data = d.features;
          //         // agsServer.addFieldFromTable(project, table.data, table.joinField, table.addField);
          //         switch (name){
          //           case 'engTypes':
          //             scope.engTypes = table.data;
          //             break;
          //           case 'sheetTypes':
          //             scope.sheetTypes = table.data;
          //             break;
          //           case 'docTypes':
          //             scope.docTypes = table.data;
          //             break;
          //           default:
          //             console.log('Table not found');
          //         }
          //       });
          //     });
          //     //Adds new key value pair to data object for edit controls and sets boolean values to text
          //     //Probably should make this a method of ags service
              var utils = ['WATER', 'SEWER', 'REUSE', 'STORM'];
          //       project.forEach(function(data){
          //         //Sets all edit states to false
          //         data.edit = false;
          //         //Checks if file currently exisits
          //         checkUpload(data.attributes.PROJECTID + '-' + data.attributes.DOCTYPEID + '-' + data.attributes.DOCID).then(function(res){
          //           data.upload = res.data;
          //           data.upload.isSuccess = false;
          //         },
          //         function (error){
          //           console.error(error);
          //         });
          //         //Sets boolean values for utility options
          //         for (var _i = 0, _len = utils.length; _i < _len; _i++){
          //          data.attributes[utils[_i]] = data.attributes[utils[_i]] ? true : false;
          //         }
          //         //Convert number to date object
          //         if (typeof data.attributes.SEALDATE === 'number' && !isNaN(data.attributes.SEALDATE)){
          //           data.attributes.SEALDATE = new Date(data.attributes.SEALDATE);
          //         }
          //
          //       });
          //   }
          //   console.log(scope.project)
          // };
          //

          //Add new document visibility controll
          scope.addDoc = true;
          //Master Copy of projects base  data
          scope.master = [];
          //Get pick lists for table
          var helperTables = DocumentFactory.getTables()
            .then(function(data){
              console.log(data);
              scope.engTypes = data[0].features;
              scope.sheetTypes = data[1].features;
              scope.docTypes = data[2].features;
            })
            .catch(function(err){
              console.error(err);
            });

          //Setup Boolean option for utilies options..could/should switch to service or provider
          scope.selectionOptions = {
            bool: [{'name': 'true', 'id': 1}, {'name': 'false', 'id': 0}],
          };

          scope.$watchCollection('project',function(newVal, oldVal){
            console.log(newVal)
            scope.project = newVal;
            if (scope.project !== undefined && Array.isArray(scope.project)){
              scope.project.forEach(function(data){
                //Sets all edit states to false
                data.edit = false;
                //Checks if file currently exisits
                checkUpload(data.attributes.PROJECTID + '-' + data.attributes.DOCTYPEID + '-' + data.attributes.DOCID).then(function(res){
                    data.upload = res.data;
                    data.upload.isSuccess = false;
                },
                function (error){
                    console.error(error);
                });

                //Convert number to date object
                if (typeof data.attributes.SEALDATE === 'number' && !isNaN(data.attributes.SEALDATE)){
                  data.attributes.SEALDATE = new Date(data.attributes.SEALDATE);
                }

              });
            }
          });

        //Starts edit session on selected table row
        scope.edit = function (doc) {
          //resets documet
          scope.project.forEach(function(data){
            data.edit = false;
          });
          //Activates editor
          doc.edit = true;
          //Turns off editor after 10 seconds
          $timeout(function(){
            doc.edit = false;
          }, (60000 * 5));
        };

        scope.add = function(){
          var data = scope.project;
          if (data.length === 1 && data[0].new){
            //Set first document id
            data[0].attributes.DOCID =  1;
            utils.forEach(function(item){
              data[0].attributes[item] = 0;
            });
            //Add document
            DocumentFactory.add(data[0].attributes)
              .then(function(res){
                console.log(res);
                //Sets boolean values for utility options
                utils.forEach(function(item){
                  data[0].attributes[item] = false;
                });

                scope.project.splice(0, 1, {attributes: data[0].attributes, edit: false});
              })
              .catch(function(err){
                console.log(err);
              });
          }
          else{
            var count = data.length + 1,
                index = count - 2,
                fillData = data[index].attributes,
                // angular.copy(data[index].attributes, fillData),
                addData = {
                  DOCID: count,
                  DEVPLANID: fillData.DEVPLANID,
                  PROJECTID: fillData.PROJECTID,
                  PROJECTNAME: fillData.PROJECTNAME
                };

                if (fillData.ENGID){
                  addData.ENGID = fillData.ENGID;
                }
                if (fillData.SEALDATE instanceof Date){
                  addData.SEALDATE = fillData.SEALDATE.getTime();
                }

            console.log(addData);
            DocumentFactory.add(addData)
              .then(function(res){
                console.log(res);
                if (addData.ENGID){
                  scope.engTypes.forEach(function(data){
                    addData.SIMPLIFIEDNAME = addData.ENGID === data.attributes.ENGID ? data.attributes.SIMPLIFIEDNAME : addData.SIMPLIFIEDNAME;
                  });
                  scope.project.push({attributes: addData, edit: false});
                }
                else{
                  scope.project.push({attributes: addData, edit: false});
                }

              })
              .catch(function(err){
                console.log(res);
              });
          }
          // var firstRecord, engid;
          // // scope.addDoc = false;
          // if (scope.project){
          //   console.log(scope.project)
          //   if (scope.project.length === 1){
          //     firstRecord = scope.project[0].attributes
          //     scope.newDocument = new DocumentFactory({
          //       PROJECTNAME: firstRecord.PROJECTNAME,
          //       PROJECTID: firstRecord.PROJECTID,
          //       DEVPLANID: firstRecord.DEVPLANID || undefined,
          //       DOCID: 1
          //     });
          //
          //     scope.newDocument.postNewDoc();
          //     scope.newDoc = scope.newDocument.getData();
          //     scope.project.push({attributes: scope.newDoc, edit: false});
          //   }
          //   else {
          //     var fillData = scope.project[scope.project.length -1].attributes,
          //         sealdate = fillData.SEALDATE;
          //
          //     //Convert date object to timestamp
          //     if (sealdate instanceof Date){
          //       sealdate = sealdate.getTime();
          //     }
          //
          //     if (fillData.ENGID){
          //       engid = {
          //         ENGID: fillData.ENGID,
          //         SIMPLIFIEDNAME: fillData.SIMPLIFIEDNAME
          //       };
          //     }
          //     else{
          //       engid = scope.project.length > 1 ? scope.project[1].ENGID.attributes : undefined;
          //     }
          //       // var engid = scope.project.length > 1 ? scope.project[1].ENGID.attributes : undefined;
          //       console.log(engid, scope.project.length)
          //
          //     scope.newDocument = new DocumentFactory({
          //       PROJECTNAME: fillData.PROJECTNAME,
          //       PROJECTID: fillData.PROJECTID,
          //       DEVPLANID: fillData.DEVPLANID || undefined,
          //       ENGID: engid.ENGID || undefined,
          //       SEALDATE: sealdate,
          //       DOCID: scope.project[scope.project.length - 1].attributes.DOCID + 1 || 1
          //     });
          //
          //     //POSTS new document to AGS server
          //     scope.newDocument.postNewDoc();
          //     scope.newDoc = scope.newDocument.getData();
          //
          //     // var sealdate = scope.newDoc.SEALDATE;
          //     console.log(scope.newDoc);
          //     //Set engineering firm for display
          //     scope.newDoc.SIMPLIFIEDNAME = engid.SIMPLIFIEDNAME;
          //     scope.project.push({attributes: scope.newDoc, edit: false});
          //     // scope.addDoc = true;
          //   }
          // }
          // else{
          //   console.log('Please try again')
          // }
        };

        //Post data to server
        scope.post = function(data){
          var targ;
        	if (!e) var e = window.event;
        	if (e.target) targ = e.target;
        	else if (e.srcElement) targ = e.srcElement;
        	if (targ.nodeType == 3) // defeat Safari bug
        		targ = targ.parentNode;
            angular.element(targ).removeClass('animated shake addDocFailure addDocSuccess');

          console.log(data);

          DocumentFactory.update(data)
            .then(function(res){
              if (res.error){
                angular.element(targ).addClass('animated shake addDocFailure');
              }
              else{
                angular.element(targ).addClass('addDocSuccess');
              }
            })
            .catch(function(err){
              angular.element(targ).addClass('animated shake addDocFailure');
            });
          //Sets updated values
          // scope.updateDocument = new DocumentFactory(data).setValue(data);
          //Updates document on server
          // scope.updateDocument.updateDoc()
          // .then(function(data){
          //   if (data.error){
          //     console.log(data.error);
          //     angular.element(targ).addClass('animated shake addDocFailure');
          //   }
          //   else{
          //     angular.element(targ).addClass('addDocSuccess');
          //   }
          // },
          // function(err){
          //   angular.element(targ).addClass('animated shake addDocFailure');
          // });
        };

        scope.delete = function (index, data){
          var master = {
            attributes: {
              DEVPLANID: '',
              PROJECTID: '',
              PROJECTNAME: ''
            },
            new: true,
            edit: false
          };

          DocumentFactory.delete(data)
            .then(function(res){
              if (index === 0){
                angular.extend(master, scope.project[0]);
                scope.project.splice(0, 1, master);
              }
              else{
                //Deletes document object from array
                scope.project.splice(index, 1);
              }
              console.log(res);
            })
            .catch(function(err){
              console.log(err);
            });
        };

        function checkUpload (filename){
          var config = {
            params: {
              filename: filename
            }
          };
          return $http.get('/api/documents', config);
        }

      }
    };
  }
]);
<commit_msg>Removed old comments<commit_after>'use strict';

angular.module('pumprApp')
  .directive('documentForm',  ['agsServer', 'DocumentFactory', 'streetSearch', '$timeout', '$filter', '$http',
    function (agsServer, DocumentFactory, streetSearch, $timeout, $filter, $http) {
    return {
      restrict: 'E',
      transclude: true,
      scope: {
        project: '='
      },
      templateUrl: 'app/directives/documentForm/documentForm.html',
      link: function (scope) {

              var utils = ['WATER', 'SEWER', 'REUSE', 'STORM'];

          //Add new document visibility controll
          scope.addDoc = true;
          //Master Copy of projects base  data
          scope.master = [];
          //Get pick lists for table
          var helperTables = DocumentFactory.getTables()
            .then(function(data){
              console.log(data);
              scope.engTypes = data[0].features;
              scope.sheetTypes = data[1].features;
              scope.docTypes = data[2].features;
            })
            .catch(function(err){
              console.error(err);
            });

          //Setup Boolean option for utilies options..could/should switch to service or provider
          scope.selectionOptions = {
            bool: [{'name': 'true', 'id': 1}, {'name': 'false', 'id': 0}],
          };

          scope.$watchCollection('project',function(newVal, oldVal){
            console.log(newVal)
            scope.project = newVal;
            if (scope.project !== undefined && Array.isArray(scope.project)){
              scope.project.forEach(function(data){
                //Sets all edit states to false
                data.edit = false;
                //Checks if file currently exisits
                checkUpload(data.attributes.PROJECTID + '-' + data.attributes.DOCTYPEID + '-' + data.attributes.DOCID).then(function(res){
                    data.upload = res.data;
                    data.upload.isSuccess = false;
                },
                function (error){
                    console.error(error);
                });

                //Convert number to date object
                if (typeof data.attributes.SEALDATE === 'number' && !isNaN(data.attributes.SEALDATE)){
                  data.attributes.SEALDATE = new Date(data.attributes.SEALDATE);
                }

              });
            }
          });

        //Starts edit session on selected table row
        scope.edit = function (doc) {
          //resets documet
          scope.project.forEach(function(data){
            data.edit = false;
          });
          //Activates editor
          doc.edit = true;
          //Turns off editor after 10 seconds
          $timeout(function(){
            doc.edit = false;
          }, (60000 * 5));
        };

        scope.add = function(){
          var data = scope.project;
          if (data.length === 1 && data[0].new){
            //Set first document id
            data[0].attributes.DOCID =  1;
            utils.forEach(function(item){
              data[0].attributes[item] = 0;
            });
            //Add document
            DocumentFactory.add(data[0].attributes)
              .then(function(res){
                console.log(res);
                //Sets boolean values for utility options
                utils.forEach(function(item){
                  data[0].attributes[item] = false;
                });

                scope.project.splice(0, 1, {attributes: data[0].attributes, edit: false});
              })
              .catch(function(err){
                console.log(err);
              });
          }
          else{
            var count = data.length + 1,
                index = count - 2,
                fillData = data[index].attributes,
                // angular.copy(data[index].attributes, fillData),
                addData = {
                  DOCID: count,
                  DEVPLANID: fillData.DEVPLANID,
                  PROJECTID: fillData.PROJECTID,
                  PROJECTNAME: fillData.PROJECTNAME
                };

                if (fillData.ENGID){
                  addData.ENGID = fillData.ENGID;
                }
                if (fillData.SEALDATE instanceof Date){
                  addData.SEALDATE = fillData.SEALDATE.getTime();
                }

            console.log(addData);
            DocumentFactory.add(addData)
              .then(function(res){
                console.log(res);
                if (addData.ENGID){
                  scope.engTypes.forEach(function(data){
                    addData.SIMPLIFIEDNAME = addData.ENGID === data.attributes.ENGID ? data.attributes.SIMPLIFIEDNAME : addData.SIMPLIFIEDNAME;
                  });
                  scope.project.push({attributes: addData, edit: false});
                }
                else{
                  scope.project.push({attributes: addData, edit: false});
                }

              })
              .catch(function(err){
                console.log(res);
              });
          }

        };

        //Post data to server
        scope.post = function(data){
          var targ;
        	if (!e) var e = window.event;
        	if (e.target) targ = e.target;
        	else if (e.srcElement) targ = e.srcElement;
        	if (targ.nodeType == 3) // defeat Safari bug
        		targ = targ.parentNode;
            angular.element(targ).removeClass('animated shake addDocFailure addDocSuccess');

          console.log(data);

          DocumentFactory.update(data)
            .then(function(res){
              if (res.error){
                angular.element(targ).addClass('animated shake addDocFailure');
              }
              else{
                angular.element(targ).addClass('addDocSuccess');
              }
            })
            .catch(function(err){
              angular.element(targ).addClass('animated shake addDocFailure');
            });

        };

        scope.delete = function (index, data){
          var master = {
            attributes: {
              DEVPLANID: '',
              PROJECTID: '',
              PROJECTNAME: ''
            },
            new: true,
            edit: false
          };

          DocumentFactory.delete(data)
            .then(function(res){
              if (index === 0){
                angular.extend(master, scope.project[0]);
                scope.project.splice(0, 1, master);
              }
              else{
                //Deletes document object from array
                scope.project.splice(index, 1);
              }
              console.log(res);
            })
            .catch(function(err){
              console.log(err);
            });
        };

        function checkUpload (filename){
          var config = {
            params: {
              filename: filename
            }
          };
          return $http.get('/api/documents', config);
        }

      }
    };
  }
]);
<|endoftext|>


<commit_before>;(function(w, d, undefined) {
  'use strict';

  var _defaults = {
    name: null,
    duration: '1s',
    delay: 0,
    easing: 'linear',
    waits: null,
    repeat: 1,
    callback: null,
    'fill-mode': 'forwards',
    direction: 'normal',
    iterations: 1,
    play: 'true',
    bind: 'none'
  },
  _valid_properties = Object.keys(_defaults),
  _init = {},
  _waits = {};

  var _slice = Array.prototype.slice,
  _hop = Object.prototype.hasOwnProperty,
  _on = d.addEventListener || d.attachEvent,
  _off = d.removeEventListener || d.detachEvent,
  //_to_camel_case = function(underscored) {
    //return underscored
    //.replace(/^-/g, '')
    //.replace(/-([a-z])/g, function(match, letter) {
      //return letter.toUpperCase();
    //});
  //},
  _extend = function (target, source) {
    for (var k in source) {
      if (_hop.call(source, k)) {
        target[k] = source[k];
      }
    }

    return target;
  },
  _find_by_id = function() {
    return d.getElementById.apply(d, arguments);
  },
  _find_by_tag = function(el) {
    return el.getElementsByTagName.apply(el, _slice.call(arguments, 1));
  };

  var _instance,
      _style = d.createElement('style'),
      _ID = 0,
      _keyframe_content = '@%key%keyframes %name% {%keyframes% }',
      _crossbrowser_keys = ['-webkit-', '-moz-', '-o-', ''],
      _animation_properties = {
        delay: 'delay',
        direction: 'direction',
        duration: 'duration',
        'fill-mode': 'fill-mode',
        iterations: 'iteration-count',
        'easing': 'timing-function'
      },
      _unit = function(a) {
        return a.replace(String(parseFloat(a)), '').trim();
      },
      _crossbrowser = function(prop, value) {
        var _output = '';

        for (var k = 0, l = _crossbrowser_keys.length, key; k < l; k++) {
          key = _crossbrowser_keys[k];
          if (value === undefined) {
            prop(key);
          } else  {
            _output += key + prop + ':' + value + ';';
          }
        }

        return _output;
      },
      _functions = {
        random: function(a, b)  {
          var _a = parseInt(a, 10),
              _b = parseInt(b, 10);
          console.assert(_unit(a), _unit(b));

          return _a + Math.floor(Math.random() * (_b - _a)) + _unit(b);
        },
        ap: (function() {
          var AP = {};

          return function(initial, ratio) {
            var id = this.original_id || this.id;

            if (!AP[id]) {
             AP[id] = initial;
            } else {
             AP[id] = ParseInt(AP[id], 10) + ratio + _unit(AP[id]);
            }

            return AP[id];
          };
        })(),
        gp: (function() {
          var GP = {};

          return function(initial, ratio) {
            var id = this.original_id || this.id;

            if (!GP[id]) {
             GP[id] = initial;
            } else {
             GP[id] = parseInt(GP[id], 10) * ratio + _unit(GP[id]);
            }

            return GP[id];
          };
        })(),
        log: (function() {
          var LOG = {};

          return function(value, base) {
            var id = this.original_id || this.id;

            base = base || Math.E;

            if (!LOG[id]) {
             LOG[id] = 1;
            } else {
             LOG[id] ++;
            }

            return parseInt(value, 10) * (Math.log(LOG[id]) / Math.log(base)) + _unit(value);
          };
        })(),
        easing: function(value) {
          return _crossbrowser('animation-timing-function', value);
        },
        calc: function(prop, value) {
          if (!value) {
            return 'calc(' + prop + ')';
          } else {
            var _output = '';

            _crossbrowser(function(key) {
              _output += prop + ':' + key + 'calc(' + value + ');';
            });

            return _output;
          }
        },
        transform: function() {
          var value = [].join.call(arguments, ',');
          return _crossbrowser('transform', value);
        }
      },
      _functions_regex = /^([a-z]+)\((.*)\)$/;

  d.head.appendChild(_style);

  var console = w.console = w.console || {
    log: function() {
    },
    assert: function() {
    }
  };

  w.Animate = new (function Animate() {
    if (_instance) {
      throw 'class Animate should not be instantiated';
    }

    _instance = this;

    Animate.init = function(id) {
      var body = _find_by_id(id || 'animation-body');

      if (!body)  {
        throw 'Animation body not found! Unable to start';
      } else if (_init[body.id] === true) {
        return;
      }

      _init[body.id] = true;

      var elements = _slice.call(_find_by_tag(body, '*'), 0);

      for (var k = 0, l = elements.length, element; k < l; k++) {
        element = elements[k];

        if (element.attributes.length) {
          _instance.process(body, element);
        }
      }
    };

    Animate.VERSION = '0.0.1';

    this.process = function(body, element) {
      var el = new Animate.Element(element);
      el.parse();
    };

    Animate.Element = (function () {
      function Element(element) {
        this.element = element;
        this.original_id = this.id = ++_ID;

        this._name = '__animate_keyframes_' + this.id;
        this._bind = '';

        if (!element.id) {
          element.id = 'animate-element-' + this.id;
        }
      }

      return Element;
    })();

    Animate.Element.prototype.parse = function() {
      var _prop = /^data-([0-9\-]+)$/,
          _param = /^data-(.*)$/,
          _params = _extend({}, _defaults),
          _keyframes = {},
          _keyframes_str = '',
          _element_style = '',
          _this = this;

      for (var k = 0, l = this.element.attributes.length, attr, n, v, match; k < l; k++) {
        attr = this.element.attributes[k];
        n = attr.nodeName;
        v = attr.value || attr.nodeValue;

        if ((match = n.match(_prop))) {
          var keys = match[1].trim().split('-');
          console.log(keys);
          for (var x = 0, y = keys.length, key; x < y; x++) {
            key = keys[x];
            console.log(key);
            if (key) {
              if (!_hop.call(_keyframes, key)) {
                _keyframes[key] = '';
              }
              _keyframes[key] += this.parse_css(v);
            }
          }
        } else if ((match = n.match(_param))) {
          if (_valid_properties.indexOf(match[1]) !== -1) {
            _params[match[1]] = this.parse_value(v);
          }
        }
      }

      for (var key in _keyframes) {
        if (_hop.call(_keyframes, key)) {
          _keyframes_str += key + '%{' + _keyframes[key] + '}';
        }
      }

      if (!_keyframes_str.length) {
        return;
      }

      if (_params.repeat > 1 && !this._prevent_repeat) {
        var parse = function (element) {
          return function() {
            element.parse();
          };
        };

        for (k = 0; k < _params.repeat - 1; k++) {
          var clone = this.element.cloneNode(true);
          clone.id = clone.id + '-repeat-' + (k + 1);
          this.element.parentNode.appendChild(clone);
          var element = new Animate.Element(clone);
          element._prevent_repeat = true;
          element.original_id = this.id;

          setTimeout(parse(element), 0);
        }
      }

      _crossbrowser(function(key) {
        _style.innerHTML += _keyframe_content
          .replace('%key%', key)
          .replace('%name%', _this._name)
          .replace('%keyframes%', _keyframes_str);
      });

      _crossbrowser(function(key) {
        _element_style += key + 'animation-play-state:' + (_params.play === 'false' ? 'paused' : 'running') + ';';

        for (var k in _animation_properties) {
          if (_hop.call(_animation_properties, k)) {
            _element_style += key + 'animation-' + _animation_properties[k] + ':' + _params[k] + ';';
          }
        }
      });

      _style.innerHTML += '#' + this.element.id + '{' + _element_style + '}';

      var fn = function(e) {
        _off.call(this, 'webkitAnimationEnd', fn, false);
        _off.call(this, 'animationend', fn, false);
        _off.call(this, 'onanimationend', fn, false);

        if (_params.callback && w[_params.callback] && typeof w[_params.callback] === 'function') {
          w[_params.callback].call(_this.element, e || window.event);
        }

        if (_hop.call(_waits, _this.element.id)) {
          var ws = _waits[_this.element.id];
          for (var k = 0, l = ws.length; k < l; k++) {
            ws[k].start();
          }
          delete _waits[_this.element.id];
        }
      };

      _on.call(this.element, 'webkitAnimationEnd', fn, false);
      _on.call(this.element, 'animationend', fn, false);
      _on.call(this.element, 'onanimationend', fn, false);

      if (_params.bind) {
        switch (_params.bind) {
          case 'click':
          case 'onclick':
          case 'active':
            this._bind = ':active';
            break;
          case 'hover':
          case 'over':
          case 'mouseover':
            this._bind = ':hover';
            break;
        }
      }

      if (!_params.waits) {
        this.start();
      } else {
        if (!_hop.call(_waits, _params.waits)) {
          _waits[_params.waits] = [];
        }

        _waits[_params.waits].push(this);
      }
    };

    Animate.Element.prototype.start = function() {
      var _element_style = '',
          _this = this;
      _crossbrowser(function(key) {
        _element_style += key + 'animation-name:' + _this._name + ';';
      });

      _style.innerHTML += '#' + this.element.id + this._bind + '{' + _element_style + '}';
    };

    Animate.Element.prototype.parse_value = function(value) {
      var match = value.trim().match(_functions_regex),
          _arguments = match && match[2].split(',').filter(function (a) { return a.trim(); }),
          _fn_name = match && match[1].replace(/\s/g, '');

      if (_hop.call(w, _fn_name)) {
        value = w[_fn_name].apply(this, _arguments);
      } else if (_hop.call(_functions, _fn_name)) {
        value = _functions[_fn_name].apply(this, _arguments);
      }

      return value;
    };

    Animate.Element.prototype.parse_css_entry = function(prop, value) {
      return prop + ':' + this.parse_value(value) + ';';
    };

    Animate.Element.prototype.parse_css = function(styles) {
      var _output = '';

      styles = styles.split(';');

      for (var k = 0, l = styles.length, style, prop, value; k < l; k++) {
        if ((style = styles[k].split(':')).length !== 2) {
          _output += this.parse_value(styles[k]);
        } else {
          prop = style[0].trim();
          value = style[1].trim();

          _output += this.parse_css_entry(prop, value);
        }
      }

      return _output;
    };

    return Animate;
  })();

    /*!
   * contentloaded.js
   *
   * Author: Diego Perini (diego.perini at gmail.com)
   * Summary: cross-browser wrapper for DOMContentLoaded
   * Updated: 20101020
   * License: MIT
   * Version: 1.2
   *
   * URL:
   * http://javascript.nwbox.com/ContentLoaded/
   * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
   *
   */

  // @win window reference
  // @fn function reference
  function contentLoaded(win, fn) {

    var done = false, top = true,

    doc = win.document, root = doc.documentElement,

    add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
    rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
    pre = doc.addEventListener ? '' : 'on',

    init = function(e) {
      if (e.type === 'readystatechange' && doc.readyState !== 'complete') {
        return;
      }

      (e.type === 'load' ? win : doc)[rem](pre + e.type, init, false);

      if (!done && (done = true)) {
        fn.call(win, e.type || e);
      }
    },

    poll = function() {
      try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
      init('poll');
    };

    if (doc.readyState === 'complete') {
      fn.call(win, 'lazy');
    } else {
      if (doc.createEventObject && root.doScroll) {
        try { top = !win.frameElement; } catch(e) { }
        if (top) {
          poll();
        }
      }
      doc[add](pre + 'DOMContentLoaded', init, false);
      doc[add](pre + 'readystatechange', init, false);
      win[add](pre + 'load', init, false);
    }

  }

  contentLoaded(w, function() {
    w.Animate.init();
  });
})(window, document);
<commit_msg>Added parse for style attribute<commit_after>;(function(w, d, undefined) {
  'use strict';

  var _defaults = {
    name: null,
    duration: '1s',
    delay: 0,
    easing: 'linear',
    waits: null,
    repeat: 1,
    callback: null,
    'fill-mode': 'forwards',
    direction: 'normal',
    iterations: 1,
    play: 'true',
    bind: 'none'
  },
  _valid_properties = Object.keys(_defaults),
  _init = {},
  _waits = {};

  var _slice = Array.prototype.slice,
  _hop = Object.prototype.hasOwnProperty,
  _on = d.addEventListener || d.attachEvent,
  _off = d.removeEventListener || d.detachEvent,
  //_to_camel_case = function(underscored) {
    //return underscored
    //.replace(/^-/g, '')
    //.replace(/-([a-z])/g, function(match, letter) {
      //return letter.toUpperCase();
    //});
  //},
  _extend = function (target, source) {
    for (var k in source) {
      if (_hop.call(source, k)) {
        target[k] = source[k];
      }
    }

    return target;
  },
  _find_by_id = function() {
    return d.getElementById.apply(d, arguments);
  },
  _find_by_tag = function(el) {
    return el.getElementsByTagName.apply(el, _slice.call(arguments, 1));
  };

  var _instance,
      _style = d.createElement('style'),
      _ID = 0,
      _keyframe_content = '@%key%keyframes %name% {%keyframes% }',
      _crossbrowser_keys = ['-webkit-', '-moz-', '-o-', ''],
      _animation_properties = {
        delay: 'delay',
        direction: 'direction',
        duration: 'duration',
        'fill-mode': 'fill-mode',
        iterations: 'iteration-count',
        'easing': 'timing-function'
      },
      _unit = function(a) {
        return a.replace(String(parseFloat(a)), '').trim();
      },
      _crossbrowser = function(prop, value) {
        var _output = '';

        for (var k = 0, l = _crossbrowser_keys.length, key; k < l; k++) {
          key = _crossbrowser_keys[k];
          if (value === undefined) {
            prop(key);
          } else  {
            _output += key + prop + ':' + value + ';';
          }
        }

        return _output;
      },
      _functions = {
        random: function(a, b)  {
          var _a = parseInt(a, 10),
              _b = parseInt(b, 10);
          console.assert(_unit(a), _unit(b));

          return _a + Math.floor(Math.random() * (_b - _a)) + _unit(b);
        },
        ap: (function() {
          var AP = {};

          return function(initial, ratio) {
            var id = this.original_id || this.id;

            if (!AP[id]) {
             AP[id] = initial;
            } else {
             AP[id] = ParseInt(AP[id], 10) + ratio + _unit(AP[id]);
            }

            return AP[id];
          };
        })(),
        gp: (function() {
          var GP = {};

          return function(initial, ratio) {
            var id = this.original_id || this.id;

            if (!GP[id]) {
             GP[id] = initial;
            } else {
             GP[id] = parseInt(GP[id], 10) * ratio + _unit(GP[id]);
            }

            return GP[id];
          };
        })(),
        log: (function() {
          var LOG = {};

          return function(value, base) {
            var id = this.original_id || this.id;

            base = base || Math.E;

            if (!LOG[id]) {
             LOG[id] = 1;
            } else {
             LOG[id] ++;
            }

            return parseInt(value, 10) * (Math.log(LOG[id]) / Math.log(base)) + _unit(value);
          };
        })(),
        easing: function(value) {
          return _crossbrowser('animation-timing-function', value);
        },
        calc: function(prop, value) {
          if (!value) {
            return 'calc(' + prop + ')';
          } else {
            var _output = '';

            _crossbrowser(function(key) {
              _output += prop + ':' + key + 'calc(' + value + ');';
            });

            return _output;
          }
        },
        transform: function() {
          var value = [].join.call(arguments, ',');
          return _crossbrowser('transform', value);
        }
      },
      _functions_regex = /^([a-z]+)\((.*)\)$/;

  d.head.appendChild(_style);

  var console = w.console = w.console || {
    log: function() {
    },
    assert: function() {
    }
  };

  w.Animate = new (function Animate() {
    if (_instance) {
      throw 'class Animate should not be instantiated';
    }

    _instance = this;

    Animate.init = function(id) {
      var body = _find_by_id(id || 'animation-body');

      if (!body)  {
        throw 'Animation body not found! Unable to start';
      } else if (_init[body.id] === true) {
        return;
      }

      _init[body.id] = true;

      var elements = _slice.call(_find_by_tag(body, '*'), 0);

      for (var k = 0, l = elements.length, element; k < l; k++) {
        element = elements[k];

        if (element.attributes.length) {
          _instance.process(body, element);
        }
      }
    };

    Animate.VERSION = '0.0.1';

    this.process = function(body, element) {
      var el = new Animate.Element(element);
      el.parse();
    };

    Animate.Element = (function () {
      function Element(element) {
        this.element = element;
        this.original_id = this.id = ++_ID;

        this._name = '__animate_keyframes_' + this.id;
        this._bind = '';

        if (!element.id) {
          element.id = 'animate-element-' + this.id;
        }
      }

      return Element;
    })();

    Animate.Element.prototype.parse = function() {
      var _prop = /^data-([0-9\-]+)$/,
          _param = /^data-(.*)$/,
          _params = _extend({}, _defaults),
          _keyframes = {},
          _keyframes_str = '',
          _element_style = '',
          _this = this;

      for (var k = 0, l = this.element.attributes.length, attr, n, v, match; k < l; k++) {
        attr = this.element.attributes[k];
        n = attr.nodeName;
        v = attr.value || attr.nodeValue;

        if ((match = n.match(_prop))) {
          var keys = match[1].trim().split('-');
          for (var x = 0, y = keys.length, key; x < y; x++) {
            key = keys[x];
            if (key) {
              if (!_hop.call(_keyframes, key)) {
                _keyframes[key] = '';
              }
              _keyframes[key] += this.parse_css(v);
            }
          }
        } else if ((match = n.match(_param))) {
          if (_valid_properties.indexOf(match[1]) !== -1) {
            _params[match[1]] = this.parse_value(v);
          }
        } else if (n === 'style') {
          this.element.setAttribute(n, this.parse_css(v));
        }
      }

      for (var key in _keyframes) {
        if (_hop.call(_keyframes, key)) {
          _keyframes_str += key + '%{' + _keyframes[key] + '}';
        }
      }

      if (!_keyframes_str.length) {
        return;
      }

      if (_params.repeat > 1 && !this._prevent_repeat) {
        var parse = function (element) {
          return function() {
            element.parse();
          };
        };

        for (k = 0; k < _params.repeat - 1; k++) {
          var clone = this.element.cloneNode(true);
          clone.id = clone.id + '-repeat-' + (k + 1);
          this.element.parentNode.appendChild(clone);
          var element = new Animate.Element(clone);
          element._prevent_repeat = true;
          element.original_id = this.id;

          setTimeout(parse(element), 0);
        }
      }

      _crossbrowser(function(key) {
        _style.innerHTML += _keyframe_content
          .replace('%key%', key)
          .replace('%name%', _this._name)
          .replace('%keyframes%', _keyframes_str);
      });

      _crossbrowser(function(key) {
        _element_style += key + 'animation-play-state:' + (_params.play === 'false' ? 'paused' : 'running') + ';';

        for (var k in _animation_properties) {
          if (_hop.call(_animation_properties, k)) {
            _element_style += key + 'animation-' + _animation_properties[k] + ':' + _params[k] + ';';
          }
        }
      });

      _style.innerHTML += '#' + this.element.id + '{' + _element_style + '}';

      var fn = function(e) {
        _off.call(this, 'webkitAnimationEnd', fn, false);
        _off.call(this, 'animationend', fn, false);
        _off.call(this, 'onanimationend', fn, false);

        if (_params.callback && w[_params.callback] && typeof w[_params.callback] === 'function') {
          w[_params.callback].call(_this.element, e || window.event);
        }

        if (_hop.call(_waits, _this.element.id)) {
          var ws = _waits[_this.element.id];
          for (var k = 0, l = ws.length; k < l; k++) {
            ws[k].start();
          }
          delete _waits[_this.element.id];
        }
      };

      _on.call(this.element, 'webkitAnimationEnd', fn, false);
      _on.call(this.element, 'animationend', fn, false);
      _on.call(this.element, 'onanimationend', fn, false);

      if (_params.bind) {
        switch (_params.bind) {
          case 'click':
          case 'onclick':
          case 'active':
            this._bind = ':active';
            break;
          case 'hover':
          case 'over':
          case 'mouseover':
            this._bind = ':hover';
            break;
        }
      }

      if (!_params.waits) {
        this.start();
      } else {
        if (!_hop.call(_waits, _params.waits)) {
          _waits[_params.waits] = [];
        }

        _waits[_params.waits].push(this);
      }
    };

    Animate.Element.prototype.start = function() {
      var _element_style = '',
          _this = this;
      _crossbrowser(function(key) {
        _element_style += key + 'animation-name:' + _this._name + ';';
      });

      _style.innerHTML += '#' + this.element.id + this._bind + '{' + _element_style + '}';
    };

    Animate.Element.prototype.parse_value = function(value) {
      var match = value.trim().match(_functions_regex),
          _arguments = match && match[2].split(',').filter(function (a) { return a.trim(); }),
          _fn_name = match && match[1].replace(/\s/g, '');

      if (_hop.call(w, _fn_name)) {
        value = w[_fn_name].apply(this, _arguments);
      } else if (_hop.call(_functions, _fn_name)) {
        value = _functions[_fn_name].apply(this, _arguments);
      }

      return value;
    };

    Animate.Element.prototype.parse_css_entry = function(prop, value) {
      return prop + ':' + this.parse_value(value) + ';';
    };

    Animate.Element.prototype.parse_css = function(styles) {
      var _output = '';

      styles = styles.split(';');

      for (var k = 0, l = styles.length, style, prop, value; k < l; k++) {
        if ((style = styles[k].split(':')).length !== 2) {
          _output += this.parse_value(styles[k]);
        } else {
          prop = style[0].trim();
          value = style[1].trim();

          _output += this.parse_css_entry(prop, value);
        }
      }

      return _output;
    };

    return Animate;
  })();

    /*!
   * contentloaded.js
   *
   * Author: Diego Perini (diego.perini at gmail.com)
   * Summary: cross-browser wrapper for DOMContentLoaded
   * Updated: 20101020
   * License: MIT
   * Version: 1.2
   *
   * URL:
   * http://javascript.nwbox.com/ContentLoaded/
   * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
   *
   */

  // @win window reference
  // @fn function reference
  function contentLoaded(win, fn) {

    var done = false, top = true,

    doc = win.document, root = doc.documentElement,

    add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
    rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
    pre = doc.addEventListener ? '' : 'on',

    init = function(e) {
      if (e.type === 'readystatechange' && doc.readyState !== 'complete') {
        return;
      }

      (e.type === 'load' ? win : doc)[rem](pre + e.type, init, false);

      if (!done && (done = true)) {
        fn.call(win, e.type || e);
      }
    },

    poll = function() {
      try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
      init('poll');
    };

    if (doc.readyState === 'complete') {
      fn.call(win, 'lazy');
    } else {
      if (doc.createEventObject && root.doScroll) {
        try { top = !win.frameElement; } catch(e) { }
        if (top) {
          poll();
        }
      }
      doc[add](pre + 'DOMContentLoaded', init, false);
      doc[add](pre + 'readystatechange', init, false);
      win[add](pre + 'load', init, false);
    }

  }

  contentLoaded(w, function() {
    w.Animate.init();
  });
})(window, document);
<|endoftext|>


<commit_before>'use strict';
/* global d3 */

// A simple prototype of drawing the intervals track via canvas rendering

const KEY_FIELD = 'intervals_1606149097681_13_src:state_name';
const START_FIELD = 'intervals_1606149097681_13_src:start';
const END_FIELD = 'intervals_1606149097681_13_src:end';
const COLOR_FIELD = 'intervals_1606149097681_13_src:itemRgb';

const REGION_START = 21940000;
const REGION_END = 22190000;

// Layout options
const ROW_HEIGHT = 10;
const ROW_SPACING = 5;
const HITAREA_SIZE = 3;

// Coordinates (start, end) are cached to facilitate hit detection
const XCS = Symbol.for('lzXCS');
const YCS = Symbol.for('lzYCS');
const XCE = Symbol.for('lzXCE');
const YCE = Symbol.for('lzYCE');

function _detectHit(grouped_data, x, y) {
    // Detect whether a given item overlaps a given interval
    let search_row;
    for (let i = 0; i < grouped_data.length; i++) {
        // All y values are the same for a given row, so we only need to compare y coords to the first item
        const row = grouped_data[i];
        const item = row[0];
        if (item[YCS] <= y && item[YCE] >= y) {
            search_row = row;
            break;
        }
    }

    if (!search_row) {
        return null;
    }

    for (let i = 0; i < search_row.length; i++) {
        // Once we've found a row, scan all items and return the first one that overlaps the mouse position.
        const item = search_row[i];
        if (item[XCS] <= x && item[XCE] >= x) {
            return item;
        }
    }
    return null;
}

function _arrangeTrackSplit(data) {
    // Split data into tracks such that anything with a common grouping field is in the same track
    const result = {};
    data.forEach((item) => {
        const item_key = item[KEY_FIELD];
        if (!Object.prototype.hasOwnProperty.call(result, item_key)) {
            result[item_key] = [];
        }
        result[item_key].push(item);
    });
    return Object.values(result);
}

function _arrangeTracksLinear(data) {
    // Split data into tracks using a simple greedy algorithm such that no two items overlap (share same interval)
    // Assumes that the data are sorted so item1.start always <= item2.start.

    // Data is sorted by start position to facilitate grouping
    data.sort((a, b) => a[START_FIELD] - b[START_FIELD]);

    const grouped_data = [[]]; // Prevent two items from colliding by rendering them to different rows, like genes
    data.forEach((item, index) => {
        for (let i = 0; i < grouped_data.length; i++) {
            // Iterate over all rows of the
            const row_to_test = grouped_data[i];
            const last_item = row_to_test[row_to_test.length - 1];
            const has_overlap = last_item && (item[START_FIELD] <= last_item[END_FIELD]) && (last_item[START_FIELD] <= item[END_FIELD]);
            if (!has_overlap) {
                // If there is no overlap, add item to current row, and move on to the next item
                row_to_test.push(item);
                return;
            }
        }
        // If this item would collide on all existing rows, create a new row
        grouped_data.push([item]);
    });
    return grouped_data;
}

// eslint-disable-next-line no-unused-vars
class IntervalPlot {
    constructor(selector_id, data, split_tracks = true) {
        this.canvas = document.getElementById(selector_id);
        this.context = this.canvas.getContext('2d');

        this.data = data;

        this.split_tracks = split_tracks;
    }

    render() {
        const { data, canvas, context } = this;

        let grouped_data = this.split_tracks ? _arrangeTrackSplit(data) : _arrangeTracksLinear(data);
        const n_rows = grouped_data.length;
        const target_height = n_rows * ROW_HEIGHT + (n_rows + 1) * ROW_SPACING;

        // Set scales
        const x_scale = d3.scaleLinear()
            .domain([REGION_START, REGION_END])
            .range([0, canvas.width]);

        const y_scale = d3.scaleLinear()
            .domain([0, n_rows])
            .range([0, target_height]);

        // Rescale canvas to fit the data. Adjust for high res on retina screens
        // Auto-scaling is disabled for now, because some datasets have too many rows for FF.
        // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1485730
        const scale = 1; // window.devicePixelRatio;
        canvas.style.width = `800px`;
        canvas.style.height = `${target_height}px`;

        canvas.width = Math.floor(800 * scale);
        canvas.height = Math.floor(target_height * scale);

        // Normalize coordinate system to use css pixels.
        context.scale(scale, scale);

        canvas.height = target_height;
        context.clearRect(0, 0, canvas.width, canvas.height);

        // Iterate through the data and render it
        grouped_data.forEach((group, row_index) => {
            group.forEach((item) => {
                // Prior to rendering, cache the x/y coords so they can be used later for hit detection
                item[XCS] = x_scale(item[START_FIELD]);
                item[XCE] = x_scale(item[END_FIELD]);
                item[YCS] = y_scale(row_index) + ROW_SPACING; // TODO: this one is the problem
                item[YCE] = item[YCS] + ROW_HEIGHT;
                this._render_row(item);
            });
        });

        // One mousemove event listener for entire canvas
        let last_hit = {};
        canvas.addEventListener('mousemove', (event) => {
            const {offsetX: x, offsetY: y} = event;
            const hit_data = _detectHit(grouped_data, x, y);

            if (hit_data && last_hit[KEY_FIELD] !== hit_data[KEY_FIELD]) {
                // Deduplicate events by only warning on unique ones
                last_hit = hit_data;
                console.log('hit found!', hit_data);
            }
        });
    }

    _render_row(item) {
        const { context } = this;
        context.fillStyle = `rgb(${item[COLOR_FIELD]})`;
        context.fillRect(
            item[XCS],
            item[YCS],
            item[XCE] - item[XCS],
            ROW_HEIGHT
        );
    }

    // Returns null or the data object for the given row
    detect_hit(grouped_data, x, y) {
        // First find the row where it matches
        let target_row;
        for (let i = 0; i < grouped_data.length; i++) {
            const first_item = grouped_data[i][0]; // all items in a row have the same y coordinates by definition
            if (first_item[YCS] <= y && first_item[YCE] >= y) {
                target_row = grouped_data[i];
                break;
            }
        }
        if (!target_row) {
            return null;
        }

        // Allow hit regions to be slightly wider than the box, rightmost element "wins" analogous to svg
        // TODO: implement hit areas. Make sure that the "almost match" does not override a true "best match"
        for (let i = target_row.length - 1; i >= 0; i--) {
            const item = target_row[i];
            if (item[XCS] <= x && item[XCE] >= x) {
                return item;
            }
        }
        // If no match found, explicitly return null
        return null;
    }
}
<commit_msg>Add hitareas along x direction for canvas rendering<commit_after>'use strict';
/* global d3 */

// A simple prototype of drawing the intervals track via canvas rendering

const KEY_FIELD = 'intervals_1606149097681_13_src:state_name';
const START_FIELD = 'intervals_1606149097681_13_src:start';
const END_FIELD = 'intervals_1606149097681_13_src:end';
const COLOR_FIELD = 'intervals_1606149097681_13_src:itemRgb';

const REGION_START = 21940000;
const REGION_END = 22190000;

// Layout options
const ROW_HEIGHT = 10;
const ROW_SPACING = 5;
const HITAREA_SIZE = 3;

// Coordinates (start, end) are cached to facilitate hit detection
const XCS = Symbol.for('lzXCS');
const YCS = Symbol.for('lzYCS');
const XCE = Symbol.for('lzXCE');
const YCE = Symbol.for('lzYCE');

function _detectHit(grouped_data, x, y) {
    // Detect whether a given item overlaps a given interval
    let search_row;
    for (let i = 0; i < grouped_data.length; i++) {
        // All y values are the same for a given row, so we only need to compare y coords to the first item
        const row = grouped_data[i];
        const item = row[0];
        if (item[YCS] <= y && item[YCE] >= y) {
            search_row = row;
            break;
        }
    }

    if (!search_row) {
        return null;
    }

    // Once we've found a row, find the item that overlaps the x position
    let soft_match;
    for (let i = 0; i < search_row.length; i++) {
        // There are two kinds of overlap: hard match (exactly overlaps mouse pointer), and soft match (within hit area-
        //  don't return until we've checked adjacent points for a better match
        // We only do this in the x direction, b/c tracks are always tall enough to click, but not always wide enough
        const item = search_row[i];
        if (item[XCS] <= x && item[XCE] >= x) {
            // Hard (exact) match: return immediately; this is the point we want!
            return item;
        }
        if ((item[XCS] - HITAREA_SIZE) <= x && (item[XCE] + HITAREA_SIZE) >= x) {
            // Soft match: keep track of it, but consider adjacent items to see if the next point has better overlap
            // This is equivalent to the "rightmost/last point added to DOM wins" behavior we'd see with SVG hitareas
            soft_match = item;
            continue;
        }
        if (soft_match) {
            // If this item wasn't any kind of match, return the previous soft match- it's the best we're going to get
            //  (this assumes that dataset is sorted in x direction, eg "we tested everything nearby")
            return soft_match;
        }
    }
    return null;
}

function _arrangeTrackSplit(data) {
    // Split data into tracks such that anything with a common grouping field is in the same track
    const result = {};
    data.forEach((item) => {
        const item_key = item[KEY_FIELD];
        if (!Object.prototype.hasOwnProperty.call(result, item_key)) {
            result[item_key] = [];
        }
        result[item_key].push(item);
    });
    return Object.values(result);
}

function _arrangeTracksLinear(data) {
    // Split data into tracks using a simple greedy algorithm such that no two items overlap (share same interval)
    // Assumes that the data are sorted so item1.start always <= item2.start.

    // Data is sorted by start position to facilitate grouping
    data.sort((a, b) => a[START_FIELD] - b[START_FIELD]);

    const grouped_data = [[]]; // Prevent two items from colliding by rendering them to different rows, like genes
    data.forEach((item, index) => {
        for (let i = 0; i < grouped_data.length; i++) {
            // Iterate over all rows of the
            const row_to_test = grouped_data[i];
            const last_item = row_to_test[row_to_test.length - 1];
            const has_overlap = last_item && (item[START_FIELD] <= last_item[END_FIELD]) && (last_item[START_FIELD] <= item[END_FIELD]);
            if (!has_overlap) {
                // If there is no overlap, add item to current row, and move on to the next item
                row_to_test.push(item);
                return;
            }
        }
        // If this item would collide on all existing rows, create a new row
        grouped_data.push([item]);
    });
    return grouped_data;
}

// eslint-disable-next-line no-unused-vars
class IntervalPlot {
    constructor(selector_id, data, split_tracks = true) {
        this.canvas = document.getElementById(selector_id);
        this.context = this.canvas.getContext('2d');

        this.data = data;

        this.split_tracks = split_tracks;
    }

    render() {
        const { data, canvas, context } = this;

        let grouped_data = this.split_tracks ? _arrangeTrackSplit(data) : _arrangeTracksLinear(data);
        const n_rows = grouped_data.length;
        const target_height = n_rows * ROW_HEIGHT + (n_rows + 1) * ROW_SPACING;

        // Set scales
        const x_scale = d3.scaleLinear()
            .domain([REGION_START, REGION_END])
            .range([0, canvas.width]);

        const y_scale = d3.scaleLinear()
            .domain([0, n_rows])
            .range([0, target_height]);

        // Rescale canvas to fit the data. Adjust for high res on retina screens
        // Auto-scaling is disabled for now, because some datasets have too many rows for FF.
        // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1485730
        const scale = 1; // window.devicePixelRatio;
        canvas.style.width = `800px`;
        canvas.style.height = `${target_height}px`;

        canvas.width = Math.floor(800 * scale);
        canvas.height = Math.floor(target_height * scale);

        // Normalize coordinate system to use css pixels.
        context.scale(scale, scale);

        canvas.height = target_height;
        context.clearRect(0, 0, canvas.width, canvas.height);

        // Iterate through the data and render it
        grouped_data.forEach((group, row_index) => {
            group.forEach((item) => {
                // Prior to rendering, cache the x/y coords so they can be used later for hit detection
                item[XCS] = x_scale(item[START_FIELD]);
                item[XCE] = x_scale(item[END_FIELD]);
                item[YCS] = y_scale(row_index) + ROW_SPACING; // TODO: this one is the problem
                item[YCE] = item[YCS] + ROW_HEIGHT;
                this._render_row(item);
            });
        });

        // One mousemove event listener for entire canvas
        let last_hit = {};
        canvas.addEventListener('mousemove', (event) => {
            const {offsetX: x, offsetY: y} = event;
            const hit_data = _detectHit(grouped_data, x, y);

            if (hit_data && last_hit[KEY_FIELD] !== hit_data[KEY_FIELD]) {
                // Deduplicate events by only warning on unique ones
                last_hit = hit_data;
                console.log('hit found!', hit_data);
            }
        });
    }

    _render_row(item) {
        const { context } = this;
        context.fillStyle = `rgb(${item[COLOR_FIELD]})`;
        context.fillRect(
            item[XCS],
            item[YCS],
            item[XCE] - item[XCS],
            ROW_HEIGHT
        );
    }

    // Returns null or the data object for the given row
    detect_hit(grouped_data, x, y) {
        // First find the row where it matches
        let target_row;
        for (let i = 0; i < grouped_data.length; i++) {
            const first_item = grouped_data[i][0]; // all items in a row have the same y coordinates by definition
            if (first_item[YCS] <= y && first_item[YCE] >= y) {
                target_row = grouped_data[i];
                break;
            }
        }
        if (!target_row) {
            return null;
        }

        // Allow hit regions to be slightly wider than the box, rightmost element "wins" analogous to svg
        // TODO: implement hit areas. Make sure that the "almost match" does not override a true "best match"
        for (let i = target_row.length - 1; i >= 0; i--) {
            const item = target_row[i];
            if (item[XCS] <= x && item[XCE] >= x) {
                return item;
            }
        }
        // If no match found, explicitly return null
        return null;
    }
}
<|endoftext|>


<commit_before>import { helper } from '@ember/component/helper';

export function formatNum(value) {
  if (value === 0) {
    return '0';
  }

  let ret = '';
  let cnt = 0;
  while (value > 0) {
    if (cnt > 0 && cnt % 3 === 0) {
      ret = `,${ret}`;
      cnt = 0;
    }
    ret = (value % 10) + ret;
    cnt += 1;
    value = Math.floor(value / 10);
  }
  return ret;
}

export default helper(params => formatNum(params[0]));
<commit_msg>Auto merge of #2210 - Turbo87:format-num, r=locks<commit_after>import { helper } from '@ember/component/helper';

const numberFormat = new Intl.NumberFormat('en');

export function formatNum(value) {
  return numberFormat.format(value);
}

export default helper(params => formatNum(params[0]));
<|endoftext|>