<commit_before>'use strict';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import moment from 'moment';
import { Input } from '../../libs/bootstrap/form';
import { getAffiliationName } from '../../libs/get_affiliation_name';
import { renderSelectedModeInheritance } from '../../libs/render_mode_inheritance';
import DayPickerInput from 'react-day-picker/DayPickerInput';
import MomentLocaleUtils, { formatDate, parseDate } from 'react-day-picker/moment';

class CurationSnapshots extends Component {
    constructor(props) {
        super(props);
    }

    componentDidUpdate(prevProps, prevState) {
        // Finds all hgvs terms in
 and  nodes
        // Then sets 'title' and 'class' attributes if text overflows
        let provisionalList = document.querySelectorAll('li.snapshot-item[data-status="Provisioned"]');
        let approvalList = document.querySelectorAll('li.snapshot-item[data-status="Approved"]');
        let provisionalSnapshotNodes = Array.from(provisionalList);
        let approvalSnapshotNodes = Array.from(approvalList);
        if (approvalSnapshotNodes && approvalSnapshotNodes.length) {
            approvalSnapshotNodes.forEach(approval => {
                let label = document.createElement('LABEL');
                approval.appendChild(label);

                if (approval.getAttribute('data-associated').length) {
                    for (let provisional of provisionalSnapshotNodes) {
                        if (provisional.getAttribute('data-key') === approval.getAttribute('data-associated')) {
                            provisional.appendChild(label);
                        }
                    }
                }
            });
        }
    }

    viewSnapshotSummary(snapshotId, type, e) {
        e.preventDefault(); e.stopPropagation();
        const snapshotUuid = snapshotId.slice(11, -1);
        if (type === 'classification') {
            window.open('/gene-disease-evidence-summary/?snapshot=' + snapshotUuid, '_blank');
        } else if (type === 'interpretation') {
            window.open('/variant-interpretation-summary/?snapshot=' + snapshotUuid, '_blank');
        }
    }

    /**
     * Method to display classification tag/label in the interpretation header
     * @param {string} status - The status of a given classification in an interpretation
     */
    renderClassificationStatusTag(status) {
        if (status === 'Provisioned') {
            return PROVISIONAL;
        } else if (status === 'Approved') {
            return APPROVED;
        }
    }

    renderProvisionalSnapshotStatusIcon(index) {
        if (index.toString() === "0") {
            return

;
        } else if (index.toString() === "1") {
            if (this.props.snapshots[0].approvalStatus === 'Approved') {
                return

;
            } else {
                return

;
            }
        } else {
            return

;
        }
    }

    renderProvisionalSnapshotViewSummaryBtn(index) {
        let buttonClass;
        if (index.toString() === "0") {
            buttonClass = 'btn-primary';
        } else if (index.toString() === "1") {
            if (this.props.snapshots[0].approvalStatus === 'Approved') {
                buttonClass = 'btn-primary';
            } else {
                buttonClass = 'btn-default';
            }
        } else {
            buttonClass = 'btn-default';
        }
        return buttonClass;
    }

    /**
     * Method to render snapshots in table rows
     * @param {object} snapshot - A saved copy of a provisioned/approved classification and its parent GDM/Interpretation
     */
    renderSnapshot(snapshot, index) {
        const type = snapshot.resourceType;
        let buttonClass = index.toString() === "0" || index.toString() === "1" ? 'btn-primary' : 'btn-default';

        if (snapshot.approvalStatus === 'Provisioned') {
            return (

                                    {snapshot.resource && snapshot.resource.affiliation ?

ClinGen Affiliation:

{getAffiliationName(snapshot.resource.affiliation)}

                                        : null}

Provisional Classification entered by:

{snapshot.resource.provisionalSubmitter}

Date saved as Provisional:

{snapshot.resource.provisionalDate ? formatDate(snapshot.resource.provisionalDate, "YYYY MMM DD, h:mm a") : null}

                                        {this.renderClassificationStatusTag(snapshot.approvalStatus)}

Date reviewed:

{snapshot.resource.provisionalReviewDate ? formatDate(snapshot.resource.provisionalReviewDate, "YYYY MMM DD") : null}

{type === 'interpretation' ? 'Saved Pathogenicity:' : 'Saved Classification:'}

{snapshot.resource.alteredClassification ? {snapshot.resource.alteredClassification} (modified) : snapshot.resource.autoClassification}

Disease:

{snapshot.resourceParent && snapshot.resourceParent.disease && snapshot.resourceParent.disease.term ? snapshot.resourceParent.disease.term : 'None'}

Mode of Inheritance:

{renderSelectedModeInheritance(snapshot.resourceParent)}

Additional comments:

{snapshot.resource.provisionalComment ? snapshot.resource.provisionalComment : null}

                                    {this.renderProvisionalSnapshotStatusIcon(index)}
                                    <Input type="button" inputClassName={this.renderProvisionalSnapshotViewSummaryBtn(index)} title="View Provisional Summary" clickHandler={this.viewSnapshotSummary.bind(this, snapshot['@id'], type)} />

            );
        } else if (snapshot.approvalStatus === 'Approved') {
            return (

                                    {snapshot.resource && snapshot.resource.affiliation ?

ClinGen Affiliation:

{getAffiliationName(snapshot.resource.affiliation)}

                                        : null}

Approved Classification entered by:

{snapshot.resource.approvalSubmitter}

                                    {snapshot.resource && snapshot.resource.classificationApprover ?

Approver:

{snapshot.resource.classificationApprover}

                                        : null}

Date saved as Approved:

{snapshot.resource.approvalDate ? formatDate(snapshot.resource.approvalDate, "YYYY MMM DD, h:mm a") : null}

                                        {this.renderClassificationStatusTag(snapshot.approvalStatus)}

Date reviewed:

{snapshot.resource.approvalReviewDate ? formatDate(snapshot.resource.approvalReviewDate, "YYYY MMM DD") : null}

{type === 'interpretation' ? 'Saved Pathogenicity:' : 'Saved Classification:'}

{snapshot.resource.alteredClassification ? {snapshot.resource.alteredClassification} (modified) : snapshot.resource.autoClassification}

Disease:

{snapshot.resourceParent && snapshot.resourceParent.disease && snapshot.resourceParent.disease.term ? snapshot.resourceParent.disease.term : 'None'}

Mode of Inheritance:

{renderSelectedModeInheritance(snapshot.resourceParent)}

Additional comments:

{snapshot.resource.approvalComment ? snapshot.resource.approvalComment : null}

                                    {index.toString() === "0" || index.toString() === "1" ?

                                        :

                                    }
                                    <Input type="button" inputClassName={buttonClass} title="View Approved Summary" clickHandler={this.viewSnapshotSummary.bind(this, snapshot['@id'], type)} />

            );
        }
    }

    render() {
        const { snapshots } = this.props;

        return (

                    {snapshots.map((snapshot, i) => this.renderSnapshot(snapshot, i))}

        );
    }
}

CurationSnapshots.propTypes = {
    snapshots: PropTypes.array
};

export default CurationSnapshots;<commit_msg>Added a link to the snapshot for user to approve the current provisional in GCI<commit_after>'use strict';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import moment from 'moment';
import { Input } from '../../libs/bootstrap/form';
import { getAffiliationName } from '../../libs/get_affiliation_name';
import { renderSelectedModeInheritance } from '../../libs/render_mode_inheritance';
import DayPickerInput from 'react-day-picker/DayPickerInput';
import MomentLocaleUtils, { formatDate, parseDate } from 'react-day-picker/moment';

class CurationSnapshots extends Component {
    constructor(props) {
        super(props);
    }

    componentDidUpdate(prevProps, prevState) {
        // Finds all hgvs terms in
 and  nodes
        // Then sets 'title' and 'class' attributes if text overflows
        let provisionalList = document.querySelectorAll('li.snapshot-item[data-status="Provisioned"]');
        let approvalList = document.querySelectorAll('li.snapshot-item[data-status="Approved"]');
        let provisionalSnapshotNodes = Array.from(provisionalList);
        let approvalSnapshotNodes = Array.from(approvalList);
        if (approvalSnapshotNodes && approvalSnapshotNodes.length) {
            approvalSnapshotNodes.forEach(approval => {
                let label = document.createElement('LABEL');
                approval.appendChild(label);

                if (approval.getAttribute('data-associated').length) {
                    for (let provisional of provisionalSnapshotNodes) {
                        if (provisional.getAttribute('data-key') === approval.getAttribute('data-associated')) {
                            provisional.appendChild(label);
                        }
                    }
                }
            });
        }
    }

    viewSnapshotSummary(snapshotId, type, e) {
        e.preventDefault(); e.stopPropagation();
        const snapshotUuid = snapshotId.slice(11, -1);
        if (type === 'classification') {
            window.open('/gene-disease-evidence-summary/?snapshot=' + snapshotUuid, '_blank');
        } else if (type === 'interpretation') {
            window.open('/variant-interpretation-summary/?snapshot=' + snapshotUuid, '_blank');
        }
    }

    /**
     * Method to display classification tag/label in the interpretation header
     * @param {string} status - The status of a given classification in an interpretation
     */
    renderClassificationStatusTag(status) {
        if (status === 'Provisioned') {
            return PROVISIONAL;
        } else if (status === 'Approved') {
            return APPROVED;
        }
    }

    renderProvisionalSnapshotStatusIcon(index) {
        if (index.toString() === "0") {
            return

;
        } else if (index.toString() === "1") {
            if (this.props.snapshots[0].approvalStatus === 'Approved') {
                return

;
            } else {
                return

;
            }
        } else {
            return

;
        }
    }

    renderProvisionalSnapshotViewSummaryBtn(index) {
        let buttonClass;
        if (index.toString() === "0") {
            buttonClass = 'btn-primary';
        } else if (index.toString() === "1") {
            if (this.props.snapshots[0].approvalStatus === 'Approved') {
                buttonClass = 'btn-primary';
            } else {
                buttonClass = 'btn-default';
            }
        } else {
            buttonClass = 'btn-default';
        }
        return buttonClass;
    }

    renderProvisionalSnapshotApprovalLink(snapshot, index) {
        let gdm = snapshot.resourceParent;
        let pathname = window.location.pathname;
        if (index.toString() === "0" && pathname.indexOf('provisional-curation') > -1) {
            return [ Approve this Saved Provisional ];
        }
    }

