<commit_before>'use strict';

var _window = typeof unsafeWindow === 'undefined' ? window : unsafeWindow;

/*
 * Rules for identifying ads on individual domains.
 *
 * example: Example URL that should trigger, used for testing.
 * match: Returns true if the current article is sponsored.
 * getSponsor: Returns the name of the sponsor. Null if unknown.
 */
_window.AD_DETECTOR_RULES = {
  'ad-assets.nytimes.com': [
    {
      example: 'http://ad-assets.nytimes.com/paidpost/dell/will-millennials-ever-completely-shun-the-office.html',
      match: function() {
        return true;
      },
      getSponsor: function() {
        var paidElts = document.getElementsByClassName('paid-head-tag');
        if (paidElts.length < 1) {
          return null;
        }
        return paidElts[0].innerHTML.replace('PAID FOR AND POSTED BY ', '');
      },
    },
  ],
  'blogs.vancouversun.com': [
    {
      example: 'http://blogs.vancouversun.com/2014/03/12/cyberwarfare-expert-cancels-vancouver-talk-over-fear-of-revealing-critical-infrastructure-risks/',
      match: function() {
        return document.getElementsByClassName('tag-sponsored').length > 0;
      },
      getSponsor: function() {
        return null;
      }
    }
  ],
  'buzzfeed.com': [
    {
      example: 'http://www.buzzfeed.com/bravo/ways-to-up-your-online-dating-game',
      match: function() {
        var elts = document.getElementsByClassName('author_title');
        if (elts.length > 0) {
          return elts[0].innerHTML.indexOf('Brand Publisher') > -1;
        }
        return false;
      },
      getSponsor: function() {
        var elts = document.querySelectorAll('[rel="author"]');
        if (elts.length > 0) {
          return elts[0].innerHTML.trim();
        }
        return null;
      },
    },
  ],
  'deadspin.com': [
    {
      example: 'http://deadspin.com/5969545/exclusive-could-this-be-chris-pauls-secret-twin-brother',
      match: function() {
        return document.getElementsByClassName('sponsored-label').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'fastcompany.com': [
    {
      example: 'http://www.fastcompany.com/3002725/infographic-upss-2012-change-supply-chain-survey',
      match: function() {
        return _window.bootstrap_obj ? _window.bootstrap_obj.sponsored : false;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'forbes.com': [
    {
      example: 'http://www.forbes.com/sites/fidelity/2014/04/29/should-you-accept-your-employers-pension-buyout-offer/',
      match: function() {
        return document.getElementsByClassName('brandvoice').length > 0;
      },
      getSponsor: function() {
        return document.getElementsByClassName('brandvoice')[0].textContent;
      },
    },
  ],
  'fortune.com': [
    {
      example: 'http://fortune.com/contentfrom/2014/07/01/Content-Marketing-A-Winner-on-Mobile/?ntv_a=0pABAL54BAfxgFA',
      match: function() {
        return _window.location.href.indexOf('/contentfrom/') > -1 ||
            document.getElementsByClassName('sponsor-name').length > 0;
      },
      getSponsor: function() {
        var elt = document.querySelector('.sponsor-name span');
        return elt ? elt.innerHTML : null;
      }
    }
  ],
  'gawker.com': [
    {
      example: 'http://gawker.com/5974129/how-to-transform-into-a-total-nerd-babe/',
      match: function() {
        return document.getElementsByClassName('sponsored-label').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'huffingtonpost.com': [
    {
      example: 'http://www.huffingtonpost.com/2014/07/24/things-you-never-knew-about-tequila_n_5589092.html',
      match: function() {
        return document.getElementsByClassName('sponsor_wrapper').length > 0;
      },
      getSponsor: function() {
        var paidElts = document.querySelectorAll('.sponsor_wrapper .sponsor_title_wrapper span');
        if (paidElts.length < 1) {
          return null;
        }
        return paidElts[0].innerHTML.replace('Presented by ', '');
      }
    }
  ],
  'latimes.com': [
    {
      example: 'http://www.latimes.com/brandpublishing/localplus/ucsandiego/la-ss-ucsd-playhouse-dto-story.html',
      match: function() {
        return _window.location.href.indexOf('/brandpublishing') > -1;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'lifehacker.com': [
    {
      example: 'http://lifehacker.com/5751962/gawker-artists-open-call-for-artists-and-exhibitors',
      match: function() {
        return document.getElementsByClassName('sponsored-label').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'mashable.com': [
    {
      example: 'http://mashable.com/2013/03/12/dog-mans-best-friend/',
      match: function() {
        return _window.__o.content_source_type === 'Supported' ||
            _window.__o.content_source_type === 'Sponsored' ||
            _window.__o.topics.toLowerCase().indexOf('sponsored') > -1;
      },
      getSponsor: function() {
        var source = _window.__o.content_source_name;
        if (!source || source === 'Internal') {
          // Discard false positives.
          return null;
        }
        return source[0].toUpperCase() + source.slice(1);
      },
    },
  ],
  'newsweek.com': [
    {
      example: 'http://www.newsweek.com/10-best-personal-injury-attorneys',
      match: function() {
        return document.getElementsByClassName('sponsored-insight').length > 0;
      },
      getSponsor: function() {
        // Newsweek doesn't say; sometimes there are many sponsors for a single list.
        return null;
      },
    },
  ],
  'nydailynews.com': [
    {
      example: 'http://www.nydailynews.com/services/cuny-citizenship-immigration-centers-announce-expanded-summer-hours-article-1.1860540',
      match: function() {
        var elt = document.getElementById('a-credits');
        if (!elt) {
          return false;
        }
        return elt.innerHTML.indexOf('CONTENT SPONSORED') > -1;
      },
      getSponsor: function() {
        var elt = document.getElementById('a-credits');
        return elt ? elt.innerHTML.replace('CONTENT SPONSORED BY ', '') : null;
      },
    },
  ],
  'online.wsj.com': [
    {
      example: 'http://online.wsj.com/ad/article/narratives_brocade_67186.html?prx_t=cpIBAiqcBAu2QFA',
      match: function() {
        return _window.location.href.indexOf('/ad/') > -1;
      },
      getSponsor: function() {
        var elts = document.querySelectorAll('.author a');
        if (elts.length < 1) {
          return null;
        }
        return elts[0].innerHTML;
      },
    },
  ],
  'paidpost.nytimes.com': [
    {
      example: 'http://paidpost.nytimes.com/vacheron-constantin/transmitting-craftsmanship.html',
      match: function() {
        return true;
      },
      getSponsor: function() {
        var paidElts = document.getElementsByClassName('paid-top-border-txt');
        if (paidElts.length < 1) {
          return null;
        }
        return paidElts[0].innerHTML.replace('PAID FOR AND POSTED BY ', '');
      },
    },
  ],
  'pando.com': [
    {
      example: 'http://pando.com/2013/03/01/you-shouldnt-be-bored-at-a-board-meeting-pt-2-structure-for-success/',
      match: function() {
        // Haven't figured out how to match their sponsored articles...
        return false;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'slate.com': [
    {
      example: 'http://www.slate.com/articles/news_and_politics/uc/2014/06/living_forever_the_right_way.html',
      match: function() {
        return document.getElementsByClassName('provided-by').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'suntimes.com': [
    {
      example: 'http://www.suntimes.com/sponsored/28700806-816/live-music-for-every-palate-playing-all-summer-long.html',
      match: function() {
        return _window.location.href.indexOf('/sponsored/') > -1 ||
            document.getElementsByClassName('sponsored-heading').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'theatlantic.com': [
    {
      example: 'http://www.theatlantic.com/sponsored/ibm-big-data/big-data-grows-new-role-emerges-chief-data-officer/102/',
      match: function() {
        return document.getElementsByClassName('sponsor-warning').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'theonion.com': [
    {
      example: 'http://www.theonion.com/sponsored/woman-going-to-take-quick-break-after-filling-out,85/',
      match: function() {
        return document.getElementById('sponsored-box') !== null;
      },
      getSponsor: function() {
        var elts = document.querySelectorAll('#sponsor-explanation-text h1');
        if (elts.length < 1) {
          return null;
        }
        var text = elts[0].lastChild.textContent;
        return text.slice(3, text.lastIndexOf('·') - 1);
      },
    },
  ],
  'usatoday.com': [
    {
      example: 'http://www.usatoday.com/story/sponsor-story/dell/2014/05/13/dell-tablets-and-culture/9002541/',
      match: function() {
        return _window.location.href.indexOf('/sponsor-story/') > -1;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'vanityfair.com': [
    {
      example: 'http://www.vanityfair.com/online/oscars/2013/12/hennessy-sir-malcolm-campbell-speed-racer',
      match: function() {
        var elts = document.getElementsByClassName('rubric');
        if (elts.length < 1) {
          return false;
        }
        return elts[0].innerHTML === 'SPONSOR CONTENT';
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  // For testing:
  'ianww.com': [
    {
      example: 'http://ianww.com/ad-detector/ad-test.html',
      match: function() {
        return _window.location.href.indexOf('ad-test') > -1;
      },
      getSponsor: function() {
        // Displayed sponsor should always be 'windowVar' to verify that we are
        // not in a sandboxed window.
        return _window.foo;
      },
    },
  ],
  'washingtonpost.com': [
    {
      example: 'http://www.washingtonpost.com/sf/brand-connect/wp/enterprise/one-year-later-a-commitment-renewed/',
      match: function() {
        // TODO Can also check for WP Brand Connect in URL, "left title-bar", or in title
        var elts = document.querySelectorAll('.bylines .byline .byline-title');
        if (elts.length < 1) {
          return false;
        }
        return elts[0].innerHTML.indexOf('Sponsor Generated Content') > -1;
      },
      getSponsor: function() {
        // Uses images of sponsors' logos
        return null;
      }
    }
  ]
};
<commit_msg>rebase merge solution<commit_after>'use strict';

var _window = typeof unsafeWindow === 'undefined' ? window : unsafeWindow;

/*
 * Rules for identifying ads on individual domains.
 *
 * example: Example URL that should trigger, used for testing.
 * match: Returns true if the current article is sponsored.
 * getSponsor: Returns the name of the sponsor. Null if unknown.
 */
_window.AD_DETECTOR_RULES = {
  'ad-assets.nytimes.com': [
    {
      example: 'http://ad-assets.nytimes.com/paidpost/dell/will-millennials-ever-completely-shun-the-office.html',
      match: function() {
        return true;
      },
      getSponsor: function() {
        var paidElts = document.getElementsByClassName('paid-head-tag');
        if (paidElts.length < 1) {
          return null;
        }
        return paidElts[0].innerHTML.replace('PAID FOR AND POSTED BY ', '');
      },
    },
  ],
  'blogs.vancouversun.com': [
    {
      example: 'http://blogs.vancouversun.com/2014/03/12/cyberwarfare-expert-cancels-vancouver-talk-over-fear-of-revealing-critical-infrastructure-risks/',
      match: function() {
        return document.getElementsByClassName('tag-sponsored').length > 0;
      },
      getSponsor: function() {
        return null;
      }
    }
  ],
  'buzzfeed.com': [
    {
      example: 'http://www.buzzfeed.com/bravo/ways-to-up-your-online-dating-game',
      match: function() {
        var elts = document.getElementsByClassName('author_title');
        if (elts.length > 0) {
          return elts[0].innerHTML.indexOf('Brand Publisher') > -1;
        }
        return false;
      },
      getSponsor: function() {
        var elts = document.querySelectorAll('[rel="author"]');
        if (elts.length > 0) {
          return elts[0].innerHTML.trim();
        }
        return null;
      },
    },
  ],
  'deadspin.com': [
    {
      example: 'http://deadspin.com/5969545/exclusive-could-this-be-chris-pauls-secret-twin-brother',
      match: function() {
        return document.getElementsByClassName('sponsored-label').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'fastcompany.com': [
    {
      example: 'http://www.fastcompany.com/3002725/infographic-upss-2012-change-supply-chain-survey',
      match: function() {
        return _window.bootstrap_obj ? _window.bootstrap_obj.sponsored : false;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'forbes.com': [
    {
      example: 'http://www.forbes.com/sites/fidelity/2014/04/29/should-you-accept-your-employers-pension-buyout-offer/',
      match: function() {
        return document.getElementsByClassName('brandvoice').length > 0;
      },
      getSponsor: function() {
        return document.getElementsByClassName('brandvoice')[0].textContent;
      },
    },
  ],
  'fortune.com': [
    {
      example: 'http://fortune.com/contentfrom/2014/07/01/Content-Marketing-A-Winner-on-Mobile/?ntv_a=0pABAL54BAfxgFA',
      match: function() {
        return _window.location.href.indexOf('/contentfrom/') > -1 ||
            document.getElementsByClassName('sponsor-name').length > 0;
      },
      getSponsor: function() {
        var elt = document.querySelector('.sponsor-name span');
        return elt ? elt.innerHTML : null;
      }
    }
  ],
  'gawker.com': [
    {
      example: 'http://gawker.com/5974129/how-to-transform-into-a-total-nerd-babe/',
      match: function() {
        return document.getElementsByClassName('sponsored-label').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'huffingtonpost.com': [
    {
      example: 'http://www.huffingtonpost.com/2014/07/24/things-you-never-knew-about-tequila_n_5589092.html',
      match: function() {
        return document.getElementsByClassName('sponsor_wrapper').length > 0;
      },
      getSponsor: function() {
        var paidElts = document.querySelectorAll('.sponsor_wrapper .sponsor_title_wrapper span');
        if (paidElts.length < 1) {
          return null;
        }
        return paidElts[0].innerHTML.replace('Presented by ', '');
      }
    }
  ],
  'innovationinsights.wired.com': [
    {
      example: 'http://innovationinsights.wired.com/insights/2014/03/cloud-finding-way-fog/',
      match: function() {
        return true;
      },
      getSponsor: function() {
        return 'IBM';
      }
    }
  ],
  'latimes.com': [
    {
      example: 'http://www.latimes.com/brandpublishing/localplus/ucsandiego/la-ss-ucsd-playhouse-dto-story.html',
      match: function() {
        return _window.location.href.indexOf('/brandpublishing') > -1;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'lifehacker.com': [
    {
      example: 'http://lifehacker.com/5751962/gawker-artists-open-call-for-artists-and-exhibitors',
      match: function() {
        return document.getElementsByClassName('sponsored-label').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'mashable.com': [
    {
      example: 'http://mashable.com/2013/03/12/dog-mans-best-friend/',
      match: function() {
        return _window.__o.content_source_type === 'Supported' ||
            _window.__o.content_source_type === 'Sponsored' ||
            _window.__o.topics.toLowerCase().indexOf('sponsored') > -1;
      },
      getSponsor: function() {
        var source = _window.__o.content_source_name;
        if (!source || source === 'Internal') {
          // Discard false positives.
          return null;
        }
        return source[0].toUpperCase() + source.slice(1);
      },
    },
  ],
  'newsweek.com': [
    {
      example: 'http://www.newsweek.com/10-best-personal-injury-attorneys',
      match: function() {
        return document.getElementsByClassName('sponsored-insight').length > 0;
      },
      getSponsor: function() {
        // Newsweek doesn't say; sometimes there are many sponsors for a single list.
        return null;
      },
    },
  ],
  'nydailynews.com': [
    {
      example: 'http://www.nydailynews.com/services/cuny-citizenship-immigration-centers-announce-expanded-summer-hours-article-1.1860540',
      match: function() {
        var elt = document.getElementById('a-credits');
        if (!elt) {
          return false;
        }
        return elt.innerHTML.indexOf('CONTENT SPONSORED') > -1;
      },
      getSponsor: function() {
        var elt = document.getElementById('a-credits');
        return elt ? elt.innerHTML.replace('CONTENT SPONSORED BY ', '') : null;
      },
    },
  ],
  'online.wsj.com': [
    {
      example: 'http://online.wsj.com/ad/article/narratives_brocade_67186.html?prx_t=cpIBAiqcBAu2QFA',
      match: function() {
        return _window.location.href.indexOf('/ad/') > -1;
      },
      getSponsor: function() {
        var elts = document.querySelectorAll('.author a');
        if (elts.length < 1) {
          return null;
        }
        return elts[0].innerHTML;
      },
    },
  ],
  'paidpost.nytimes.com': [
    {
      example: 'http://paidpost.nytimes.com/vacheron-constantin/transmitting-craftsmanship.html',
      match: function() {
        return true;
      },
      getSponsor: function() {
        var paidElts = document.getElementsByClassName('paid-top-border-txt');
        if (paidElts.length < 1) {
          return null;
        }
        return paidElts[0].innerHTML.replace('PAID FOR AND POSTED BY ', '');
      },
    },
  ],
  'pando.com': [
    {
      example: 'http://pando.com/2013/03/01/you-shouldnt-be-bored-at-a-board-meeting-pt-2-structure-for-success/',
      match: function() {
        // Haven't figured out how to match their sponsored articles...
        return false;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'slate.com': [
    {
      example: 'http://www.slate.com/articles/news_and_politics/uc/2014/06/living_forever_the_right_way.html',
      match: function() {
        return document.getElementsByClassName('provided-by').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'suntimes.com': [
    {
      example: 'http://www.suntimes.com/sponsored/28700806-816/live-music-for-every-palate-playing-all-summer-long.html',
      match: function() {
        return _window.location.href.indexOf('/sponsored/') > -1 ||
            document.getElementsByClassName('sponsored-heading').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'theatlantic.com': [
    {
      example: 'http://www.theatlantic.com/sponsored/ibm-big-data/big-data-grows-new-role-emerges-chief-data-officer/102/',
      match: function() {
        return document.getElementsByClassName('sponsor-warning').length > 0;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'theonion.com': [
    {
      example: 'http://www.theonion.com/sponsored/woman-going-to-take-quick-break-after-filling-out,85/',
      match: function() {
        return document.getElementById('sponsored-box') !== null;
      },
      getSponsor: function() {
        var elts = document.querySelectorAll('#sponsor-explanation-text h1');
        if (elts.length < 1) {
          return null;
        }
        var text = elts[0].lastChild.textContent;
        return text.slice(3, text.lastIndexOf('·') - 1);
      },
    },
  ],
  'usatoday.com': [
    {
      example: 'http://www.usatoday.com/story/sponsor-story/dell/2014/05/13/dell-tablets-and-culture/9002541/',
      match: function() {
        return _window.location.href.indexOf('/sponsor-story/') > -1;
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  'vanityfair.com': [
    {
      example: 'http://www.vanityfair.com/online/oscars/2013/12/hennessy-sir-malcolm-campbell-speed-racer',
      match: function() {
        var elts = document.getElementsByClassName('rubric');
        if (elts.length < 1) {
          return false;
        }
        return elts[0].innerHTML === 'SPONSOR CONTENT';
      },
      getSponsor: function() {
        return null;
      },
    },
  ],
  // For testing:
  'ianww.com': [
    {
      example: 'http://ianww.com/ad-detector/ad-test.html',
      match: function() {
        return _window.location.href.indexOf('ad-test') > -1;
      },
      getSponsor: function() {
        // Displayed sponsor should always be 'windowVar' to verify that we are
        // not in a sandboxed window.
        return _window.foo;
      },
    },
  ],
  'washingtonpost.com': [
    {
      example: 'http://www.washingtonpost.com/sf/brand-connect/wp/enterprise/one-year-later-a-commitment-renewed/',
      match: function() {
        // TODO Can also check for WP Brand Connect in URL, "left title-bar", or in title
        var elts = document.querySelectorAll('.bylines .byline .byline-title');
        if (elts.length < 1) {
          return false;
        }
        return elts[0].innerHTML.indexOf('Sponsor Generated Content') > -1;
      },
      getSponsor: function() {
        // Uses images of sponsors' logos
        return null;
      }
    }
  ],
  'wired.com': [
    {
      example: 'http://www.wired.com/partners/netflix/',
      match: function() {
        return _window.location.href.indexOf('/partners/') > -1;
      },
      getSponsor: function() {
        return null;
      }
    }
  ],
  // For testing:
  'ianww.com': [
    {
      example: 'http://ianww.com/ad-detector/ad-test.html',
      match: function() {
        return _window.location.href.indexOf('ad-test') > -1;
      },
      getSponsor: function() {
        // Displayed sponsor should always be 'windowVar' to verify that we are
        // not in a sandboxed window.
        return _window.foo;
      },
    },
  ],
};
<|endoftext|>


<commit_before><commit_msg>update files<commit_after><|endoftext|>


<commit_before><commit_msg>fix: update sync-docs.js (#257)<commit_after><|endoftext|>


<commit_before><commit_msg>Remove quo.js dependency<commit_after><|endoftext|>


<commit_before>module.exports = function(gulp, defaults, subtasks) {

    var taskname = 'tsd';

    gulp.desc(taskname, 'Discover and centralize TypeScript definition files');

    var _ = require('lodash');
    var flatten = require('gulp-flatten');
    var fs = require('fs');
    var gutil = require('gulp-util');
    var mkdirp = require('mkdirp');
    var path = require('path');
    var join = require('join');
    var tap = require('gulp-tap');

    var discoverInternalTaskname = taskname + ':discover:internal';
    var discoverExternalTaskname = taskname + ':discover:external';
    var detectCollisionsTaskname = taskname + ':detectCollisions';
    var copyTaskname = taskname + ':copy';
    var gitignoreTaskname = taskname + ':gitignore';

    var deps = [].concat(defaults.path.dependencies);
    var externalTsdSrc = deps.map(function(dir) {
        return join(dir, defaults.glob.tsd);
    });
    var internalTsdSrc = defaults.path.api + defaults.glob.tsd;

    var internalDefs = [];
    var externalDefs = [];

    function getIgnoredFiles(cwd) {
        try {
            var gitignoreData = fs.readFileSync(path.join(cwd, '.gitignore'), {encoding: 'utf8'});
            return gitignoreData.split('\n');
        } catch (e) {
            return [];
        }
    }

    function getTSDInstalledFiles(root) {
        try {
            var tsdData = fs.readFileSync(path.join(root, 'tsd.json'), {encoding: 'utf8'});
            return Object.keys(JSON.parse(tsdData).installed);
        } catch (e) {
            return [];
        }
    }

    // survey the api directory and discover internal tsd files
    gulp.task(discoverInternalTaskname, function() {
        internalDefs = [];

        // get list of ignored files (ignored means external)
        var ignored = getIgnoredFiles(defaults.path.api);

        // discover internal tsd files in api directory
        return gulp.src(internalTsdSrc)
            .pipe(tap(function(file) {
                // it's internal if it's not ignored
                if (!_.contains(ignored, file.relative)) {
                    internalDefs.push({
                        name: path.basename(file.path),
                        path: file.path,
                        internal: true
                    });
                }
            }));
    });

    // survey the dependency directories and tsd.json to discover external tsd files
    gulp.task(discoverExternalTaskname, [discoverInternalTaskname], function() {
        externalDefs = [];

        // include all external definition files installed via the tsd package manager
        var tsdInstalled = getTSDInstalledFiles(defaults.path.root);
        tsdInstalled.forEach(function(file) {
            externalDefs.push({
                name: file,
                path: path.join(defaults.path.api, file),
                internal: false
            });
        });

        // discover external tsd files in dependency directories
        return gulp.src(externalTsdSrc)
            .pipe(tap(function(file) {
                externalDefs.push({
                    name: path.basename(file.path),
                    path: file.path,
                    internal: false
                });
            }));
    });

    // using the list of internal and external definitions, detect name collisions
    gulp.task(detectCollisionsTaskname, [discoverInternalTaskname, discoverExternalTaskname], function() {
        var dupeMap = {};
        [].concat(internalDefs, externalDefs).forEach(function(def) {
            if (!dupeMap[def.name]) {
                dupeMap[def.name] = [];
            }
            dupeMap[def.name].push(def);
        });

        var collisionsPathMapFn = function(def) {
            // map definition object to its path as a string
            return '\t' + def.path;
        };
        var warnFn = function(warning) {
            // log a gulp warning
            gutil.log(gutil.colors.yellow(warning));
        };
        var internalDefCheck = function(def) {
            // check if a definition is internal and throw if it is to prevent overwriting it
            if (def.internal) {
                gutil.log(gutil.colors.red('Error: The above collision would overwrite this TS definition:'));
                gutil.log(gutil.colors.red('\t' + def.path));
                process.exit(1);
            }
        };

        for (var name in dupeMap) {
            if (dupeMap.hasOwnProperty(name)) {
                if (dupeMap[name].length > 1) {
                    // collision!
                    var collisionWarnings = ['Warning: a collision occurred between the following TS definitions:'];
                    collisionWarnings = [].concat(collisionWarnings, dupeMap[name].map(collisionsPathMapFn));
                    collisionWarnings.forEach(warnFn);

                    // if an internal definition is involved in the collision,
                    // then we should fail to prevent it from being overwritten
                    dupeMap[name].forEach(internalDefCheck);
                }
            }
        }
    });

    // discover all tsd files in dependencies directories and move them to api directory
    gulp.task(copyTaskname, [discoverInternalTaskname, discoverExternalTaskname, detectCollisionsTaskname], function() {
        // ensure the api directory exists
        mkdirp.sync(defaults.path.api);

        // flatten and copy to api directory
        return gulp.src(externalTsdSrc)
            .pipe(flatten())
            .pipe(gulp.dest(defaults.path.api));
    });

    // generate a gitignore for the api directory
    gulp.task(gitignoreTaskname, [discoverInternalTaskname, discoverExternalTaskname, copyTaskname], function() {
        // use the list of external definitions to generate the .gitignore
        var apiGitignore = externalDefs.map(function(def) { return def.name; }).join('\n');
        fs.writeFile(path.join(defaults.path.api, '.gitignore'), apiGitignore);

        // check the project .gitignore to ensure it ignores this generated .gitignore
        var isIgnored = false;
        var target = path.join(defaults.path.api, '.gitignore').replace('./', '');
        var ignored = getIgnoredFiles(defaults.path.root);
        ignored.forEach(function(file) {
            if (file === target) {
                isIgnored = true;
                return false;
            }
        });

        if (!isIgnored) {
            var gitignoreWarning = 'Warning: we recommend adding `' + target + '` to this project\'s gitignore';
            gutil.log(gutil.colors.yellow(gitignoreWarning));
        }
    });

    gulp.task(taskname, [
        discoverInternalTaskname,
        discoverExternalTaskname,
        detectCollisionsTaskname,
        copyTaskname,
        gitignoreTaskname
    ]);
};
<commit_msg>Fixing require typo<commit_after>module.exports = function(gulp, defaults, subtasks) {

    var taskname = 'tsd';

    gulp.desc(taskname, 'Discover and centralize TypeScript definition files');

    var _ = require('lodash');
    var flatten = require('gulp-flatten');
    var fs = require('fs');
    var gutil = require('gulp-util');
    var mkdirp = require('mkdirp');
    var path = require('path');
    var join = path.join;
    var tap = require('gulp-tap');

    var discoverInternalTaskname = taskname + ':discover:internal';
    var discoverExternalTaskname = taskname + ':discover:external';
    var detectCollisionsTaskname = taskname + ':detectCollisions';
    var copyTaskname = taskname + ':copy';
    var gitignoreTaskname = taskname + ':gitignore';

    var deps = [].concat(defaults.path.dependencies);
    var externalTsdSrc = deps.map(function(dir) {
        return join(dir, defaults.glob.tsd);
    });
    var internalTsdSrc = defaults.path.api + defaults.glob.tsd;

    var internalDefs = [];
    var externalDefs = [];

    function getIgnoredFiles(cwd) {
        try {
            var gitignoreData = fs.readFileSync(path.join(cwd, '.gitignore'), {encoding: 'utf8'});
            return gitignoreData.split('\n');
        } catch (e) {
            return [];
        }
    }

    function getTSDInstalledFiles(root) {
        try {
            var tsdData = fs.readFileSync(path.join(root, 'tsd.json'), {encoding: 'utf8'});
            return Object.keys(JSON.parse(tsdData).installed);
        } catch (e) {
            return [];
        }
    }

    // survey the api directory and discover internal tsd files
    gulp.task(discoverInternalTaskname, function() {
        internalDefs = [];

        // get list of ignored files (ignored means external)
        var ignored = getIgnoredFiles(defaults.path.api);

        // discover internal tsd files in api directory
        return gulp.src(internalTsdSrc)
            .pipe(tap(function(file) {
                // it's internal if it's not ignored
                if (!_.contains(ignored, file.relative)) {
                    internalDefs.push({
                        name: path.basename(file.path),
                        path: file.path,
                        internal: true
                    });
                }
            }));
    });

    // survey the dependency directories and tsd.json to discover external tsd files
    gulp.task(discoverExternalTaskname, [discoverInternalTaskname], function() {
        externalDefs = [];

        // include all external definition files installed via the tsd package manager
        var tsdInstalled = getTSDInstalledFiles(defaults.path.root);
        tsdInstalled.forEach(function(file) {
            externalDefs.push({
                name: file,
                path: path.join(defaults.path.api, file),
                internal: false
            });
        });

        // discover external tsd files in dependency directories
        return gulp.src(externalTsdSrc)
            .pipe(tap(function(file) {
                externalDefs.push({
                    name: path.basename(file.path),
                    path: file.path,
                    internal: false
                });
            }));
    });

    // using the list of internal and external definitions, detect name collisions
    gulp.task(detectCollisionsTaskname, [discoverInternalTaskname, discoverExternalTaskname], function() {
        var dupeMap = {};
        [].concat(internalDefs, externalDefs).forEach(function(def) {
            if (!dupeMap[def.name]) {
                dupeMap[def.name] = [];
            }
            dupeMap[def.name].push(def);
        });

        var collisionsPathMapFn = function(def) {
            // map definition object to its path as a string
            return '\t' + def.path;
        };
        var warnFn = function(warning) {
            // log a gulp warning
            gutil.log(gutil.colors.yellow(warning));
        };
        var internalDefCheck = function(def) {
            // check if a definition is internal and throw if it is to prevent overwriting it
            if (def.internal) {
                gutil.log(gutil.colors.red('Error: The above collision would overwrite this TS definition:'));
                gutil.log(gutil.colors.red('\t' + def.path));
                process.exit(1);
            }
        };

        for (var name in dupeMap) {
            if (dupeMap.hasOwnProperty(name)) {
                if (dupeMap[name].length > 1) {
                    // collision!
                    var collisionWarnings = ['Warning: a collision occurred between the following TS definitions:'];
                    collisionWarnings = [].concat(collisionWarnings, dupeMap[name].map(collisionsPathMapFn));
                    collisionWarnings.forEach(warnFn);

                    // if an internal definition is involved in the collision,
                    // then we should fail to prevent it from being overwritten
                    dupeMap[name].forEach(internalDefCheck);
                }
            }
        }
    });

    // discover all tsd files in dependencies directories and move them to api directory
    gulp.task(copyTaskname, [discoverInternalTaskname, discoverExternalTaskname, detectCollisionsTaskname], function() {
        // ensure the api directory exists
        mkdirp.sync(defaults.path.api);

        // flatten and copy to api directory
        return gulp.src(externalTsdSrc)
            .pipe(flatten())
            .pipe(gulp.dest(defaults.path.api));
    });

    // generate a gitignore for the api directory
    gulp.task(gitignoreTaskname, [discoverInternalTaskname, discoverExternalTaskname, copyTaskname], function() {
        // use the list of external definitions to generate the .gitignore
        var apiGitignore = externalDefs.map(function(def) { return def.name; }).join('\n');
        fs.writeFile(path.join(defaults.path.api, '.gitignore'), apiGitignore);

        // check the project .gitignore to ensure it ignores this generated .gitignore
        var isIgnored = false;
        var target = path.join(defaults.path.api, '.gitignore').replace('./', '');
        var ignored = getIgnoredFiles(defaults.path.root);
        ignored.forEach(function(file) {
            if (file === target) {
                isIgnored = true;
                return false;
            }
        });

        if (!isIgnored) {
            var gitignoreWarning = 'Warning: we recommend adding `' + target + '` to this project\'s gitignore';
            gutil.log(gutil.colors.yellow(gitignoreWarning));
        }
    });

    gulp.task(taskname, [
        discoverInternalTaskname,
        discoverExternalTaskname,
        detectCollisionsTaskname,
        copyTaskname,
        gitignoreTaskname
    ]);
};
<|endoftext|>


<commit_before>// saved buffer

var saveFlowTimeout = null;
var wordcount = 0;
var score = 0;
var sv_time = 0;
var flowing = false;

function saveFlow() {
    var text = $('#playingfield').val();
    var chars = text.length;
    var words = getWordCount(text);
    var flow_time = getTime() - sv_time;
    //var flow_score = Math.round(words * flow_time / 1000);

    $('.tekstflyt').before("

" + text + "

");
    $('#playingfield').val("");

    wordcount += words;
    score += getScore(text, flow_time);

    $('#scoreboard').html("
Words: " + wordcount + " | Score: " + score + "
");

    updateFlowStatus();
    $("html, body").animate({ scrollTop: $('#playingfield').offset().top }, "slow");

    flowing = false;
}

// scores should be higher the longer the text is
// scores should be higher the longer the time is
// scores should be higher the higher the ratio of text to time is
function getScore(text, time) {
    var chars = text.length;
    var words = getWordCount(text);
    var wpm = (words / time) * 60;
    var score = words*5 + Math.round(chars * time * Math.pow(wpm / 40, 40 / wpm) / 10);
    return score;
}

function getWordCount(text) {
    if (text == "") {
        return 0;
    }

    s = text.replace(/(^\s*)|(\s*$)/gi,"");
    s = s.replace(/[ ]{2,}/gi," ");
    s = s.replace(/\n /,"\n");
    return s.split(' ').length;
}

updateFlowStatus = function() {
    var text = $('#playingfield').val();
    var chars = text.length;
    var words = getWordCount(text);
    var seconds = getElapsedSeconds();
    var wpm = Math.round(words / seconds * 60);
    $('.stats').html('
Words: ' + words + ' | WPM: ' + wpm + '

');
}

updateFlowState = function() {
    if (! flowing) {
        sv_time = getTime();
        flowing = true;
    }
    if (saveFlowTimeout) {
        window.clearTimeout(saveFlowTimeout);
    }

    updateFlowStatus();

    saveFlowTimeout = window.setTimeout(saveFlow, 1000);
}

function getTime() {
    return (new Date).getTime();
}

function getElapsedSeconds() {
    return (getTime() - sv_time) / 1000;
}

document.getElementById("playingfield").onkeyup = updateFlowState;

//function bind(sc, f) {
//    Mousetrap.bind(sc, function(e) {
//        if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; }
//        f();
//        status();
//    });
//}
//
//bind('ctrl+h', function() { left(); });
//bind('ctrl+l', function() { right(); });
//bind('ctrl+h', function() { left(); });
//bind('ctrl+l', function() { right(); });

//bind('alt+left', function() { left(); });
//bind('alt+right', function() { right(); });
//bind('alt+up', function() { commit(); });
//bind('alt+down', function() { scratch(); });

//bind('ctrl+s', function() { commit(); });
//bind('ctrl+space', function() { scratch(); });
<commit_msg>new scoring system<commit_after>// saved buffer

var saveFlowTimeout = null;
var wordcount = 0;
var score = 0;
var sv_time = 0;
var flowing = false;

function saveFlow() {
    var text = $('#playingfield').val();
    var chars = text.length;
    var words = getWordCount(text);
    var flow_time = getElapsedSeconds();
    //var flow_score = Math.round(words * flow_time / 1000);

    $('.tekstflyt').before("

" + text + "

");
    $('#playingfield').val("");

    wordcount += words;
    score += getScore(text, flow_time);

    $('#scoreboard').html("
Words: " + wordcount + " | Score: " + score + "
");

    updateFlowStatus();
    $("html, body").animate({ scrollTop: $('#playingfield').offset().top }, "slow");

    flowing = false;
}

// scores should be higher the longer the text is
// scores should be higher the longer the time is
// scores should be higher the higher the ratio of text to time is
function getScore(text, time) {
    var chars = text.length;
    var words = getWordCount(text);
    var wpm = (words / time) * 60;
    var score = Math.round(words*5*wpm/40);
    return score;
}

function getWordCount(text) {
    if (text == "") {
        return 0;
    }

    s = text.replace(/(^\s*)|(\s*$)/gi,"");
    s = s.replace(/[ ]{2,}/gi," ");
    s = s.replace(/\n /,"\n");
    return s.split(' ').length;
}

updateFlowStatus = function() {
    var text = $('#playingfield').val();
    var chars = text.length;
    var words = getWordCount(text);
    var seconds = getElapsedSeconds();
    var wpm = Math.round(words / seconds * 60);
    $('.stats').html('
Words: ' + words + ' (+' + words*5 + ' pts) | WPM: ' + wpm + ' (x' + (wpm / 40).toFixed(1) + ' bonus)

');
}

updateFlowState = function() {
    if (! flowing) {
        sv_time = getTime();
        flowing = true;
    }
    if (saveFlowTimeout) {
        window.clearTimeout(saveFlowTimeout);
    }

    updateFlowStatus();

    saveFlowTimeout = window.setTimeout(saveFlow, 1000);
}

function getTime() {
    return (new Date).getTime();
}

function getElapsedSeconds() {
    return (getTime() - sv_time) / 1000;
}

document.getElementById("playingfield").onkeyup = updateFlowState;

//function bind(sc, f) {
//    Mousetrap.bind(sc, function(e) {
//        if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; }
//        f();
//        status();
//    });
//}
//
//bind('ctrl+h', function() { left(); });
//bind('ctrl+l', function() { right(); });
//bind('ctrl+h', function() { left(); });
//bind('ctrl+l', function() { right(); });

//bind('alt+left', function() { left(); });
//bind('alt+right', function() { right(); });
//bind('alt+up', function() { commit(); });
//bind('alt+down', function() { scratch(); });

//bind('ctrl+s', function() { commit(); });
//bind('ctrl+space', function() { scratch(); });
<|endoftext|>


<commit_before>var express = require('express'),
	router = express.Router(),
	net = require('net'),
	fs = require('fs'),
	socketPath = '/tmp/haproxy';

/* GET home page. */
router.post('/', function(req, res) {
	// console.log(req.body);
	// you can get commit information from request body

	var client = net.createConnection(socketPath);

	client.on('connect', function () {
		winston.debug('check connection');

		client.write('show health');

		client.on('data', function (data) {
			winston.debug('DATA: '+data);
		});
	});

	/*
	fs.stat(socketPath, function (err) {
		if (!err) {
			fs.unlinkSync(socketPath);
			return;
		}

		var unixServer = net.createServer(function (sock) {
			sock.write('show health');

			sock.on('data', function (data) {
				winston.debug('DATA: '+data);
				sock.destroy();
			});

		}).listen(socketPath);
	});
	*/

	res.send('complete');
});

module.exports = router;
<commit_msg>Check write method result<commit_after>var express = require('express'),
	router = express.Router(),
	net = require('net'),
	fs = require('fs'),
	socketPath = '/tmp/haproxy';

/* GET home page. */
router.post('/', function(req, res) {
	// console.log(req.body);
	// you can get commit information from request body

	var client = net.createConnection(socketPath);

	client.on('connect', function () {
		console.debug('check connection');

		var writeResult = client.write('show health');

		console.log(writeResult);

		client.on('data', function (data) {
			console.debug('DATA: '+data);
		});
	});

	/*
	fs.stat(socketPath, function (err) {
		if (!err) {
			fs.unlinkSync(socketPath);
			return;
		}

		var unixServer = net.createServer(function (sock) {
			sock.write('show health');

			sock.on('data', function (data) {
				winston.debug('DATA: '+data);
				sock.destroy();
			});

		}).listen(socketPath);
	});
	*/

	res.send('complete');
});

module.exports = router;
<|endoftext|>


<commit_before>// @flow
import * as React from 'react'
import {connect} from 'react-redux'

import {selectors} from '../labware-ingred/reducers'
import {
  openIngredientSelector,

  createContainer,
  deleteContainer,
  modifyContainer,

  openLabwareSelector,
  closeLabwareSelector,

  setCopyLabwareMode,
  copyLabware
} from '../labware-ingred/actions'
import {selectors as steplistSelectors} from '../steplist'

import {LabwareOnDeck} from '../components/labware'
import type {BaseState} from '../types'
import type {DeckSlot} from '@opentrons/components'

type OwnProps = {
  slot: DeckSlot
}

type Props = React.ElementProps<typeof LabwareOnDeck>

type DispatchProps = {
  createContainer: mixed,
  deleteContainer: mixed,
  modifyContainer: mixed,

  openIngredientSelector: mixed,
  openLabwareSelector: mixed,

  closeLabwareSelector: mixed,

  setCopyLabwareMode: mixed,
  copyLabware: mixed
}

type StateProps = $Diff<Props, DispatchProps>

function mapStateToProps (state: BaseState, ownProps: OwnProps): StateProps {
  const {slot} = ownProps
  const container = selectors.containersBySlot(state)[ownProps.slot]
  const labwareNames = selectors.getLabwareNames(state)
  const containerInfo = (container)
    ? {containerType: container.type, containerId: container.id, containerName: labwareNames[container.id]}
    : {}

  const selectedContainer = selectors.getSelectedContainer(state)
  const isSelectedSlot = !!(selectedContainer && selectedContainer.slot === slot)

  const deckSetupMode = steplistSelectors.deckSetupMode(state)
  return {
    ...containerInfo,
    slot,
    showNameOverlay: (container && !selectors.getSavedLabware(state)[container.id]),
    canAdd: selectors.canAdd(state),
    activeModals: selectors.activeModals(state),
    labwareToCopy: selectors.labwareToCopy(state),
    highlighted: (deckSetupMode)
      // in deckSetupMode, labware is highlighted when selected (currently editing ingredients)
      // or when targeted by an open "Add Labware" modal
      ? (isSelectedSlot || selectors.canAdd(state) === slot)
      // outside of deckSetupMode, labware is highlighted when step/substep is hovered
      : steplistSelectors.hoveredStepLabware(state).includes(container && container.id),
    deckSetupMode
  }
}

const dispatchObj = {
  createContainer,
  deleteContainer,
  modifyContainer,

  openIngredientSelector,
  openLabwareSelector,

  closeLabwareSelector,

  setCopyLabwareMode,
  copyLabware
}

export default connect(mapStateToProps, dispatchObj)(LabwareOnDeck)
<commit_msg>feat(protocol-designer): remove name labware prompt for tipracks (#1853)<commit_after>// @flow
import * as React from 'react'
import {connect} from 'react-redux'

import {getLabware} from '@opentrons/shared-data'
import {selectors} from '../labware-ingred/reducers'
import {
  openIngredientSelector,

  createContainer,
  deleteContainer,
  modifyContainer,

  openLabwareSelector,
  closeLabwareSelector,

  setCopyLabwareMode,
  copyLabware
} from '../labware-ingred/actions'
import {selectors as steplistSelectors} from '../steplist'

import {LabwareOnDeck} from '../components/labware'
import type {BaseState} from '../types'
import type {DeckSlot} from '@opentrons/components'

type OwnProps = {
  slot: DeckSlot
}

type Props = React.ElementProps<typeof LabwareOnDeck>

type DispatchProps = {
  createContainer: mixed,
  deleteContainer: mixed,
  modifyContainer: mixed,

  openIngredientSelector: mixed,
  openLabwareSelector: mixed,

  closeLabwareSelector: mixed,

  setCopyLabwareMode: mixed,
  copyLabware: mixed
}

type StateProps = $Diff<Props, DispatchProps>

function mapStateToProps (state: BaseState, ownProps: OwnProps): StateProps {
  const {slot} = ownProps
  const container = selectors.containersBySlot(state)[ownProps.slot]
  const labwareNames = selectors.getLabwareNames(state)
  const containerInfo = (container)
    ? {containerType: container.type, containerId: container.id, containerName: labwareNames[container.id]}
    : {}

  const selectedContainer = selectors.getSelectedContainer(state)
  const isSelectedSlot = !!(selectedContainer && selectedContainer.slot === slot)

  const deckSetupMode = steplistSelectors.deckSetupMode(state)
  const labwareHasName = container && selectors.getSavedLabware(state)[container.id]
  const labwareData = container && getLabware(container.type)
  // TODO: Ian 2018-07-10 use shared-data accessor
  const isTiprack = labwareData && labwareData.metadata.isTiprack

  return {
    ...containerInfo,
    slot,
    showNameOverlay: container && !isTiprack && !labwareHasName,
    canAdd: selectors.canAdd(state),
    activeModals: selectors.activeModals(state),
    labwareToCopy: selectors.labwareToCopy(state),
    highlighted: (deckSetupMode)
      // in deckSetupMode, labware is highlighted when selected (currently editing ingredients)
      // or when targeted by an open "Add Labware" modal
      ? (isSelectedSlot || selectors.canAdd(state) === slot)
      // outside of deckSetupMode, labware is highlighted when step/substep is hovered
      : steplistSelectors.hoveredStepLabware(state).includes(container && container.id),
    deckSetupMode
  }
}

const dispatchObj = {
  createContainer,
  deleteContainer,
  modifyContainer,

  openIngredientSelector,
  openLabwareSelector,

  closeLabwareSelector,

  setCopyLabwareMode,
  copyLabware
}

export default connect(mapStateToProps, dispatchObj)(LabwareOnDeck)
<|endoftext|>


<commit_before>'use strict';

angular
    .module('app')
    .controller('rgiNewRefDialogCtrl', function (
        $q,
        $scope,
        $rootScope,
        $route,
        $timeout,
        $http,
        ngDialog,
        rgiDialogFactory,
        rgiNotifier,
        FileUploader,
        rgiUtilsSrvc,
        rgiFileUploaderSrvc,
        rgiRequestSubmitterSrvc,
        //rgiUrlCheckSrvc,
        rgiAnswerMethodSrvc,
        rgiAssessmentSrvc,
        rgiIntervieweeSrvc,
        rgiIntervieweeMethodSrvc
    ) {
        /////////////
        //INTERVIEWEE
        /////////////
        $scope.role_opts = [
            {text: 'Government', value: 'government'},
            {text: 'CSO', value: 'cso'},
            {text: 'Industry', value: 'industry'},
            {text: 'Expert', value: 'expert'},
            {text: 'Other', value: 'other'}];
        $scope.salutation_opts = ['mr.', 'mrs.', 'ms.'];
        //Datepicker opts
        var today = new Date();
        $scope.date_default = today;
        $scope.date_max_limit = today;
        $scope.date_options = {
            formatYear: 'yy',
            startingDay: 1
        };
        $scope.date_formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
        $scope.date_format = $scope.date_formats[0];
        $scope.status = {
            opened: false
        };
        $scope.calendarOpen = function () {
            $scope.status.opened = true;
        };

        $scope.answer_update = $scope.$parent.answer;
        $scope.interviewee_list = [];
        //rgiIntervieweeSrvc.get({assessment_ID: 'DZ-2015-PI'}, function (interviewees) {
        rgiIntervieweeSrvc.query({}, function (interviewees) {
            interviewees.forEach(function (interviewee) {
                var interviewee_add = {
                    firstName: interviewee.firstName,
                    lastName: interviewee.lastName,
                    id: interviewee._id,
                    assessments: interviewee.assessments,
                    email: interviewee.email,
                    assessment_countries: []
                };
                interviewee.assessments.forEach(function (assessment_ID) {
                    rgiAssessmentSrvc.get({assessment_ID: assessment_ID}, function (assessment) {
                        interviewee_add.assessment_countries.push(assessment.country);
                    });
                });
                $scope.interviewee_list.push(interviewee_add);
            });
        });

        $scope.intervieweeSelect = function (selection) {
            $scope.interviewee_selection = selection;
        };

        $scope.interviewRefSubmit = function (selected_interviewee) {
            var new_answer_data, contact_date, email_domain, new_ref_data, current_user, selected_interviewee_ID;
            new_answer_data = $scope.answer_update;
            current_user = $scope.current_user;
            //error handling
            if (!new_answer_data.human_ref_comment) {
                rgiNotifier.error('You must enter interview content!');
            } else if (!new_answer_data.human_ref_contact_date) {
                rgiNotifier.error('You must enter interview date!');
            } else if (!selected_interviewee) {
                rgiNotifier.error('You must select an existing contact or create a new one!');
            } else {
                contact_date = new Date(new_answer_data.human_ref_contact_date).toISOString();

                if ($scope.interviewee_selection==='new') {
                    if (!selected_interviewee.firstName || !selected_interviewee.lastName) {
                        rgiNotifier.error('You must enter a first and last name for new interviewees!');
                    } else if (!selected_interviewee.role) {
                        rgiNotifier.error('You must select a role for new interviewees!');
                    } else if (!selected_interviewee.title) {
                        rgiNotifier.error('You must enter a position for new interviewees!');
                    } else if (!selected_interviewee.organization) {
                        rgiNotifier.error('You must enter an organization for new interviewees!');
                    } else {
                        if (!selected_interviewee.email) {
                            rgiNotifier.error('You must enter a valid email address!');
                        } else {
                            email_domain = 'http://' + selected_interviewee.email.split('@')[1];
                            if (email_domain === 'http://undefined') {
                                rgiNotifier.error('You must enter a valid email address!');
                            } else {
                                selected_interviewee.answers = [new_answer_data.answer_ID];
                                selected_interviewee.assessments = [new_answer_data.assessment_ID];
                                selected_interviewee.questions = [new_answer_data.question_ID];
                                selected_interviewee.users = [current_user._id];
                                rgiIntervieweeMethodSrvc.createInterviewee(selected_interviewee)
                                    .then(function (interviewee) {
                                        new_ref_data = {
                                            citation_type: 'interview',
                                            interviewee_ID: interviewee._id,
                                            contact_date: contact_date,
                                            comment: new_answer_data.human_ref_comment,
                                            author: current_user._id
                                        };
                                        new_answer_data.references.push(new_ref_data);
                                        rgiAnswerMethodSrvc.updateAnswer(new_answer_data);
                                    })
                                    .then(function () {
                                        $scope.closeThisDialog();
                                        rgiNotifier.notify('Reference added');
                                        $route.reload();
                                    }, function (reason) {
                                        rgiNotifier.notify(reason);
                                    });
                            }
                        }
                    }
                } else if ($scope.interviewee_selection==='existing') {
                    selected_interviewee_ID = selected_interviewee.originalObject.id;
                    new_ref_data = {
                        citation_type: 'interview',
                        interviewee_ID: selected_interviewee_ID,
                        contact_date: contact_date,
                        comment: new_answer_data.human_ref_comment,
                        author: current_user._id
                    };
                    new_answer_data.references.push(new_ref_data);

                    rgiIntervieweeSrvc.get({_id: selected_interviewee_ID}, function (interviewee) {
                        ['answer', 'assessment', 'question'].forEach(function (el) {
                            if (interviewee[el+'s'] !== undefined && interviewee[el+'s'].indexOf(new_answer_data[el+'_ID']) < 0) {
                                interviewee[el+'s'].push(new_answer_data[el+'_ID']);
                            } else if (interviewee[el+'s'] === undefined) {
                                interviewee[el+'s'] = [new_answer_data[el+'_ID']];
                            }
                        });
                        if (interviewee.users !== undefined && interviewee.users.indexOf(current_user._id) < 0) {
                            interviewee.users.push(current_user._id);
                        } else if (interviewee.users === undefined) {
                            interviewee.users = [current_user._id];
                        }
                        rgiAnswerMethodSrvc.updateAnswer(new_answer_data).then(function () {
                            rgiIntervieweeMethodSrvc.updateInterviewee(interviewee);
                            $scope.closeThisDialog();
                            rgiNotifier.notify('Reference added!');
                            $route.reload();
                        }, function (reason) {
                            rgiNotifier.error(reason);
                        });
                    });
                } else {
                    rgiNotifier.error('Something happened assigning interviewees!');
                }
            }
        };

        $scope.closeDialog = function () {
            ngDialog.close();
            $rootScope.$broadcast('RESET_SELECTED_REFERENCE_ACTION');
        };

        ///////////////
        //FILE UPLOAD
        ///////////////
        //$scope.fileUrl = '';
        $scope.fileUploading = false;
        $scope.answer_update = $scope.$parent.answer;
        var uploader = $scope.uploader = rgiFileUploaderSrvc.get({
            isHTML5: true,
            withCredentials: true,
            url: 'file-upload'
        });
        uploader.filters.push({
            name: 'customFilter',
            //fn: function () {
            fn: function () {
                return this.queue.length < 1;
            }
        });
        ////TODO handle doc and txt documents
        uploader.onCompleteItem = function (fileItem, response, status) {
            $scope.uploader.queue = [];
            if (status === 400) {
                rgiNotifier.error(response.reason);
            } else {// TODO add cancel upload after initial document pass
                $scope.new_document = response;
                $scope.value = true;
                var scope = $scope.$parent;
                scope.new_document = $scope.new_document;
                //rgiDialogFactory[scope.ref_selection + 'Create']($scope);
                if (scope.ref_selection === 'document') {
                    rgiDialogFactory.documentCreate(scope);
                } else if (scope.ref_selection === 'webpage') {
                    rgiDialogFactory.webpageCreate(scope);
                }
            }
        };
        $scope.uploadFileByUrl = function (fileUrl) {
            var handleFileUploadStatus = function (responseStatus) {
                $scope.uploader.queue[$scope.uploader.queue.length - 1].progress = responseStatus.data.completion * 100;

                if (responseStatus.data.completion < 1) {
                    $timeout(function () {
                        rgiRequestSubmitterSrvc.get('/api/remote-file/upload-progress/' + responseStatus.data._id).then(handleFileUploadStatus);
                    }, 1000);
                } else {
                    rgiRequestSubmitterSrvc.get('/api/remote-file/document/' + responseStatus.data._id).then(function (responseDocument) {
                        $scope.fileUploading = false;
                        uploader.onCompleteItem({}, responseDocument.data, responseDocument.status);
                    });
                }
            };

            $scope.fileUploading = true;

            rgiRequestSubmitterSrvc.get('/api/remote-file-upload?url=' + encodeURIComponent(fileUrl)).then(function (response) {
                if (response.data.reason) {
                    $scope.fileUploading = false;
                    rgiNotifier.error('The file cannot be uploaded');
                } else {
                    $scope.uploader.queue.push({
                        file: {
                            name: fileUrl.split('/')[fileUrl.split('/').length - 1],
                            size: response.data.size
                        },
                        isUploading: true,
                        progress: response.data.completion * 100
                    });
                    handleFileUploadStatus(response);
                }
            });
        };
    });<commit_msg>added error catching for remote urls that dont have pdf extension<commit_after>'use strict';

angular
    .module('app')
    .controller('rgiNewRefDialogCtrl', function (
        $q,
        $scope,
        $rootScope,
        $route,
        $timeout,
        $http,
        ngDialog,
        rgiDialogFactory,
        rgiNotifier,
        FileUploader,
        rgiUtilsSrvc,
        rgiFileUploaderSrvc,
        rgiRequestSubmitterSrvc,
        //rgiUrlCheckSrvc,
        rgiAnswerMethodSrvc,
        rgiAssessmentSrvc,
        rgiIntervieweeSrvc,
        rgiIntervieweeMethodSrvc
    ) {
        /////////////
        //INTERVIEWEE
        /////////////
        $scope.role_opts = [
            {text: 'Government', value: 'government'},
            {text: 'CSO', value: 'cso'},
            {text: 'Industry', value: 'industry'},
            {text: 'Expert', value: 'expert'},
            {text: 'Other', value: 'other'}];
        $scope.salutation_opts = ['mr.', 'mrs.', 'ms.'];
        //Datepicker opts
        var today = new Date();
        $scope.date_default = today;
        $scope.date_max_limit = today;
        $scope.date_options = {
            formatYear: 'yy',
            startingDay: 1
        };
        $scope.date_formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
        $scope.date_format = $scope.date_formats[0];
        $scope.status = {
            opened: false
        };
        $scope.calendarOpen = function () {
            $scope.status.opened = true;
        };

        $scope.answer_update = $scope.$parent.answer;
        $scope.interviewee_list = [];
        //rgiIntervieweeSrvc.get({assessment_ID: 'DZ-2015-PI'}, function (interviewees) {
        rgiIntervieweeSrvc.query({}, function (interviewees) {
            interviewees.forEach(function (interviewee) {
                var interviewee_add = {
                    firstName: interviewee.firstName,
                    lastName: interviewee.lastName,
                    id: interviewee._id,
                    assessments: interviewee.assessments,
                    email: interviewee.email,
                    assessment_countries: []
                };
                interviewee.assessments.forEach(function (assessment_ID) {
                    rgiAssessmentSrvc.get({assessment_ID: assessment_ID}, function (assessment) {
                        interviewee_add.assessment_countries.push(assessment.country);
                    });
                });
                $scope.interviewee_list.push(interviewee_add);
            });
        });

        $scope.intervieweeSelect = function (selection) {
            $scope.interviewee_selection = selection;
        };

        $scope.interviewRefSubmit = function (selected_interviewee) {
            var new_answer_data, contact_date, email_domain, new_ref_data, current_user, selected_interviewee_ID;
            new_answer_data = $scope.answer_update;
            current_user = $scope.current_user;
            //error handling
            if (!new_answer_data.human_ref_comment) {
                rgiNotifier.error('You must enter interview content!');
            } else if (!new_answer_data.human_ref_contact_date) {
                rgiNotifier.error('You must enter interview date!');
            } else if (!selected_interviewee) {
                rgiNotifier.error('You must select an existing contact or create a new one!');
            } else {
                contact_date = new Date(new_answer_data.human_ref_contact_date).toISOString();

                if ($scope.interviewee_selection==='new') {
                    if (!selected_interviewee.firstName || !selected_interviewee.lastName) {
                        rgiNotifier.error('You must enter a first and last name for new interviewees!');
                    } else if (!selected_interviewee.role) {
                        rgiNotifier.error('You must select a role for new interviewees!');
                    } else if (!selected_interviewee.title) {
                        rgiNotifier.error('You must enter a position for new interviewees!');
                    } else if (!selected_interviewee.organization) {
                        rgiNotifier.error('You must enter an organization for new interviewees!');
                    } else {
                        if (!selected_interviewee.email) {
                            rgiNotifier.error('You must enter a valid email address!');
                        } else {
                            email_domain = 'http://' + selected_interviewee.email.split('@')[1];
                            if (email_domain === 'http://undefined') {
                                rgiNotifier.error('You must enter a valid email address!');
                            } else {
                                selected_interviewee.answers = [new_answer_data.answer_ID];
                                selected_interviewee.assessments = [new_answer_data.assessment_ID];
                                selected_interviewee.questions = [new_answer_data.question_ID];
                                selected_interviewee.users = [current_user._id];
                                rgiIntervieweeMethodSrvc.createInterviewee(selected_interviewee)
                                    .then(function (interviewee) {
                                        new_ref_data = {
                                            citation_type: 'interview',
                                            interviewee_ID: interviewee._id,
                                            contact_date: contact_date,
                                            comment: new_answer_data.human_ref_comment,
                                            author: current_user._id
                                        };
                                        new_answer_data.references.push(new_ref_data);
                                        rgiAnswerMethodSrvc.updateAnswer(new_answer_data);
                                    })
                                    .then(function () {
                                        $scope.closeThisDialog();
                                        rgiNotifier.notify('Reference added');
                                        $route.reload();
                                    }, function (reason) {
                                        rgiNotifier.notify(reason);
                                    });
                            }
                        }
                    }
                } else if ($scope.interviewee_selection==='existing') {
                    selected_interviewee_ID = selected_interviewee.originalObject.id;
                    new_ref_data = {
                        citation_type: 'interview',
                        interviewee_ID: selected_interviewee_ID,
                        contact_date: contact_date,
                        comment: new_answer_data.human_ref_comment,
                        author: current_user._id
                    };
                    new_answer_data.references.push(new_ref_data);

                    rgiIntervieweeSrvc.get({_id: selected_interviewee_ID}, function (interviewee) {
                        ['answer', 'assessment', 'question'].forEach(function (el) {
                            if (interviewee[el+'s'] !== undefined && interviewee[el+'s'].indexOf(new_answer_data[el+'_ID']) < 0) {
                                interviewee[el+'s'].push(new_answer_data[el+'_ID']);
                            } else if (interviewee[el+'s'] === undefined) {
                                interviewee[el+'s'] = [new_answer_data[el+'_ID']];
                            }
                        });
                        if (interviewee.users !== undefined && interviewee.users.indexOf(current_user._id) < 0) {
                            interviewee.users.push(current_user._id);
                        } else if (interviewee.users === undefined) {
                            interviewee.users = [current_user._id];
                        }
                        rgiAnswerMethodSrvc.updateAnswer(new_answer_data).then(function () {
                            rgiIntervieweeMethodSrvc.updateInterviewee(interviewee);
                            $scope.closeThisDialog();
                            rgiNotifier.notify('Reference added!');
                            $route.reload();
                        }, function (reason) {
                            rgiNotifier.error(reason);
                        });
                    });
                } else {
                    rgiNotifier.error('Something happened assigning interviewees!');
                }
            }
        };

        $scope.closeDialog = function () {
            ngDialog.close();
            $rootScope.$broadcast('RESET_SELECTED_REFERENCE_ACTION');
        };

        ///////////////
        //FILE UPLOAD
        ///////////////
        //$scope.fileUrl = '';
        $scope.fileUploading = false;
        $scope.answer_update = $scope.$parent.answer;
        var uploader = $scope.uploader = rgiFileUploaderSrvc.get({
            isHTML5: true,
            withCredentials: true,
            url: 'file-upload'
        });
        uploader.filters.push({
            name: 'customFilter',
            //fn: function () {
            fn: function () {
                return this.queue.length < 1;
            }
        });
        ////TODO handle doc and txt documents
        uploader.onCompleteItem = function (fileItem, response, status) {
            $scope.uploader.queue = [];
            if (status === 400) {
                rgiNotifier.error(response.reason);
            } else {// TODO add cancel upload after initial document pass
                $scope.new_document = response;
                $scope.value = true;
                var scope = $scope.$parent;
                scope.new_document = $scope.new_document;
                //rgiDialogFactory[scope.ref_selection + 'Create']($scope);
                if (scope.ref_selection === 'document') {
                    rgiDialogFactory.documentCreate(scope);
                } else if (scope.ref_selection === 'webpage') {
                    rgiDialogFactory.webpageCreate(scope);
                }
            }
        };
        $scope.uploadFileByUrl = function (fileUrl) {
            var handleFileUploadStatus = function (responseStatus) {
                $scope.uploader.queue[$scope.uploader.queue.length - 1].progress = responseStatus.data.completion * 100;

                if (responseStatus.data.completion < 1) {
                    $timeout(function () {
                        rgiRequestSubmitterSrvc.get('/api/remote-file/upload-progress/' + responseStatus.data._id).then(handleFileUploadStatus);
                    }, 1000);
                } else {
                    rgiRequestSubmitterSrvc.get('/api/remote-file/document/' + responseStatus.data._id).then(function (responseDocument) {
                        $scope.fileUploading = false;
                        uploader.onCompleteItem({}, responseDocument.data, responseDocument.status);
                    });
                }
            };

            $scope.fileUploading = true;

            if (fileUrl.split('.')[fileUrl.split('.').length - 1].toLowerCase() !== 'pdf') {
                rgiNotifier.error('The URL does not point to a document!');
            } else {
                rgiRequestSubmitterSrvc.get('/api/remote-file-upload?url=' + encodeURIComponent(fileUrl)).then(function (response) {
                    if (response.data.reason) {
                        $scope.fileUploading = false;
                        rgiNotifier.error('The file cannot be uploaded');
                            } else {
                                $scope.uploader.queue.push({
                                    file: {
                                        name: fileUrl.split('/')[fileUrl.split('/').length - 1],
                                        size: response.data.size
                                    },
                                    isUploading: true,
                                    progress: response.data.completion * 100
                                });
                                handleFileUploadStatus(response);
                            }
                    });
            }

        };
    });<|endoftext|>


<commit_before>define([
    'jquery',
    'fancytree',
    'underscore',
    'backbone',
    'app',
    'collections/navigationtree/NavigationTreeCollection',
    'views/navigationtree/NavigationTreeView'
], function($, fancytree, _, Backbone, app, NavigationTreeCollection, NavigationTreeView) {

    var NavigationTreeView = Backbone.View.extend({

        initialize: function(options) {
            _.bindAll(this, 'render', 'convertToTree');

            if (typeof options.draggable !== typeof undefined) {
                this.draggable = options.draggable;
            } else {
                this.draggable = false;
            }

            this.collection = new NavigationTreeCollection();
            //this.listenTo(this.collection, 'reset', this.render);

            this.$el.attr('id', 'navigation-tree');
            this.$el.attr('class', 'ui list');
        },

        events: {

        },

        convertToTree: function(parent, children) {
            for (idx in children) {
                var child = children[idx];
                var folder = parseInt(child.node_type_id) === 3 ? false : true;
                var node = {
                    title: child.display_name,
                    key: child.descendant,
                    folder: folder,
                    expanded: true,
                    children: []
                };
                parent.children.push(node);
                this.convertToTree(node, child.children);
            }
        },

        render: function() {
            console.log('Rendering navigation tree for project ID [' + this.projectId + ']');
            var self = this;
            this.collection.setProjectId(this.projectId);
            this.collection.fetch({
                reset: true,
                success: function(results) {
                    var models = self.collection.models;
                    var model = null;
                    if (models.length > 0) {
                        model = models[0].toJSON();
                    }

                    tree = [];
                    var node = {
                        title: model.display_name,
                        key: model.descendant,
                        folder: true,
                        expanded: true,
                        children: []
                    };
                    self.convertToTree(node, model.children);
                    tree.push(node);
                    console.log(tree);

                    var data = {
                        project_id: self.projectId
                    };

                    // enable drag and drop
                    if (self.draggable) {
                        self.$el.fancytree({
                            source: tree,
                            extensions: ["dnd"],
                            activeVisible: true, // Make sure, active nodes are visible (expanded).
                            aria: false, // Enable WAI-ARIA support.
                            autoActivate: true, // Automatically activate a node when it is focused (using keys).
                            autoCollapse: false, // Automatically collapse all siblings, when a node is expanded.
                            autoScroll: false, // Automatically scroll nodes into visible area.
                            clickFolderMode: 1, // 1:activate, 2:expand, 3:activate and expand, 4:activate (dblclick expands)
                            checkbox: false, // Show checkboxes.
                            debugLevel: 1, // 0:quiet, 1:normal, 2:debug
                            disabled: false, // Disable control
                            generateIds: false, // Generate id attributes like
                            idPrefix: "ft_", // Used to generate node id´s like <span id='fancytree-id-<key>'>.
                            icon: true, // Display node icons.
                            keyboard: true, // Support keyboard navigation.
                            keyPathSeparator: "/", // Used by node.getKeyPath() and tree.loadKeyPath().
                            minExpandLevel: 2, // 1: root node is not collapsible
                            selectMode: 1, // 1:single, 2:multi, 3:multi-hier
                            tabindex: 0, // Whole tree behaves as one single control
                            childcounter: {
                                deep: true,
                                hideZeros: true,
                                hideExpanded: true
                            },
                            focus: function(e, data) {
                                var node = data.node;
                                // Auto-activate focused node after 1 second
                                if(node.data.href){
                                    node.scheduleAction("activate", 100000);
                                }
                            },
                            blur: function(e, data) {
                                data.node.scheduleAction("cancel");
                            },
                            activate: function(e, data) {
                                if (data.draggable)
                                    return; // prevent false hits
                                var node = data.node;
                                if(node.data.href){
                                    window.open(node.data.href, node.data.target);
                                }
                            },
                            click: function(e, data) { // allow re-loads
                                var node = data.node;
                                if(node.isActive() && node.data.href){
                                    // TODO: data.tree.reactivate();
                                }
                            },
                            dnd: {
                                preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
                                preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
                                autoExpandMS: 400,
                                dragStart: function(node, data) {
                                    // Defines whether this node is draggable or not
                                    // The top level project should have dnd disabled
                                    if (node.data.nodeType == 1) {
                                        return false;
                                    }
                                    return true;
                                },
                                dragStop: function(node, data) {

                                },
                                dragOver: function(node, data) {
                                },
                                dragEnter: function(node, data) {
                                    // Defines whether another node can be dragged on this node
                                    // Return ['before', 'after'] to restrict available hitModes.
                                    //  Any other return value will calc the hitMode from the cursor position.
                                    // Prevent dropping a parent below another parent (only sort
                                    // nodes under the same parent)
                                    // if(node.parent !== data.otherNode.parent){
                                    //   return false;
                                    // }
                                    // Don't allow dropping *over* a node (would create a child)
                                    // return ["before", "after"];

                                    var selectedNode = data.otherNode; // the selected node
                                    if (selectedNode.data.nodeType == 3) {
                                        // Test cases should not be dnd onto projects or test cases, only test suites
                                        if (node.data.nodeType != 2) {
                                            return false;
                                        }
                                        // Test cases should not be dnd onto its own parent
                                        if (node == selectedNode.parent) {
                                            return false;
                                        }
                                    }
                                    if (selectedNode.data.nodeType == 2) {
                                        // Test suites should not be dnd onto test cases
                                        if (node.data.nodeType == 3) {
                                            return false;
                                        }
                                        // Test suites should not be dnd onto its own parent
                                        if (node == selectedNode.parent) {
                                            return false;
                                        }
                                    }
                                    return "over";
                                },
                                dragDrop: function(node, data) {
                                    var selectedNode = data.otherNode; // the selected node
                                    var descendant = '' + selectedNode.data.nodeType + '-' + selectedNode.data.nodeId;
                                    var ancestor = '' + node.data.nodeType + '-' + node.data.nodeId;
                                    var url = '{{ URL.to("api/v1/nodes/move") }}';
                                    $.ajax({
                                      type: "POST",
                                      url: url,
                                      data: {descendant: descendant, ancestor: ancestor},
                                      success: function(jqXHR, textStatus, data) {
                                        selectedNode.moveTo(node, jqXHR.hitMode);
                                        var rootNode = node.tree.rootNode;
                                        rootNode.sortChildren(sortCmp, true);

                                        var $messagesHolder = jQuery("#messages-holder");
                                        $messagesHolder.empty();
                                        console.log($messagesHolder);
                                        $messagesHolder.append("
\
                                        <button type='button' class='close' data-dismiss='alert'>×</button>\

Node moved successfully!
\

");
                                      },
                                      error: function(jqXHR, textStatus, data) {
                                        var responseText = jQuery.parseJSON(jqXHR.responseText);

                                        //alert(responseText.error.message);
                                        var $messagesHolder = jQuery("#messages-holder");
                                        $messagesHolder.empty();
                                        console.log($messagesHolder);
                                        $messagesHolder.append("
\
                                        <button type='button' class='close' data-dismiss='alert'>×</button>\

"+responseText.error.message+"
\

");
                                      }
                                    });
                                },
                                dragLeave: function(node, data) {
                                }
                            }
                        });
                        console.log('drag...');
                    }
                },
                error: function(collection, response, options) {
                    throw new Error("Failed to fetch projects");
                }
            });
        }

    });

    return NavigationTreeView;

});<commit_msg>Add links to navigation tree<commit_after>define([
    'jquery',
    'fancytree',
    'underscore',
    'backbone',
    'app',
    'collections/navigationtree/NavigationTreeCollection',
    'views/navigationtree/NavigationTreeView'
], function($, fancytree, _, Backbone, app, NavigationTreeCollection, NavigationTreeView) {

    var NavigationTreeView = Backbone.View.extend({

        initialize: function(options) {
            _.bindAll(this, 'render', 'convertToTree', 'getNodeTitle');

            this.projectId = 0;

            if (typeof options !== typeof undefined && typeof options.draggable !== typeof undefined) {
                this.draggable = options.draggable;
            } else {
                this.draggable = false;
            }

            this.collection = new NavigationTreeCollection();
            //this.listenTo(this.collection, 'reset', this.render);

            this.$el.attr('id', 'navigation-tree');
            this.$el.attr('class', 'ui list');
        },

        events: {

        },

        getNodeTitle: function(node, parent) {
            var url = '/#/projects/' + this.projectId + '/testsuites/';
            if (parseInt(node.node_type_id) === 2) {
                url += node.node_id;
            } else {
                url += parent.node_id + '/testcases/' + node.node_id;
            }
            var title = "" + node.display_name + "";
            return title;
        },

        convertToTree: function(parent, children) {
            for (idx in children) {
                var child = children[idx];
                var folder = parseInt(child.node_type_id) === 3 ? false : true;
                var node = {
                    title: this.getNodeTitle(child, parent),
                    key: child.descendant,
                    folder: folder,
                    expanded: true,
                    children: [],
                    node_id: child.node_id,
                    node_type_id: child.node_type_id
                };
                parent.children.push(node);
                this.convertToTree(node, child.children);
            }
        },

        render: function() {
            console.log('Rendering navigation tree for project ID [' + this.projectId + ']');
            var self = this;
            this.collection.setProjectId(this.projectId);
            this.collection.fetch({
                reset: true,
                success: function(results) {
                    var models = self.collection.models;
                    var model = null;
                    if (models.length > 0) {
                        model = models[0].toJSON();
                    }

                    tree = [];
                    var node = {
                        title: '' + model.display_name + '',
                        key: model.descendant,
                        folder: true,
                        expanded: true,
                        children: [],
                        node_id: model.node_id,
                        node_type_id: model.node_type_id
                    };
                    self.convertToTree(node, model.children);
                    tree.push(node);

                    var data = {
                        project_id: self.projectId
                    };

                    // enable drag and drop
                    if (self.draggable) {
                        self.$el.fancytree({
                            source: tree,
                            extensions: ["dnd"],
                            activeVisible: true, // Make sure, active nodes are visible (expanded).
                            aria: false, // Enable WAI-ARIA support.
                            autoActivate: true, // Automatically activate a node when it is focused (using keys).
                            autoCollapse: false, // Automatically collapse all siblings, when a node is expanded.
                            autoScroll: false, // Automatically scroll nodes into visible area.
                            clickFolderMode: 1, // 1:activate, 2:expand, 3:activate and expand, 4:activate (dblclick expands)
                            checkbox: false, // Show checkboxes.
                            debugLevel: 1, // 0:quiet, 1:normal, 2:debug
                            disabled: false, // Disable control
                            generateIds: false, // Generate id attributes like
                            idPrefix: "ft_", // Used to generate node id´s like <span id='fancytree-id-<key>'>.
                            icon: true, // Display node icons.
                            keyboard: true, // Support keyboard navigation.
                            keyPathSeparator: "/", // Used by node.getKeyPath() and tree.loadKeyPath().
                            minExpandLevel: 2, // 1: root node is not collapsible
                            selectMode: 1, // 1:single, 2:multi, 3:multi-hier
                            tabindex: 0, // Whole tree behaves as one single control
                            childcounter: {
                                deep: true,
                                hideZeros: true,
                                hideExpanded: true
                            },
                            focus: function(e, data) {
                                var node = data.node;
                                // Auto-activate focused node after 1 second
                                if(node.data.href){
                                    node.scheduleAction("activate", 100000);
                                }
                            },
                            blur: function(e, data) {
                                data.node.scheduleAction("cancel");
                            },
                            activate: function(e, data) {
                                if (data.draggable)
                                    return; // prevent false hits
                                var node = data.node;
                                if(node.data.href){
                                    window.open(node.data.href, node.data.target);
                                }
                            },
                            click: function(e, data) { // allow re-loads
                                var node = data.node;
                                if(node.isActive() && node.data.href){
                                    // TODO: data.tree.reactivate();
                                }
                            },
                            dnd: {
                                preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
                                preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
                                autoExpandMS: 400,
                                dragStart: function(node, data) {
                                    // Defines whether this node is draggable or not
                                    // The top level project should have dnd disabled
                                    if (node.data.nodeType == 1) {
                                        return false;
                                    }
                                    return true;
                                },
                                dragStop: function(node, data) {

                                },
                                dragOver: function(node, data) {
                                },
                                dragEnter: function(node, data) {
                                    // Defines whether another node can be dragged on this node
                                    // Return ['before', 'after'] to restrict available hitModes.
                                    //  Any other return value will calc the hitMode from the cursor position.
                                    // Prevent dropping a parent below another parent (only sort
                                    // nodes under the same parent)
                                    // if(node.parent !== data.otherNode.parent){
                                    //   return false;
                                    // }
                                    // Don't allow dropping *over* a node (would create a child)
                                    // return ["before", "after"];

                                    var selectedNode = data.otherNode; // the selected node
                                    if (selectedNode.data.nodeType == 3) {
                                        // Test cases should not be dnd onto projects or test cases, only test suites
                                        if (node.data.nodeType != 2) {
                                            return false;
                                        }
                                        // Test cases should not be dnd onto its own parent
                                        if (node == selectedNode.parent) {
                                            return false;
                                        }
                                    }
                                    if (selectedNode.data.nodeType == 2) {
                                        // Test suites should not be dnd onto test cases
                                        if (node.data.nodeType == 3) {
                                            return false;
                                        }
                                        // Test suites should not be dnd onto its own parent
                                        if (node == selectedNode.parent) {
                                            return false;
                                        }
                                    }
                                    return "over";
                                },
                                dragDrop: function(node, data) {
                                    var selectedNode = data.otherNode; // the selected node
                                    var descendant = '' + selectedNode.data.nodeType + '-' + selectedNode.data.nodeId;
                                    var ancestor = '' + node.data.nodeType + '-' + node.data.nodeId;
                                    var url = '{{ URL.to("api/v1/nodes/move") }}';
                                    $.ajax({
                                      type: "POST",
                                      url: url,
                                      data: {descendant: descendant, ancestor: ancestor},
                                      success: function(jqXHR, textStatus, data) {
                                        selectedNode.moveTo(node, jqXHR.hitMode);
                                        var rootNode = node.tree.rootNode;
                                        rootNode.sortChildren(sortCmp, true);

                                        var $messagesHolder = jQuery("#messages-holder");
                                        $messagesHolder.empty();
                                        console.log($messagesHolder);
                                        $messagesHolder.append("
\
                                        <button type='button' class='close' data-dismiss='alert'>×</button>\

Node moved successfully!
\

");
                                      },
                                      error: function(jqXHR, textStatus, data) {
                                        var responseText = jQuery.parseJSON(jqXHR.responseText);

                                        //alert(responseText.error.message);
                                        var $messagesHolder = jQuery("#messages-holder");
                                        $messagesHolder.empty();
                                        console.log($messagesHolder);
                                        $messagesHolder.append("
\
                                        <button type='button' class='close' data-dismiss='alert'>×</button>\

"+responseText.error.message+"
\

");
                                      }
                                    });
                                },
                                dragLeave: function(node, data) {
                                }
                            }
                        });
                        console.log('drag...');
                    }
                },
                error: function(collection, response, options) {
                    throw new Error("Failed to fetch projects");
                }
            });
        }

    });

    return NavigationTreeView;

});<|endoftext|>