<commit_before>var run = function () {
    var fetchVersions = function () {
        var request = new XMLHttpRequest();

        request.onerror = function (e) {
            console.error('Unable to load version data: ' + e.message);
        };

        request.onload = function () {
            if (request.status < 200 || request.status > 499) {
                console.error(
                    'Unable to load version data: ' +
                    request.statusText + ' (' + request.status + ')'
                );

                return;
            }

            var pageMatch = window.location.pathname.match(/\/([^/]+)$/)
            var page = pageMatch ? pageMatch[1] : ''

            var versions = JSON.parse(request.responseText);
            var currentVersion = document.body.getAttribute('data-version');
            var versionList = document.getElementById('versions');
            var isLatest = window.location.pathname.match(/\/latest\/$/);

            var latestItem = document.createElement('li');
            var latest = document.createElement('a');
            latest.textContent = 'latest (' + versions[0] + ')';
            latest.setAttribute(
                'href',
                '../latest/' + page + window.location.hash
            );

            if (isLatest) {
                latest.setAttribute('class', 'current');
            }

            latestItem.appendChild(latest);
            versionList.appendChild(latestItem);

            for (var i = 0; i < versions.length; ++i) {
                var versionItem = document.createElement('li');
                var version = document.createElement('a');
                version.textContent = versions[i];
                version.setAttribute(
                    'href',
                    '../' + encodeURIComponent(versions[i]) +
                        '/' + page + window.location.hash
                );

                if (!isLatest && versions[i] === currentVersion) {
                    version.setAttribute('class', 'current');
                }

                versionItem.appendChild(version);
                versionList.appendChild(versionItem);
            }
        };

        request.open('GET', '../data/versions.json', true);
        request.send();
    };

    var contentElement = document.getElementById('content');
    var tocElement = document.getElementById('toc');
    var tocScrollElement = document.getElementById('toc-scroll');
    var tocListElement = contentElement.querySelector('ul');
    var tocListElementCopy = tocListElement.cloneNode(true);

    tocListElement.style.display = 'none';
    tocScrollElement.appendChild(tocListElementCopy);

    tocScrollElement.addEventListener('wheel', function (event) {
        var tocHeight = tocScrollElement.clientHeight;
        var tocScrollHeight = tocScrollElement.scrollHeight;

        if (tocScrollHeight <= tocHeight) {
            return;
        }

        var scrollBottom = tocScrollHeight - tocHeight;
        var newScrollTop = tocScrollElement.scrollTop + event.deltaY;
        var shouldSuppress = false;

        if (newScrollTop >= scrollBottom) {
            newScrollTop = scrollBottom;
            shouldSuppress = true;
        } else if (newScrollTop < 1) {
            newScrollTop = 0;
            shouldSuppress = true;
        }

        if (shouldSuppress) {
            tocScrollElement.scrollTop = newScrollTop;

            event.stopPropagation();
            event.preventDefault();
            event.returnValue = false;

            return false;
        }

        return true;
    });

    var mainHeading = document.querySelector('h1')
    var mainHeadingAnchor = mainHeading.querySelector('a')

    var mainHeadingLink = document.createElement('a');
    mainHeadingLink.href = mainHeadingAnchor.hash;
    mainHeadingLink.appendChild(document.createTextNode(mainHeading.innerText));

    var mainHeadingListItem = document.createElement('li');
    mainHeadingListItem.style.display = 'none';
    mainHeadingListItem.appendChild(mainHeadingLink);

    tocListElementCopy.insertBefore(
        mainHeadingListItem,
        tocListElementCopy.querySelector('li')
    );

    var activateTocHeading = function (event) {
        if (!event) {
            tocScrollElement.scrollTop = 0;

            return;
        }

        var end = event.target;
        var tocHeight = tocScrollElement.clientHeight;
        var endOffset = end.offsetTop;

        if (tocScrollElement.scrollHeight > tocHeight) {
            tocScrollElement.scrollTop = endOffset - Math.floor(tocHeight / 2);
        }
    };

    var redrawToc = function () {
        tocElement.style.marginLeft = (870 - document.body.scrollLeft) + 'px';
    };

    var tocShowElement = document.getElementById('toc-show');
    var tocHideElement = document.getElementById('toc-hide');

    var showToc = function () {
        tocShowElement.style.display = 'none';
        tocHideElement.style.display = 'inline';
        tocListElement.style.display = 'block';
    };

    var hideToc = function () {
        tocHideElement.style.display = 'none';
        tocShowElement.style.display = 'inline';
        tocListElement.style.display = 'none';
    };

    var documentTitle = mainHeading.innerText;

    var dispatch = function (event) {
        var versionLinks = document.querySelectorAll('#versions a');

        for (var i = 0; i < versionLinks.length; ++i) {
            versionLinks[i].setAttribute(
                'href',
                versionLinks[i].pathname + window.location.hash
            );
        }

        if (window.location.hash) {
            hash = decodeURIComponent(window.location.hash.substring(1));

            var target;

            try {
                target = document.querySelector('#' + hash);
            } catch (e) {
                // not a standard anchor link
            }

            if (target && target.classList.contains('anchor')) {
                document.title =
                    target.parentNode.innerText + ' - ' + documentTitle;
            }

            target = null;

            try {
                target = document.querySelector('a[name="' + hash + '"]');
            } catch (e) {
                // not a standard anchor link
            }

            if (target) {
                var matches = hash.match(/^(\w+)\.(\w+)$/);

                if (matches) {
                    if ('facade' === matches[1]) {
                        document.title = matches[2] + '() - ' + documentTitle;
                    } else {
                        document.title =
                            '$' + matches[1] +
                            '->' + matches[2] +
                            '() - ' + documentTitle;
                    }
                }

                var matches = hash.match(/^(\w+)\.(\w+)\.(\w+)$/);

                if (matches) {
                    document.title =
                        '$' + matches[1] +
                        ' ' + matches[2] +
                        ' ' + matches[3] +
                        ' - ' + documentTitle;
                }
            }
        } else {
            document.title = documentTitle;
        }

        if ('#toc' === window.location.hash) {
            if (event) {
                event.preventDefault();
            }

            showToc();
            tocListElement.scrollIntoView();
        }
    };

    var upgradeSvg = function () {
        var images = document.querySelectorAll('img[src$=".svg"]');

        for (var i = 0; i < images.length; ++i) {
            var image = images[i];
            var link = image.parentNode;
            var container = link.parentNode;

            container.appendChild(image);
            container.removeChild(link);
        }

        SVGInjector(
            images,
            {},
            function () {
                hash = window.location.hash;
                window.location.hash = '#';
                window.location.hash = hash;
            }
        );
    };

    window.addEventListener('hashchange', dispatch);
    document.addEventListener('scroll', function () {
        requestAnimationFrame(redrawToc)
    });
    document.addEventListener('resize', function () {
        requestAnimationFrame(activateTocHeading)
    });
    tocHideElement.addEventListener('click', hideToc);

    new Gumshoe(
        '#toc-scroll > ul a',
        {
            nested: true,
            offset: 30,
            reflow: true,
        }
    );

    document.addEventListener('gumshoeActivate', activateTocHeading)

    fetchVersions();
    dispatch();
    upgradeSvg();
    redrawToc();
};