    /**
     * Method to render snapshots in table rows
     * @param {object} snapshot - A saved copy of a provisioned/approved classification and its parent GDM/Interpretation
     */
    renderSnapshot(snapshot, index) {
        const type = snapshot.resourceType;
        let buttonClass = index.toString() === "0" || index.toString() === "1" ? 'btn-primary' : 'btn-default';

        if (snapshot.approvalStatus === 'Provisioned') {
            return (

                                    {snapshot.resource && snapshot.resource.affiliation ?

ClinGen Affiliation:

{getAffiliationName(snapshot.resource.affiliation)}

                                        : null}

Provisional Classification entered by:

{snapshot.resource.provisionalSubmitter}

Date saved as Provisional:

{snapshot.resource.provisionalDate ? formatDate(snapshot.resource.provisionalDate, "YYYY MMM DD, h:mm a") : null}

                                        {this.renderClassificationStatusTag(snapshot.approvalStatus)}

Date reviewed:

{snapshot.resource.provisionalReviewDate ? formatDate(snapshot.resource.provisionalReviewDate, "YYYY MMM DD") : null}

{type === 'interpretation' ? 'Saved Pathogenicity:' : 'Saved Classification:'}

{snapshot.resource.alteredClassification ? {snapshot.resource.alteredClassification} (modified) : snapshot.resource.autoClassification}

Disease:

{snapshot.resourceParent && snapshot.resourceParent.disease && snapshot.resourceParent.disease.term ? snapshot.resourceParent.disease.term : 'None'}

Mode of Inheritance:

{renderSelectedModeInheritance(snapshot.resourceParent)}

Additional comments:

{snapshot.resource.provisionalComment ? snapshot.resource.provisionalComment : null}

                                    {this.renderProvisionalSnapshotStatusIcon(index)}
                                    {snapshot.resourceParent && snapshot.resourceParent['@type'][0] === 'gdm' ? this.renderProvisionalSnapshotApprovalLink(snapshot, index) : null}
                                    <Input type="button" inputClassName={this.renderProvisionalSnapshotViewSummaryBtn(index)} title="View Provisional Summary" clickHandler={this.viewSnapshotSummary.bind(this, snapshot['@id'], type)} />

            );
        } else if (snapshot.approvalStatus === 'Approved') {
            return (

                                    {snapshot.resource && snapshot.resource.affiliation ?

ClinGen Affiliation:

{getAffiliationName(snapshot.resource.affiliation)}

                                        : null}

Approved Classification entered by:

{snapshot.resource.approvalSubmitter}

                                    {snapshot.resource && snapshot.resource.classificationApprover ?

Approver:

{snapshot.resource.classificationApprover}

                                        : null}

Date saved as Approved:

{snapshot.resource.approvalDate ? formatDate(snapshot.resource.approvalDate, "YYYY MMM DD, h:mm a") : null}

                                        {this.renderClassificationStatusTag(snapshot.approvalStatus)}

Date reviewed:

{snapshot.resource.approvalReviewDate ? formatDate(snapshot.resource.approvalReviewDate, "YYYY MMM DD") : null}

{type === 'interpretation' ? 'Saved Pathogenicity:' : 'Saved Classification:'}

{snapshot.resource.alteredClassification ? {snapshot.resource.alteredClassification} (modified) : snapshot.resource.autoClassification}

Disease:

{snapshot.resourceParent && snapshot.resourceParent.disease && snapshot.resourceParent.disease.term ? snapshot.resourceParent.disease.term : 'None'}

Mode of Inheritance:

{renderSelectedModeInheritance(snapshot.resourceParent)}

Additional comments:

{snapshot.resource.approvalComment ? snapshot.resource.approvalComment : null}

                                    {index.toString() === "0" || index.toString() === "1" ?

                                        :

                                    }
                                    <Input type="button" inputClassName={buttonClass} title="View Approved Summary" clickHandler={this.viewSnapshotSummary.bind(this, snapshot['@id'], type)} />

            );
        }
    }

    render() {
        const { snapshots } = this.props;

        return (

                    {snapshots.map((snapshot, i) => this.renderSnapshot(snapshot, i))}

        );
    }
}

CurationSnapshots.propTypes = {
    snapshots: PropTypes.array
};

export default CurationSnapshots;<|endoftext|>


<commit_before>import {cache} from 'tocco-util'
import {login, notification, rest} from 'tocco-app-extensions'
import {all, call, delay, put, select, takeLatest} from 'redux-saga/effects'
import Cookies from 'js-cookie'

import * as actions from './actions'

export const sessionSelector = state => state.session

export function* sessionHeartBeat(sessionTimeout) {
  const threeQuarterSeconds = sessionTimeout * 45000
  yield call(delayByTimeout, threeQuarterSeconds)
  const {success, adminAllowed} = yield call(login.doSessionRequest)
  yield put(login.setLoggedIn(success))
  yield put(login.setAdminAllowed(adminAllowed))
  yield call(sessionHeartBeat, sessionTimeout)
}

/**
 * this is only here because 'yield delay(timeout)' is a pain to be called when testing
 * see https://github.com/jfairbank/redux-saga-test-plan/issues/257
 * @param timeout the time to wait
 */
export function* delayByTimeout(timeout) {
  yield delay(timeout)
}

export function* doLogoutRequest() {
  return yield call(login.doRequest, `${__BACKEND_URL__}/nice2/logout`, login.getOptions())
}

export function* loginSuccessful({payload}) {
  const {sessionTimeout} = payload
  yield put(login.setLoggedIn(true))
  yield put(notification.connectSocket())
  yield call(sessionHeartBeat, sessionTimeout)
}

export function* logout({payload}) {
  yield call(Cookies.remove, 'sso-autologin')
  yield call(doLogoutRequest)
  yield put(login.setLoggedIn(false))
  yield put(notification.closeSocket())
}

export function* loadPrincipal() {
  const {username, currentBusinessUnit} = yield call(rest.fetchPrincipal)
  yield put(actions.setUsername(username))
  yield put(actions.setCurrentBusinessUnit(currentBusinessUnit))
}

export function* loadBusinessUnits() {
  const bUs = yield call(rest.requestSaga, 'principals/businessunits')
  yield put(actions.setBusinessUnits(bUs.body.data))
}

export function* changeBusinessUnitId({payload: {businessUnitId}}) {
  const {username} = yield select(sessionSelector)
  const resource = `principals/${username}/businessunit`
  yield call(rest.requestSaga, resource, {method: 'PUT', body: {businessUnit: businessUnitId}})
  yield call(cache.clearShortTerm)
  location.reload()
}

export function* checkSsoAvailable() {
  const cachedSsoAvailable = cache.getLongTerm('session', 'ssoAvailable')
  if (cachedSsoAvailable !== undefined) {
    yield put(actions.setSsoAvailable(cachedSsoAvailable))
  } else {
    const ssoAvailable = yield call(isSsoAvailable)
    cache.addLongTerm('session', 'ssoAvailable', ssoAvailable)
    yield put(actions.setSsoAvailable(ssoAvailable))
  }
}

export function* isSsoAvailable() {
  const modules = yield call(rest.requestSaga, 'modules')
  const ssoModuleAvailable = modules.body.modules.includes('nice.optional.sso')
  if (!ssoModuleAvailable) {
    return false
  }
  const ssoProviderCount = yield call(rest.fetchEntityCount, 'Openid_provider', {where: 'active == true'})
  return ssoProviderCount > 0
}

export default function* mainSagas() {
  yield all([
    takeLatest(actions.LOGIN_SUCCESSFUL, loginSuccessful),
    takeLatest(actions.DO_LOGOUT, logout),
    takeLatest(actions.LOAD_PRINCIPAL, loadPrincipal),
    takeLatest(actions.LOAD_BUSINESS_UNITS, loadBusinessUnits),
    takeLatest(actions.CHANGE_BUSINESS_UNIT, changeBusinessUnitId),
    takeLatest(actions.CHECK_SSO_AVAILABLE, checkSsoAvailable)
  ])
}
<commit_msg>fix(admin): fix "hide content and menu when admin is forbidden"<commit_after>import {cache} from 'tocco-util'
import {login, notification, rest} from 'tocco-app-extensions'
import {all, call, delay, put, select, takeLatest} from 'redux-saga/effects'
import Cookies from 'js-cookie'

import * as actions from './actions'

export const sessionSelector = state => state.session

export function* sessionHeartBeat(sessionTimeout) {
  const threeQuarterSeconds = sessionTimeout * 45000
  const {success, adminAllowed} = yield call(login.doSessionRequest)
  yield put(login.setLoggedIn(success))
  yield put(login.setAdminAllowed(adminAllowed))
  yield call(delayByTimeout, threeQuarterSeconds)
  yield call(sessionHeartBeat, sessionTimeout)
}

/**
 * this is only here because 'yield delay(timeout)' is a pain to be called when testing
 * see https://github.com/jfairbank/redux-saga-test-plan/issues/257
 * @param timeout the time to wait
 */
export function* delayByTimeout(timeout) {
  yield delay(timeout)
}

export function* doLogoutRequest() {
  return yield call(login.doRequest, `${__BACKEND_URL__}/nice2/logout`, login.getOptions())
}

export function* loginSuccessful({payload}) {
  const {sessionTimeout} = payload
  yield put(login.setLoggedIn(true))
  yield put(notification.connectSocket())
  yield call(sessionHeartBeat, sessionTimeout)
}

export function* logout({payload}) {
  yield call(Cookies.remove, 'sso-autologin')
  yield call(doLogoutRequest)
  yield put(login.setLoggedIn(false))
  yield put(notification.closeSocket())
}

export function* loadPrincipal() {
  const {username, currentBusinessUnit} = yield call(rest.fetchPrincipal)
  yield put(actions.setUsername(username))
  yield put(actions.setCurrentBusinessUnit(currentBusinessUnit))
}

export function* loadBusinessUnits() {
  const bUs = yield call(rest.requestSaga, 'principals/businessunits')
  yield put(actions.setBusinessUnits(bUs.body.data))
}

export function* changeBusinessUnitId({payload: {businessUnitId}}) {
  const {username} = yield select(sessionSelector)
  const resource = `principals/${username}/businessunit`
  yield call(rest.requestSaga, resource, {method: 'PUT', body: {businessUnit: businessUnitId}})
  yield call(cache.clearShortTerm)
  location.reload()
}

export function* checkSsoAvailable() {
  const cachedSsoAvailable = cache.getLongTerm('session', 'ssoAvailable')
  if (cachedSsoAvailable !== undefined) {
    yield put(actions.setSsoAvailable(cachedSsoAvailable))
  } else {
    const ssoAvailable = yield call(isSsoAvailable)
    cache.addLongTerm('session', 'ssoAvailable', ssoAvailable)
    yield put(actions.setSsoAvailable(ssoAvailable))
  }
}

export function* isSsoAvailable() {
  const modules = yield call(rest.requestSaga, 'modules')
  const ssoModuleAvailable = modules.body.modules.includes('nice.optional.sso')
  if (!ssoModuleAvailable) {
    return false
  }
  const ssoProviderCount = yield call(rest.fetchEntityCount, 'Openid_provider', {where: 'active == true'})
  return ssoProviderCount > 0
}

export default function* mainSagas() {
  yield all([
    takeLatest(actions.LOGIN_SUCCESSFUL, loginSuccessful),
    takeLatest(actions.DO_LOGOUT, logout),
    takeLatest(actions.LOAD_PRINCIPAL, loadPrincipal),
    takeLatest(actions.LOAD_BUSINESS_UNITS, loadBusinessUnits),
    takeLatest(actions.CHANGE_BUSINESS_UNIT, changeBusinessUnitId),
    takeLatest(actions.CHECK_SSO_AVAILABLE, checkSsoAvailable)
  ])
}
<|endoftext|>