if (document.readyState != 'loading'){
    run();
} else {
    document.addEventListener('DOMContentLoaded', run);
}
<commit_msg>Fix "latest" detection for guides<commit_after>var run = function () {
    var fetchVersions = function () {
        var request = new XMLHttpRequest();

        request.onerror = function (e) {
            console.error('Unable to load version data: ' + e.message);
        };

        request.onload = function () {
            if (request.status < 200 || request.status > 499) {
                console.error(
                    'Unable to load version data: ' +
                    request.statusText + ' (' + request.status + ')'
                );

                return;
            }

            var pageMatch = window.location.pathname.match(/\/([^/]+)$/)
            var page = pageMatch ? pageMatch[1] : ''

            var versions = JSON.parse(request.responseText);
            var currentVersion = document.body.getAttribute('data-version');
            var versionList = document.getElementById('versions');
            var isLatest = window.location.pathname.match(/\/latest\//);

            var latestItem = document.createElement('li');
            var latest = document.createElement('a');
            latest.textContent = 'latest (' + versions[0] + ')';
            latest.setAttribute(
                'href',
                '../latest/' + page + window.location.hash
            );

            if (isLatest) {
                latest.setAttribute('class', 'current');
            }

            latestItem.appendChild(latest);
            versionList.appendChild(latestItem);

            for (var i = 0; i < versions.length; ++i) {
                var versionItem = document.createElement('li');
                var version = document.createElement('a');
                version.textContent = versions[i];
                version.setAttribute(
                    'href',
                    '../' + encodeURIComponent(versions[i]) +
                        '/' + page + window.location.hash
                );

                if (!isLatest && versions[i] === currentVersion) {
                    version.setAttribute('class', 'current');
                }

                versionItem.appendChild(version);
                versionList.appendChild(versionItem);
            }
        };

        request.open('GET', '../data/versions.json', true);
        request.send();
    };

    var contentElement = document.getElementById('content');
    var tocElement = document.getElementById('toc');
    var tocScrollElement = document.getElementById('toc-scroll');
    var tocListElement = contentElement.querySelector('ul');
    var tocListElementCopy = tocListElement.cloneNode(true);

    tocListElement.style.display = 'none';
    tocScrollElement.appendChild(tocListElementCopy);

    tocScrollElement.addEventListener('wheel', function (event) {
        var tocHeight = tocScrollElement.clientHeight;
        var tocScrollHeight = tocScrollElement.scrollHeight;

        if (tocScrollHeight <= tocHeight) {
            return;
        }

        var scrollBottom = tocScrollHeight - tocHeight;
        var newScrollTop = tocScrollElement.scrollTop + event.deltaY;
        var shouldSuppress = false;

        if (newScrollTop >= scrollBottom) {
            newScrollTop = scrollBottom;
            shouldSuppress = true;
        } else if (newScrollTop < 1) {
            newScrollTop = 0;
            shouldSuppress = true;
        }

        if (shouldSuppress) {
            tocScrollElement.scrollTop = newScrollTop;

            event.stopPropagation();
            event.preventDefault();
            event.returnValue = false;

            return false;
        }

        return true;
    });

    var mainHeading = document.querySelector('h1')
    var mainHeadingAnchor = mainHeading.querySelector('a')

    var mainHeadingLink = document.createElement('a');
    mainHeadingLink.href = mainHeadingAnchor.hash;
    mainHeadingLink.appendChild(document.createTextNode(mainHeading.innerText));

    var mainHeadingListItem = document.createElement('li');
    mainHeadingListItem.style.display = 'none';
    mainHeadingListItem.appendChild(mainHeadingLink);

    tocListElementCopy.insertBefore(
        mainHeadingListItem,
        tocListElementCopy.querySelector('li')
    );

    var activateTocHeading = function (event) {
        if (!event) {
            tocScrollElement.scrollTop = 0;

            return;
        }

        var end = event.target;
        var tocHeight = tocScrollElement.clientHeight;
        var endOffset = end.offsetTop;

        if (tocScrollElement.scrollHeight > tocHeight) {
            tocScrollElement.scrollTop = endOffset - Math.floor(tocHeight / 2);
        }
    };

    var redrawToc = function () {
        tocElement.style.marginLeft = (870 - document.body.scrollLeft) + 'px';
    };

    var tocShowElement = document.getElementById('toc-show');
    var tocHideElement = document.getElementById('toc-hide');

    var showToc = function () {
        tocShowElement.style.display = 'none';
        tocHideElement.style.display = 'inline';
        tocListElement.style.display = 'block';
    };

    var hideToc = function () {
        tocHideElement.style.display = 'none';
        tocShowElement.style.display = 'inline';
        tocListElement.style.display = 'none';
    };

    var documentTitle = mainHeading.innerText;

    var dispatch = function (event) {
        var versionLinks = document.querySelectorAll('#versions a');

        for (var i = 0; i < versionLinks.length; ++i) {
            versionLinks[i].setAttribute(
                'href',
                versionLinks[i].pathname + window.location.hash
            );
        }

        if (window.location.hash) {
            hash = decodeURIComponent(window.location.hash.substring(1));

            var target;

            try {
                target = document.querySelector('#' + hash);
            } catch (e) {
                // not a standard anchor link
            }

            if (target && target.classList.contains('anchor')) {
                document.title =
                    target.parentNode.innerText + ' - ' + documentTitle;
            }

            target = null;

            try {
                target = document.querySelector('a[name="' + hash + '"]');
            } catch (e) {
                // not a standard anchor link
            }

            if (target) {
                var matches = hash.match(/^(\w+)\.(\w+)$/);

                if (matches) {
                    if ('facade' === matches[1]) {
                        document.title = matches[2] + '() - ' + documentTitle;
                    } else {
                        document.title =
                            '$' + matches[1] +
                            '->' + matches[2] +
                            '() - ' + documentTitle;
                    }
                }

                var matches = hash.match(/^(\w+)\.(\w+)\.(\w+)$/);

                if (matches) {
                    document.title =
                        '$' + matches[1] +
                        ' ' + matches[2] +
                        ' ' + matches[3] +
                        ' - ' + documentTitle;
                }
            }
        } else {
            document.title = documentTitle;
        }

        if ('#toc' === window.location.hash) {
            if (event) {
                event.preventDefault();
            }

            showToc();
            tocListElement.scrollIntoView();
        }
    };

    var upgradeSvg = function () {
        var images = document.querySelectorAll('img[src$=".svg"]');

        for (var i = 0; i < images.length; ++i) {
            var image = images[i];
            var link = image.parentNode;
            var container = link.parentNode;

            container.appendChild(image);
            container.removeChild(link);
        }

        SVGInjector(
            images,
            {},
            function () {
                hash = window.location.hash;
                window.location.hash = '#';
                window.location.hash = hash;
            }
        );
    };

    window.addEventListener('hashchange', dispatch);
    document.addEventListener('scroll', function () {
        requestAnimationFrame(redrawToc)
    });
    document.addEventListener('resize', function () {
        requestAnimationFrame(activateTocHeading)
    });
    tocHideElement.addEventListener('click', hideToc);

    new Gumshoe(
        '#toc-scroll > ul a',
        {
            nested: true,
            offset: 30,
            reflow: true,
        }
    );

    document.addEventListener('gumshoeActivate', activateTocHeading)

    fetchVersions();
    dispatch();
    upgradeSvg();
    redrawToc();
};

if (document.readyState != 'loading'){
    run();
} else {
    document.addEventListener('DOMContentLoaded', run);
}
<|endoftext|>


<commit_before>{
    name : 'Demo',
    appFolder : '/portal/app',
    paths : {
        'Portal' : '/portal/app',
        'Demo' : '/portal/app',
        'DemoSingleton' : '/portal/app/DemoSingleton.js',

        'Ext' : '/ext/src',
        'Ext.ux.form.field.BoxSelect' : '/portal/app/plugin/BoxSelect.js'
    },
    dependTypes : {
        requires : true,
        uses : true,
        controllers : true,
        models : true,
        stores : true,
        views : true,
        includes : true
    },
    extClasses : {
        'Ext' : true
    }
}<commit_msg>comments added<commit_after>{
    name : 'Demo',
    appFolder : '/portal/app',
    paths : {
        'Demo' : '/portal/app',
        'DemoSingleton' : '/portal/app/DemoSingleton.js',
        'Portal' : '/portal/app', // alternative for 'Demo' class. Points to the same folder

        'Ext' : '/ext/src', // path to ExtJS sources
        'Ext.ux.form.field.BoxSelect' : '/portal/app/plugin/BoxSelect.js' // custom ExtJS class
    },
    dependTypes : {
        requires : true,
        uses : true,
        controllers : true,
        models : true,
        stores : true,
        views : true,
        includes : true // custom dependency type (not documented in ExtJS)
                        // useful in dev environment when ExtJS is not loading sources
    },
    extClasses : {
        'Ext' : true // include Ext sources
    }
}<|endoftext|>


<commit_before>import Service, { inject as service } from '@ember/service'
import ENV from 'pilasbloques/config/environment'
import seedrandom from 'seedrandom';
import { computed } from '@ember/object'

export default Service.extend({

  group: ENV.experimentGroup,
  decompositionTreatmentLength: ENV.decompositionTreatmentLength,
  storage: service(),
  pilasBloquesApi: service(),
  challengeExpectations: service(),

  possibleGroups: ["treatment", "control", "notAffected"],
  decompositionTreatmentLength: ENV.decompositionTreatmentLength,

  solvedChallenges: computed('storage', function () {
    return this.get('storage').getSolvedChallenges()
  }),

  isTreatmentGroup() {
    return this.experimentGroup() === this.possibleGroups[0]
  },

  isControlGroup() {
    return this.experimentGroup() === this.possibleGroups[1]
  },

  isNotAffected() {
    return !(this.isTreatmentGroup() || this.isControlGroup())
  },

  isAutoAssignGroup(){
    return this.group === "autoassign"
  },

  experimentGroup() {
    return this.isAutoAssignGroup() ? this.getExperimentGroupAssigned() : this.group
  },

  getExperimentGroupAssigned(){
    return this.storage.getExperimentGroup() || this.pilasBloquesApi.getUser()?.experimentGroup || this.randomizeAndSaveExperimentGroup() // jshint ignore:line
  },

  randomizeAndSaveExperimentGroup(){
    const randomExperimentGroup = this.getRandomExperimentGroup()
    this.storage.saveExperimentGroup(randomExperimentGroup)

    if(this.pilasBloquesApi.getUser()){
      this.pilasBloquesApi.saveExperimentGroup(randomExperimentGroup)
    }

    return randomExperimentGroup
  },

  getRandomExperimentGroup(){
    const ip = this.storage.getUserIp()
    return this.possibleGroups[this.randomIndex(ip)]
  },

  randomIndex(seed){
    const randomizedSeed = seedrandom(seed)
    const experimentGroupNumber = randomizedSeed() * (this.possibleGroups.length - 1)

    return Math.floor(experimentGroupNumber)
  },

  async saveUserIP(){
    if(!this.storage.getUserIp()){
      const response = await fetch("https://api64.ipify.org?format=json")
      const jsonIp = await response.json()
      this.storage.saveUserIp(jsonIp.ip)
    }
  },

  groupId() {
    return this.group.charAt(0)
  },

  updateSolvedChallenges(challenge){
    const _solvedChallenges = this.solvedChallenges
    if (this.shouldUpdateSolvedChallenges(challenge)){
      _solvedChallenges.push(challenge.id)
      this.storage.saveSolvedChallenges(_solvedChallenges)
    }
  },

  shouldShowCongratulationsModal(){
    return this.isNotAffected()
  },

  shouldShowBlocksExpectationFeedback(){
    return this.isTreatmentGroup() && !this.feedbackIsDisabled()
  },

  shouldShowScoredExpectations(){
    return !(this.isControlGroup() || this.feedbackIsDisabled())
  },

  feedbackIsDisabled(){
    return this.solvedChallenges.length >= this.decompositionTreatmentLength
  },

  shouldUpdateSolvedChallenges(challenge){
    return !this.solvedChallenges.includes(challenge.id) && this.hasDecompositionExpect(challenge)
  },

  hasDecompositionExpect(challenge){
    return this.challengeExpectations.hasDecomposition(challenge)
  }
});
<commit_msg>fix merge<commit_after>import Service, { inject as service } from '@ember/service'
import ENV from 'pilasbloques/config/environment'
import seedrandom from 'seedrandom';
import { computed } from '@ember/object'

export default Service.extend({

  group: ENV.experimentGroup,
  storage: service(),
  pilasBloquesApi: service(),
  challengeExpectations: service(),

  possibleGroups: ["treatment", "control", "notAffected"],
  decompositionTreatmentLength: ENV.decompositionTreatmentLength,

  solvedChallenges: computed('storage', function () {
    return this.get('storage').getSolvedChallenges()
  }),

  isTreatmentGroup() {
    return this.experimentGroup() === this.possibleGroups[0]
  },

  isControlGroup() {
    return this.experimentGroup() === this.possibleGroups[1]
  },

  isNotAffected() {
    return !(this.isTreatmentGroup() || this.isControlGroup())
  },

  isAutoAssignGroup(){
    return this.group === "autoassign"
  },

  experimentGroup() {
    return this.isAutoAssignGroup() ? this.getExperimentGroupAssigned() : this.group
  },

  getExperimentGroupAssigned(){
    return this.storage.getExperimentGroup() || this.pilasBloquesApi.getUser()?.experimentGroup || this.randomizeAndSaveExperimentGroup() // jshint ignore:line
  },

  randomizeAndSaveExperimentGroup(){
    const randomExperimentGroup = this.getRandomExperimentGroup()
    this.storage.saveExperimentGroup(randomExperimentGroup)

    if(this.pilasBloquesApi.getUser()){
      this.pilasBloquesApi.saveExperimentGroup(randomExperimentGroup)
    }

    return randomExperimentGroup
  },

  getRandomExperimentGroup(){
    const ip = this.storage.getUserIp()
    return this.possibleGroups[this.randomIndex(ip)]
  },

  randomIndex(seed){
    const randomizedSeed = seedrandom(seed)
    const experimentGroupNumber = randomizedSeed() * (this.possibleGroups.length - 1)

    return Math.floor(experimentGroupNumber)
  },

  async saveUserIP(){
    if(!this.storage.getUserIp()){
      const response = await fetch("https://api64.ipify.org?format=json")
      const jsonIp = await response.json()
      this.storage.saveUserIp(jsonIp.ip)
    }
  },

  groupId() {
    return this.group.charAt(0)
  },

  updateSolvedChallenges(challenge){
    const _solvedChallenges = this.solvedChallenges
    if (this.shouldUpdateSolvedChallenges(challenge)){
      _solvedChallenges.push(challenge.id)
      this.storage.saveSolvedChallenges(_solvedChallenges)
    }
  },

  shouldShowCongratulationsModal(){
    return this.isNotAffected()
  },

  shouldShowBlocksExpectationFeedback(){
    return this.isTreatmentGroup() && !this.feedbackIsDisabled()
  },

  shouldShowScoredExpectations(){
    return !(this.isControlGroup() || this.feedbackIsDisabled())
  },

  feedbackIsDisabled(){
    return this.solvedChallenges.length >= this.decompositionTreatmentLength
  },

  shouldUpdateSolvedChallenges(challenge){
    return !this.solvedChallenges.includes(challenge.id) && this.hasDecompositionExpect(challenge)
  },

  hasDecompositionExpect(challenge){
    return this.challengeExpectations.hasDecomposition(challenge)
  }
});
<|endoftext|>


<commit_before>const EventEmitter = require('events');
const PSQL = require('cartodb-psql');
const copyTo = require('pg-copy-streams').to;
const copyFrom = require('pg-copy-streams').from;

module.exports = class StreamCopy extends EventEmitter {
    constructor (sql, userDbParams) {
        super();

        this.pg = new PSQL(userDbParams);
        this.sql = sql;
        this.connectionClosedByClient = false;
    }

    to(cb) {
        this.pg.connect((err, client, done)  => {
            if (err) {
                return cb(err);
            }

            const copyToStream = copyTo(this.sql);
            const pgstream = client.query(copyToStream);

            pgstream
                .on('error', err => {
                    if (!this.connectionClosedByClient) {
                        done(err);
                    }
                })
                .on('end', () => {
                    done();
                });

            cb(null, pgstream, copyToStream, client, done);
        });
    }

    from(cb) {
        this.pg.connect((err, client, done) => {
            if (err) {
                return cb(err);
            }

            const copyFromStream = copyFrom(this.sql);
            const pgstream = client.query(copyFromStream);

            pgstream
                .on('error', err => {
                    done(err);
                })
                .on('end', () => {
                    done();
                });

            cb(null, pgstream, copyFromStream, client, done);
        });
    }

    setConnectionClosedByClient(connectionClosedByClient) {
        this.connectionClosedByClient = connectionClosedByClient;
    }
};
<commit_msg>Do not extend from EventEmitter<commit_after>const PSQL = require('cartodb-psql');
const copyTo = require('pg-copy-streams').to;
const copyFrom = require('pg-copy-streams').from;

module.exports = class StreamCopy {
    constructor (sql, userDbParams) {
        this.pg = new PSQL(userDbParams);
        this.sql = sql;
        this.connectionClosedByClient = false;
    }

    to(cb) {
        this.pg.connect((err, client, done)  => {
            if (err) {
                return cb(err);
            }

            const copyToStream = copyTo(this.sql);
            const pgstream = client.query(copyToStream);

            pgstream
                .on('error', err => {
                    if (!this.connectionClosedByClient) {
                        done(err);
                    }
                })
                .on('end', () => {
                    done();
                });

            cb(null, pgstream, copyToStream, client, done);
        });
    }

    from(cb) {
        this.pg.connect((err, client, done) => {
            if (err) {
                return cb(err);
            }

            const copyFromStream = copyFrom(this.sql);
            const pgstream = client.query(copyFromStream);

            pgstream
                .on('error', err => {
                    done(err);
                })
                .on('end', () => {
                    done();
                });

            cb(null, pgstream, copyFromStream, client, done);
        });
    }

    setConnectionClosedByClient(connectionClosedByClient) {
        this.connectionClosedByClient = connectionClosedByClient;
    }
};
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import 'bootstrap/dist/css/bootstrap.css'
import {
  Route,
  BrowserRouter as Router,
  Redirect,
  Switch
} from 'react-router-dom'
import Home from './Home'
import Intro from './Intro'
import DashboardContainer from '../containers/Dashboard'
import ServiceContainer from '../containers/Service'
import DepartmentContainer from '../containers/Department'
import LearnMore from './Department/LearnMore'
import ExplainContainer from '../containers/Explain'
import SubmitContainer from '../containers/Submit'
import User from './User'
import Done from './Done'
import { firebaseAuth } from '../config/constants'
import { logout } from '../helpers/auth'
import { Provider } from 'react-redux'
import { IntlProvider } from 'react-intl'

import store from '../store';

export default class App extends Component {
  state = {
    authed: false,
    loading: true,
    user: {},
  }

  componentDidMount() {
    this.removeListener = firebaseAuth().onAuthStateChanged(user => this.updateAuthState(user))
  }

  componentWillUnmount() {
    this.removeListener()
  }

  componentDidMount() {
    this.removeListener = firebaseAuth().onAuthStateChanged(user => this.updateAuthState(user))
  }

  componentWillUnmount() {
    this.removeListener()
  }

  updateAuthState(user) {
    console.log('user in index.js', user);
    if (user) {
      this.setState({
        authed: true,
        loading: false,
        user,
      })
    } else {
      this.setState({
        loading: false,
      })
    }
  }

  handleLogout() {
    const warning = confirm('Are you sure you want to log out?')
    if (warning) {
      console.log("LOGGED OUT")
      logout()
      this.setState({ authed: false })
    }
  }

  render() {
    const { authed, user, loading } = this.state
    return loading === true ?
Loading
 : (
      <IntlProvider locale="en">
        <Provider store={store}>
          <Router>

                <Switch className="row">
                  <Route
                    path="/" exact render={() => {
                      return this.state.authed
                      ? <Redirect to="/dashboard" />
                      : <Redirect to="/login" />
                    }}
                  />
                  <Route
                    path="/login" isAuthed={this.state.authed} render={() => {
                      return this.state.authed
                      ? <Redirect to="/intro/1" />
                      : <Home />
                    }}
                  />
                  <Route path="/intro/:id" render={props => <Intro {...props} />} />
                  <Route path="/dashboard" render={props => <DashboardContainer {...props} />} />
                  <Route path="/service/:id" exact render={props => <ServiceContainer {...props} />} />
                  <Route path="/service/:service_id/department/:id" exact
                    render={props => <DepartmentContainer {...props} />}
                  />
                  <Route path="/service/:service_id/department/:id/learn-more"
                    render={props => <LearnMore {...props} />}
                  />
                  <Route path="/service/:service_id/department/:id/explain"
                    render={props => <ExplainContainer {...props} />}
                  />
                  <Route path="/user" render={() => {
                    return (
                      <User isAuthed={this.state.authed}
                        handleLogout={this.handleLogout.bind(this)}
                      />
                    )
                  }} />
                  <Route path="/submit" render={(props) => {
                    return <SubmitContainer {...props} />
                  }} />
                  <Route path="/done" render={(props) => {
                    return <Done {...props} />
                  }} />
                  <Route render={() =>
404, you ain't supposed to be here
} />
                </Switch>

          </Router>
        </Provider>
      </IntlProvider>
    );
  }
}
<commit_msg>eslint told me so<commit_after>import React, { Component } from 'react'
import { Provider } from 'react-redux'
import { IntlProvider } from 'react-intl'
import 'bootstrap/dist/css/bootstrap.css'
import {
  Route,
  BrowserRouter as Router,
  Redirect,
  Switch
} from 'react-router-dom'
import Home from './Home'
import Intro from './Intro'
import DashboardContainer from '../containers/Dashboard'
import ServiceContainer from '../containers/Service'
import DepartmentContainer from '../containers/Department'
import LearnMore from './Department/LearnMore'
import ExplainContainer from '../containers/Explain'
import SubmitContainer from '../containers/Submit'
import User from './User'
import Done from './Done'
import { firebaseAuth } from '../config/constants'
import { logout } from '../helpers/auth'

import store from '../store';

export default class App extends Component {
  state = {
    authed: false,
    loading: true,
    user: {},
  }

  componentDidMount() {
    this.removeListener = firebaseAuth().onAuthStateChanged(user => this.updateAuthState(user))
  }

  componentWillUnmount() {
    this.removeListener()
  }

  componentDidMount() {
    this.removeListener = firebaseAuth().onAuthStateChanged(user => this.updateAuthState(user))
  }

  componentWillUnmount() {
    this.removeListener()
  }

  updateAuthState(user) {
    console.log('user in index.js', user);
    if (user) {
      this.setState({
        authed: true,
        loading: false,
        user,
      })
    } else {
      this.setState({
        loading: false,
      })
    }
  }

  handleLogout() {
    const warning = confirm('Are you sure you want to log out?')
    if (warning) {
      console.log("LOGGED OUT")
      logout()
      this.setState({ authed: false })
    }
  }

  render() {
    const { authed, user, loading } = this.state
    return loading === true ?
Loading
 : (
      <IntlProvider locale="en">
        <Provider store={store}>
          <Router>

                <Switch className="row">
                  <Route
                    path="/" exact render={() => {
                      return this.state.authed
                      ? <Redirect to="/dashboard" />
                      : <Redirect to="/login" />
                    }}
                  />
                  <Route
                    path="/login" isAuthed={this.state.authed} render={() => {
                      return this.state.authed
                      ? <Redirect to="/intro/1" />
                      : <Home />
                    }}
                  />
                  <Route path="/intro/:id" render={props => <Intro {...props} />} />
                  <Route path="/dashboard" render={props => <DashboardContainer {...props} />} />
                  <Route path="/service/:id" exact render={props => <ServiceContainer {...props} />} />
                  <Route path="/service/:service_id/department/:id" exact
                    render={props => <DepartmentContainer {...props} />}
                  />
                  <Route path="/service/:service_id/department/:id/learn-more"
                    render={props => <LearnMore {...props} />}
                  />
                  <Route path="/service/:service_id/department/:id/explain"
                    render={props => <ExplainContainer {...props} />}
                  />
                  <Route path="/user" render={() => {
                    return (
                      <User isAuthed={this.state.authed}
                        handleLogout={this.handleLogout.bind(this)}
                      />
                    )
                  }} />
                  <Route path="/submit" render={(props) => {
                    return <SubmitContainer {...props} />
                  }} />
                  <Route path="/done" render={(props) => {
                    return <Done {...props} />
                  }} />
                  <Route render={() =>
404, you ain't supposed to be here
} />
                </Switch>

          </Router>
        </Provider>
      </IntlProvider>
    );
  }
}
<|endoftext|>


<commit_before>/* globals define */

/**
 * This is the stages selection menu view
 */
define(function(require, exports, module) {
  var Engine        = require('famous/core/Engine');
  var View          = require('famous/core/View');
  var Surface       = require('famous/core/Surface');
  var Transform     = require('famous/core/Transform');
  var Transitionable = require('famous/transitions/Transitionable');
  var StateModifier = require('famous/modifiers/StateModifier');
  var Easing        = require('famous/transitions/Easing');
  var ContainerSurface = require('famous/surfaces/ContainerSurface');
  var RenderNode    = require('famous/core/RenderNode');
  var SpringTransition = require('famous/transitions/SpringTransition');
  var SnapTransition = require('famous/transitions/SnapTransition');

  // ## Layout
  var Layout        = require('famous/views/HeaderFooterLayout');

  // ## Views
  var Scrollview    = require('famous/views/Scrollview');
  var StageView     = require('views/StageView');

  // ## Shared
  var H = window.innerHeight;

  Transitionable.registerMethod('spring', SpringTransition);
  Transitionable.registerMethod('snap', SnapTransition);

  function _createLayout() {
    this.layout = new Layout({
      headerSize: this.options.headerHeight
    });

    var mod = new StateModifier({
      transform: Transform.translate(0, 0, 0.1)
    });

    this.add(mod).add(this.layout);
  }

  // function _createBackground() {
  //   this.bg = new Surface({
  //     size: [undefined, undefined],
  //     content: 'Temp',
  //     properties: {
  //       backgroundColor: 'red'
  //     }
  //   });

  //   this.bg.setClasses(['bg-stages']);

  //   var mod = new StateModifier({
  //     transform: Transform.behind
  //   });

  //   this.add(mod).add(this.bg);
  // }

  // ## Setup layout.header

  function _createHeader() {
    var bg = new Surface({
      properties: {
        backgroundColor: 'black'
      }
    });

    this.homeIcon = new Surface({
      size: [true, true],
      content: '',
      properties: {
        color: 'white'
      }
    });

    bg.setClasses(['navbar']);

    // Modifiers
    var headerMod = new StateModifier({
      transform: Transform.translate(0,0,0.1)
    });

    var bgMod = new StateModifier({
      transform: Transform.behind
    });

    var iconMod = new StateModifier({
      align: [1, 0.5],
      origin: [1, 0.5],
      transform: Transform.translate(-12,0,0)
    });

    var node = this.layout.header.add(headerMod);
    node.add(bgMod).add(bg);
    node.add(iconMod).add(this.homeIcon);
  }

  // ## Setup layout.content

  function _createScrollViewNode(options) {
    var view = new StageView({
      index: options.index,
      height: options.height,
      expandedHeight: options.expandedHeight,
      backgroundColor: options.backgroundColor,
    });

    view.pipe(this.scrollView);
    view.on('selectStage', this.scrollToStage.bind(this));

    return view;
  }

  function _createScrollView() {
    this.scrollViewNodes = [];
    this.scrollView = new Scrollview({
      // if paginated === true, a click event on a scrollview item
      // triggers ScrollView.goToNextPage so we can't use it
      // paginated: true
    });

    for (var i = 0; i < 30; i++) {
      var node = _createScrollViewNode.call(this, {
        index: i,
        height: this.options.stripHeight,
        expandedHeight: this.options.stripExpandedHeight,
        backgroundColor: 'hsl(' + i * 360/30 + ', 100%, 50%)'
      });

      this.scrollViewNodes.push(node);
    }

    this.scrollView.sequenceFrom(this.scrollViewNodes);

    this.scrollView._eventInput.on('end', function() {

      // if we are not at the top edge tell AppView to stop responding
      // to Touch/Scroll Events
      // if (this.scrollView.getPosition() > 0) {
      if (this.scrollView._scroller.onEdge() !== -1) {
        this._eventOutput.emit('stagesView:scrollViewInContent');
      } else {
        this._eventOutput.emit('stagesView:scrollViewEdgeHit');
      }
    }.bind(this));

    this.scrollView.pipe(this._eventOutput);
  }

  function _createContent() {

    _createScrollView.call(this);

    var container = new ContainerSurface({
      size: [undefined, H - this.options.headerHeight],
      properties: {
        overflow: 'hidden'
      }
    });

    // var mod = new StateModifier({
    //   size: [undefined, H - this.options.headerHeight],
    //   transform: Transform.translate(0, 0, 0)
    // });

    container.add(this.scrollView);
    this.layout.content.add(container);
  }

  function _getNodeAtIndex(index) {
    return this.scrollViewNodes[index];
  }

  function _setListeners() {
    this.homeIcon.on('click', function() {
      this._eventOutput.emit('nav:loadHome');
    }.bind(this));
  }

  function StagesView() {
    View.apply(this, arguments);

    // _createBackground.call(this);
    _createLayout.call(this);
    _createHeader.call(this);
    _createContent.call(this);

    // Init Event Listeners
    _setListeners.call(this);

    // set initial active stage
    this.prevIndex = this.options.activeStage - 1;
    this.activeIndex = this.options.activeStage - 1;
    this.loadStage();
  }

  StagesView.prototype = Object.create(View.prototype);
  StagesView.prototype.constructor = StagesView;

  StagesView.DEFAULT_OPTIONS = {
    headerHeight: 44,
    stripHeight: 100,
    stripExpandedHeight: H - 44, // window height minus the header height
    activeStage: 2
  };

  /**
   * Taken from famous/views/Scrollview because _shiftOrigin is not exposed
   */
  function _shiftOrigin(amount) {
    var sv = this.scrollView;

    /** @enum */
    var SpringStates = {
        NONE: 0,
        EDGE: 1,
        PAGE: 2
    };

    sv._edgeSpringPosition += amount;
    sv._pageSpringPosition += amount;
    sv.setPosition(sv.getPosition() + amount);
    if (sv._springState === SpringStates.EDGE) {
        sv.spring.setOptions({anchor: [sv._edgeSpringPosition, 0, 0]});
    }
    else if (sv._springState === SpringStates.PAGE) {
        sv.spring.setOptions({anchor: [sv._pageSpringPosition, 0, 0]});
    }
  }

  // @NOTE this works only when the scrollview items are all the same height
  // function _getYOffset(clickY) {

  //   var svPos = this.scrollView.getPosition();

  //   clickY -= this.options.headerHeight;
  //   var offset = clickY - clickY % this.options.stripHeight;

  //   console.log('click offset', offset);
  //   console.log('scrollView position', svPos);
  //   console.log('expanded height', this.options.stripExpandedHeight);

  //   // scrollView position is the number of pixels above the scrollview container
  //   // that the first visible scrollview node is... so for instance if the bottom 5 pixels
  //   // of the first visible node is showing and the node height is 100 then the scrollview
  //   // position is 95
  //   //
  //   // So in order to align the node with the top of the scrollview we need to adjust the
  //   // offset if the scrollView position is greater than 0 but less than the node height
  //   if (svPos > 0) {
  //     if (svPos < this.options.stripHeight) {
  //       if (svPos <= this.options.stripHeight * 0.5) {
  //         offset -= svPos;
  //       } else {
  //         offset += this.options.stripHeight - svPos;
  //       }
  //     }
  //   }

  //   return offset;
  // }

  function _getYOffset(clickY) {
    var offset = clickY - this.options.headerHeight;
    return offset;
  }

  /**
   * This calls _shiftOrigin
   *
   * @param {number} delta The number of pixels to shift the scrollview origin by. If this
   * number is positive then it will be shift up by that many pixels. Vice versa if down.
   *
   * @param {function} callback The callback function to execute when scrolling is done
   */
  function _scrollOrigin(delta, transition, callback) {

    // set up a transitionable that will be used to animate scroll position change
    var transitionable = new Transitionable(0);

    if (typeof transition === 'function') callback = transition;

    // default transition
    if (!transition) {
      // transition = {
      //   duration: 200,
      //   curve: 'linear'
      // };
      transition = {
        method: 'snap',
        period: 200
      };
    }

    // @NOTE
    // This is hacky... but it works. Unlike with a standard transform where the
    // transformation is calculated from the initial position everytime, _shiftOrigin
    // saves its position on each invocation so we are keeping track of previous moved
    // moved amount in order to adjust what we pass into _shiftOrigin so that the
    // move amount doesn't end up accumulating on itself
    var prevMove = 0;

    // function to fire with each Engine 'prerender' event
    var prerender = function() {
      var size = [];
      var move = transitionable.get() - prevMove;
      prevMove = transitionable.get();

      _shiftOrigin.call(this, move);
    }.bind(this);

    var complete = function() {
      Engine.removeListener('prerender', prerender);
      if(callback) callback();
    }.bind(this);

    Engine.on('prerender', prerender);

    transitionable.set(delta, transition, complete);
  }

  function _alignWithTop(count) {

    // Because this is being called recursively we add a failsafe in here
    // to make sure it doesn't continue forever
    count = count || 1;
    if (count > 2) return;

    var transition;
    var svPos = this.scrollView.getPosition();
    var delta = -(svPos+2);

    transition = {
      method: 'spring',
      period: 600,
      dampingRatio: 0.3
    };

    // The plus two here is hacky but svPos seems to be consistently off by a
    // pixel or two so we need to adjust for it to get a nice alignment
    _scrollOrigin.call(this, delta, transition, function() {
      var svPos = this.scrollView.getPosition();
      if (svPos < 10) {
        _alignWithTop.call(this, count++);
      }
    }.bind(this));
  }

  StagesView.prototype.scrollToStage = function(data) {
    var e = data.event;
    var index = data.index;
    var node = data.node;

    // stop from executing if their is a second click on an already active node
    if (this.activeIndex === index) return;

    this.prevIndex = this.activeIndex;
    this.activeIndex = index;

    var bgColor = data.backgroundColor;
    var yOffset = _getYOffset.call(this, e.y);

    // We are doing loadStage and _scrollOrigin simultaneously so that the fact
    // that we need to to first scroll past the top of the scollview in order to
    // calculate how to align the top with the top of the scrollview feels more
    this.loadStage();
    _scrollOrigin.call(this, yOffset, function() {
      _alignWithTop.call(this);
      this.closeExpanded();
    }.bind(this));
  };

  StagesView.prototype.closeExpanded = function(callback) {
    var prevNode = _getNodeAtIndex.call(this, this.prevIndex);
    var activeNode = _getNodeAtIndex.call(this, this.activeIndex);

    // close the currently expanded node
    if (this.prevIndex !== this.activeIndex) {
      prevNode.contract(callback);
    }
  };

  StagesView.prototype.loadStage = function() {
    var activeNode = _getNodeAtIndex.call(this, this.activeIndex);

    // open the new node
    activeNode.expand();
  };

  module.exports = StagesView;
});
<commit_msg>fixed align scrollview item with top when clicked<commit_after>/* globals define */

/**
 * This is the stages selection menu view
 */
define(function(require, exports, module) {
  var Engine        = require('famous/core/Engine');
  var View          = require('famous/core/View');
  var Surface       = require('famous/core/Surface');
  var Transform     = require('famous/core/Transform');
  var Transitionable = require('famous/transitions/Transitionable');
  var StateModifier = require('famous/modifiers/StateModifier');
  var Easing        = require('famous/transitions/Easing');
  var ContainerSurface = require('famous/surfaces/ContainerSurface');
  var RenderNode    = require('famous/core/RenderNode');
  var SpringTransition = require('famous/transitions/SpringTransition');
  var SnapTransition = require('famous/transitions/SnapTransition');

  // ## Layout
  var Layout        = require('famous/views/HeaderFooterLayout');

  // ## Views
  var Scrollview    = require('famous/views/Scrollview');
  var StageView     = require('views/StageView');

  // ## Shared
  var H = window.innerHeight;

  Transitionable.registerMethod('spring', SpringTransition);
  Transitionable.registerMethod('snap', SnapTransition);

  function _createLayout() {
    this.layout = new Layout({
      headerSize: this.options.headerHeight
    });

    var mod = new StateModifier({
      transform: Transform.translate(0, 0, 0.1)
    });

    this.add(mod).add(this.layout);
  }

  // function _createBackground() {
  //   this.bg = new Surface({
  //     size: [undefined, undefined],
  //     content: 'Temp',
  //     properties: {
  //       backgroundColor: 'red'
  //     }
  //   });

  //   this.bg.setClasses(['bg-stages']);

  //   var mod = new StateModifier({
  //     transform: Transform.behind
  //   });

  //   this.add(mod).add(this.bg);
  // }

  // ## Setup layout.header

  function _createHeader() {
    var bg = new Surface({
      properties: {
        backgroundColor: 'black'
      }
    });

    this.homeIcon = new Surface({
      size: [true, true],
      content: '',
      properties: {
        color: 'white'
      }
    });

    bg.setClasses(['navbar']);

    // Modifiers
    var headerMod = new StateModifier({
      transform: Transform.translate(0,0,0.1)
    });

    var bgMod = new StateModifier({
      transform: Transform.behind
    });

    var iconMod = new StateModifier({
      align: [1, 0.5],
      origin: [1, 0.5],
      transform: Transform.translate(-12,0,0)
    });

    var node = this.layout.header.add(headerMod);
    node.add(bgMod).add(bg);
    node.add(iconMod).add(this.homeIcon);
  }

  // ## Setup layout.content

  function _createScrollViewNode(options) {
    var view = new StageView({
      index: options.index,
      height: options.height,
      expandedHeight: options.expandedHeight,
      backgroundColor: options.backgroundColor,
    });

    view.pipe(this.scrollView);
    view.on('selectStage', this.scrollToStage.bind(this));

    return view;
  }

  function _createScrollView() {
    this.scrollViewNodes = [];
    this.scrollView = new Scrollview({
      // if paginated === true, a click event on a scrollview item
      // triggers ScrollView.goToNextPage so we can't use it
      // paginated: true
    });

    for (var i = 0; i < 30; i++) {
      var node = _createScrollViewNode.call(this, {
        index: i,
        height: this.options.stripHeight,
        expandedHeight: this.options.stripExpandedHeight,
        backgroundColor: 'hsl(' + i * 360/30 + ', 100%, 50%)'
      });

      this.scrollViewNodes.push(node);
    }

    this.scrollView.sequenceFrom(this.scrollViewNodes);

    this.scrollView._eventInput.on('end', function() {

      // if we are not at the top edge tell AppView to stop responding
      // to Touch/Scroll Events
      // if (this.scrollView.getPosition() > 0) {
      if (this.scrollView._scroller.onEdge() !== -1) {
        this._eventOutput.emit('stagesView:scrollViewInContent');
      } else {
        this._eventOutput.emit('stagesView:scrollViewEdgeHit');
      }
    }.bind(this));

    this.scrollView.pipe(this._eventOutput);
  }

  function _createContent() {

    _createScrollView.call(this);

    var container = new ContainerSurface({
      size: [undefined, H - this.options.headerHeight],
      properties: {
        overflow: 'hidden'
      }
    });

    // var mod = new StateModifier({
    //   size: [undefined, H - this.options.headerHeight],
    //   transform: Transform.translate(0, 0, 0)
    // });

    container.add(this.scrollView);
    this.layout.content.add(container);
  }

  function _getNodeAtIndex(index) {
    return this.scrollViewNodes[index];
  }

  function _setListeners() {
    this.homeIcon.on('click', function() {
      this._eventOutput.emit('nav:loadHome');
    }.bind(this));
  }

  function StagesView() {
    View.apply(this, arguments);

    // _createBackground.call(this);
    _createLayout.call(this);
    _createHeader.call(this);
    _createContent.call(this);

    // Init Event Listeners
    _setListeners.call(this);

    // set initial active stage
    this.prevIndex = this.options.activeStage - 1;
    this.activeIndex = this.options.activeStage - 1;
    this.loadStage();
  }

  StagesView.prototype = Object.create(View.prototype);
  StagesView.prototype.constructor = StagesView;

  StagesView.DEFAULT_OPTIONS = {
    headerHeight: 44,
    stripHeight: 100,
    stripExpandedHeight: H - 44, // window height minus the header height
    activeStage: 2
  };

  /**
   * Taken from famous/views/Scrollview because _shiftOrigin is not exposed
   */
  function _shiftOrigin(amount) {
    var sv = this.scrollView;

    /** @enum */
    var SpringStates = {
        NONE: 0,
        EDGE: 1,
        PAGE: 2
    };

    sv._edgeSpringPosition += amount;
    sv._pageSpringPosition += amount;
    sv.setPosition(sv.getPosition() + amount);
    if (sv._springState === SpringStates.EDGE) {
        sv.spring.setOptions({anchor: [sv._edgeSpringPosition, 0, 0]});
    }
    else if (sv._springState === SpringStates.PAGE) {
        sv.spring.setOptions({anchor: [sv._pageSpringPosition, 0, 0]});
    }
  }

  /**
   * Calculates the height of the first visible scrollview item
   */
  function _getFirstVisibleHeight() {
    var svPos = this.scrollView.getPosition();
    var firstIndex = this.scrollView._scroller._node.index;

    if (firstIndex === 0) return 0;

    var firstVisibile = _getNodeAtIndex.call(this, firstIndex);
    var firstHeight = firstVisibile.getSize()[1];
    var height = firstHeight - svPos;

    return height;
  }

  /**
   * Calculates how far up we need to scroll in order to have the
   * top of the item that was click line up with the top of the
   * scrollview
   */
  function _getYOffset(clickY) {
    var firstVisibileHeight = _getFirstVisibleHeight.call(this);
    var offset = clickY - firstVisibileHeight;
    offset = offset - this.options.headerHeight;
    offset = offset - offset % this.options.stripHeight;

    return firstVisibileHeight + offset;
  }

  /**
   * This calls _shiftOrigin
   *
   * @param {number} delta The number of pixels to shift the scrollview origin by. If this
   * number is positive then it will be shift up by that many pixels. Vice versa if down.
   *
   * @param {function} callback The callback function to execute when scrolling is done
   */
  function _scrollOrigin(delta, transition, callback) {

    // set up a transitionable that will be used to animate scroll position change
    var transitionable = new Transitionable(0);

    if (typeof transition === 'function') {
      callback = transition;
      transition = null;
    }

    // default transition
    if (!transition) {
      transition = {
        duration: 200,
        curve: 'linear'
      };
    }

    // @NOTE
    // This is hacky... but it works. Unlike with a standard transform where the
    // transformation is calculated from the initial position everytime, _shiftOrigin
    // saves its position on each invocation so we are keeping track of previous moved
    // moved amount in order to adjust what we pass into _shiftOrigin so that the
    // move amount doesn't end up accumulating on itself
    var prevMove = 0;

    // function to fire with each Engine 'prerender' event
    var prerender = function() {
      var size = [];
      var move = transitionable.get() - prevMove;
      prevMove = transitionable.get();

      _shiftOrigin.call(this, move);
    }.bind(this);

    var complete = function() {
      Engine.removeListener('prerender', prerender);
      if(callback) callback();
    }.bind(this);

    Engine.on('prerender', prerender);

    transitionable.set(delta, transition, complete);
  }

  StagesView.prototype.scrollToStage = function(data) {
    var e = data.event;
    var index = data.index;
    var node = data.node;

    // stop from executing if their is a second click on an already active node
    if (this.activeIndex === index) return;

    this.prevIndex = this.activeIndex;
    this.activeIndex = index;

    var bgColor = data.backgroundColor;
    var yOffset = _getYOffset.call(this, e.y);

    this.expandStage();
    _scrollOrigin.call(this, yOffset, function() {
      this.closeExpanded();
    }.bind(this));
  };

  StagesView.prototype.closeExpanded = function(callback) {
    var prevNode = _getNodeAtIndex.call(this, this.prevIndex);
    var activeNode = _getNodeAtIndex.call(this, this.activeIndex);

    // close the currently expanded node
    if (this.prevIndex !== this.activeIndex) {
      prevNode.contract(callback);
    }
  };

  StagesView.prototype.expandStage = function() {
    var activeNode = _getNodeAtIndex.call(this, this.activeIndex);

    // open the new node
    activeNode.expand();
  };

  StagesView.prototype.loadStage = function() {
    this.expandStage();
  };

  module.exports = StagesView;
});
<|endoftext|>


<commit_before>const process = require('process');

const LogFit = require('logfit');
const Rollbar = require('rollbar');
const varsnap = require('varsnap');

function setupRollbar() {
  const rollbarConfig = {
    accessToken: process.env.ROLLBAR_CLIENT_TOKEN,
    captureUncaught: true,
    payload: {
      environment: process.env.ENVIRONMENT,
    }
  };
  return Rollbar.init(rollbarConfig);
}

function setupLogfit() {
  const logfit = new LogFit({
    source: process.env.LOGFIT_CLIENT_TOKEN,
  });
  logfit.report();
}

function setupVarsnap() {
  varsnap.updateConfig({
    varsnap: 'true',
    env: process.env.ENV,
    producerToken: process.env.VARSNAP_PRODUCER_TOKEN,
    consumerToken: process.env.VARSNAP_CONSUMER_TOKEN,
  });
}

module.exports = {
  rollbar: setupRollbar,
  logfit: setupLogfit,
  varsnap: setupVarsnap,
};
<commit_msg>Fix rollbar env<commit_after>const process = require('process');

const LogFit = require('logfit');
const Rollbar = require('rollbar');
const varsnap = require('varsnap');

function setupRollbar() {
  const rollbarConfig = {
    accessToken: process.env.ROLLBAR_CLIENT_TOKEN,
    captureUncaught: true,
    payload: {
      environment: process.env.ENV,
    }
  };
  return Rollbar.init(rollbarConfig);
}

function setupLogfit() {
  const logfit = new LogFit({
    source: process.env.LOGFIT_CLIENT_TOKEN,
  });
  logfit.report();
}

function setupVarsnap() {
  varsnap.updateConfig({
    varsnap: 'true',
    env: process.env.ENV,
    producerToken: process.env.VARSNAP_PRODUCER_TOKEN,
    consumerToken: process.env.VARSNAP_CONSUMER_TOKEN,
  });
}

module.exports = {
  rollbar: setupRollbar,
  logfit: setupLogfit,
  varsnap: setupVarsnap,
};
<|endoftext|>


<commit_before>'use strict';

angular.module('core').controller('HomeController', ['$scope', 'Authentication',
  function ($scope, Authentication) {
    // This provides Authentication context.
    $scope.authentication = Authentication;
  }
]);
<commit_msg>Home controller now checks for user auth before allowing root index to be displayed<commit_after>'use strict';

angular.module('core').controller('HomeController', ['$scope', 'Authentication', '$location',
  function ($scope, Authentication, $location) {
    // This provides Authentication context.
    $scope.authentication = Authentication;

    if(!Authentication.user) {
      $location.path('/authentication/signin');
    }
  }
]);
<|endoftext|>


<commit_before>//.DS_Store(function () {
//'use strict';

//  angular.module('core').controller('HomeController', HomeController);

//  function HomeController() {
//    var vm = this;
//  }//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//}());   //figering uot the andular 2.0 is not cool the docs suk!!!!!!!!!!!!!!!!!!
"use strict";

angular.module("core").controller("HomeController", ["$scope", "Authentication",
  function($scope, Authentication) {
    // aut context
    $scope.authentication = Authentication;

    $scope.alerts = [{
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "total customers"
      }

      {
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "total customers"
      } {
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "total customers"
      } {
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "new customers"
      } {
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "total inventorie"
      }
    ];
  }
]);
<commit_msg>controler fix<commit_after>//.DS_Store(function () {
//'use strict';

//  angular.module('core').controller('HomeController', HomeController);

//  function HomeController() {
//    var vm = this;
//  }////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//}());   //figering uot the andular 2.0 is not cool the docs suk!!!!!!!!!!!!!!!!!!
"use strict";

angular.module("core").controller("HomeController", ["$scope", "Authentication",
  function($scope, Authentication) {
    // aut context
    $scope.authentication = Authentication;

    $scope.alerts = [{
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "total customers"
      }

      {
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "total customers"
      } {
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "total customers"
      } {
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "new customers"
      } {
        icon: "giyphicon-user",
        colour: "btn-succes",
        total: "20,408",
        description: "total inventorie"
      }
    ];
  }
]);
<|endoftext|>


<commit_before>'use strict';

angular.module('core').controller('HomeController', ['$scope','Authentication','$facebook',
  function ($scope, Authentication,$facebook) {
    // This provides Authentication context.
    $scope.authentication = Authentication;
      $scope.loadFriends = function() {
          $facebook.api("/864549880333392/friends").then(
              function(response) {
                  $scope.myFriends = response.data;
              },
              function(err) {
                  $scope.myFriends = "Please log in";
              });
      };
  }
]);
<commit_msg>global declaration<commit_after>'use strict';

angular.module('core').controller('HomeController', ['$scope','Authentication','$facebook',
  function ($scope, Authentication,$facebook) {
    // This provides Authentication context.
    $scope.authentication = Authentication;
      $scope.loadFriends = function() {
          $facebook.api("/864549880333392/friends").then(
              function(response) {
                  $scope.myFriends = response;
              },
              function(err) {
                  $scope.myFriends = "Please log in";
              });
      };
  }
]);
<|endoftext|>


<commit_before>'use strict';

var ReactDOM = require('react-dom/server');

// react components
var helloMessage = require('../../client/components/message.js');

/**
 * Render the main applicaion page
 */
exports.renderIndexPage = function( req, res ) {
    var testA = {
        test: 'awefawef'
    };

    console.log(testA);

    res.render('modules/core/server/views/index', {
        markup: ReactDOM.renderToString(helloMessage)
    });

};
<commit_msg>removed test var<commit_after>'use strict';

var ReactDOM = require('react-dom/server');

// react components
var helloMessage = require('../../client/components/message.js');

/**
 * Render the main applicaion page
 */
exports.renderIndexPage = function( req, res ) {

    res.render('modules/core/server/views/index', {
        markup: ReactDOM.renderToString(helloMessage)
    });

};
<|endoftext|>


<commit_before>/*jshint node:true, es3:false*/
(function() {
  'use strict';
  module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt); // Load grunt tasks automatically
    // Project configuration.
    grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      jshint: {
        all: ['Gruntfile.js', 'src/**/*.js', 'tests/*.js']
      },
      watch: {
        options: {
          spawn: false
        },
        //watches all scripts an rerun hinting and the tests immediately
        scripts: {
          files: ['<%= jshint.all %>'],
          tasks: ['jshint', 'karma:server:run']
        }
      },
      karma: {
        options: {
          configFile: 'karma.conf.js'
        },
        //for a single run of test
        once: {
          singleRun: true,
        },
        //for use while developing and in combination with watch task
        server: {
          background: true,
        },
      }
    });

    //For development
    grunt.registerTask('develop', ['jshint', 'karma:server', 'watch:scripts']);

    //For testing
    grunt.registerTask('test', ['jshint', 'karma:once']);
  };
})();
<commit_msg>proper jshint<commit_after>/*jshint node:true, es3:false*/
(function() {
  'use strict';
  module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt); // Load grunt tasks automatically
    // Project configuration.
    grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      jshint: {
        all: ['Gruntfile.js', 'src/**/*.js', 'spec/**/*.js']
      },
      watch: {
        options: {
          spawn: false
        },
        //watches all scripts an rerun hinting and the tests immediately
        scripts: {
          files: ['<%= jshint.all %>'],
          tasks: ['jshint', 'karma:server:run']
        }
      },
      karma: {
        options: {
          configFile: 'karma.conf.js'
        },
        //for a single run of test
        once: {
          singleRun: true,
        },
        //for use while developing and in combination with watch task
        server: {
          background: true,
        },
      }
    });

    //For development
    grunt.registerTask('develop', ['jshint', 'karma:server', 'watch:scripts']);

    //For testing
    grunt.registerTask('test', ['jshint', 'karma:once']);
  };
})();
<|endoftext|>


<commit_before>/*global define,require,window,console,_ */
/*jslint    devel:true,
            white: true
 */
define([
        'jquery',
        'underscore',
        './<%= extensionName.toLowerCase() %>-properties',
        './<%= extensionName.toLowerCase() %>-initialproperties',
        'text!./lib/css/style.css'
],
function ($, _, props, initProps css) {
    'use strict';

    return {

        definition: props,
        initialProperties: initProps,

        snapshot: { canTakeSnapshot: true },

        // Resize
        resize : function() {
            //do nothing
        },
        // (Resize)

//        clearSelectedValues : function($element) {
//
//        },

        // Angular Template
        //template: '',
        // (Angular Template)

        // Angular Controller
        controller: ['$scope', function ($scope) {

        }],
        // (Angular Controller)

        // Paint Method
        paint: function ($element, layout) {

            console.groupCollapsed('Basic Objects');
            console.info('$element:');
            console.log($element);
            console.info('layout:');
            console.log(layout);
            console.groupEnd();

            $element.html('This is extension "<%= extensionName%>"');
        }
    };

});<commit_msg>Loading CSS<commit_after>/*global define,require,window,console,_ */
/*jslint    devel:true,
            white: true
 */
define([
        'jquery',
        'underscore',
        './<%= extensionName.toLowerCase() %>-properties',
        './<%= extensionName.toLowerCase() %>-initialproperties',
        'text!./lib/css/style.css'
],
function ($, _, props, initProp, cssContent) {
    'use strict';

    $("<style>").html(cssContent).appendTo("head");

    return {

        definition: props,
        initialProperties: initProps,

        snapshot: { canTakeSnapshot: true },

        // Resize
        resize : function() {
            //do nothing
        },
        // (Resize)

//        clearSelectedValues : function($element) {
//
//        },

        // Angular Template
        //template: '',
        // (Angular Template)

        // Angular Controller
        controller: ['$scope', function ($scope) {

        }],
        // (Angular Controller)

        // Paint Method
        paint: function ($element, layout) {

            console.groupCollapsed('Basic Objects');
            console.info('$element:');
            console.log($element);
            console.info('layout:');
            console.log(layout);
            console.groupEnd();

            $element.html('This is extension "<%= extensionName%>"');
        }
    };

});<|endoftext|>