<commit_before>(function ($, Vel) {
  'use strict';

  let _defaults = {
    duration: 300,
    onShow: null,
    swipeable: false,
    responsiveThreshold: Infinity, // breakpoint for swipeable
  };

  /**
   * @class
   *
   */
  class Tabs {
    /**
     * Construct Tabs instance
     * @constructor
     * @param {Element} el
     * @param {Object} options
     */
    constructor(el, options) {
      // If exists, destroy and reinitialize
      if (!!el.M_Tabs) {
        el.M_Tabs.destroy();
      }

      /**
       * The jQuery element
       * @type {jQuery}
       */
      this.$el = $(el);

      this.el = el;

      /**
       * Options for the carousel
       * @member Tabs#options
       * @prop {Number} duration
       * @prop {Function} onShow
       * @prop {Boolean} swipeable
       * @prop {Number} responsiveThreshold
       */
      this.options = $.extend({}, Tabs.defaults, options);

      this.el.M_Tabs = this;

      // Setup
      this.$tabLinks = this.$el.children('li.tab').children('a');
      this.index = 0;
      this._setTabsAndTabWidth();
      this._setupActiveTabLink();
      this._createIndicator();

      if (this.options.swipeable) {
        this._setupSwipeableTabs();

      } else {
        this._setupNormalTabs();
      }

      this._setupEventHandlers();
    }

    static get defaults() {
      return _defaults;
    }

    static init($els, options) {
      let arr = [];
      $els.each(function() {
        arr.push(new Tabs(this, options));
      });
      return arr;
    }

    /**
     * Get Instance
     */
    static getInstance(el) {
      let domElem = !!el.jquery ? el[0] : el;
      return domElem.M_Tabs;
    }

    /**
     * Teardown component
     */
    destroy() {
      this._removeEventHandlers();
      this._indicator.parentNode.removeChild(this._indicator);

      if (this.options.swipeable) {
        this._teardownSwipeableTabs();
      } else {
        this._teardownNormalTabs();
      }

      this.$el[0].M_Tabs = undefined;
    }

    /**
     * Setup Event Handlers
     */
    _setupEventHandlers() {
      this._handleWindowResizeBound = this._handleWindowResize.bind(this);
      window.addEventListener('resize', this._handleWindowResizeBound);

      this._handleTabClickBound = this._handleTabClick.bind(this);
      this.el.addEventListener('click', this._handleTabClickBound);
    }

    /**
     * Remove Event Handlers
     */
    _removeEventHandlers() {
      window.removeEventListener('resize', this._handleWindowResizeBound);
      this.el.removeEventListener('click', this._handleTabClickBound);
    }

    /**
     * Handle window Resize
     */
    _handleWindowResize() {
      this._setTabsAndTabWidth();

      if (this.tabWidth !== 0 && this.tabsWidth !== 0) {
        this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px';
        this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px';
      }
    }

    /**
     * Handle tab click
     * @param {Event} e
     */
    _handleTabClick(e) {
      let tab = $(e.target).closest('li.tab');
      let tabLink = $(e.target).closest('a');

      // Handle click on tab link only
      if (!tabLink.length || !tabLink.parent().hasClass('tab')) {
        return;
      }

      if (tab.hasClass('disabled')) {
        e.preventDefault();
        return;
      }

      // Act as regular link if target attribute is specified.
      if (!!tabLink.attr("target")) {
        return;
      }

      this._setTabsAndTabWidth();

      // Make the old tab inactive.
      this.$activeTabLink.removeClass('active');
      let $oldContent = this.$content;

      // Update the variables with the new link and content
      this.$activeTabLink = tabLink;
      this.$content = $(M.escapeHash(tabLink[0].hash));
      this.$tabLinks = this.$el.children('li.tab').children('a');

      // Make the tab active.
      this.$activeTabLink.addClass('active');
      let prevIndex = this.index;
      this.index = Math.max(this.$tabLinks.index(tabLink), 0);

      // Swap content
      if (this.options.swipeable) {
        if (this._tabsCarousel) {
          this._tabsCarousel.set(this.index, () => {
            if (typeof(this.options.onShow) === "function") {
              this.options.onShow.call(this, this.$content[0]);
            }
          });
        }
      } else {
        if (this.$content.length) {
          this.$content[0].style.display = 'block';
          this.$content.addClass('active');
          if (typeof(this.options.onShow) === 'function') {
            this.options.onShow.call(this, this.$content[0]);
          }

          if ($oldContent.length &&
              !$oldContent.is(this.$content)) {
            $oldContent[0].style.display = 'none';
            $oldContent.removeClass('active');
          }
        }
      }

      // Update indicator
      this._animateIndicator(prevIndex);

      // Prevent the anchor's default click action
      e.preventDefault();
    }

    /**
     * Generate elements for tab indicator.
     */
    _createIndicator() {
      let indicator = document.createElement('li');
      indicator.classList.add('indicator');

      this.el.appendChild(indicator);
      this._indicator = indicator;

      setTimeout(() => {
        this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px';
        this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px';
      }, 0);
    }

    /**
     * Setup first active tab link.
     */
    _setupActiveTabLink() {
      // If the location.hash matches one of the links, use that as the active tab.
      this.$activeTabLink = $(this.$tabLinks.filter('[href="'+location.hash+'"]'));

      // If no match is found, use the first link or any with class 'active' as the initial active tab.
      if (this.$activeTabLink.length === 0) {
        this.$activeTabLink = this.$el.children('li.tab').children('a.active').first();
      }
      if (this.$activeTabLink.length === 0) {
        this.$activeTabLink = this.$el.children('li.tab').children('a').first();
      }

      this.$tabLinks.removeClass('active');
      this.$activeTabLink[0].classList.add('active');

      this.index = Math.max(this.$tabLinks.index(this.$activeTabLink), 0);

      if (this.$activeTabLink.length) {
        this.$content = $(M.escapeHash(this.$activeTabLink[0].hash));
        this.$content.addClass('active');
      }
    }

    /**
     * Setup swipeable tabs
     */
    _setupSwipeableTabs() {
      // Change swipeable according to responsive threshold
      if (window.innerWidth > options.responsiveThreshold) {
        this.options.swipeable = false;
      }

      let $tabsContent = $();
      this.$tabLinks.each((link) => {
        let $currContent = $(M.escapeHash(link.hash));
        $currContent.addClass('carousel-item');
        $tabsContent = $tabsContent.add($currContent);
      });

      let $tabsWrapper = $('

');
      $tabsContent.first().before($tabsWrapper);
      $tabsWrapper.append($tabsContent);
      $tabsContent[0].style.display = '';

      this._tabsCarousel = new M.Carousel($tabsWrapper[0], {
        fullWidth: true,
        noWrap: true,
        onCycleTo: (item) => {
          let prevIndex = this.index;
          this.index = $(item).index();
          this.$activeTabLink.removeClass('active');
          this.$activeTabLink = this.$tabLinks.eq(this.index);
          this.$activeTabLink.addClass('active');
          this._animateIndicator(prevIndex);
          if (typeof(this.options.onShow) === "function") {
            this.options.onShow.call(this, this.$content);
          }
        },
      });
    }

    /**
     * Teardown normal tabs.
     */
    _teardownSwipeableTabs() {
      let $tabsWrapper = this._tabsCarousel.$el;
      this._tabsCarousel.destroy();

      // Unwrap
      $tabsWrapper.after($tabsWrapper.children());
      $tabsWrapper.remove();
    }

    /**
     * Setup normal tabs.
     */
    _setupNormalTabs() {
      // Hide Tabs Content
      this.$tabLinks.not(this.$activeTabLink).each((link) => {
        if (!!link.hash) {
          let $currContent = $(M.escapeHash(link.hash));
          if ($currContent.length) {
            $currContent[0].style.display = 'none';
          }
        }
      });
    }

    /**
     * Teardown normal tabs.
     */
    _teardownNormalTabs() {
      // show Tabs Content
      this.$tabLinks.each((link) => {
        if (!!link.hash) {
          let $currContent = $(M.escapeHash(link.hash));
          if ($currContent.length) {
            $currContent[0].style.display = '';
          }
        }
      });
    }

    /**
     * set tabs and tab width
     */
    _setTabsAndTabWidth() {
      this.tabsWidth = this.$el.width();
      this.tabWidth = Math.max(this.tabsWidth, this.el.scrollWidth) / this.$tabLinks.length;
    }

    /**
     * Finds right attribute for indicator based on active tab.
     * @param {cash} el
     */
    _calcRightPos(el) {
      return Math.ceil(this.tabsWidth - el.position().left - el[0].getBoundingClientRect().width);
    }

    /**
     * Finds left attribute for indicator based on active tab.
     * @param {cash} el
     */
    _calcLeftPos(el) {
      return Math.floor(el.position().left);
    }

    updateTabIndicator() {
      this._animateIndicator(this.index);
    }

    /**
     * Animates Indicator to active tab.
     * @param {Number} prevIndex
     */
    _animateIndicator(prevIndex) {
      let velOptions = {
        duration: this.options.duration,
        queue: false,
        easing: 'easeOutQuad'
      };
      let velOptionsLeft, velOptionsRight;

      if ((this.index - prevIndex) >= 0) {
        velOptionsLeft = $.extend({}, velOptions, {delay: 90});
        velOptionsRight = velOptions;

      } else {
        velOptionsLeft = velOptions;
        velOptionsRight = $.extend({}, velOptions, {delay: 90});
      }

      // Animate with velocity
      Vel(
        this._indicator,
        {left: this._calcLeftPos(this.$activeTabLink) },
        velOptionsLeft
      );
      Vel(
        this._indicator,
        {right: this._calcRightPos(this.$activeTabLink) },
        velOptionsRight
      );
    }

    /**
     * Select tab.
     * @param {String} tabId
     */
    select(tabId) {
      let tab = this.$tabLinks.filter('[href="#' + tabId + '"]');
      if (tab.length) {
        tab.trigger('click');
      }
    }
  }

  window.M.Tabs = Tabs;

  if (M.jQueryLoaded) {
    M.initializeJqueryWrapper(Tabs, 'tabs', 'M_Tabs');
  }

})(cash, M.Vel);
<commit_msg>fix some typo.<commit_after>(function ($, Vel) {
  'use strict';

  let _defaults = {
    duration: 300,
    onShow: null,
    swipeable: false,
    responsiveThreshold: Infinity, // breakpoint for swipeable
  };

  /**
   * @class
   *
   */
  class Tabs {
    /**
     * Construct Tabs instance
     * @constructor
     * @param {Element} el
     * @param {Object} options
     */
    constructor(el, options) {
      // If exists, destroy and reinitialize
      if (!!el.M_Tabs) {
        el.M_Tabs.destroy();
      }

      /**
       * The jQuery element
       * @type {jQuery}
       */
      this.$el = $(el);

      this.el = el;

      /**
       * Options for the Tabs
       * @member Tabs#options
       * @prop {Number} duration
       * @prop {Function} onShow
       * @prop {Boolean} swipeable
       * @prop {Number} responsiveThreshold
       */
      this.options = $.extend({}, Tabs.defaults, options);

      this.el.M_Tabs = this;

      // Setup
      this.$tabLinks = this.$el.children('li.tab').children('a');
      this.index = 0;
      this._setTabsAndTabWidth();
      this._setupActiveTabLink();
      this._createIndicator();

      if (this.options.swipeable) {
        this._setupSwipeableTabs();

      } else {
        this._setupNormalTabs();
      }

      this._setupEventHandlers();
    }

    static get defaults() {
      return _defaults;
    }

    static init($els, options) {
      let arr = [];
      $els.each(function() {
        arr.push(new Tabs(this, options));
      });
      return arr;
    }

    /**
     * Get Instance
     */
    static getInstance(el) {
      let domElem = !!el.jquery ? el[0] : el;
      return domElem.M_Tabs;
    }

    /**
     * Teardown component
     */
    destroy() {
      this._removeEventHandlers();
      this._indicator.parentNode.removeChild(this._indicator);

      if (this.options.swipeable) {
        this._teardownSwipeableTabs();
      } else {
        this._teardownNormalTabs();
      }

      this.$el[0].M_Tabs = undefined;
    }

    /**
     * Setup Event Handlers
     */
    _setupEventHandlers() {
      this._handleWindowResizeBound = this._handleWindowResize.bind(this);
      window.addEventListener('resize', this._handleWindowResizeBound);

      this._handleTabClickBound = this._handleTabClick.bind(this);
      this.el.addEventListener('click', this._handleTabClickBound);
    }

    /**
     * Remove Event Handlers
     */
    _removeEventHandlers() {
      window.removeEventListener('resize', this._handleWindowResizeBound);
      this.el.removeEventListener('click', this._handleTabClickBound);
    }

    /**
     * Handle window Resize
     */
    _handleWindowResize() {
      this._setTabsAndTabWidth();

      if (this.tabWidth !== 0 && this.tabsWidth !== 0) {
        this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px';
        this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px';
      }
    }

    /**
     * Handle tab click
     * @param {Event} e
     */
    _handleTabClick(e) {
      let tab = $(e.target).closest('li.tab');
      let tabLink = $(e.target).closest('a');

      // Handle click on tab link only
      if (!tabLink.length || !tabLink.parent().hasClass('tab')) {
        return;
      }

      if (tab.hasClass('disabled')) {
        e.preventDefault();
        return;
      }

      // Act as regular link if target attribute is specified.
      if (!!tabLink.attr("target")) {
        return;
      }

      this._setTabsAndTabWidth();

      // Make the old tab inactive.
      this.$activeTabLink.removeClass('active');
      let $oldContent = this.$content;

      // Update the variables with the new link and content
      this.$activeTabLink = tabLink;
      this.$content = $(M.escapeHash(tabLink[0].hash));
      this.$tabLinks = this.$el.children('li.tab').children('a');

      // Make the tab active.
      this.$activeTabLink.addClass('active');
      let prevIndex = this.index;
      this.index = Math.max(this.$tabLinks.index(tabLink), 0);

      // Swap content
      if (this.options.swipeable) {
        if (this._tabsCarousel) {
          this._tabsCarousel.set(this.index, () => {
            if (typeof(this.options.onShow) === "function") {
              this.options.onShow.call(this, this.$content[0]);
            }
          });
        }
      } else {
        if (this.$content.length) {
          this.$content[0].style.display = 'block';
          this.$content.addClass('active');
          if (typeof(this.options.onShow) === 'function') {
            this.options.onShow.call(this, this.$content[0]);
          }

          if ($oldContent.length &&
              !$oldContent.is(this.$content)) {
            $oldContent[0].style.display = 'none';
            $oldContent.removeClass('active');
          }
        }
      }

      // Update indicator
      this._animateIndicator(prevIndex);

      // Prevent the anchor's default click action
      e.preventDefault();
    }

    /**
     * Generate elements for tab indicator.
     */
    _createIndicator() {
      let indicator = document.createElement('li');
      indicator.classList.add('indicator');

      this.el.appendChild(indicator);
      this._indicator = indicator;

      setTimeout(() => {
        this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px';
        this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px';
      }, 0);
    }

    /**
     * Setup first active tab link.
     */
    _setupActiveTabLink() {
      // If the location.hash matches one of the links, use that as the active tab.
      this.$activeTabLink = $(this.$tabLinks.filter('[href="'+location.hash+'"]'));

      // If no match is found, use the first link or any with class 'active' as the initial active tab.
      if (this.$activeTabLink.length === 0) {
        this.$activeTabLink = this.$el.children('li.tab').children('a.active').first();
      }
      if (this.$activeTabLink.length === 0) {
        this.$activeTabLink = this.$el.children('li.tab').children('a').first();
      }

      this.$tabLinks.removeClass('active');
      this.$activeTabLink[0].classList.add('active');

      this.index = Math.max(this.$tabLinks.index(this.$activeTabLink), 0);

      if (this.$activeTabLink.length) {
        this.$content = $(M.escapeHash(this.$activeTabLink[0].hash));
        this.$content.addClass('active');
      }
    }

    /**
     * Setup swipeable tabs
     */
    _setupSwipeableTabs() {
      // Change swipeable according to responsive threshold
      if (window.innerWidth > options.responsiveThreshold) {
        this.options.swipeable = false;
      }

      let $tabsContent = $();
      this.$tabLinks.each((link) => {
        let $currContent = $(M.escapeHash(link.hash));
        $currContent.addClass('carousel-item');
        $tabsContent = $tabsContent.add($currContent);
      });

      let $tabsWrapper = $('

');
      $tabsContent.first().before($tabsWrapper);
      $tabsWrapper.append($tabsContent);
      $tabsContent[0].style.display = '';

      this._tabsCarousel = new M.Carousel($tabsWrapper[0], {
        fullWidth: true,
        noWrap: true,
        onCycleTo: (item) => {
          let prevIndex = this.index;
          this.index = $(item).index();
          this.$activeTabLink.removeClass('active');
          this.$activeTabLink = this.$tabLinks.eq(this.index);
          this.$activeTabLink.addClass('active');
          this._animateIndicator(prevIndex);
          if (typeof(this.options.onShow) === "function") {
            this.options.onShow.call(this, this.$content[0]);
          }
        },
      });
    }

    /**
     * Teardown normal tabs.
     */
    _teardownSwipeableTabs() {
      let $tabsWrapper = this._tabsCarousel.$el;
      this._tabsCarousel.destroy();

      // Unwrap
      $tabsWrapper.after($tabsWrapper.children());
      $tabsWrapper.remove();
    }

    /**
     * Setup normal tabs.
     */
    _setupNormalTabs() {
      // Hide Tabs Content
      this.$tabLinks.not(this.$activeTabLink).each((link) => {
        if (!!link.hash) {
          let $currContent = $(M.escapeHash(link.hash));
          if ($currContent.length) {
            $currContent[0].style.display = 'none';
          }
        }
      });
    }

    /**
     * Teardown normal tabs.
     */
    _teardownNormalTabs() {
      // show Tabs Content
      this.$tabLinks.each((link) => {
        if (!!link.hash) {
          let $currContent = $(M.escapeHash(link.hash));
          if ($currContent.length) {
            $currContent[0].style.display = '';
          }
        }
      });
    }

    /**
     * set tabs and tab width
     */
    _setTabsAndTabWidth() {
      this.tabsWidth = this.$el.width();
      this.tabWidth = Math.max(this.tabsWidth, this.el.scrollWidth) / this.$tabLinks.length;
    }

    /**
     * Finds right attribute for indicator based on active tab.
     * @param {cash} el
     */
    _calcRightPos(el) {
      return Math.ceil(this.tabsWidth - el.position().left - el[0].getBoundingClientRect().width);
    }

    /**
     * Finds left attribute for indicator based on active tab.
     * @param {cash} el
     */
    _calcLeftPos(el) {
      return Math.floor(el.position().left);
    }

    updateTabIndicator() {
      this._animateIndicator(this.index);
    }

    /**
     * Animates Indicator to active tab.
     * @param {Number} prevIndex
     */
    _animateIndicator(prevIndex) {
      let velOptions = {
        duration: this.options.duration,
        queue: false,
        easing: 'easeOutQuad'
      };
      let velOptionsLeft, velOptionsRight;

      if ((this.index - prevIndex) >= 0) {
        velOptionsLeft = $.extend({}, velOptions, {delay: 90});
        velOptionsRight = velOptions;

      } else {
        velOptionsLeft = velOptions;
        velOptionsRight = $.extend({}, velOptions, {delay: 90});
      }

      // Animate with velocity
      Vel(
        this._indicator,
        {left: this._calcLeftPos(this.$activeTabLink) },
        velOptionsLeft
      );
      Vel(
        this._indicator,
        {right: this._calcRightPos(this.$activeTabLink) },
        velOptionsRight
      );
    }

    /**
     * Select tab.
     * @param {String} tabId
     */
    select(tabId) {
      let tab = this.$tabLinks.filter('[href="#' + tabId + '"]');
      if (tab.length) {
        tab.trigger('click');
      }
    }
  }

  window.M.Tabs = Tabs;

  if (M.jQueryLoaded) {
    M.initializeJqueryWrapper(Tabs, 'tabs', 'M_Tabs');
  }

})(cash, M.Vel);
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const Table = require('easy-table');

const plugin = require('../index');

/**
 * This module exports a function that enrich the interactive command line and return a promise
 * @returns {Promise} - a promise that resolve when the operation is done
 */
module.exports = (icli) => {

  // Build the lists of choices
  const choicesLists = getChoices();

  const config = {
    section: 'Api Gateway plugin',
    cmd: 'deploy-apis',
    description: 'deploy apis',
    parameters: [{
      cmdSpec: '[api-identifiers...]',
      type: 'checkbox',
      choices: choicesLists.apiIdentifiers,
      question: {
        message: 'Which APIs do you want to deploy?'
      }
    }, {
      cmdSpec: '-r, --region <region>',
      description: 'select the AWS region',
      type: 'list',
      choices: choicesLists.region,
      validationMsgLabel: 'AWS region',
      question: {
        message: 'On which AWS region do you want to deploy?'
      }
    }, {
      cmdSpec: '-e, --environment <environment>',
      description: 'select the environment',
      type: 'input',
      default: 'DEV',
      question: {
        message: 'On which environment do you want to deploy?',
        when: (answers, cmdParameterValues) => {
          return cmdParameterValues['environment'] === undefined && plugin.myrmex.getConfig('environment') === undefined;
        }
      }
    }, {
      cmdSpec: '-s, --stage <stage>',
      description: 'select the API stage',
      type: 'input',
      default: 'v0',
      question: {
        message: 'Which API stage do you want to deploy?',
        when: (answers, cmdParameterValues) => {
          return cmdParameterValues['stage'] === undefined && plugin.myrmex.getConfig('stage') === undefined;
        }
      }
    }],
    execute: executeCommand
  };

  /**
   * Create the command and the prompt
   */
  return icli.createSubCommand(config);

  /**
   * Build the choices for "list" and "checkbox" parameters
   * @returns {Object} - collection of lists of choices for "list" and "checkbox" parameters
   */
  function getChoices() {
    return {
      apiIdentifiers: () => {
        return plugin.loadApis()
        .then(apis => {
          if (!apis.length) {
            icli.print(icli.format.error('This project does not contain any API.'));
            process.exit(1);
          }
          return _.map(apis, api => {
            return {
              value: api.getIdentifier(),
              name: icli.format.info(api.getIdentifier()) + (api.spec.info && api.spec.info.title ? ' - ' + api.spec.info.title : '')
            };
          });
        });
      },
      region: [
        {
          value: 'us-east-1',
          name: icli.format.info('us-east-1') + '      US East (N. Virginia)',
          short: 'us-east-1 - US East (N. Virginia)'
        }, {
          value: 'us-east-2',
          name: icli.format.info('us-east-2') + '      US East (Ohio)',
          short: 'us-east-2 - US East (Ohio)'
        }, {
          value: 'us-west-1',
          name: icli.format.info('us-west-1') + '      US West (N. California)',
          short: 'us-west-1 - US West (N. California)'
        }, {
          value: 'us-west-2',
          name: icli.format.info('us-west-2') + '      US West (Oregon)',
          short: 'us-west-2 - US West (Oregon)'
        }, {
          value: 'ca-central-1',
          name: icli.format.info('ca-central-1') + '   Canada (Central)',
          short: 'ca-central-1 - Canada (Central)'
        }, {
          value: 'sa-east-1',
          name: icli.format.info('sa-east-1') + '      South America (São Paulo)',
          short: 'sa-east-1 - South America (São Paulo)'
        }, {
          value: 'eu-west-1',
          name: icli.format.info('eu-west-1') + '      EU (Ireland)',
          short: 'eu-west-1 - EU (Ireland)'
        }, {
          value: 'eu-west-2',
          name: icli.format.info('eu-west-2') + '      EU (London)',
          short: 'eu-west-2 - EU (London)'
        }, {
          value: 'eu-west-3',
          name: icli.format.info('eu-west-3') + '      EU (Paris)',
          short: 'eu-west-3 - EU (Paris)'
        }, {
          value: 'eu-central-1',
          name: icli.format.info('eu-central-1') + '   EU (Frankfurt)',
          short: 'eu-central-1 - EU (Frankfurt)'
        }, {
          value: 'ap-south-1',
          name: icli.format.info('ap-south-1') + '     Asia Pacific (Mumbai)',
          short: 'ap-south-1 - Asia Pacific (Mumbai)'
        }, {
          value: 'ap-northeast-1',
          name: icli.format.info('ap-northeast-1') + ' Asia Pacific (Tokyo)',
          short: 'ap-northeast-1 - Asia Pacific (Tokyo)'
        }, {
          value: 'ap-northeast-2',
          name: icli.format.info('ap-northeast-2') + ' Asia Pacific (Seoul)',
          short: 'ap-northeast-2 - Asia Pacific (Seoul)'
        }, {
          value: 'ap-northeast-3',
          name: icli.format.info('ap-northeast-3') + ' Asia Pacific (Osaka-Local)',
          short: 'ap-northeast-3 - Asia Pacific (Osaka-Local)'
        }, {
          value: 'ap-southeast-1',
          name: icli.format.info('ap-southeast-1') + ' Asia Pacific (Singapore)',
          short: 'ap-southeast-1 - Asia Pacific (Singapore)'
        }, {
          value: 'ap-southeast-2',
          name: icli.format.info('ap-southeast-2') + ' Asia Pacific (Sydney)',
          short: 'ap-southeast-2 - Asia Pacific (Sydney)'
        }
      ]
    };
  }

  /**
   * Execute the deployment
   * @param {Object} parameters - the parameters provided in the command and in the prompt
   * @returns {Promise<null>} - The execution stops here
   */
  function executeCommand(parameters) {
    if (parameters.environment === undefined) { parameters.environment = plugin.myrmex.getConfig('environment'); }
    if (parameters.stage === undefined) { parameters.stage = plugin.myrmex.getConfig('stage'); }
    const context = {
      environment: parameters.environment,
      stage: parameters.stage
    };

    return plugin.loadApis()
    .then(apis => {
      // Give an overview of what will be deployed
      apis = _.filter(apis, api => { return parameters.apiIdentifiers.indexOf(api.getIdentifier()) !== -1; });
      const endpoints = _.union.apply(null, _.map(apis, api => { return api.getEndpoints(); }));
      const t = new Table();
      _.forEach(endpoints, endpoint => {
        t.cell('Path', endpoint.getResourcePath());
        t.cell('Method', endpoint.getMethod());
        _.forEach(endpoint.getSpec()['x-myrmex'].apis, apiIdentifier => {
          if (parameters.apiIdentifiers.indexOf(apiIdentifier) > -1) {
            t.cell(apiIdentifier, 'X');
          }
        });
        t.newRow();
      });
      icli.print();
      icli.print('Endpoints to deploy');
      icli.print();
      icli.print(t.toString());

      // Load endpoints integrations
      return Promise.all([
        apis,
        plugin.loadIntegrations(parameters.region, context, endpoints)
      ]);
    })
    .spread((apis, integrations) => {
      // Deploy in API Gateway
      // To avoid TooManyRequestsException, we delay the deployment of each API
      const promises = [];
      let delay = 0;
      _.forEach(apis, api => {
        promises.push(new Promise((resolve, reject) => {
          // 35 seconds delay
          setTimeout(() => {
            icli.print('Deploying ' + icli.format.info(api.getIdentifier()) + ' ...');
            resolve(api.deploy(parameters.region, context));
          }, delay * 35000);
        }));
        delay++;
      });
      return Promise.all([
        apis,
        Promise.all(promises)
      ]);
    })
    .spread((apis, results) => {
      // Display deployment result
      let success = true;
      const t = new Table();
      _.forEach(results, result => {
        t.cell('Identifier', result.api.getIdentifier());
        t.cell('Name', result.report.name);
        t.cell('Operation', result.report.operation);
        t.cell('Stage', result.report.stage);
        t.cell('AWS identifier', result.report.awsId);
        if (result.report.failed) {
          t.cell('Url', icli.format.error(result.report.failed));
          success = false;
        } else {
          t.cell(
            'Url',
            icli.format.info('https://' + result.report.awsId + '.execute-api.' + result.report.region + '.amazonaws.com/' + result.report.stage)
          );
        }
        t.newRow();
      });
      icli.print();
      icli.print(icli.format.success('Deployment done'));
      icli.print();
      icli.print(t.toString());

      // Publish the APIs
      if (success) {
        return Promise.map(apis, api => { return api.publish(parameters.region, context); })
        .then(() => {
          icli.print(icli.format.success('APIs have been published'));
          icli.print();
        })
        .catch(e => {
          icli.print(icli.format.error('The deployment of APIs succeed but the publication step failed.'));
          icli.print(e);
          process.exit(1);
        });
      } else {
        icli.print(icli.format.error('The deployment of one or more APIs failed. The publication step will not be performed.'));
        icli.print();
        process.exit(1);
      }
    });
  }

};
<commit_msg>fix(api-gateway): remove duplicated endpoints rows from deployment information table<commit_after>'use strict';

const _ = require('lodash');
const Table = require('easy-table');

const plugin = require('../index');

/**
 * This module exports a function that enrich the interactive command line and return a promise
 * @returns {Promise} - a promise that resolve when the operation is done
 */
module.exports = (icli) => {

  // Build the lists of choices
  const choicesLists = getChoices();

  const config = {
    section: 'Api Gateway plugin',
    cmd: 'deploy-apis',
    description: 'deploy apis',
    parameters: [{
      cmdSpec: '[api-identifiers...]',
      type: 'checkbox',
      choices: choicesLists.apiIdentifiers,
      question: {
        message: 'Which APIs do you want to deploy?'
      }
    }, {
      cmdSpec: '-r, --region <region>',
      description: 'select the AWS region',
      type: 'list',
      choices: choicesLists.region,
      validationMsgLabel: 'AWS region',
      question: {
        message: 'On which AWS region do you want to deploy?'
      }
    }, {
      cmdSpec: '-e, --environment <environment>',
      description: 'select the environment',
      type: 'input',
      default: 'DEV',
      question: {
        message: 'On which environment do you want to deploy?',
        when: (answers, cmdParameterValues) => {
          return cmdParameterValues['environment'] === undefined && plugin.myrmex.getConfig('environment') === undefined;
        }
      }
    }, {
      cmdSpec: '-s, --stage <stage>',
      description: 'select the API stage',
      type: 'input',
      default: 'v0',
      question: {
        message: 'Which API stage do you want to deploy?',
        when: (answers, cmdParameterValues) => {
          return cmdParameterValues['stage'] === undefined && plugin.myrmex.getConfig('stage') === undefined;
        }
      }
    }],
    execute: executeCommand
  };

  /**
   * Create the command and the prompt
   */
  return icli.createSubCommand(config);

  /**
   * Build the choices for "list" and "checkbox" parameters
   * @returns {Object} - collection of lists of choices for "list" and "checkbox" parameters
   */
  function getChoices() {
    return {
      apiIdentifiers: () => {
        return plugin.loadApis()
        .then(apis => {
          if (!apis.length) {
            icli.print(icli.format.error('This project does not contain any API.'));
            process.exit(1);
          }
          return _.map(apis, api => {
            return {
              value: api.getIdentifier(),
              name: icli.format.info(api.getIdentifier()) + (api.spec.info && api.spec.info.title ? ' - ' + api.spec.info.title : '')
            };
          });
        });
      },
      region: [
        {
          value: 'us-east-1',
          name: icli.format.info('us-east-1') + '      US East (N. Virginia)',
          short: 'us-east-1 - US East (N. Virginia)'
        }, {
          value: 'us-east-2',
          name: icli.format.info('us-east-2') + '      US East (Ohio)',
          short: 'us-east-2 - US East (Ohio)'
        }, {
          value: 'us-west-1',
          name: icli.format.info('us-west-1') + '      US West (N. California)',
          short: 'us-west-1 - US West (N. California)'
        }, {
          value: 'us-west-2',
          name: icli.format.info('us-west-2') + '      US West (Oregon)',
          short: 'us-west-2 - US West (Oregon)'
        }, {
          value: 'ca-central-1',
          name: icli.format.info('ca-central-1') + '   Canada (Central)',
          short: 'ca-central-1 - Canada (Central)'
        }, {
          value: 'sa-east-1',
          name: icli.format.info('sa-east-1') + '      South America (São Paulo)',
          short: 'sa-east-1 - South America (São Paulo)'
        }, {
          value: 'eu-west-1',
          name: icli.format.info('eu-west-1') + '      EU (Ireland)',
          short: 'eu-west-1 - EU (Ireland)'
        }, {
          value: 'eu-west-2',
          name: icli.format.info('eu-west-2') + '      EU (London)',
          short: 'eu-west-2 - EU (London)'
        }, {
          value: 'eu-west-3',
          name: icli.format.info('eu-west-3') + '      EU (Paris)',
          short: 'eu-west-3 - EU (Paris)'
        }, {
          value: 'eu-central-1',
          name: icli.format.info('eu-central-1') + '   EU (Frankfurt)',
          short: 'eu-central-1 - EU (Frankfurt)'
        }, {
          value: 'ap-south-1',
          name: icli.format.info('ap-south-1') + '     Asia Pacific (Mumbai)',
          short: 'ap-south-1 - Asia Pacific (Mumbai)'
        }, {
          value: 'ap-northeast-1',
          name: icli.format.info('ap-northeast-1') + ' Asia Pacific (Tokyo)',
          short: 'ap-northeast-1 - Asia Pacific (Tokyo)'
        }, {
          value: 'ap-northeast-2',
          name: icli.format.info('ap-northeast-2') + ' Asia Pacific (Seoul)',
          short: 'ap-northeast-2 - Asia Pacific (Seoul)'
        }, {
          value: 'ap-northeast-3',
          name: icli.format.info('ap-northeast-3') + ' Asia Pacific (Osaka-Local)',
          short: 'ap-northeast-3 - Asia Pacific (Osaka-Local)'
        }, {
          value: 'ap-southeast-1',
          name: icli.format.info('ap-southeast-1') + ' Asia Pacific (Singapore)',
          short: 'ap-southeast-1 - Asia Pacific (Singapore)'
        }, {
          value: 'ap-southeast-2',
          name: icli.format.info('ap-southeast-2') + ' Asia Pacific (Sydney)',
          short: 'ap-southeast-2 - Asia Pacific (Sydney)'
        }
      ]
    };
  }

  /**
   * Execute the deployment
   * @param {Object} parameters - the parameters provided in the command and in the prompt
   * @returns {Promise<null>} - The execution stops here
   */
  function executeCommand(parameters) {
    if (parameters.environment === undefined) { parameters.environment = plugin.myrmex.getConfig('environment'); }
    if (parameters.stage === undefined) { parameters.stage = plugin.myrmex.getConfig('stage'); }
    const context = {
      environment: parameters.environment,
      stage: parameters.stage
    };

    return plugin.loadApis()
    .then(apis => {
      // Give an overview of what will be deployed
      apis = _.filter(apis, api => { return parameters.apiIdentifiers.indexOf(api.getIdentifier()) !== -1; });
      const endpoints = _.concat.apply(null, _.map(apis, api => { return api.getEndpoints(); }));
      const filteredEndpoints = _.reduce(endpoints, (result, endpoint) => {
        let r = _.find(result, (o) => { return o.path === endpoint.getResourcePath() && o.method === endpoint.getMethod() });
        if (!r) {
          r = {
            path: endpoint.getResourcePath(),
            method: endpoint.getMethod(),
            apis: []
          }
          result.push(r);
        }
        r.apis = _.union(r.apis, endpoint.getSpec()['x-myrmex'].apis);
        return result;
      }, []);
      const sortedEndpoints = _.sortBy(filteredEndpoints, ['path', 'method']);
      const t = new Table();
      _.forEach(sortedEndpoints, endpoint => {
        t.cell('Path', endpoint.path);
        t.cell('Method', endpoint.method);
        _.forEach(endpoint.apis, apiIdentifier => {
          if (parameters.apiIdentifiers.indexOf(apiIdentifier) > -1) {
            t.cell(apiIdentifier, 'X');
          }
        });
        t.newRow();
      });
      icli.print();
      icli.print('Endpoints to deploy');
      icli.print();
      icli.print(t.toString());

      // Load endpoints integrations
      return Promise.all([
        apis,
        plugin.loadIntegrations(parameters.region, context, endpoints)
      ]);
    })
    .spread((apis, integrations) => {
      // Deploy in API Gateway
      // To avoid TooManyRequestsException, we delay the deployment of each API
      const promises = [];
      let delay = 0;
      _.forEach(apis, api => {
        promises.push(new Promise((resolve, reject) => {
          // 35 seconds delay
          setTimeout(() => {
            icli.print('Deploying ' + icli.format.info(api.getIdentifier()) + ' ...');
            resolve(api.deploy(parameters.region, context));
          }, delay * 35000);
        }));
        delay++;
      });
      return Promise.all([
        apis,
        Promise.all(promises)
      ]);
    })
    .spread((apis, results) => {
      // Display deployment result
      let success = true;
      const t = new Table();
      _.forEach(results, result => {
        t.cell('Identifier', result.api.getIdentifier());
        t.cell('Name', result.report.name);
        t.cell('Operation', result.report.operation);
        t.cell('Stage', result.report.stage);
        t.cell('AWS identifier', result.report.awsId);
        if (result.report.failed) {
          t.cell('Url', icli.format.error(result.report.failed));
          success = false;
        } else {
          t.cell(
            'Url',
            icli.format.info('https://' + result.report.awsId + '.execute-api.' + result.report.region + '.amazonaws.com/' + result.report.stage)
          );
        }
        t.newRow();
      });
      icli.print();
      icli.print(icli.format.success('Deployment done'));
      icli.print();
      icli.print(t.toString());

      // Publish the APIs
      if (success) {
        return Promise.map(apis, api => { return api.publish(parameters.region, context); })
        .then(() => {
          icli.print(icli.format.success('APIs have been published'));
          icli.print();
        })
        .catch(e => {
          icli.print(icli.format.error('The deployment of APIs succeed but the publication step failed.'));
          icli.print(e);
          process.exit(1);
        });
      } else {
        icli.print(icli.format.error('The deployment of one or more APIs failed. The publication step will not be performed.'));
        icli.print();
        process.exit(1);
      }
    });
  }

};
<|endoftext|>


<commit_before>var wWidth;
var wHeight;
var wArea;
var wCenter;
var bSize;

var bawls = new Array(0);

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var animationLocation = getEccTabElement();
canvas.id = 'bawls';

animationLocation.appendChild(canvas);

window.addEventListener('resize', init);
document.getElementsByClassName('list-group')[0].addEventListener('click', init);

function getEccTabElement(){
  return document.getElementsByClassName('ecc-tab')[0];
}

function init() {
  var animationLocation = getEccTabElement();
  wWidth = animationLocation.offsetWidth;
  wHeight = animationLocation.offsetHeight;
  wArea = wWidth * wHeight;
  wCenter = { x: wWidth / 2, y: wHeight / 2 };
  bSize = wArea / 60000;
  // posNeg gives negative or positive direction to starting x/y velocities randomly
  var posNeg = [1, -1];

  var bawlSizes = [
    bSize,
    bSize * 5.5,
    bSize * 2,
    bSize * 3.8,
    bSize * 1.7,
    bSize * 2.5,
    bSize / 1.5,
    bSize * 12,
    bSize / 1.1,
    bSize * 1.5,
    bSize * 1.8,
    bSize * 3,
    bSize * 4.4,
    bSize * 2,
    bSize / 2,
    bSize * 4,
    bSize,
    bSize,
    bSize * 1.2,
    bSize * 6.3,
  ]; //[11, 13, 15, 17, 19];

  // choose number of bawls
  bawls.length = 20;
  // set canvas size
  canvas.width = wWidth;
  canvas.height = wHeight;

  // set starting places
  var bawlPlace = {
    x: [
      wCenter.x + wWidth / 20,
      wCenter.x + wWidth / 8,
      wCenter.x + wWidth / 5,
      wCenter.x - wWidth / 3.2,
      wCenter.x - wWidth / 15,
      wCenter.x - wWidth / 4,
      wCenter.x - wWidth / 10,
      wCenter.x - wWidth / 12,
      wCenter.x + wWidth / 2.5,
      wCenter.x + wWidth / 4.8,
      wCenter.x,
      wCenter.x,
      wCenter.x + wWidth / 9,
      wCenter.x + wWidth / 7,
      wCenter.x + wWidth / 16,
      wCenter.x - wWidth / 8,
      wCenter.x + wWidth / 6,
      wCenter.x - wWidth / 4.4,
      wCenter.x - wWidth / 7,
      wCenter.x + wWidth / 3.5,
    ],
    y: [
      wCenter.y + wHeight / 20,
      wCenter.y - wHeight / 4.5,
      wCenter.y + wHeight / 8,
      wCenter.y + wHeight / 3.5,
      wCenter.y,
      wCenter.y - wHeight / 4.5,
      wCenter.y - wHeight / 2.5,
      wCenter.y + wHeight / 12,
      wCenter.y - wHeight / 3,
      wCenter.y - wHeight / 8,
      wCenter.y + wHeight / 2.5,
      wCenter.y - wHeight / 6,
      wCenter.y + wHeight / 8,
      wCenter.y + wHeight / 5.2,
      wCenter.y - wHeight / 3,
      wCenter.y - wHeight / 14,
      wCenter.y + wHeight / 20,
      wCenter.y + wHeight / 12,
      wCenter.y - wHeight / 4,
      wCenter.y + wHeight / 20,
    ],
  };

  // create bawls
  var i, len;
  for ((i = 0), (len = bawls.length); i < len; i++) {
    bawls[i] = {
      // set bawl sizes
      m: bawlSizes[i],
    };
    // set starting velocities in x and y direction
    (bawls[i].vx = Math.random() /
      14 *
      posNeg[Math.floor(Math.random() * posNeg.length)]), (bawls[
      i
    ].vy = Math.random() /
      16 *
      posNeg[Math.floor(Math.random() * posNeg.length)]), (bawls[
      i
    ].x = bawlPlace.x[i]);
    bawls[i].y = bawlPlace.y[i];
    bawls[i].ix = bawls[i].x;
    bawls[i].iy = bawls[i].y;
  }
}

function render() {
  var i, j, bawlA, bawlB, len;

  // request new animationFrame
  requestAnimationFrame(render);

  // clear canvas
  ctx.clearRect(0, 0, wWidth, wHeight);

  // refresh bawls
  for ((i = 0), (len = bawls.length); i < len; i++) {
    // x coordinates
    var x = bawls[i].x;
    // y coordinates
    var y = bawls[i].y;
    // set opacity of stroke around bawls
    ctx.lineWidth = 0.12;
    ctx.globalAlpha = 1;
    var radius = bawls[i].m;
    var startAngle = 0;
    var endAngle = 2 * Math.PI;
    // draw the thangs
    ctx.beginPath();
    ctx.arc(x, y, radius, startAngle, endAngle);
    ctx.save();
    ctx.strokeStyle = '#006666';
    ctx.stroke();
    // set opacity of bawls
    ctx.globalAlpha = 0.05;
    ctx.beginPath();
    ctx.arc(x, y, radius, startAngle, endAngle);

    // set gradient for bawls color
    var gradient = ctx.createRadialGradient(x, y, 0, x, y, radius);
    gradient.addColorStop(0.4, '#FFFFFF');
    gradient.addColorStop(1, '#006666');
    ctx.fillStyle = gradient;
    ctx.fill();

    bawls[i].x += bawls[i].vx;
    bawls[i].y += bawls[i].vy;
    var diam = bawls[i].m;
    // freeMotion is the invisible box each origin moves about in
    var freeMotion = 8;
    if (
      bawls[i].x >= bawls[i].ix + freeMotion ||
      bawls[i].x <= bawls[i].ix - freeMotion
    ) {
      bawls[i].vx = -bawls[i].vx;
    }
    if (
      bawls[i].y >= bawls[i].iy + freeMotion ||
      bawls[i].y <= bawls[i].iy - freeMotion
    ) {
      bawls[i].vy = -bawls[i].vy;
    }
  }
  // update links
  for ((i = 0), (len = bawls.length - 1); i < len; i++) {
    for (j = i + 1; j < len + 1; j++) {
      bawlA = bawls[i];
      bawlB = bawls[j];

      // draw lines
      // set opacity of lines
      if (j == len) {
        // if last bawl, have lines carry more weight by changing the m value in 'if' statement
        var m = 1;
      } else {
        var m = 1;
      }
      ctx.globalAlpha = 0.09 * m;
      ctx.strokeStyle = '#006666';
      ctx.beginPath();
      ctx.moveTo(bawlA.x, bawlA.y - bawlA.m);
      ctx.lineWidth = 0.2;
      ctx.lineTo(bawlB.x, bawlB.y + bawlB.m);
      ctx.stroke();
      ctx.beginPath();
      ctx.globalAlpha = 0.13 * m;
      ctx.moveTo(bawlA.x, bawlA.y + bawlA.m);
      ctx.lineWidth = 0.3;
      ctx.lineTo(bawlB.x, bawlB.y - bawlB.m);
      ctx.stroke();
      ctx.beginPath();
      ctx.globalAlpha = 0.035 * m;
      ctx.moveTo(bawlA.x + bawlA.m, bawlA.y);
      ctx.lineWidth = 0.3;
      ctx.lineTo(bawlB.x - bawlB.m, bawlB.y);
      ctx.stroke();
      ctx.beginPath();
      ctx.globalAlpha = 0.03 * m;
      ctx.moveTo(bawlA.x - bawlA.m, bawlA.y);
      ctx.lineWidth = 0.2;
      ctx.lineTo(bawlB.x + bawlB.m, bawlB.y);
      ctx.stroke();
    }
  }
}

init();
render();
<commit_msg>latest animarion update<commit_after>var wWidth, wHeight, wArea,
  wCenter,
  bSize,
  bawls = new Array(0);

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var animationLocation = getEccTabElement();
canvas.id = 'bawls';

animationLocation.appendChild(canvas);
document.getElementsByClassName('list-group')[0].addEventListener('click', init);

function getEccTabElement(){
  return document.getElementsByClassName('ecc-tab')[0];
}

function init() {
  wWidth = animationLocation.offsetWidth;
  wHeight = animationLocation.offsetHeight;
  wArea = wWidth * wHeight;
  wCenter = { x: wWidth / 2, y: wHeight / 2 };
  bSize = wArea / 60000;
  // posNeg gives negative or positive direction to starting x/y velocities randomly
  var posNeg = [1, -1];

  var bawlSizes = [bSize, bSize*5.5, bSize*2, bSize*3.8, bSize*1.7, bSize*2.5, bSize/1.5, bSize*12,
  bSize/1.1, bSize*1.5, bSize*1.8, bSize*3, bSize/4, bSize*2, bSize/2, bSize*4, bSize, bSize/1.3,
  bSize*1.2, bSize*1.3, bSize*3.3, bSize/3, bSize/5];

  // choose number of bawls
  bawls.length = 23;
  // set canvas size
  canvas.width = wWidth;
  canvas.height = wHeight;

  // set starting places
  var bawlPlace =
  {
    'x' : [wCenter.x + wWidth/20, wCenter.x + wWidth/8, wCenter.x + wWidth/5,
    wCenter.x - wWidth/2.5, wCenter.x - wWidth/15, wCenter.x - wWidth/3.5, wCenter.x - wWidth/10,
    wCenter.x - wWidth/12, wCenter.x + wWidth/2.4, wCenter.x + wWidth/4.8, wCenter.x,
    wCenter.x, wCenter.x + wWidth/9, wCenter.x + wWidth/7, wCenter.x + wWidth/16,
    wCenter.x - wWidth/8, wCenter.x + wWidth/4.2, wCenter.x - wWidth/4.15, wCenter.x - wWidth/7,
    wCenter.x + wWidth/4, wCenter.x + wWidth/3.9, wCenter.x + wWidth/5, wCenter.x + wWidth/3.5],

    'y' : [wCenter.y + wHeight/5, wCenter.y - wHeight/4.5, wCenter.y + wHeight/8,
    wCenter.y + wHeight/3, wCenter.y, wCenter.y - wHeight/4, wCenter.y - wHeight/2.5,
    wCenter.y + wHeight/8, wCenter.y - wHeight/4, wCenter.y - wHeight/8, wCenter.y + wHeight/2.5,
    wCenter.y - wHeight/7, wCenter.y + wHeight/8, wCenter.y + wHeight/4, wCenter.y - wArea/4500,
    wCenter.y + wHeight/5, wCenter.y + wHeight/3.15, wCenter.y, wCenter.y - wHeight/3.7,
    wCenter.y + wHeight/3.6, wCenter.y, wCenter.y + wHeight/7, wCenter.y + wHeight/5]
  };

  // create bawls
  var i, len;
  for (i = 0, len = bawls.length; i < len; i++) {
    bawls[i] = {
      // set bawl sizes
      m: bawlSizes[i]
    };
    // set starting velocities in x and y direction
    bawls[i].vx = ((Math.random()*posNeg[Math.floor(Math.random()*posNeg.length)])) / (1 + (4000/wWidth));
    bawls[i].vy = ((Math.random()*posNeg[Math.floor(Math.random()*posNeg.length)])) / (1 + (4000/wWidth));
    bawls[i].x = bawlPlace.x[i];
    bawls[i].y = bawlPlace.y[i];
    bawls[i].ix = bawls[i].x;
    bawls[i].iy = bawls[i].y;
  }
}

function render () {
  var i, j,
    bawlA, bawlB,
    len;

  // request new animationFrame
  requestAnimationFrame(render);

  // clear canvas
  ctx.clearRect(0, 0, wWidth, wHeight);

  // refresh bawls
  for (i = 0, len = bawls.length; i < len; i++) {
      // x coordinates
      var x = bawls[i].x;
      // y coordinates
      var y = bawls[i].y;

      // set opacity of stroke around bawls
      ctx.lineWidth = 0.5 * (wWidth / 1000);
      ctx.globalAlpha = 0.2;
      var radius = bawls[i].m;
      var startAngle = 0;
      var endAngle = (2*Math.PI);
      // draw the thangs
      ctx.beginPath();
      ctx.arc(x, y, radius, startAngle, endAngle);
      ctx.save();
      ctx.strokeStyle = '#006666';
      ctx.stroke();
      // set opacity of bawls
      ctx.globalAlpha = 0.09;
      ctx.beginPath();
      ctx.arc(x, y, radius, startAngle, endAngle);

      // set gradient for bawls color
      var gradient = ctx.createRadialGradient(x, y, radius/2, x, y, radius);
      gradient.addColorStop(0.1, '#FFFFFF');
      gradient.addColorStop(1, '#004d4d');
      ctx.fillStyle = gradient;
      ctx.fill();

      bawls[i].x += bawls[i].vx;
      bawls[i].y += bawls[i].vy;
      var diam = bawls[i].m;

      // freeMotion is the invisible box each origin moves about in
      var freeMotion = 8 + wWidth/45;
      if (bawls[i].x >= (bawls[i].ix + (freeMotion)) || bawls[i].x <= bawls[i].ix - (freeMotion)) {
        bawls[i].vx = -bawls[i].vx;
      }
      if (bawls[i].y >= (bawls[i].iy + (freeMotion)) || bawls[i].y <= (bawls[i].iy - (freeMotion))) {
        bawls[i].vy = -bawls[i].vy;
      }
  }
    // update links
  for (i = 0, len = bawls.length - 1; i < len; i++) {
    for (j = i + 1; j < len + 1; j++) {
      bawlA = bawls[i];
      bawlB = bawls[j];

      // draw lines
      // set opacity of lines
      if (j == len) {
        // if last bawl, have lines carry more weight by changing the m value in 'if' statement
        var m = 6
      }
      else {
        var m = 1
      }
      var widthy = 0.01 / (wWidth/2000)
      ctx.globalAlpha = 0.09 - widthy;
      ctx.strokeStyle = '#006666';
      ctx.beginPath();
      ctx.moveTo(bawlA.x, bawlA.y - (bawlA.m));
      ctx.lineWidth =  0.3;
      ctx.lineTo(bawlB.x, bawlB.y + (bawlB.m));
      ctx.stroke();
      ctx.beginPath();
      ctx.globalAlpha = 0.07 - widthy;
      ctx.moveTo(bawlA.x, bawlA.y + (bawlA.m));
      ctx.lineWidth = 0.9;
      ctx.lineTo(bawlB.x, bawlB.y - (bawlB.m));
      ctx.stroke();
      ctx.beginPath();
      ctx.globalAlpha = 0.07 - widthy;
      ctx.moveTo(bawlA.x + (bawlA.m), bawlA.y);
      ctx.lineWidth = 0.5;
      ctx.lineTo(bawlB.x - (bawlB.m), bawlB.y);
      ctx.stroke();
      ctx.beginPath();
      ctx.globalAlpha = 0.1 - widthy;
      ctx.moveTo(bawlA.x - (bawlA.m), bawlA.y);
      ctx.lineWidth = 0.2;
      ctx.lineTo(bawlB.x + (bawlB.m), bawlB.y);
      ctx.stroke();
    }
  }
}

init();
render();<|endoftext|>


<commit_before>/* jshint evil: true */
var supportsES6Syntax = false,
    isPromise = Y.Promise.isPromise;

try {
    // check if a function with an asterisk is valid syntax by evaluating it
    eval("function* f(){}");
    supportsES6Syntax = true;
    Y.log('Using ES6 syntax generators', 'info');
} catch (e) {
    Y.log('Using Old Firefox generators', 'info');
}

/**
Wraps a generator function in a Task. Tasks allow you to yield a promise,
effectively treating your promise based code as synchronous.

@method task
@for YUI
@param {Function} spawn Function that yield generators.
@return {Promise} Promise that gets resolved or rejected based on the result of
                the generator function
@example

YUI().use('gallery-io-utils', 'gallery-task', function (Y) {
  Y.task(function () {
    var data = yield Y.io.getJSON('/foo.json');
    yield Y.io.postJSON('/bar', {data: data});
    Y.log('done');
  });
});

**/
Y.task = function (spawn) {
    return new Task(spawn).promise;
};

/**
This class is not intended to be instantiated by the user, but to be used
internally by `Y.task()`.

@class task.Task
@constructor
@param {Function} spawn A generator function
**/
function Task(spawn) {
    var self = this;

    /**
    A promise to be returned by `Y.task()`.

    @property promise
    @type {Promise}
    **/
    this.promise = new Y.Promise(function (fulfill, reject) {
        /**
        Resolves the exposed promise with the provided value

        @method resolve
        @param {Any} value Any value
        **/
        self.resolve = function (value) {
            if (Y.Promise.isPromise(value)) {
                value.then(fulfill, reject);
            } else {
                fulfill(value);
            }
        };
        /**
        Rejects the exposed promise with the provided reason

        @method reject
        @param {Any} reason Any value for the rejection reason. Usually an error.
        **/
        self.reject = reject;
    });
    this.accept = function (value) {
        self.next(null, value);
    };
    this.fail = function (error) {
        self.next(error);
    };
    /**
    The generator instance.

    @property thread
    @type {Object}
    **/
    try {
        this.thread = spawn.call(this);
        this.next();
    } catch (err) {
        this.reject(err);
    }
}
/**
Step function that gets called every time the generator function yields.
When a promise is yielded, it observes the promise's result. If the promise
is successfully resolved, it calls itself with a null error and the value
of the promise. If the promise was rejected, it calls itself with an error.

Internally it passes the value or the error to the generator's `throw()`
or `send()` methods, so that the error or value passed to it are the value
taken by the left side of the yield expression:

// the value of foo is the value passed as the second parameter
// of task.next()
var foo = yield somePromise;

This function rewrites itself for all instances of Task the first time it
is called, being replaced by _nextES6 or _nextFF depending on the platform.

@method next
@param {Any} [error] An optional error to pass to the generator function
@param {Any} [value] A value to pass to the generator function
**/
Task.prototype.next = supportsES6Syntax ? function (error, value) {
    var result,
        resultValue;

    try {
        // using arguments.length to allow rejections for falsy reasons
        result = arguments.length === 1 ? this.thread.throw(error) :
                this.thread.send(value);
    } catch (e) {
        // error thrown inside the generator function are turned into
        // rejections for the promise that Y.task() returns
        return this.reject(e);
    }

    resultValue = result.value;

    // ES6 generators return an object that in the last iteration have a
    // "done" property. When done, resolve the promise.
    if (result.done) {
        this.resolve(resultValue);
    // Using isPromise and not Y.when() to prevent speedbumps in Node
    // This may be revisited if there is an async behavior we want to keep
    } else if (isPromise(resultValue)) {
        resultValue.then(this.accept, this.fail);
    } else {
        this.accept(resultValue);
    }
} : function (error, value) {
    var result;

    try {
        // using arguments.length to allow rejections for falsy reasons
        result = arguments.length === 1 ? this.thread.throw(error) :
                this.thread.send(value);
    } catch (e) {
        // Old Firefox iterators throw an exception when done
        if (e instanceof StopIteration) {
            this.resolve(this.result);
        } else {
            this.reject(e);
        }
        return;
    }
    this.result = result;

    // Using isPromise and not Y.when() to prevent speedbumps in Node
    // This may be revisited if there is an async behavior we want to keep
    if (isPromise(result)) {
        result.then(this.accept, this.fail);
    } else {
        this.accept(result);
    }
};

Y.task.Task = Task;
<commit_msg>Use local refence to isPromise<commit_after>/* jshint evil: true */
var supportsES6Syntax = false,
    isPromise = Y.Promise.isPromise;

try {
    // check if a function with an asterisk is valid syntax by evaluating it
    eval("function* f(){}");
    supportsES6Syntax = true;
    Y.log('Using ES6 syntax generators', 'info');
} catch (e) {
    Y.log('Using Old Firefox generators', 'info');
}

/**
Wraps a generator function in a Task. Tasks allow you to yield a promise,
effectively treating your promise based code as synchronous.

@method task
@for YUI
@param {Function} spawn Function that yield generators.
@return {Promise} Promise that gets resolved or rejected based on the result of
                the generator function
@example

YUI().use('gallery-io-utils', 'gallery-task', function (Y) {
  Y.task(function () {
    var data = yield Y.io.getJSON('/foo.json');
    yield Y.io.postJSON('/bar', {data: data});
    Y.log('done');
  });
});

**/
Y.task = function (spawn) {
    return new Task(spawn).promise;
};

/**
This class is not intended to be instantiated by the user, but to be used
internally by `Y.task()`.

@class task.Task
@constructor
@param {Function} spawn A generator function
**/
function Task(spawn) {
    var self = this;

    /**
    A promise to be returned by `Y.task()`.

    @property promise
    @type {Promise}
    **/
    this.promise = new Y.Promise(function (fulfill, reject) {
        /**
        Resolves the exposed promise with the provided value

        @method resolve
        @param {Any} value Any value
        **/
        self.resolve = function (value) {
            if (isPromise(value)) {
                value.then(fulfill, reject);
            } else {
                fulfill(value);
            }
        };
        /**
        Rejects the exposed promise with the provided reason

        @method reject
        @param {Any} reason Any value for the rejection reason. Usually an error.
        **/
        self.reject = reject;
    });
    this.accept = function (value) {
        self.next(null, value);
    };
    this.fail = function (error) {
        self.next(error);
    };
    /**
    The generator instance.

    @property thread
    @type {Object}
    **/
    try {
        this.thread = spawn.call(this);
        this.next();
    } catch (err) {
        this.reject(err);
    }
}
/**
Step function that gets called every time the generator function yields.
When a promise is yielded, it observes the promise's result. If the promise
is successfully resolved, it calls itself with a null error and the value
of the promise. If the promise was rejected, it calls itself with an error.

Internally it passes the value or the error to the generator's `throw()`
or `send()` methods, so that the error or value passed to it are the value
taken by the left side of the yield expression:

// the value of foo is the value passed as the second parameter
// of task.next()
var foo = yield somePromise;

This function rewrites itself for all instances of Task the first time it
is called, being replaced by _nextES6 or _nextFF depending on the platform.

@method next
@param {Any} [error] An optional error to pass to the generator function
@param {Any} [value] A value to pass to the generator function
**/
Task.prototype.next = supportsES6Syntax ? function (error, value) {
    var result,
        resultValue;

    try {
        // using arguments.length to allow rejections for falsy reasons
        result = arguments.length === 1 ? this.thread.throw(error) :
                this.thread.send(value);
    } catch (e) {
        // error thrown inside the generator function are turned into
        // rejections for the promise that Y.task() returns
        return this.reject(e);
    }

    resultValue = result.value;

    // ES6 generators return an object that in the last iteration have a
    // "done" property. When done, resolve the promise.
    if (result.done) {
        this.resolve(resultValue);
    // Using isPromise and not Y.when() to prevent speedbumps in Node
    // This may be revisited if there is an async behavior we want to keep
    } else if (isPromise(resultValue)) {
        resultValue.then(this.accept, this.fail);
    } else {
        this.accept(resultValue);
    }
} : function (error, value) {
    var result;

    try {
        // using arguments.length to allow rejections for falsy reasons
        result = arguments.length === 1 ? this.thread.throw(error) :
                this.thread.send(value);
    } catch (e) {
        // Old Firefox iterators throw an exception when done
        if (e instanceof StopIteration) {
            this.resolve(this.result);
        } else {
            this.reject(e);
        }
        return;
    }
    this.result = result;

    // Using isPromise and not Y.when() to prevent speedbumps in Node
    // This may be revisited if there is an async behavior we want to keep
    if (isPromise(result)) {
        result.then(this.accept, this.fail);
    } else {
        this.accept(result);
    }
};

Y.task.Task = Task;
<|endoftext|>


<commit_before>var app = angular.module('testApp', ['ngMaterial', 'ngMessages']);
// Config
app.config(function ($mdIconProvider) {
    $mdIconProvider.defaultIconSet('/img/mdi.svg');
    console.info('Successfully initialized!');
});
app.controller('MainController', function ($scope, $mdSidenav, $mdDialog, $mdToast) {
    // Refresh page, direct from server
    console.info('MainController successfully loaded!');
    $scope.refreshPage = function () {
        window.location.reload(true);
    };
    // Sidenav
    $scope.openLeftMenu = function () {
        $mdSidenav('left').toggle();
    };
    $scope.oriFeedback = {
        name: "",
        email: "",
        sendFeedback: ""
    };
    // Declare a variable called oriFeedback
    var oriFeedback = angular.copy($scope.oriFeedback);

    // On initial, set feedback to original
    $scope.feedback = angular.copy(oriFeedback);

    // Reset form
    $scope.reset = function () {
        $scope.feedback = angular.copy(oriFeedback);
        // Reset form
        $scope.feedbackbeta.$setPristine();
        // Reset validation errors
        $scope.feedbackbeta.$setUntouched();
    };
    // Feedback Form ($mdToast)
    $scope.submitForm = function () {
        var toast = $mdToast.simple()
            .textContent('Form was submitted')
            .action('UNDO')
            .highlightAction(true)
            .position('bottom left')
            .hideDelay(3000);

        $mdToast.show(toast).then(function (response) {
            if (response == 'ok') {
                console.info('User clicked Undo.');
                console.log('Successfully undone');
            }
        });
    };
    // Reset Form
    $scope.resetForm = function () {
        var toast = $mdToast.simple()
            .textContent('Form was reset')
            .action('UNDO')
            .highlightAction(true)
            .position('bottom left')
            .hideDelay(3000);

        $mdToast.show(toast).then(function (response) {
            if (response == 'ok') {
                console.info('User clicked Undo.');
                console.log('Successfully undone');
            }
        });
    };

    // More menu
    var originatorEv;

    $scope.openMenu = function ($mdOpenMenu, ev) {
        originatorEv = ev;
        $mdOpenMenu(ev);
    };

    // Initialize switches
    $scope.switch = {
        form_debug: false,
    };
    // $mdDialog (start)
    $scope.whats_new = function (ev) {
        $mdDialog.show({
            controller: DialogController,
            templateUrl: '/templates/whats_new_tmpl.html',
            parent: angular.element(document.body),
            targetEvent: ev,
            clickOutsideToClose: true,
        });
    };
    $scope.settings = function (ev) {
        $mdDialog.show({
            controller: DialogController,
            teplateUrl: '/templates/settings_tmpl.html',
            parent: angular.element(document.body),
            targetEvent: ev,
            clickOutsideToClose: true,
        });
    };

    // $mdDialog (end)

    $scope.about_site = function () {
        window.location.href = "https://chan4077.github.io/about#angular";
    };
    $scope.fabitems = [
        { name: 'Facebook', icon: 'facebook-box' },
        { name: 'Twitter', icon: 'twitter-box' },
        { name: 'Google+', icon: 'google-plus' }
    ];
    function DialogController($scope, $mdDialog) {
        $scope.hide = function () {
            $mdDialog.hide();
        };
        $scope.cancel = function () {
            $mdDialog.cancel();
        };
    };

});

app.controller('SideNavController', function ($scope, $mdSidenav) {
    console.info('SideNavController successfully loaded!');

    $scope.top = [
        { url: 'https://chan4077.github.io', title: 'Main', icon: 'home' },
        { url: 'https://chan4077.github.io/about', title: 'About Me', icon: 'account-box' },
        { url: 'https://chan4077.github.io/blog', title: 'Blog', icon: 'blogger' },
        { url: 'https://chan4077.github.io/media', title: 'Social Media', icon: 'google-plus' },
        { url: 'https://chan4077.github.io/angular', title: 'Angular', icon: 'angular' },
    ];
    $scope.other = [
        { url: 'https://github.com/Chan4077/chan4077.github.io', title: 'Project Page', icon: 'github-circle' },
        { url: 'https://chan4077.github.io/preferences', title: 'Preferences', icon: 'settings' },
        { url: '', title: 'Submit Feedback', icon: 'message-alert' },
        { url: '', title: 'Get Help', icon: 'help-circle' },
    ];
    $scope.made = [
        { url: 'https://materialdesignicons.com', title: 'MaterialDesignIcons', icon: 'vector-square' },
        { url: 'https://material.angularjs.org/latest', title: 'Angular Material', icon: 'angular' },
        { url: 'https://angularjs.org', title: 'Angular', icon: 'angular' },
        { url: 'https://pages.github.com', title: 'Github Pages', icon: 'github-circle' }
    ]
    $scope.openLeftMenu = function () {
        $mdSidenav('left').toggle();
    }
});
/*
*  Directives
*/
// Sidenav
app.directive('siteSidenav', function() {
    return {
        restrict: 'E',
        templateUrl: '/templates/sitesidenav.html',
        transclude: true
    };
});
// Feedback Form
app.directive('siteFeedback', function() {
    return {
        restrict: 'E',
        templateUrl: '/templates/feedback.html',
        transclude: true
    };
});
// Toolbar
app.directive('siteToolbar', function() {
    return {
        restrict: 'E',
        templateUrl: '/templates/toolbar.html',
        transclude: true
    };
});
// Speed Dial
app.directive('siteSpeedDial', function() {
    return {
        restrict: 'E',
        templateUrl: '/templates/fab_speeddial.html',
        transclude: true
    };
});<commit_msg>Disable Aria warnings<commit_after>var app = angular.module('testApp', ['ngMaterial', 'ngMessages']);
// Config
app.config(function ($mdIconProvider, $mdAriaProvider) {
    $mdIconProvider.defaultIconSet('/img/mdi.svg');
    console.info('Successfully initialized!');
    $mdAriaProvider.disableWarnings();
});
app.controller('MainController', function ($scope, $mdSidenav, $mdDialog, $mdToast) {
    // Refresh page, direct from server
    console.info('MainController successfully loaded!');
    $scope.refreshPage = function () {
        window.location.reload(true);
    };
    // Sidenav
    $scope.openLeftMenu = function () {
        $mdSidenav('left').toggle();
    };
    $scope.oriFeedback = {
        name: "",
        email: "",
        sendFeedback: ""
    };
    // Declare a variable called oriFeedback
    var oriFeedback = angular.copy($scope.oriFeedback);

    // On initial, set feedback to original
    $scope.feedback = angular.copy(oriFeedback);

    // Reset form
    $scope.reset = function () {
        $scope.feedback = angular.copy(oriFeedback);
        // Reset form
        $scope.feedbackbeta.$setPristine();
        // Reset validation errors
        $scope.feedbackbeta.$setUntouched();
    };
    // Feedback Form ($mdToast)
    $scope.submitForm = function () {
        var toast = $mdToast.simple()
            .textContent('Form was submitted')
            .action('UNDO')
            .highlightAction(true)
            .position('bottom left')
            .hideDelay(3000);

        $mdToast.show(toast).then(function (response) {
            if (response == 'ok') {
                console.info('User clicked Undo.');
                console.log('Successfully undone');
            }
        });
    };
    // Reset Form
    $scope.resetForm = function () {
        var toast = $mdToast.simple()
            .textContent('Form was reset')
            .action('UNDO')
            .highlightAction(true)
            .position('bottom left')
            .hideDelay(3000);

        $mdToast.show(toast).then(function (response) {
            if (response == 'ok') {
                console.info('User clicked Undo.');
                console.log('Successfully undone');
            }
        });
    };

    // More menu
    var originatorEv;

    $scope.openMenu = function ($mdOpenMenu, ev) {
        originatorEv = ev;
        $mdOpenMenu(ev);
    };

    // Initialize switches
    $scope.switch = {
        form_debug: false,
    };
    // $mdDialog (start)
    $scope.whats_new = function (ev) {
        $mdDialog.show({
            controller: DialogController,
            templateUrl: '/templates/whats_new_tmpl.html',
            parent: angular.element(document.body),
            targetEvent: ev,
            clickOutsideToClose: true,
        });
    };
    $scope.settings = function (ev) {
        $mdDialog.show({
            controller: DialogController,
            teplateUrl: '/templates/settings_tmpl.html',
            parent: angular.element(document.body),
            targetEvent: ev,
            clickOutsideToClose: true,
        });
    };

    // $mdDialog (end)

    $scope.about_site = function () {
        window.location.href = "https://chan4077.github.io/about#angular";
    };
    $scope.fabitems = [
        { name: 'Facebook', icon: 'facebook-box' },
        { name: 'Twitter', icon: 'twitter-box' },
        { name: 'Google+', icon: 'google-plus' }
    ];
    function DialogController($scope, $mdDialog) {
        $scope.hide = function () {
            $mdDialog.hide();
        };
        $scope.cancel = function () {
            $mdDialog.cancel();
        };
    };

});

app.controller('SideNavController', function ($scope, $mdSidenav) {
    console.info('SideNavController successfully loaded!');

    $scope.top = [
        { url: 'https://chan4077.github.io', title: 'Main', icon: 'home' },
        { url: 'https://chan4077.github.io/about', title: 'About Me', icon: 'account-box' },
        { url: 'https://chan4077.github.io/blog', title: 'Blog', icon: 'blogger' },
        { url: 'https://chan4077.github.io/media', title: 'Social Media', icon: 'google-plus' },
        { url: 'https://chan4077.github.io/angular', title: 'Angular', icon: 'angular' },
    ];
    $scope.other = [
        { url: 'https://github.com/Chan4077/chan4077.github.io', title: 'Project Page', icon: 'github-circle' },
        { url: 'https://chan4077.github.io/preferences', title: 'Preferences', icon: 'settings' },
        { url: '', title: 'Submit Feedback', icon: 'message-alert' },
        { url: '', title: 'Get Help', icon: 'help-circle' },
    ];
    $scope.made = [
        { url: 'https://materialdesignicons.com', title: 'MaterialDesignIcons', icon: 'vector-square' },
        { url: 'https://material.angularjs.org/latest', title: 'Angular Material', icon: 'angular' },
        { url: 'https://angularjs.org', title: 'Angular', icon: 'angular' },
        { url: 'https://pages.github.com', title: 'Github Pages', icon: 'github-circle' }
    ]
    $scope.openLeftMenu = function () {
        $mdSidenav('left').toggle();
    }
});
/*
*  Directives
*/
// Sidenav
app.directive('siteSidenav', function() {
    return {
        restrict: 'E',
        templateUrl: '/templates/sitesidenav.html',
        transclude: true
    };
});
// Feedback Form
app.directive('siteFeedback', function() {
    return {
        restrict: 'E',
        templateUrl: '/templates/feedback.html',
        transclude: true
    };
});
// Toolbar
app.directive('siteToolbar', function() {
    return {
        restrict: 'E',
        templateUrl: '/templates/toolbar.html',
        transclude: true
    };
});
// Speed Dial
app.directive('siteSpeedDial', function() {
    return {
        restrict: 'E',
        templateUrl: '/templates/fab_speeddial.html',
        transclude: true
    };
});<|endoftext|>