<commit_before>'use strict';

module.exports = function(grunt)
{
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.loadNpmTasks('grunt-contrib-watch');

  // load all grunt tasks
  grunt.initConfig({
    watch: {
      styles: {
        files: ['**/*.less'],
        tasks: ['less'],
        options: {
          spawn: false,
        },
      },
      <% if(themeUsesCoffee) { %>
      scripts: {
        files: ['**/*.coffee'],
        tasks: ['coffee'],
        options: {
          spawn: false,
        },
      },
      <%}%>
    },
    less: {
      development: {
        options: {
          strictImports: true
        },
        files: {
          "css/style.css": "less/*.less"
        }
      }
    },
    coffee: {
      compile: {
        files: {
          'js/script.js' : 'coffee/*.coffee'
        }
      }
    }
  });
}<commit_msg>Add if statement to gruntifle for conditionally watching LESS<commit_after>'use strict';

module.exports = function(grunt)
{
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.loadNpmTasks('grunt-contrib-watch');

  // load all grunt tasks
  grunt.initConfig({
    watch: {
      <% if(themeUsesLESS) { %>
      styles: {
        files: ['**/*.less'],
        tasks: ['less'],
        options: {
          spawn: false,
        },
      },
      <%}%>
      <% if(themeUsesCoffee) { %>
      scripts: {
        files: ['**/*.coffee'],
        tasks: ['coffee'],
        options: {
          spawn: false,
        },
      },
      <%}%>
    },
    less: {
      development: {
        options: {
          strictImports: true
        },
        files: {
          "css/style.css": "less/*.less"
        }
      }
    },
    coffee: {
      compile: {
        files: {
          'js/script.js' : 'coffee/*.coffee'
        }
      }
    }
  });
}<|endoftext|>


<commit_before>const colors = require("colors");
const chai = require("chai");
const path = require("path");
const {
  Web3Shim,
  createInterfaceAdapter
} = require("@truffle/interface-adapter");
const Config = require("@truffle/config");
const Contracts = require("@truffle/workflow-compile/new");
const Resolver = require("@truffle/resolver");
const TestRunner = require("./testing/testrunner");
const TestResolver = require("./testing/testresolver");
const TestSource = require("./testing/testsource");
const SolidityTest = require("./testing/soliditytest");
const expect = require("@truffle/expect");
const Migrate = require("@truffle/migrate");
const Profiler = require("@truffle/compile-solidity/profiler");
const originalrequire = require("original-require");
const Codec = require("@truffle/codec");
const debug = require("debug")("lib:test");
const Debugger = require("@truffle/debugger");
const semver = require("semver");

let Mocha; // Late init with "mocha" or "mocha-parallel-tests"

chai.use(require("./assertions"));

const Test = {
  run: async function(options) {
    expect.options(options, [
      "contracts_directory",
      "contracts_build_directory",
      "migrations_directory",
      "test_files",
      "network",
      "network_id",
      "provider"
    ]);

    const config = Config.default().merge(options);

    config.test_files = config.test_files.map(testFile => {
      return path.resolve(testFile);
    });

    const interfaceAdapter = createInterfaceAdapter({
      provider: config.provider,
      networkType: config.networks[config.network].type
    });

    // `accounts` will be populated before each contract() invocation
    // and passed to it so tests don't have to call it themselves.
    const web3 = new Web3Shim({
      provider: config.provider,
      networkType: config.networks[config.network].type
        ? config.networks[config.network].type
        : "web3js"
    });

    // Override console.warn() because web3 outputs gross errors to it.
    // e.g., https://github.com/ethereum/web3.js/blob/master/lib/web3/allevents.js#L61
    // Output looks like this during tests: https://gist.github.com/tcoulter/1988349d1ec65ce6b958
    const warn = config.logger.warn;
    config.logger.warn = function(message) {
      if (message === "cannot find event for log") {
        return;
      } else {
        if (warn) warn.apply(console, arguments);
      }
    };

    const mocha = this.createMocha(config);

    const jsTests = config.test_files.filter(file => {
      return path.extname(file) !== ".sol";
    });

    const solTests = config.test_files.filter(file => {
      return path.extname(file) === ".sol";
    });

    // Add Javascript tests because there's nothing we need to do with them.
    // Solidity tests will be handled later.
    jsTests.forEach(file => {
      // There's an idiosyncracy in Mocha where the same file can't be run twice
      // unless we delete the `require` cache.
      // https://github.com/mochajs/mocha/issues/995
      delete originalrequire.cache[file];

      mocha.addFile(file);
    });

    const accounts = await this.getAccounts(interfaceAdapter);

    if (!config.resolver) config.resolver = new Resolver(config);

    const testSource = new TestSource(config);
    const testResolver = new TestResolver(
      config.resolver,
      testSource,
      config.contracts_build_directory
    );
    testResolver.cache_on = false;

    const { compilations } = await this.compileContractsWithTestFilesIfNeeded(
      solTests,
      config,
      testResolver
    );

    const testContracts = solTests.map(testFilePath => {
      return testResolver.require(testFilePath);
    });

    const runner = new TestRunner(config);

    await this.performInitialDeploy(config, testResolver);

    await this.defineSolidityTests(
      mocha,
      testContracts,
      compilations.solc.sourceIndexes,
      runner
    );

    const debuggerCompilations = Codec.Compilations.Utils.shimArtifacts(
      compilations.solc.contracts,
      compilations.solc.sourceIndexes
    );

    //for stack traces, we'll need to set up a light-mode debugger...
    let bugger;
    if (config.stacktrace) {
      debug("stacktraces on!");
      bugger = await Debugger.forProject({
        compilations: debuggerCompilations,
        provider: config.provider,
        lightMode: true
      });
    }

    await this.setJSTestGlobals({
      config,
      web3,
      interfaceAdapter,
      accounts,
      testResolver,
      runner,
      compilations: debuggerCompilations,
      bugger
    });

    // Finally, run mocha.
    process.on("unhandledRejection", reason => {
      throw reason;
    });

    return new Promise(resolve => {
      this.mochaRunner = mocha.run(failures => {
        config.logger.warn = warn;
        resolve(failures);
      });
    });
  },

  createMocha: function(config) {
    // Allow people to specify config.mocha in their config.
    const mochaConfig = config.mocha || {};

    // Propagate --bail option to mocha
    mochaConfig.bail = config.bail;

    // If the command line overrides color usage, use that.
    if (config.color != null) {
      mochaConfig.color = config.color;
    } else if (config.colors != null) {
      // --colors is a mocha alias for --color
      mochaConfig.color = config.colors;
    }

    // Default to true if configuration isn't set anywhere.
    if (mochaConfig.color == null) {
      mochaConfig.color = true;
    }

    Mocha = mochaConfig.package || require("mocha");
    delete mochaConfig.package;
    const mocha = new Mocha(mochaConfig);

    return mocha;
  },

  getAccounts: function(interfaceAdapter) {
    return interfaceAdapter.getAccounts();
  },

  compileContractsWithTestFilesIfNeeded: async function(
    solidityTestFiles,
    config,
    testResolver
  ) {
    const updated =
      (await Profiler.updated(config.with({ resolver: testResolver }))) || [];

    let compileConfig = config.with({
      all: config.compileAll === true,
      files: updated.concat(solidityTestFiles),
      resolver: testResolver,
      quiet: config.runnerOutputOnly || config.quiet,
      quietWrite: true
    });
    if (config.compileAllDebug) {
      let versionString = ((compileConfig.compilers || {}).solc || {}).version;
      //note: I'm relying here on the fact that the current
      //default version, 0.5.16, is <0.6.3
      //the following line works with prereleases
      const satisfies = semver.satisfies(versionString, ">=0.6.3", {
        includePrerelease: true,
        loose: true
      });
      //the following line doesn't, despite the flag, but does work with version ranges
      const intersects =
        semver.validRange(versionString) &&
        semver.intersects(versionString, ">=0.6.3", {
          includePrerelease: true,
          loose: true
        }); //intersects will throw if given undefined so must ward against
      if (satisfies || intersects) {
        compileConfig = compileConfig.merge({
          compilers: {
            solc: {
              settings: {
                debug: {
                  revertStrings: "debug"
                }
              }
            }
          }
        });
      } else {
        config.logger.log(
          `\n${colors.bold(
            "Warning:"
          )} Extra revert string info requires Solidity v0.6.3 or higher. For more\n  information, see release notes <https://github.com/ethereum/solidity/releases/tag/v0.6.3>`
        );
      }
    }
    // Compile project contracts and test contracts
    const { contracts, compilations } = await Contracts.compile(compileConfig);

    await Contracts.save(compileConfig, contracts);

    return {
      contracts,
      compilations
    };
  },

  performInitialDeploy: function(config, resolver) {
    const migrateConfig = config.with({
      reset: true,
      resolver: resolver,
      quiet: true
    });
    return Migrate.run(migrateConfig);
  },

  defineSolidityTests: async (mocha, contracts, dependencyPaths, runner) => {
    for (const contract of contracts) {
      await SolidityTest.define(contract, dependencyPaths, runner, mocha);
      debug("defined solidity tests for %s", contract.contractName);
    }
  },

  setJSTestGlobals: async function({
    config,
    web3,
    interfaceAdapter,
    accounts,
    testResolver,
    runner,
    compilations,
    bugger //for stacktracing
  }) {
    global.interfaceAdapter = interfaceAdapter;
    global.web3 = web3;
    global.assert = chai.assert;
    global.expect = chai.expect;
    global.artifacts = {
      require: importPath => {
        let contract = testResolver.require(importPath);
        //HACK: both of the following should go by means
        //of the provisioner, but I'm not sure how to make
        //that work at the moment
        contract.reloadJson = function() {
          const reloaded = testResolver.require(importPath);
          this._json = reloaded._json;
        };
        if (bugger) {
          contract.debugger = bugger;
        }
        return contract;
      }
    };

    global[config.debugGlobal] = async operation => {
      if (!config.debug) {
        config.logger.log(
          `${colors.bold(
            "Warning:"
          )} Invoked in-test debugger without --debug flag. ` +
            `Try: \`truffle test --debug\``
        );
        return operation;
      }

      // wrapped inside function so as not to load debugger on every test
      const { CLIDebugHook } = require("./debug/mocha");

      // note: this.mochaRunner will be available by the time debug()
      // is invoked
      const hook = new CLIDebugHook(config, compilations, this.mochaRunner);

      return await hook.debug(operation);
    };

    const template = function(tests) {
      this.timeout(runner.TEST_TIMEOUT);

      before("prepare suite", async function() {
        this.timeout(runner.BEFORE_TIMEOUT);
        await runner.initialize();
      });

      beforeEach("before test", async function() {
        await runner.startTest();
      });

      afterEach("after test", async function() {
        await runner.endTest(this);
      });

      tests(accounts);
    };

    global.contract = function(name, tests) {
      Mocha.describe("Contract: " + name, function() {
        template.bind(this, tests)();
      });
    };

    global.contract.only = function(name, tests) {
      Mocha.describe.only("Contract: " + name, function() {
        template.bind(this, tests)();
      });
    };

    global.contract.skip = function(name, tests) {
      Mocha.describe.skip("Contract: " + name, function() {
        template.bind(this, tests)();
      });
    };
  }
};

module.exports = Test;
<commit_msg>Add config global to JS test environment<commit_after>const colors = require("colors");
const chai = require("chai");
const path = require("path");
const {
  Web3Shim,
  createInterfaceAdapter
} = require("@truffle/interface-adapter");
const Config = require("@truffle/config");
const Contracts = require("@truffle/workflow-compile/new");
const Resolver = require("@truffle/resolver");
const TestRunner = require("./testing/testrunner");
const TestResolver = require("./testing/testresolver");
const TestSource = require("./testing/testsource");
const SolidityTest = require("./testing/soliditytest");
const expect = require("@truffle/expect");
const Migrate = require("@truffle/migrate");
const Profiler = require("@truffle/compile-solidity/profiler");
const originalrequire = require("original-require");
const Codec = require("@truffle/codec");
const debug = require("debug")("lib:test");
const Debugger = require("@truffle/debugger");
const semver = require("semver");

let Mocha; // Late init with "mocha" or "mocha-parallel-tests"

chai.use(require("./assertions"));

const Test = {
  run: async function(options) {
    expect.options(options, [
      "contracts_directory",
      "contracts_build_directory",
      "migrations_directory",
      "test_files",
      "network",
      "network_id",
      "provider"
    ]);

    const config = Config.default().merge(options);

    config.test_files = config.test_files.map(testFile => {
      return path.resolve(testFile);
    });

    const interfaceAdapter = createInterfaceAdapter({
      provider: config.provider,
      networkType: config.networks[config.network].type
    });

    // `accounts` will be populated before each contract() invocation
    // and passed to it so tests don't have to call it themselves.
    const web3 = new Web3Shim({
      provider: config.provider,
      networkType: config.networks[config.network].type
        ? config.networks[config.network].type
        : "web3js"
    });

    // Override console.warn() because web3 outputs gross errors to it.
    // e.g., https://github.com/ethereum/web3.js/blob/master/lib/web3/allevents.js#L61
    // Output looks like this during tests: https://gist.github.com/tcoulter/1988349d1ec65ce6b958
    const warn = config.logger.warn;
    config.logger.warn = function(message) {
      if (message === "cannot find event for log") {
        return;
      } else {
        if (warn) warn.apply(console, arguments);
      }
    };

    const mocha = this.createMocha(config);

    const jsTests = config.test_files.filter(file => {
      return path.extname(file) !== ".sol";
    });

    const solTests = config.test_files.filter(file => {
      return path.extname(file) === ".sol";
    });

    // Add Javascript tests because there's nothing we need to do with them.
    // Solidity tests will be handled later.
    jsTests.forEach(file => {
      // There's an idiosyncracy in Mocha where the same file can't be run twice
      // unless we delete the `require` cache.
      // https://github.com/mochajs/mocha/issues/995
      delete originalrequire.cache[file];

      mocha.addFile(file);
    });

    const accounts = await this.getAccounts(interfaceAdapter);

    if (!config.resolver) config.resolver = new Resolver(config);

    const testSource = new TestSource(config);
    const testResolver = new TestResolver(
      config.resolver,
      testSource,
      config.contracts_build_directory
    );
    testResolver.cache_on = false;

    const { compilations } = await this.compileContractsWithTestFilesIfNeeded(
      solTests,
      config,
      testResolver
    );

    const testContracts = solTests.map(testFilePath => {
      return testResolver.require(testFilePath);
    });

    const runner = new TestRunner(config);

    await this.performInitialDeploy(config, testResolver);

    await this.defineSolidityTests(
      mocha,
      testContracts,
      compilations.solc.sourceIndexes,
      runner
    );

    const debuggerCompilations = Codec.Compilations.Utils.shimArtifacts(
      compilations.solc.contracts,
      compilations.solc.sourceIndexes
    );

    //for stack traces, we'll need to set up a light-mode debugger...
    let bugger;
    if (config.stacktrace) {
      debug("stacktraces on!");
      bugger = await Debugger.forProject({
        compilations: debuggerCompilations,
        provider: config.provider,
        lightMode: true
      });
    }

    await this.setJSTestGlobals({
      config,
      web3,
      interfaceAdapter,
      accounts,
      testResolver,
      runner,
      compilations: debuggerCompilations,
      bugger
    });

    // Finally, run mocha.
    process.on("unhandledRejection", reason => {
      throw reason;
    });

    return new Promise(resolve => {
      this.mochaRunner = mocha.run(failures => {
        config.logger.warn = warn;
        resolve(failures);
      });
    });
  },

  createMocha: function(config) {
    // Allow people to specify config.mocha in their config.
    const mochaConfig = config.mocha || {};

    // Propagate --bail option to mocha
    mochaConfig.bail = config.bail;

    // If the command line overrides color usage, use that.
    if (config.color != null) {
      mochaConfig.color = config.color;
    } else if (config.colors != null) {
      // --colors is a mocha alias for --color
      mochaConfig.color = config.colors;
    }

    // Default to true if configuration isn't set anywhere.
    if (mochaConfig.color == null) {
      mochaConfig.color = true;
    }

    Mocha = mochaConfig.package || require("mocha");
    delete mochaConfig.package;
    const mocha = new Mocha(mochaConfig);

    return mocha;
  },

  getAccounts: function(interfaceAdapter) {
    return interfaceAdapter.getAccounts();
  },

  compileContractsWithTestFilesIfNeeded: async function(
    solidityTestFiles,
    config,
    testResolver
  ) {
    const updated =
      (await Profiler.updated(config.with({ resolver: testResolver }))) || [];

    let compileConfig = config.with({
      all: config.compileAll === true,
      files: updated.concat(solidityTestFiles),
      resolver: testResolver,
      quiet: config.runnerOutputOnly || config.quiet,
      quietWrite: true
    });
    if (config.compileAllDebug) {
      let versionString = ((compileConfig.compilers || {}).solc || {}).version;
      //note: I'm relying here on the fact that the current
      //default version, 0.5.16, is <0.6.3
      //the following line works with prereleases
      const satisfies = semver.satisfies(versionString, ">=0.6.3", {
        includePrerelease: true,
        loose: true
      });
      //the following line doesn't, despite the flag, but does work with version ranges
      const intersects =
        semver.validRange(versionString) &&
        semver.intersects(versionString, ">=0.6.3", {
          includePrerelease: true,
          loose: true
        }); //intersects will throw if given undefined so must ward against
      if (satisfies || intersects) {
        compileConfig = compileConfig.merge({
          compilers: {
            solc: {
              settings: {
                debug: {
                  revertStrings: "debug"
                }
              }
            }
          }
        });
      } else {
        config.logger.log(
          `\n${colors.bold(
            "Warning:"
          )} Extra revert string info requires Solidity v0.6.3 or higher. For more\n  information, see release notes <https://github.com/ethereum/solidity/releases/tag/v0.6.3>`
        );
      }
    }
    // Compile project contracts and test contracts
    const { contracts, compilations } = await Contracts.compile(compileConfig);

    await Contracts.save(compileConfig, contracts);

    return {
      contracts,
      compilations
    };
  },

  performInitialDeploy: function(config, resolver) {
    const migrateConfig = config.with({
      reset: true,
      resolver: resolver,
      quiet: true
    });
    return Migrate.run(migrateConfig);
  },

  defineSolidityTests: async (mocha, contracts, dependencyPaths, runner) => {
    for (const contract of contracts) {
      await SolidityTest.define(contract, dependencyPaths, runner, mocha);
      debug("defined solidity tests for %s", contract.contractName);
    }
  },

  setJSTestGlobals: async function({
    config,
    web3,
    interfaceAdapter,
    accounts,
    testResolver,
    runner,
    compilations,
    bugger //for stacktracing
  }) {
    global.interfaceAdapter = interfaceAdapter;
    global.web3 = web3;
    global.assert = chai.assert;
    global.expect = chai.expect;
    global.artifacts = {
      require: importPath => {
        let contract = testResolver.require(importPath);
        //HACK: both of the following should go by means
        //of the provisioner, but I'm not sure how to make
        //that work at the moment
        contract.reloadJson = function() {
          const reloaded = testResolver.require(importPath);
          this._json = reloaded._json;
        };
        if (bugger) {
          contract.debugger = bugger;
        }
        return contract;
      }
    };
    global.config = config.normalize(config);

    global[config.debugGlobal] = async operation => {
      if (!config.debug) {
        config.logger.log(
          `${colors.bold(
            "Warning:"
          )} Invoked in-test debugger without --debug flag. ` +
            `Try: \`truffle test --debug\``
        );
        return operation;
      }

      // wrapped inside function so as not to load debugger on every test
      const { CLIDebugHook } = require("./debug/mocha");

      // note: this.mochaRunner will be available by the time debug()
      // is invoked
      const hook = new CLIDebugHook(config, compilations, this.mochaRunner);

      return await hook.debug(operation);
    };

    const template = function(tests) {
      this.timeout(runner.TEST_TIMEOUT);

      before("prepare suite", async function() {
        this.timeout(runner.BEFORE_TIMEOUT);
        await runner.initialize();
      });

      beforeEach("before test", async function() {
        await runner.startTest();
      });

      afterEach("after test", async function() {
        await runner.endTest(this);
      });

      tests(accounts);
    };

    global.contract = function(name, tests) {
      Mocha.describe("Contract: " + name, function() {
        template.bind(this, tests)();
      });
    };

    global.contract.only = function(name, tests) {
      Mocha.describe.only("Contract: " + name, function() {
        template.bind(this, tests)();
      });
    };

    global.contract.skip = function(name, tests) {
      Mocha.describe.skip("Contract: " + name, function() {
        template.bind(this, tests)();
      });
    };
  }
};

module.exports = Test;
<|endoftext|>