<commit_before>$( document ).ready(function() {

	// Countdown for question
    $("#countdown").countDown({
		startNumber: 4000,
		callBack: function() {
            if ($('#id_estimate').val() == "") {
                var input = $("<input>")
                    .attr("type", "hidden")
                    .attr("name", "time_out").val("true");
                $("form").append($(input));
            }

			$("form").submit();
		}
	});

    // Format the input content, that all 3 digits are separated
    $('#id_estimate').focus();
    $('#id_estimate').keyup(function() {
        var num = $(this).val().replace(/(\s)/g, '');
        $(this).val(num.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1 "));
    });
    // reformat input value before submitting
    $('#estimate_form').submit(function() {
        var value = $('#id_estimate').val().replace(/ /g, '');
        value = value.replace(/,/g, '.');

        if (!isNumber(value)) {
            $('#question-show form .errorlist').hide();
            $('#question-show form .errorlist.not-number').show().fadeOut(4000, 'swing');
            return false;
        }

        $('#id_estimate').val(value);
    });

    function isNumber(n) {
        return !isNaN(parseFloat(n)) && isFinite(n);
    }

    // Check if estimate is given, when submit button is clicked
    $('#question-show form input[type=submit]').click(function(e) {
        if ($('#id_estimate').val() == "") {
            e.preventDefault();
            $('#question-show form .errorlist').hide();
            $('#question-show form .errorlist.empty').show().fadeOut(4000, 'swing');
            $('#id_estimate').focus();
        }
    });

    // Click handler for 'Show resolution' Button
	$('#show_btn').click(function() {
		$(this).hide();
        $('.timed_out').fadeIn();
	});

	// Click handler for mobile navigation
    var navigation = $('.navigation-wrapper nav ul');
    var naviToggle = $('#naviToggle');
    $(naviToggle).click(function(e) {
    	e.preventDefault();
    	navigation.slideToggle(function(){
    		if(navigation.is(':hidden')) {
    			navigation.removeAttr('style');
    		}
    	});
    });

    // Click handler for Register/Login Accordion on Landing Page
    var accItem = $('#register-login .accordion li');
    $(accItem).click(function(e) {
        e.preventDefault();
        if ( $(this).hasClass('not-selected') ) {
            var rel = $(this).attr('rel');
            $(accItem).removeClass('selected').addClass('not-selected');
            $(this).removeClass('not-selected').addClass('selected');

            $('#register-login .form').hide();
            $('#'+rel).fadeIn();
        }
    });

    // Click handler for 'Password change' Button
    $('span.pw-change').click(function() {
        $(this).hide();
        $('div.pw-change').fadeIn();
    });

    // Click handler for Highscore change Button
    $('.highscore-change').click(function() {
        if (!$(this).hasClass('selected')) {
            $('.highscore-change.selected').toggleClass('selected');
            $(this).toggleClass('selected');
            var rel = $(this).attr('rel');
            $('.score-list table').hide();
            $('.score-list table.'+rel).fadeIn();
            //window.history.pushState("", rel, "#"+rel);
        }
    });

});
<commit_msg>Countdown angepasst<commit_after>$( document ).ready(function() {

	// Countdown for question
    $("#countdown").countDown({
		startNumber: 40,
		callBack: function() {
            if ($('#id_estimate').val() == "") {
                var input = $("<input>")
                    .attr("type", "hidden")
                    .attr("name", "time_out").val("true");
                $("form").append($(input));
            }

			$("form").submit();
		}
	});

    // Format the input content, that all 3 digits are separated
    $('#id_estimate').focus();
    $('#id_estimate').keyup(function() {
        var num = $(this).val().replace(/(\s)/g, '');
        $(this).val(num.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1 "));
    });
    // reformat input value before submitting
    $('#estimate_form').submit(function() {
        var value = $('#id_estimate').val().replace(/ /g, '');
        value = value.replace(/,/g, '.');

        if (!isNumber(value)) {
            $('#question-show form .errorlist').hide();
            $('#question-show form .errorlist.not-number').show().fadeOut(4000, 'swing');
            return false;
        }

        $('#id_estimate').val(value);
    });

    function isNumber(n) {
        return !isNaN(parseFloat(n)) && isFinite(n);
    }

    // Check if estimate is given, when submit button is clicked
    $('#question-show form input[type=submit]').click(function(e) {
        if ($('#id_estimate').val() == "") {
            e.preventDefault();
            $('#question-show form .errorlist').hide();
            $('#question-show form .errorlist.empty').show().fadeOut(4000, 'swing');
            $('#id_estimate').focus();
        }
    });

    // Click handler for 'Show resolution' Button
	$('#show_btn').click(function() {
		$(this).hide();
        $('.timed_out').fadeIn();
	});

	// Click handler for mobile navigation
    var navigation = $('.navigation-wrapper nav ul');
    var naviToggle = $('#naviToggle');
    $(naviToggle).click(function(e) {
    	e.preventDefault();
    	navigation.slideToggle(function(){
    		if(navigation.is(':hidden')) {
    			navigation.removeAttr('style');
    		}
    	});
    });

    // Click handler for Register/Login Accordion on Landing Page
    var accItem = $('#register-login .accordion li');
    $(accItem).click(function(e) {
        e.preventDefault();
        if ( $(this).hasClass('not-selected') ) {
            var rel = $(this).attr('rel');
            $(accItem).removeClass('selected').addClass('not-selected');
            $(this).removeClass('not-selected').addClass('selected');

            $('#register-login .form').hide();
            $('#'+rel).fadeIn();
        }
    });

    // Click handler for 'Password change' Button
    $('span.pw-change').click(function() {
        $(this).hide();
        $('div.pw-change').fadeIn();
    });

    // Click handler for Highscore change Button
    $('.highscore-change').click(function() {
        if (!$(this).hasClass('selected')) {
            $('.highscore-change.selected').toggleClass('selected');
            $(this).toggleClass('selected');
            var rel = $(this).attr('rel');
            $('.score-list table').hide();
            $('.score-list table.'+rel).fadeIn();
            //window.history.pushState("", rel, "#"+rel);
        }
    });

});
<|endoftext|>


<commit_before>/*
 * Spreed WebRTC.
 * Copyright (C) 2013-2014 struktur AG
 *
 * This file is part of Spreed WebRTC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
require.config({
	waitSeconds: 300,
	paths: {
		// Major libraries
		"text": "libs/require/text",
		"jquery": 'libs/jquery/jquery.min',
		"underscore": 'libs/lodash.min', // alternative to underscore
		"modernizr": 'libs/modernizr',
		'webrtc.adapter': 'libs/webrtc.adapter',
		'angular': 'libs/angular/angular.min',
		'ui-bootstrap': 'libs/angular/ui-bootstrap-tpls.min',
		'ua-parser': 'libs/ua-parser',
		'Howler': 'libs/howler.min',
		'desktop-notify': 'libs/desktop-notify',
		'bigscreen': 'libs/bigscreen.min',
		'moment': 'libs/moment.min',
		'angular-sanitize': 'libs/angular/angular-sanitize.min',
		'angular-animate': 'libs/angular/angular-animate.min',
		'angular-route': 'libs/angular/angular-route.min',
		'angular-humanize': 'modules/angular-humanize',
		'toastr': 'libs/toastr',
		'visibly': 'libs/visibly',
		'avltree': 'libs/avltree',
		'injectCSS': 'libs/jquery/jquery.injectCSS',
		'mobile-events': 'libs/jquery/jquery.mobile-events',
		'jed': 'libs/jed',
		'audiocontext': 'libs/audiocontext',
		'rAF': 'libs/rAF',
		'humanize': 'libs/humanize',
		'sha': 'libs/sha',
		'sjcl': 'libs/sjcl',

		'partials': '../partials',
		'sounds': '../sounds',
		'translation': '../translation'
	},
	shim: {
		'modernizr': {
			exports: 'Modernizr'
		},
		'underscore': {
			exports: '_'
		},
		'angular': {
			deps: ['jquery'],
			exports: 'angular'
		},
		'ui-bootstrap': {
			deps: ['angular']
		},
		'desktop-notify': {
			exports: 'notify'
		},
		'bigscreen': {
			exports: 'BigScreen'
		},
		'moment': {
			exports: 'moment'
		},
		'angular-sanitize': {
			deps: ['angular'],
			exports: 'angular'
		},
		'angular-animate': {
			deps: ['angular'],
			exports: 'angular'
		},
		'angular-humanize': {
			deps: ['angular', 'humanize'],
			exports: 'angular'
		},
		'toastr': {
			deps: ['jquery'],
			exports: 'toastr'
		},
		'visibly': {
			exports: 'visibly'
		},
		'avltree': {
			exports: 'AvlTree'
		},
		'injectCSS': {
			deps: ['jquery'],
			exports: '$'
		},
		'mobile-events': {
			deps: ['jquery'],
			exports: '$'
		},
		'sjcl': {
			exports: 'sjcl'
		}
	}
});

(function() {
	var debugDefault = window.location.href.match(/(\?|&)debug($|&|=)/);
	// Overwrite console to not log stuff per default.
	// Write debug(true) in console to enable or start with ?debug parameter.
	window.consoleBackup = null;
	window.debug = function(flag) {
		if (!flag) {
			if (window.consoleBackup === null) {
				window.consoleBackup = window.console;
			}
			window.console = {
				log: function() {},
				info: function() {},
				warn: function() {},
				error: function() {},
				debug: function() {},
				trace: function() {}
			}
		} else {
			if (window.consoleBackup) {
				window.console = window.consoleBackup;
			}
		}
	};
	window.debug(debugDefault && true);
}());

require.onError = (function() {
	var retrying = false;
	return function(err) {
		if (retrying) {
			console.error("Error while loading " + err.requireType, err.requireModules);
			return;
		}
		if (err.requireType === "timeout" || err.requireType === "scripterror") {
			alert('Failed to load application. Confirm to retry.');
			retrying = true;
			document.location.reload(true);
		} else {
			throw err;
		}
	};
}());

define([
	'jquery',
	'underscore',
	'angular',
	'require',
	'base'], function($, _, angular, require) {

	// Dynamic app loader with plugin support.
	var load = ['app'];
	_.each(document.getElementsByTagName('script'), function(script) {
		var dataPlugin = script.getAttribute('data-plugin');
		if (dataPlugin) {
			load.push(dataPlugin);
		}
	});
	require(load, function(App) {
		var args = Array.prototype.slice.call(arguments, 1);
		// Add Angular modules from plugins.
		var modules = [];
		_.each(args, function(plugin) {
			if (plugin && plugin.module) {
				plugin.module(modules);
			}
		});
		// External plugin support.
		var externalPlugin
		if (window.externalPlugin) {
			externalPlugin = window.externalPlugin($, _, angular);
			if (externalPlugin && externalPlugin.module) {
				externalPlugin.module(modules);
			}
		}
		// Init Angular app.
		var app = App.initialize(modules);
		// Init plugins.
		_.each(args, function(plugin) {
			if (plugin && plugin.initialize) {
				plugin.initialize(app);
			}
		});
		// Init external plugin.
		if (externalPlugin && externalPlugin.initialize) {
			externalPlugin.initialize(app);
		}
	});

});
<commit_msg>Added general ES5 compatibility check and refuse to start when no Object.create support is found.<commit_after>/*
 * Spreed WebRTC.
 * Copyright (C) 2013-2014 struktur AG
 *
 * This file is part of Spreed WebRTC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
require.config({
	waitSeconds: 300,
	paths: {
		// Major libraries
		"text": "libs/require/text",
		"jquery": 'libs/jquery/jquery.min',
		"underscore": 'libs/lodash.min', // alternative to underscore
		"modernizr": 'libs/modernizr',
		'webrtc.adapter': 'libs/webrtc.adapter',
		'angular': 'libs/angular/angular.min',
		'ui-bootstrap': 'libs/angular/ui-bootstrap-tpls.min',
		'ua-parser': 'libs/ua-parser',
		'Howler': 'libs/howler.min',
		'desktop-notify': 'libs/desktop-notify',
		'bigscreen': 'libs/bigscreen.min',
		'moment': 'libs/moment.min',
		'angular-sanitize': 'libs/angular/angular-sanitize.min',
		'angular-animate': 'libs/angular/angular-animate.min',
		'angular-route': 'libs/angular/angular-route.min',
		'angular-humanize': 'modules/angular-humanize',
		'toastr': 'libs/toastr',
		'visibly': 'libs/visibly',
		'avltree': 'libs/avltree',
		'injectCSS': 'libs/jquery/jquery.injectCSS',
		'mobile-events': 'libs/jquery/jquery.mobile-events',
		'jed': 'libs/jed',
		'audiocontext': 'libs/audiocontext',
		'rAF': 'libs/rAF',
		'humanize': 'libs/humanize',
		'sha': 'libs/sha',
		'sjcl': 'libs/sjcl',

		'partials': '../partials',
		'sounds': '../sounds',
		'translation': '../translation'
	},
	shim: {
		'modernizr': {
			exports: 'Modernizr'
		},
		'underscore': {
			exports: '_'
		},
		'angular': {
			deps: ['jquery'],
			exports: 'angular'
		},
		'ui-bootstrap': {
			deps: ['angular']
		},
		'desktop-notify': {
			exports: 'notify'
		},
		'bigscreen': {
			exports: 'BigScreen'
		},
		'moment': {
			exports: 'moment'
		},
		'angular-sanitize': {
			deps: ['angular'],
			exports: 'angular'
		},
		'angular-animate': {
			deps: ['angular'],
			exports: 'angular'
		},
		'angular-humanize': {
			deps: ['angular', 'humanize'],
			exports: 'angular'
		},
		'toastr': {
			deps: ['jquery'],
			exports: 'toastr'
		},
		'visibly': {
			exports: 'visibly'
		},
		'avltree': {
			exports: 'AvlTree'
		},
		'injectCSS': {
			deps: ['jquery'],
			exports: '$'
		},
		'mobile-events': {
			deps: ['jquery'],
			exports: '$'
		},
		'sjcl': {
			exports: 'sjcl'
		}
	}
});

(function() {
	var debugDefault = window.location.href.match(/(\?|&)debug($|&|=)/);
	// Overwrite console to not log stuff per default.
	// Write debug(true) in console to enable or start with ?debug parameter.
	window.consoleBackup = null;
	window.debug = function(flag) {
		if (!flag) {
			if (window.consoleBackup === null) {
				window.consoleBackup = window.console;
			}
			window.console = {
				log: function() {},
				info: function() {},
				warn: function() {},
				error: function() {},
				debug: function() {},
				trace: function() {}
			}
		} else {
			if (window.consoleBackup) {
				window.console = window.consoleBackup;
			}
		}
	};
	window.debug(debugDefault && true);
}());

require.onError = (function() {
	var retrying = false;
	return function(err) {
		if (retrying) {
			console.error("Error while loading " + err.requireType, err.requireModules);
			return;
		}
		if (err.requireType === "timeout" || err.requireType === "scripterror") {
			alert('Failed to load application. Confirm to retry.');
			retrying = true;
			document.location.reload(true);
		} else {
			throw err;
		}
	};
}());

// Make sure the browser knows ES5.
if (Object.create) {

	define([
		'jquery',
		'underscore',
		'angular',
		'require',
		'base'], function($, _, angular, require) {

		// Dynamic app loader with plugin support.
		var load = ['app'];
		_.each(document.getElementsByTagName('script'), function(script) {
			var dataPlugin = script.getAttribute('data-plugin');
			if (dataPlugin) {
				load.push(dataPlugin);
			}
		});
		require(load, function(App) {
			var args = Array.prototype.slice.call(arguments, 1);
			// Add Angular modules from plugins.
			var modules = [];
			_.each(args, function(plugin) {
				if (plugin && plugin.module) {
					plugin.module(modules);
				}
			});
			// External plugin support.
			var externalPlugin
			if (window.externalPlugin) {
				externalPlugin = window.externalPlugin($, _, angular);
				if (externalPlugin && externalPlugin.module) {
					externalPlugin.module(modules);
				}
			}
			// Init Angular app.
			var app = App.initialize(modules);
			// Init plugins.
			_.each(args, function(plugin) {
				if (plugin && plugin.initialize) {
					plugin.initialize(app);
				}
			});
			// Init external plugin.
			if (externalPlugin && externalPlugin.initialize) {
				externalPlugin.initialize(app);
			}
		});

	});

} else {
	alert("Your browser does not support this application. Please update your browser to the latest version.");
}<|endoftext|>


<commit_before>o2.addReady(function(){
    COMMON = {
        "setContentPath": function(path){
            COMMON.contentPath = path;
        },
        "JSON": o2.json,
        "Browser": Browser,
        "Class": o2.Class,
        "XML": o2.xml,
        "AjaxModule": {
            "load": function(urls, callback, async, reload){
                o2.load(urls, callback, reload, document);
            },
            "loadDom":  function(urls, callback, async, reload){
                o2.load(urls, callback, reload, document);
            },
            "loadCss":  function(urls, callback, async, reload, sourceDoc){
                o2.loadCss(urls, document.body, callback, reload, sourceDoc);
            }
        },
        "Request": Request,
        "typeOf": o2.typeOf
    };
    MWF = o2;
    MWF.getJSON = o2.JSON.get;
    MWF.getJSONP = o2.JSON.getJsonp;
    MWF.defaultPath = o2.session.path;
});
<commit_msg>Update compatible.js<commit_after>o2.addReady(function(){
    COMMON = {
        "setContentPath": function(path){
            COMMON.contentPath = path;
        },
        "JSON": o2.JSON,
        "Browser": Browser,
        "Class": o2.Class,
        "XML": o2.xml,
        "AjaxModule": {
            "load": function(urls, callback, async, reload){
                o2.load(urls, callback, reload, document);
            },
            "loadDom":  function(urls, callback, async, reload){
                o2.load(urls, callback, reload, document);
            },
            "loadCss":  function(urls, callback, async, reload, sourceDoc){
                o2.loadCss(urls, document.body, callback, reload, sourceDoc);
            }
        },
        "Request": Request,
        "typeOf": o2.typeOf
    };
    MWF = o2;
    MWF.getJSON = o2.JSON.get;
    MWF.getJSONP = o2.JSON.getJsonp;
    MWF.defaultPath = o2.session.path;
});
<|endoftext|>


<commit_before>var express = require('express')
  , app = express()
  , fs = require('fs')
  , db = require('./model/db')
  , mongoose = require('mongoose')
  , Measurement = mongoose.model('Measurement')
  , conf = require('./config')
  , serial = require('./serial');

app.use(express.logger());
app.use(express.bodyParser({uploadDir:'./tmp'}));
//app.use(express.favicon(__dirname + '/public/favicon.ico'))
app.use(app.router);
app.use(express.static('./public'));
app.use(function(req, res) {
    fs.createReadStream( './public/index.html').pipe(res);
});

app.listen(conf.port, conf.host, function () {
  console.log('Server running on ' + conf.host + ':' + conf.port);
});

app.get('/mock', function(req, res, next) {
  var data = {
    allValues: [
      {
        sensorId: 1,
        timestamp: 42,
        value: 21
      },
      {
        sensorId: 1,
        timestamp: 21,
        value: 11
      }
    ],
    err: null
  };

  res.send(data);
});

app.get('/values', function(req, res, next) {
  var id = req.query.sensor;

  if(id) {
    //Find 3 most recent measurements (Requested by app programmer).
    Measurement.find({sensorId: id}).sort({timestamp: 'desc'}).limit(3).exec(function(err, docs) {
		  if(err) console.error(err);
		  console.log(docs);
		  if(docs) {
		    res.send({allValues: docs, err: null});
		  } else {
		    res.send({allValues: null, err: 'No data for this sensor.'});
		  }
	  });
	} else {
	  res.send({allValues: null, err: 'Wrong sensor id.'});
	}

});

<commit_msg>Remove err field from res.<commit_after>var express = require('express')
  , app = express()
  , fs = require('fs')
  , db = require('./model/db')
  , mongoose = require('mongoose')
  , Measurement = mongoose.model('Measurement')
  , conf = require('./config')
  , serial = require('./serial');

app.use(express.logger());
app.use(express.bodyParser({uploadDir:'./tmp'}));
//app.use(express.favicon(__dirname + '/public/favicon.ico'))
app.use(app.router);
app.use(express.static('./public'));
app.use(function(req, res) {
    fs.createReadStream( './public/index.html').pipe(res);
});

app.listen(conf.port, conf.host, function () {
  console.log('Server running on ' + conf.host + ':' + conf.port);
});

app.get('/mock', function(req, res, next) {
  var data = {
    allValues: [
      {
        sensorId: 1,
        timestamp: 42,
        value: 21
      },
      {
        sensorId: 1,
        timestamp: 21,
        value: 11
      }
    ],
    err: null
  };

  res.send(data);
});

app.get('/values', function(req, res, next) {
  var id = req.query.sensor;

  if(id) {
    //Find 3 most recent measurements (Requested by app programmer).
    Measurement.find({sensorId: id}).sort({timestamp: 'desc'}).limit(3).exec(function(err, docs) {
		  if(err) console.error(err);
		  console.log(docs);
		  if(docs) {
		    res.send({allValues: docs/*, err: null*/});
		  } else {
		    res.send({allValues: null/*, err: 'No data for this sensor.'*/});
		  }
	  });
	} else {
	  res.send({allValues: null/*, err: 'Wrong sensor id.'*/});
	}

});

<|endoftext|>


<commit_before>/*global define*/
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([], factory)
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like environments that support module.exports,
    // like Node.
    module.exports = factory()
  } else {
    // Browser globals (root is window)
    root.SubclassError = factory()
  }
}(this, function () {
  var ErrorInheritor = function () {}
  function SubclassError (name, BaseError, props) {
    if (name === undefined) throw new Error('Name of subclass must be provided as first argument.')
    if (!(BaseError instanceof Function)) {
      props = BaseError
      BaseError = Error
    }
    ErrorInheritor.prototype = BaseError.prototype
    var e = function (message) {
      this.message = message

      // stack "hack"
      var goodStack = (new Error()).stack.split('\n')
      goodStack.splice(1, 1)
      goodStack[0] = name
      if (message) goodStack[0] += ': ' + message
      this.stack = goodStack.join('\n')
    }
    e.prototype = new ErrorInheritor()
    e.prototype.constructor = e
    e.prototype.name = name
    for (var prop in props) {
      e.prototype[prop] = props[prop]
    }
    return e
  }

  return SubclassError
}))
<commit_msg>Allow `message` to be inherited from prototype<commit_after>/*global define*/
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([], factory)
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like environments that support module.exports,
    // like Node.
    module.exports = factory()
  } else {
    // Browser globals (root is window)
    root.SubclassError = factory()
  }
}(this, function () {
  var ErrorInheritor = function () {}
  function SubclassError (name, BaseError, props) {
    if (name === undefined) throw new Error('Name of subclass must be provided as first argument.')
    if (!(BaseError instanceof Function)) {
      props = BaseError
      BaseError = Error
    }
    ErrorInheritor.prototype = BaseError.prototype
    var e = function (message) {
      if (message) this.message = message

      // stack "hack"
      var goodStack = (new Error()).stack.split('\n')
      goodStack.splice(1, 1)
      goodStack[0] = name
      if (message) goodStack[0] += ': ' + message
      this.stack = goodStack.join('\n')
    }
    e.prototype = new ErrorInheritor()
    e.prototype.constructor = e
    e.prototype.name = name
    for (var prop in props) {
      e.prototype[prop] = props[prop]
    }
    return e
  }

  return SubclassError
}))
<|endoftext|>


<commit_before>/* eslint-disable no-await-in-loop */
import {
  getOAuthOctokit,
  getTokenOctokit,
  getInstallationOctokit,
} from '@argos-ci/github'
import {
  Installation,
  Organization,
  Repository,
  User,
  UserOrganizationRight,
  UserRepositoryRight,
  UserInstallationRight,
  InstallationRepositoryRight,
} from '@argos-ci/database/models'
import config from '@argos-ci/config'

export async function getOrCreateInstallation(payload) {
  const installation = await Installation.query()
    .where({ githubId: payload.githubId })
    .first()

  if (installation) return installation
  return Installation.query().insertAndFetch(payload)
}

async function checkAccessTokenValidity(accessToken) {
  const oauthOctokit = getOAuthOctokit()
  try {
    await oauthOctokit.apps.checkToken({
      access_token: accessToken,
      client_id: config.get('github.clientId'),
    })
  } catch (error) {
    if (error.status === 404) {
      return false
    }

    throw error
  }

  return true
}

const OWNER_ORGANIZATION = 'Organization'
const OWNER_USER = 'User'

export class GitHubSynchronizer {
  constructor(synchronization) {
    this.synchronization = synchronization
    this.repositories = []
    this.organizationIds = []
  }

  async synchronizeAppRepositories(installationId) {
    const options = this.octokit.apps.listRepos.endpoint.DEFAULTS
    const githubRepositories = await this.octokit.paginate(options)
    const { repositories, organizations } = await this.synchronizeRepositories(
      githubRepositories,
    )

    await this.synchronizeInstallationRepositoryRights(
      repositories,
      installationId,
    )

    return { repositories, organizations }
  }

  async synchronizeUserInstallationRepositories(installation) {
    const options = this.octokit.apps.listInstallationReposForAuthenticatedUser.endpoint.merge(
      { installation_id: installation.githubId },
    )
    const githubRepositories = await this.octokit.paginate(options)
    const { repositories, organizations } = await this.synchronizeRepositories(
      githubRepositories,
    )

    await this.synchronizeInstallationRepositoryRights(
      repositories,
      installation.id,
    )

    return { repositories, organizations }
  }

  async synchronizeRepositories(githubRepositories) {
    const [
      {
        owners: organizations,
        ownerIdByRepositoryId: organizationIdByRepositoryId,
      },
      { ownerIdByRepositoryId: userIdByRepositoryId },
    ] = await Promise.all([
      this.synchronizeOwners(githubRepositories, OWNER_ORGANIZATION),
      this.synchronizeOwners(githubRepositories, OWNER_USER),
    ])

    const repositories = await Promise.all(
      githubRepositories.map(async (githubRepository) => {
        const data = {
          githubId: githubRepository.id,
          name: githubRepository.name,
          organizationId: organizationIdByRepositoryId[githubRepository.id],
          userId: userIdByRepositoryId[githubRepository.id],
          private: githubRepository.private,
        }

        let [repository] = await Repository.query().where({
          githubId: githubRepository.id,
        })

        if (repository) {
          await repository.$query().patchAndFetch(data)
        } else {
          repository = await Repository.query().insert({
            ...data,
            enabled: false,
            baselineBranch: 'master',
          })
        }

        return repository
      }),
    )

    return { repositories, organizations }
  }

  async synchronizeOwners(githubRepositories, type) {
    const githubOwners = githubRepositories.reduce(
      (githubOwners, githubRepository) => {
        if (githubRepository.owner.type !== type) {
          return githubOwners
        }

        let githubOwner = githubOwners.find(
          ({ id }) => id === githubRepository.owner.id,
        )

        if (!githubOwner) {
          githubOwner = githubRepository.owner
          githubOwners.push(githubRepository.owner)
        }

        return githubOwners
      },
      [],
    )

    let owners

    switch (type) {
      case OWNER_ORGANIZATION:
        owners = await Promise.all(
          githubOwners.map((githubOwner) =>
            this.synchronizeOrganization(githubOwner),
          ),
        )
        break
      case OWNER_USER:
        owners = await Promise.all(
          githubOwners.map((githubOwner) => this.synchronizeUser(githubOwner)),
        )
        break
      default:
        throw new Error(`Unsupported type ${type}`)
    }

    return {
      owners,
      ownerIdByRepositoryId: githubRepositories.reduce(
        (ownerIdByRepositoryId, githubRepository) => {
          if (githubRepository.owner.type === type) {
            ownerIdByRepositoryId[githubRepository.id] = owners.find(
              (owner) => owner.githubId === githubRepository.owner.id,
            ).id
          }

          return ownerIdByRepositoryId
        },
        {},
      ),
    }
  }

  // eslint-disable-next-line class-methods-use-this
  async synchronizeOrganization(githubOrganization) {
    const organizationData = await this.octokit.orgs.get({
      org: githubOrganization.login,
    })
    githubOrganization = organizationData.data
    let [organization] = await Organization.query().where({
      githubId: githubOrganization.id,
    })
    const data = {
      githubId: githubOrganization.id,
      name: githubOrganization.name,
      login: githubOrganization.login,
    }

    if (organization) {
      await organization.$query().patchAndFetch(data)
    } else {
      organization = await Organization.query().insert(data)
    }

    return organization
  }

  // eslint-disable-next-line class-methods-use-this
  async synchronizeUser(githubUser) {
    const data = { githubId: githubUser.id, login: githubUser.login }
    let user = await User.query().where({ githubId: githubUser.id }).first()

    if (user) {
      await user.$query().patchAndFetch(data)
    } else {
      user = await User.query().insert(data)
    }

    return user
  }

  async synchronizeInstallationRepositoryRights(repositories, installationId) {
    const installationRepositoryRights = await InstallationRepositoryRight.query().where(
      {
        installationId,
      },
    )

    await Promise.all(
      repositories.map(async (repository) => {
        const hasRights = installationRepositoryRights.some(
          ({ repositoryId }) => repositoryId === repository.id,
        )

        if (!hasRights) {
          await InstallationRepositoryRight.query().insert({
            installationId,
            repositoryId: repository.id,
          })
        }
      }),
    )

    await Promise.all(
      installationRepositoryRights.map(async (installationRepositoryRight) => {
        const repositoryStillExists = repositories.find(
          ({ id }) => id === installationRepositoryRight.repositoryId,
        )

        if (!repositoryStillExists) {
          await installationRepositoryRight.$query().delete()
        }
      }),
    )
  }

  async synchronizeRepositoryRights(repositories, userId) {
    const userRepositoryRights = await UserRepositoryRight.query().where({
      userId,
    })

    await Promise.all(
      repositories.map(async (repository) => {
        const hasRights = userRepositoryRights.some(
          ({ repositoryId }) => repositoryId === repository.id,
        )

        if (!hasRights) {
          await UserRepositoryRight.query().insert({
            userId,
            repositoryId: repository.id,
          })
        }
      }),
    )

    await Promise.all(
      userRepositoryRights.map(async (userRepositoryRight) => {
        const repositoryStillExists = repositories.find(
          ({ id }) => id === userRepositoryRight.repositoryId,
        )

        if (!repositoryStillExists) {
          await userRepositoryRight.$query().delete()
        }
      }),
    )
  }

  async synchronizeOrganizationRights(organizations, userId) {
    const userOrganizationRights = await UserOrganizationRight.query().where({
      userId,
    })

    await Promise.all(
      organizations.map(async (organization) => {
        const hasRights = userOrganizationRights.some(
          ({ organizationId }) => organizationId === organization.id,
        )

        if (!hasRights) {
          await UserOrganizationRight.query().insert({
            userId,
            organizationId: organization.id,
          })
        }
      }),
    )

    await Promise.all(
      userOrganizationRights.map(async (userOrganizationRight) => {
        const organizationStillExists = organizations.find(
          ({ id }) => id === userOrganizationRight.organizationId,
        )

        if (!organizationStillExists) {
          await userOrganizationRight.$query().delete()
        }
      }),
    )
  }

  async synchronizeUserInstallations() {
    const options = this.octokit.apps.listInstallationsForAuthenticatedUser
      .endpoint.DEFAULTS
    const githubInstallations = await this.octokit.paginate(options)

    return Promise.all(
      githubInstallations.map(async (githubInstallation) => {
        return getOrCreateInstallation({
          githubId: githubInstallation.id,
          deleted: false,
        })
      }),
    )
  }

  async synchronizeUserInstallationRights(installations, userId) {
    const userInstallationRights = await UserInstallationRight.query().where({
      userId,
    })

    await Promise.all(
      installations.map(async (installation) => {
        const exists = userInstallationRights.some(
          ({ installationId }) => installationId === installation.id,
        )

        if (!exists) {
          await UserInstallationRight.query().insertAndFetch({
            userId,
            installationId: installation.id,
          })
        }
      }),
    )

    await Promise.all(
      userInstallationRights.map(async (userInstallationRight) => {
        const installationStillExists = installations.find(
          ({ id }) => id === userInstallationRight.installationId,
        )

        if (!installationStillExists) {
          await userInstallationRight.$query().delete()
        }
      }),
    )

    return installations
  }

  async synchronize() {
    this.synchronization = await this.synchronization.$query()

    switch (this.synchronization.type) {
      case 'installation':
        return this.synchronizeFromInstallation(
          this.synchronization.installationId,
        )
      case 'user':
        return this.synchronizeFromUser(this.synchronization.userId)
      default:
        throw new Error(
          `Unknown synchronization type "${this.synchronization.type}"`,
        )
    }
  }

  async synchronizeFromInstallation(installationId) {
    const installation = await Installation.query()
      .findById(installationId)
      .withGraphFetched('users')

    if (installation.deleted) {
      await Promise.all(
        installation.users.map(async (user) =>
          this.synchronizeFromUser(user.id),
        ),
      )
      await this.synchronizeInstallationRepositoryRights([], installationId)
      return
    }

    this.octokit = await getInstallationOctokit(installation.githubId)

    await this.synchronizeAppRepositories(installationId)

    await Promise.all(
      installation.users.map(async (user) => this.synchronizeFromUser(user.id)),
    )
  }

  async synchronizeFromUser(userId) {
    const user = await User.query().findById(userId)
    const tokenValid = await checkAccessTokenValidity(user.accessToken)

    if (!tokenValid) {
      await this.synchronizeUserInstallationRights([], userId)
      await Promise.all([
        this.synchronizeRepositoryRights([], userId),
        this.synchronizeOrganizationRights([], userId),
      ])
      return
    }

    this.octokit = getTokenOctokit(user.accessToken)

    const installations = await this.synchronizeUserInstallations(userId)

    await this.synchronizeUserInstallationRights(installations, userId)

    const results = await Promise.all(
      installations.map((installation) =>
        this.synchronizeUserInstallationRepositories(installation),
      ),
    )

    const { repositories, organizations } = results.reduce(
      (all, result) => {
        all.repositories = [...all.repositories, ...result.repositories]
        all.organizations = [...all.organizations, ...result.organizations]
        return all
      },
      { repositories: [], organizations: [] },
    )

    await Promise.all([
      this.synchronizeRepositoryRights(repositories, userId),
      this.synchronizeOrganizationRights(organizations, userId),
    ])
  }
}
<commit_msg>fix: fix installation not found<commit_after>/* eslint-disable no-await-in-loop */
import {
  getOAuthOctokit,
  getTokenOctokit,
  getInstallationOctokit,
} from '@argos-ci/github'
import {
  Installation,
  Organization,
  Repository,
  User,
  UserOrganizationRight,
  UserRepositoryRight,
  UserInstallationRight,
  InstallationRepositoryRight,
} from '@argos-ci/database/models'
import config from '@argos-ci/config'

export async function getOrCreateInstallation(payload) {
  const installation = await Installation.query()
    .where({ githubId: payload.githubId })
    .first()

  if (installation) return installation
  return Installation.query().insertAndFetch(payload)
}

async function checkAccessTokenValidity(accessToken) {
  const oauthOctokit = getOAuthOctokit()
  try {
    await oauthOctokit.apps.checkToken({
      access_token: accessToken,
      client_id: config.get('github.clientId'),
    })
  } catch (error) {
    if (error.status === 404) {
      return false
    }

    throw error
  }

  return true
}

const OWNER_ORGANIZATION = 'Organization'
const OWNER_USER = 'User'

export class GitHubSynchronizer {
  constructor(synchronization) {
    this.synchronization = synchronization
    this.repositories = []
    this.organizationIds = []
  }

  async synchronizeAppRepositories(installationId) {
    const options = this.octokit.apps.listRepos.endpoint.DEFAULTS
    const githubRepositories = await this.octokit.paginate(options)
    const { repositories, organizations } = await this.synchronizeRepositories(
      githubRepositories,
    )

    await this.synchronizeInstallationRepositoryRights(
      repositories,
      installationId,
    )

    return { repositories, organizations }
  }

  async synchronizeUserInstallationRepositories(installation) {
    const options = this.octokit.apps.listInstallationReposForAuthenticatedUser.endpoint.merge(
      { installation_id: installation.githubId },
    )
    const githubRepositories = await this.octokit.paginate(options)
    const { repositories, organizations } = await this.synchronizeRepositories(
      githubRepositories,
    )

    await this.synchronizeInstallationRepositoryRights(
      repositories,
      installation.id,
    )

    return { repositories, organizations }
  }

  async synchronizeRepositories(githubRepositories) {
    const [
      {
        owners: organizations,
        ownerIdByRepositoryId: organizationIdByRepositoryId,
      },
      { ownerIdByRepositoryId: userIdByRepositoryId },
    ] = await Promise.all([
      this.synchronizeOwners(githubRepositories, OWNER_ORGANIZATION),
      this.synchronizeOwners(githubRepositories, OWNER_USER),
    ])

    const repositories = await Promise.all(
      githubRepositories.map(async (githubRepository) => {
        const data = {
          githubId: githubRepository.id,
          name: githubRepository.name,
          organizationId: organizationIdByRepositoryId[githubRepository.id],
          userId: userIdByRepositoryId[githubRepository.id],
          private: githubRepository.private,
        }

        let [repository] = await Repository.query().where({
          githubId: githubRepository.id,
        })

        if (repository) {
          await repository.$query().patchAndFetch(data)
        } else {
          repository = await Repository.query().insert({
            ...data,
            enabled: false,
            baselineBranch: 'master',
          })
        }

        return repository
      }),
    )

    return { repositories, organizations }
  }

  async synchronizeOwners(githubRepositories, type) {
    const githubOwners = githubRepositories.reduce(
      (githubOwners, githubRepository) => {
        if (githubRepository.owner.type !== type) {
          return githubOwners
        }

        let githubOwner = githubOwners.find(
          ({ id }) => id === githubRepository.owner.id,
        )

        if (!githubOwner) {
          githubOwner = githubRepository.owner
          githubOwners.push(githubRepository.owner)
        }

        return githubOwners
      },
      [],
    )

    let owners

    switch (type) {
      case OWNER_ORGANIZATION:
        owners = await Promise.all(
          githubOwners.map((githubOwner) =>
            this.synchronizeOrganization(githubOwner),
          ),
        )
        break
      case OWNER_USER:
        owners = await Promise.all(
          githubOwners.map((githubOwner) => this.synchronizeUser(githubOwner)),
        )
        break
      default:
        throw new Error(`Unsupported type ${type}`)
    }

    return {
      owners,
      ownerIdByRepositoryId: githubRepositories.reduce(
        (ownerIdByRepositoryId, githubRepository) => {
          if (githubRepository.owner.type === type) {
            ownerIdByRepositoryId[githubRepository.id] = owners.find(
              (owner) => owner.githubId === githubRepository.owner.id,
            ).id
          }

          return ownerIdByRepositoryId
        },
        {},
      ),
    }
  }

  // eslint-disable-next-line class-methods-use-this
  async synchronizeOrganization(githubOrganization) {
    const organizationData = await this.octokit.orgs.get({
      org: githubOrganization.login,
    })
    githubOrganization = organizationData.data
    let [organization] = await Organization.query().where({
      githubId: githubOrganization.id,
    })
    const data = {
      githubId: githubOrganization.id,
      name: githubOrganization.name,
      login: githubOrganization.login,
    }

    if (organization) {
      await organization.$query().patchAndFetch(data)
    } else {
      organization = await Organization.query().insert(data)
    }

    return organization
  }

  // eslint-disable-next-line class-methods-use-this
  async synchronizeUser(githubUser) {
    const data = { githubId: githubUser.id, login: githubUser.login }
    let user = await User.query().where({ githubId: githubUser.id }).first()

    if (user) {
      await user.$query().patchAndFetch(data)
    } else {
      user = await User.query().insert(data)
    }

    return user
  }

  async synchronizeInstallationRepositoryRights(repositories, installationId) {
    const installationRepositoryRights = await InstallationRepositoryRight.query().where(
      {
        installationId,
      },
    )

    await Promise.all(
      repositories.map(async (repository) => {
        const hasRights = installationRepositoryRights.some(
          ({ repositoryId }) => repositoryId === repository.id,
        )

        if (!hasRights) {
          await InstallationRepositoryRight.query().insert({
            installationId,
            repositoryId: repository.id,
          })
        }
      }),
    )

    await Promise.all(
      installationRepositoryRights.map(async (installationRepositoryRight) => {
        const repositoryStillExists = repositories.find(
          ({ id }) => id === installationRepositoryRight.repositoryId,
        )

        if (!repositoryStillExists) {
          await installationRepositoryRight.$query().delete()
        }
      }),
    )
  }

  async synchronizeRepositoryRights(repositories, userId) {
    const userRepositoryRights = await UserRepositoryRight.query().where({
      userId,
    })

    await Promise.all(
      repositories.map(async (repository) => {
        const hasRights = userRepositoryRights.some(
          ({ repositoryId }) => repositoryId === repository.id,
        )

        if (!hasRights) {
          await UserRepositoryRight.query().insert({
            userId,
            repositoryId: repository.id,
          })
        }
      }),
    )

    await Promise.all(
      userRepositoryRights.map(async (userRepositoryRight) => {
        const repositoryStillExists = repositories.find(
          ({ id }) => id === userRepositoryRight.repositoryId,
        )

        if (!repositoryStillExists) {
          await userRepositoryRight.$query().delete()
        }
      }),
    )
  }

  async synchronizeOrganizationRights(organizations, userId) {
    const userOrganizationRights = await UserOrganizationRight.query().where({
      userId,
    })

    await Promise.all(
      organizations.map(async (organization) => {
        const hasRights = userOrganizationRights.some(
          ({ organizationId }) => organizationId === organization.id,
        )

        if (!hasRights) {
          await UserOrganizationRight.query().insert({
            userId,
            organizationId: organization.id,
          })
        }
      }),
    )

    await Promise.all(
      userOrganizationRights.map(async (userOrganizationRight) => {
        const organizationStillExists = organizations.find(
          ({ id }) => id === userOrganizationRight.organizationId,
        )

        if (!organizationStillExists) {
          await userOrganizationRight.$query().delete()
        }
      }),
    )
  }

  async synchronizeUserInstallations() {
    const options = this.octokit.apps.listInstallationsForAuthenticatedUser
      .endpoint.DEFAULTS
    const githubInstallations = await this.octokit.paginate(options)

    return Promise.all(
      githubInstallations.map(async (githubInstallation) => {
        return getOrCreateInstallation({
          githubId: githubInstallation.id,
          deleted: false,
        })
      }),
    )
  }

  async synchronizeUserInstallationRights(installations, userId) {
    const userInstallationRights = await UserInstallationRight.query().where({
      userId,
    })

    await Promise.all(
      installations.map(async (installation) => {
        const exists = userInstallationRights.some(
          ({ installationId }) => installationId === installation.id,
        )

        if (!exists) {
          await UserInstallationRight.query().insertAndFetch({
            userId,
            installationId: installation.id,
          })
        }
      }),
    )

    await Promise.all(
      userInstallationRights.map(async (userInstallationRight) => {
        const installationStillExists = installations.find(
          ({ id }) => id === userInstallationRight.installationId,
        )

        if (!installationStillExists) {
          await userInstallationRight.$query().delete()
        }
      }),
    )

    return installations
  }

  async synchronize() {
    this.synchronization = await this.synchronization.$query()

    switch (this.synchronization.type) {
      case 'installation':
        return this.synchronizeFromInstallation(
          this.synchronization.installationId,
        )
      case 'user':
        return this.synchronizeFromUser(this.synchronization.userId)
      default:
        throw new Error(
          `Unknown synchronization type "${this.synchronization.type}"`,
        )
    }
  }

  async synchronizeFromInstallation(installationId) {
    const installation = await Installation.query()
      .findById(installationId)
      .withGraphFetched('users')

    if (installation.deleted) {
      await Promise.all(
        installation.users.map(async (user) =>
          this.synchronizeFromUser(user.id),
        ),
      )
      await this.synchronizeInstallationRepositoryRights([], installationId)
      return
    }

    const octokit = await getInstallationOctokit(installation.githubId)

    // If we don't get an octokit, then the installation has been removed
    // we deleted the installation
    if (!octokit) {
      await installation.$query().patch({ deleted: true })
      return
    }

    this.octokit = octokit

    await this.synchronizeAppRepositories(installationId)

    await Promise.all(
      installation.users.map(async (user) => this.synchronizeFromUser(user.id)),
    )
  }

  async synchronizeFromUser(userId) {
    const user = await User.query().findById(userId)
    const tokenValid = await checkAccessTokenValidity(user.accessToken)

    if (!tokenValid) {
      await this.synchronizeUserInstallationRights([], userId)
      await Promise.all([
        this.synchronizeRepositoryRights([], userId),
        this.synchronizeOrganizationRights([], userId),
      ])
      return
    }

    this.octokit = getTokenOctokit(user.accessToken)

    const installations = await this.synchronizeUserInstallations(userId)

    await this.synchronizeUserInstallationRights(installations, userId)

    const results = await Promise.all(
      installations.map((installation) =>
        this.synchronizeUserInstallationRepositories(installation),
      ),
    )

    const { repositories, organizations } = results.reduce(
      (all, result) => {
        all.repositories = [...all.repositories, ...result.repositories]
        all.organizations = [...all.organizations, ...result.organizations]
        return all
      },
      { repositories: [], organizations: [] },
    )

    await Promise.all([
      this.synchronizeRepositoryRights(repositories, userId),
      this.synchronizeOrganizationRights(organizations, userId),
    ])
  }
}
<|endoftext|>


<commit_before>define([
    'jquery',
    'underscore',
    'knockout',
    'knockout-mapping',
    'views/base-manager',
    'viewmodels/alert',
    'viewmodels/alert-json',
    'models/graph',
    'models/report',
    'views/graph/graph-manager/graph',
    'views/graph/graph-designer/graph-tree',
    'views/graph/graph-designer/node-form',
    'views/graph/graph-manager/branch-list',
    'views/graph/graph-designer/card-tree',
    'views/graph/permission-designer',
    'graph-designer-data',
    'arches',
    'viewmodels/graph-settings',
    'viewmodels/card',
    'view-data',
    'report-templates',
    'bindings/resizable-sidepanel',
    'datatype-config-components',
    'views/components/simple-switch'
], function($, _, ko, koMapping, BaseManagerView, AlertViewModel, JsonErrorAlertViewModel, GraphModel, ReportModel, GraphView, GraphTree, NodeFormView, BranchListView, CardTreeViewModel, PermissionDesigner, data, arches, GraphSettingsViewModel, CardViewModel, viewData, reportLookup) {
    var GraphDesignerView = BaseManagerView.extend({
        initialize: function(options) {
            var viewModel = options.viewModel;
            viewModel.graphid = ko.observable(data.graphid);
            viewModel.activeTab = ko.observable('graph');
            viewModel.viewState = ko.observable('design');
            viewModel.helpTemplate(viewData.help);
            viewModel.graphSettingsVisible = ko.observable(false);
            viewModel.graph = koMapping.fromJS(data['graph']);
            viewModel.ontologies = ko.observable(data['ontologies']);
            viewModel.ontologyClasses = ko.observable(data['ontologyClasses']);
            viewModel.cardComponents = data.cardComponents;
            viewModel.appliedFunctions = ko.observable(data['appliedFunctions']);

            var resources = ko.utils.arrayFilter(viewData.graphs, function(graph) {
                return graph.isresource;
            });
            var graphs = ko.utils.arrayFilter(viewData.graphs, function(graph) {
                return !graph.isresource;
            });

            var newGraph = function(url, data) {
                data = data || {};
                viewModel.loading(true);
                $.ajax({
                    type: "POST",
                    url: url,
                    data: JSON.stringify(data),
                    success: function(response) {
                        window.open(arches.urls.graph_designer(response.graphid), '_blank');
                        viewModel.loading(false);
                    },
                    error: function() {
                        viewModel.loading(false);
                    }
                });
            };
            viewModel.newResource = function() {
                newGraph('/graph/new', {isresource: true});
            };
            viewModel.newBranch = function() {
                newGraph('/graph/new', {isresource: false});
            };

            viewModel.deleteGraph = function() {
                viewModel.alert(new AlertViewModel('ep-alert-red', arches.confirmGraphDelete.title, arches.confirmGraphDelete.text, function() {
                    return;
                }, function(){
                    viewModel.loading(true);
                    $.ajax({
                        type: "DELETE",
                        url: arches.urls.delete_graph(viewModel.graph.graphid()),
                        complete: function(response, status) {
                            viewModel.loading(false);
                            if (status === 'success') {
                                window.location = arches.urls.graph;
                            } else {
                                viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', response.responseJSON));
                            }
                        }
                    });
                }));
            };
            viewModel.cloneGraph = function() {
                newGraph(arches.urls.clone_graph(viewModel.graph.graphid()));
            };
            viewModel.exportGraph = function() {
                window.open(arches.urls.export_graph(viewModel.graph.graphid()), '_blank');
            };
            viewModel.importGraph = function(data, e) {
                var formData = new FormData();
                formData.append("importedGraph", e.target.files[0]);

                $.ajax({
                    type: "POST",
                    url: '/graph/import/',
                    processData: false,
                    data: formData,
                    cache: false,
                    contentType: false,
                    success: function(response) {
                        if (response[0].length != 0) {
                            if (typeof(response[0])) {
                                response = response[0].join('<br />');
                            }
                            viewModel.alert(new AlertViewModel('ep-alert-red', arches.graphImportFailed.title, response));
                        } else {
                            viewModel.loading(false);
                            window.open(arches.urls.graph_designer(response[1].graph_id), '_blank');
                        }
                    },
                    error: function(response) {
                        viewModel.alert(new AlertViewModel('ep-alert-red', arches.graphImportFailed.title, 'Please contact your system administrator for more details.'));
                        viewModel.loading(false);
                    },
                });
            };
            viewModel.importButtonClick = function() {
                $("#fileupload").trigger('click');
            };
            viewModel.deleteInstances = function() {
                viewModel.alert(new AlertViewModel('ep-alert-red', arches.confirmAllResourceDelete.title, arches.confirmAllResourceDelete.text, function() {
                    return;
                }, function(){
                    viewModel.loading(true);
                    $.ajax({
                        type: "DELETE",
                        url: arches.urls.delete_instances(viewModel.graph.graphid()),
                        complete: function(response, status) {
                            viewModel.loading(false);
                            if (status === 'success') {
                                viewModel.alert(new AlertViewModel('ep-alert-blue', response.responseJSON.title, response.responseJSON.message));
                            } else {
                                console.log(response);
                                viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', response.responseJSON));
                            }
                        }
                    });
                }));
            };
            viewModel.graph.ontology = ko.computed(function() {
                return viewModel.ontologies().find(function(obj) {
                    return obj.ontologyid === viewModel.graph.ontology_id();
                });
            });
            viewModel.groupedGraphs = ko.observable({
                groups: [
                    { name: 'Resource Models', items: resources },
                    { name: 'Branches', items: graphs }
                ]
            });

            viewModel.graphid.subscribe(function(graphid) {
                if (graphid && graphid !== '') {
                    viewModel.navigate(arches.urls.graph_designer(graphid));
                }
            });

            viewModel.graphModel = new GraphModel({
                data: data.graph,
                datatypes: data.datatypes,
                ontology_namespaces: data.ontology_namespaces
            });

            viewModel.datatypes = _.keys(viewModel.graphModel.get('datatypelookup'));

            viewModel.graphModel.on('changed', function(model, response) {
                if (viewModel.graphView) {
                    viewModel.graphView.redraw(true);
                }
                viewModel.alert(null);
                viewModel.loading(false);
                if (response.status !== 200) {
                    viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', response.responseJSON));
                }
            });

            viewModel.graphModel.on('error', function(response) {
                viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', response.responseJSON));
            });

            viewModel.selectedNode = viewModel.graphModel.get('selectedNode');

            viewModel.saveNode = function(node) {
                if (node) {
                    viewModel.loading(true);
                    node.save(function(data) {
                        if (data.responseJSON.success === false || data.status === 500) {
                            viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', data.responseJSON));
                        }
                        else {
                            viewModel.cardTree.updateCards(viewModel.selectedNode().nodeGroupId(), data.responseJSON);
                            viewModel.permissionTree.updateCards(viewModel.selectedNode().nodeGroupId(), data.responseJSON);
                        }
                        viewModel.loading(false);
                    });
                }
            };

            viewModel.saveSelectedNode = function() {
                if (viewModel.selectedNode()) {
                    viewModel.saveNode(viewModel.selectedNode());
                }
            };

            viewModel.cardTree = new CardTreeViewModel({
                graph: viewModel.graph,
                appliedFunctions: viewModel.appliedFunctions,
                graphModel: viewModel.graphModel
            });

            viewModel.permissionTree = new CardTreeViewModel({
                graph: viewModel.graph,
                graphModel: viewModel.graphModel,
                appliedFunctions: viewModel.appliedFunctions,
                multiselect: true
            });

            viewModel.selectedCards = ko.computed(function() {
                var selection = viewModel.permissionTree.selection();
                if (selection) {
                    if (selection.widgets) {
                        return selection;
                    }
                    return selection.parent;
                } else {
                    return null;
                }
            });

            viewModel.selectedCard = ko.computed(function() {
                var selection = viewModel.cardTree.selection();
                if (selection) {
                    if (selection.widgets) {
                        return selection;
                    }
                    return selection.parent;
                } else {
                    return null;
                }
            });

            viewModel.nodeForm = new NodeFormView({
                graph: viewModel.graph,
                graphModel: viewModel.graphModel,
                loading: viewModel.loading,
                node: viewModel.selectedNode,
                appliedFunctions: viewModel.appliedFunctions,
                restrictedNodegroups: data.restrictedNodegroups
            });

            viewModel.branchListView = new BranchListView({
                el: $('#branch-library'),
                branches: data.branches,
                graphModel: viewModel.graphModel,
                loading: viewModel.loading,
                disableAppendButton: ko.computed(function() {
                    // self.node() && self.node().dirty();
                })
            });

            viewModel.permissionsDesigner = new PermissionDesigner({
                cardTree: viewModel.permissionTree
            });

            viewModel.graphSettingsViewModel = new GraphSettingsViewModel({
                designerViewModel: viewModel,
                graph: viewModel.graph,
                graphModel: viewModel.graphModel,
                ontologyClasses: viewModel.ontologyClasses,
                ontologies: viewModel.ontologies,
                ontologyClass: ko.observable(''),
                iconFilter: ko.observable(''),
                rootNodeColor: ko.observable(''),
                "ontology_namespaces": data.ontology_namespaces,
                onReset: function() {
                    var graph = koMapping.toJS(viewModel.graphSettingsViewModel.graph);
                    viewModel.report.resetConfigs(graph.config);
                    viewModel.report.get('template_id')(graph["template_id"]);
                }
            });

            viewModel.report = new ReportModel(_.extend(data, {
                graphModel: viewModel.graphModel,
                cards: viewModel.cardTree.topCards,
                preview: true
            }));

            viewModel.report.configJSON.subscribe(function(config) {
                var graph = koMapping.toJS(viewModel.graphSettingsViewModel.graph);
                graph.config = koMapping.toJS(config);
                koMapping.fromJS(graph, viewModel.graphSettingsViewModel.graph);
            });

            viewModel.report.configJSON.extend({deferred: true});

            viewModel.report.get('template_id').subscribe(function(val) {
                viewModel.graphSettingsViewModel.graph["template_id"](val);
            });

            viewModel.reportLookup = reportLookup;
            viewModel.reportTemplates = _.map(reportLookup, function(report, id) {
                report.id = id;
                return report;
            });

            viewModel.graphTree = new GraphTree({
                graphModel: viewModel.graphModel,
                graphSettings: viewModel.graphSettingsViewModel,
                cardTree: viewModel.cardTree,
                permissionTree: viewModel.permissionTree,
                appliedFunctions: viewModel.appliedFunctions,
                restrictedNodegroups: data.restrictedNodegroups
            });

            viewModel.graphTree.branchListVisible.subscribe(function(visible) {
                if (visible) {
                    viewModel.branchListView.loadDomainConnections();
                }
            }, this);

            viewModel.loadGraphSettings = function() {
                var self = this;
                viewModel.loading(true);
                $.ajax({
                    type: 'GET',
                    url: arches.urls.graph_settings(data.graphid),
                    data: {'search': true, 'csrfmiddlewaretoken': '{{ csrf_token }}'}})
                    .done(function(data) {
                        self.graphSettingsViewModel.resource_data(data.resources);
                        self.graphSettingsViewModel.icon_data(data.icons);
                        self.graphSettingsViewModel.jsonCache(self.graphSettingsViewModel.jsonData());
                        self.graphSettingsViewModel.contentLoading = viewModel.loading;
                        self.graphSettingsVisible(true);
                        viewModel.loading(false);
                    })
                    .fail(function() {
                        throw 'error loading graph settings';
                    });
            };

            var correspondingCard = function(item, cardTree){
                var cardList = cardTree.cachedFlatTree;
                if (cardList === undefined) {
                    var cardList = cardTree.flattenTree(cardTree.topCards(), []);
                    cardTree.cachedFlatTree = cardList;
                }
                var res;
                var matchingWidget;
                if (item && typeof item !== 'string') {
                    if (item.nodeGroupId) { //if the item is a node in graph tree
                        var matchingCards = _.filter(cardList, function(card){
                            return card.nodegroupid === item.nodeGroupId();
                        });
                        _.each(matchingCards, function(card){
                            var match;
                            match = _.find(card.widgets(), function(widget){
                                return widget.node_id() === item.nodeid;
                            });
                            if (match) {
                                matchingWidget = match;
                            }
                        });
                        if (matchingWidget) {
                            res = matchingWidget;
                        } else {
                            res = matchingCards[0];
                        }
                    } else { //if the item is a card or widget in the card tree
                        res = _.find(cardList, function(card){
                            if (item.nodegroupid) {
                                return card.nodegroupid === item.nodegroupid;
                            } else {
                                return card.nodegroupid === item.node.nodeGroupId();
                            }
                        });
                    }
                }
                return res;

            };

            var correspondingNode = function(card, graphTree){
                var nodeMatch;
                nodeMatch = _.find(graphTree.items(), function(node){
                    if (card) {
                        if (card.node) {
                            return node.nodeid === card.node_id();
                        } else {
                            return node.nodeGroupId() === card.nodegroupid && node.nodeid === node.nodeGroupId();
                        }
                    }
                });
                return nodeMatch;
            };

            var updateGraphSelection = function() {
                var matchingNode = correspondingNode(viewModel.cardTree.selection(), viewModel.graphTree);
                if (matchingNode) {
                    viewModel.graphTree.selectItem(matchingNode);
                }
            };

            var updateCardSelection = function() {
                var graphTreeSelection = viewModel.graphTree.selectedItems().length > 0 ? viewModel.graphTree.selectedItems()[0] : null;
                var matchingCard;
                if (graphTreeSelection) {
                    if (graphTreeSelection.istopnode === true) {
                        viewModel.cardTree.selection(viewModel.cardTree.topCards()[0]);
                    } else {
                        matchingCard = correspondingCard(graphTreeSelection, viewModel.cardTree);
                        if (matchingCard) {
                            viewModel.cardTree.selection(matchingCard);
                            viewModel.cardTree.expandToRoot(viewModel.cardTree.selection());
                        }
                    }
                }
            };

            var updatePermissionCardSelection = function() {
                var matchingCard = correspondingCard(viewModel.cardTree.selection(), viewModel.permissionTree);
                if (matchingCard) {
                    viewModel.permissionTree.expandToRoot(matchingCard);
                    viewModel.permissionTree.selection.removeAll();
                    matchingCard.selectChildCards();
                }
            };

            if (viewModel.activeTab() === 'graph') {
                viewModel.loadGraphSettings();
                // here we might load data/views asyncronously
            }

            var loadPermissionData = viewModel.activeTab.subscribe(function(tab) {
                // Loads identities and nodegroup permissions when the permissions tab is opened and then disposes the ko.subscribe.
                if (tab === 'permissions') {
                    viewModel.permissionsDesigner.getPermissionManagerData();
                    loadPermissionData.dispose();
                }
            });

            var helpContentLookup = {
                permissions: {
                    'title': 'xxxx', // dynamic title loading not implemented
                    'template': 'permissions-tab-help',
                },
                graph: {
                    'title': 'xxxx', // dynamic title loading not implemented
                    'template': 'graph-tab-help',
                },
                card: {
                    'title': 'xxxx', // dynamic title loading not implemented
                    'template': 'cards-tab-help',
                }
            };

            viewModel.activeTab.subscribe(function(tab) {
                viewModel.helpTemplate(helpContentLookup[tab]['template']);
                viewModel.getHelp();
                switch (tab) {
                case 'card':
                    updateCardSelection();
                    break;
                case 'graph':
                    updateGraphSelection();
                    break;
                case 'permissions':
                    updatePermissionCardSelection();
                    break;
                default:
                    return;
                }
            });

            viewModel.graphView = new GraphView({
                el: $('#graph'),
                graphModel: viewModel.graphModel,
                nodeSize: 15,
                nodeSizeOver: 20,
                labelOffset: 10,
                loading: this.loading
            });

            viewModel.graphModel.on('select-node', function(node) {
                viewModel.graphView.zoomTo(node);
                viewModel.graphTree.expandParentNode(node);
            });

            viewModel.showPreview = function() {
                viewModel.viewState('preview');
                viewModel.graphView.resize();
            };

            /**
            * update the sizing of elements on window resize
            */
            var resize = function() {
                $('.grid').height($(window).height() - 208);
                $('#graph').height($(window).height() - 100);
                if (!!viewModel.graphView) {
                    viewModel.graphView.resize();
                }
            };

            $(window).resize(resize);

            resize();

            BaseManagerView.prototype.initialize.apply(this, arguments);
        }
    });

    return new GraphDesignerView();
});
<commit_msg>rm console, re #5812<commit_after>define([
    'jquery',
    'underscore',
    'knockout',
    'knockout-mapping',
    'views/base-manager',
    'viewmodels/alert',
    'viewmodels/alert-json',
    'models/graph',
    'models/report',
    'views/graph/graph-manager/graph',
    'views/graph/graph-designer/graph-tree',
    'views/graph/graph-designer/node-form',
    'views/graph/graph-manager/branch-list',
    'views/graph/graph-designer/card-tree',
    'views/graph/permission-designer',
    'graph-designer-data',
    'arches',
    'viewmodels/graph-settings',
    'viewmodels/card',
    'view-data',
    'report-templates',
    'bindings/resizable-sidepanel',
    'datatype-config-components',
    'views/components/simple-switch'
], function($, _, ko, koMapping, BaseManagerView, AlertViewModel, JsonErrorAlertViewModel, GraphModel, ReportModel, GraphView, GraphTree, NodeFormView, BranchListView, CardTreeViewModel, PermissionDesigner, data, arches, GraphSettingsViewModel, CardViewModel, viewData, reportLookup) {
    var GraphDesignerView = BaseManagerView.extend({
        initialize: function(options) {
            var viewModel = options.viewModel;
            viewModel.graphid = ko.observable(data.graphid);
            viewModel.activeTab = ko.observable('graph');
            viewModel.viewState = ko.observable('design');
            viewModel.helpTemplate(viewData.help);
            viewModel.graphSettingsVisible = ko.observable(false);
            viewModel.graph = koMapping.fromJS(data['graph']);
            viewModel.ontologies = ko.observable(data['ontologies']);
            viewModel.ontologyClasses = ko.observable(data['ontologyClasses']);
            viewModel.cardComponents = data.cardComponents;
            viewModel.appliedFunctions = ko.observable(data['appliedFunctions']);

            var resources = ko.utils.arrayFilter(viewData.graphs, function(graph) {
                return graph.isresource;
            });
            var graphs = ko.utils.arrayFilter(viewData.graphs, function(graph) {
                return !graph.isresource;
            });

            var newGraph = function(url, data) {
                data = data || {};
                viewModel.loading(true);
                $.ajax({
                    type: "POST",
                    url: url,
                    data: JSON.stringify(data),
                    success: function(response) {
                        window.open(arches.urls.graph_designer(response.graphid), '_blank');
                        viewModel.loading(false);
                    },
                    error: function() {
                        viewModel.loading(false);
                    }
                });
            };
            viewModel.newResource = function() {
                newGraph('/graph/new', {isresource: true});
            };
            viewModel.newBranch = function() {
                newGraph('/graph/new', {isresource: false});
            };

            viewModel.deleteGraph = function() {
                viewModel.alert(new AlertViewModel('ep-alert-red', arches.confirmGraphDelete.title, arches.confirmGraphDelete.text, function() {
                    return;
                }, function(){
                    viewModel.loading(true);
                    $.ajax({
                        type: "DELETE",
                        url: arches.urls.delete_graph(viewModel.graph.graphid()),
                        complete: function(response, status) {
                            viewModel.loading(false);
                            if (status === 'success') {
                                window.location = arches.urls.graph;
                            } else {
                                viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', response.responseJSON));
                            }
                        }
                    });
                }));
            };
            viewModel.cloneGraph = function() {
                newGraph(arches.urls.clone_graph(viewModel.graph.graphid()));
            };
            viewModel.exportGraph = function() {
                window.open(arches.urls.export_graph(viewModel.graph.graphid()), '_blank');
            };
            viewModel.importGraph = function(data, e) {
                var formData = new FormData();
                formData.append("importedGraph", e.target.files[0]);

                $.ajax({
                    type: "POST",
                    url: '/graph/import/',
                    processData: false,
                    data: formData,
                    cache: false,
                    contentType: false,
                    success: function(response) {
                        if (response[0].length != 0) {
                            if (typeof(response[0])) {
                                response = response[0].join('<br />');
                            }
                            viewModel.alert(new AlertViewModel('ep-alert-red', arches.graphImportFailed.title, response));
                        } else {
                            viewModel.loading(false);
                            window.open(arches.urls.graph_designer(response[1].graph_id), '_blank');
                        }
                    },
                    error: function(response) {
                        viewModel.alert(new AlertViewModel('ep-alert-red', arches.graphImportFailed.title, 'Please contact your system administrator for more details.'));
                        viewModel.loading(false);
                    },
                });
            };
            viewModel.importButtonClick = function() {
                $("#fileupload").trigger('click');
            };
            viewModel.deleteInstances = function() {
                viewModel.alert(new AlertViewModel('ep-alert-red', arches.confirmAllResourceDelete.title, arches.confirmAllResourceDelete.text, function() {
                    return;
                }, function(){
                    viewModel.loading(true);
                    $.ajax({
                        type: "DELETE",
                        url: arches.urls.delete_instances(viewModel.graph.graphid()),
                        complete: function(response, status) {
                            viewModel.loading(false);
                            if (status === 'success') {
                                viewModel.alert(new AlertViewModel('ep-alert-blue', response.responseJSON.title, response.responseJSON.message));
                            } else {
                                viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', response.responseJSON));
                            }
                        }
                    });
                }));
            };
            viewModel.graph.ontology = ko.computed(function() {
                return viewModel.ontologies().find(function(obj) {
                    return obj.ontologyid === viewModel.graph.ontology_id();
                });
            });
            viewModel.groupedGraphs = ko.observable({
                groups: [
                    { name: 'Resource Models', items: resources },
                    { name: 'Branches', items: graphs }
                ]
            });

            viewModel.graphid.subscribe(function(graphid) {
                if (graphid && graphid !== '') {
                    viewModel.navigate(arches.urls.graph_designer(graphid));
                }
            });

            viewModel.graphModel = new GraphModel({
                data: data.graph,
                datatypes: data.datatypes,
                ontology_namespaces: data.ontology_namespaces
            });

            viewModel.datatypes = _.keys(viewModel.graphModel.get('datatypelookup'));

            viewModel.graphModel.on('changed', function(model, response) {
                if (viewModel.graphView) {
                    viewModel.graphView.redraw(true);
                }
                viewModel.alert(null);
                viewModel.loading(false);
                if (response.status !== 200) {
                    viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', response.responseJSON));
                }
            });

            viewModel.graphModel.on('error', function(response) {
                viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', response.responseJSON));
            });

            viewModel.selectedNode = viewModel.graphModel.get('selectedNode');

            viewModel.saveNode = function(node) {
                if (node) {
                    viewModel.loading(true);
                    node.save(function(data) {
                        if (data.responseJSON.success === false || data.status === 500) {
                            viewModel.alert(new JsonErrorAlertViewModel('ep-alert-red', data.responseJSON));
                        }
                        else {
                            viewModel.cardTree.updateCards(viewModel.selectedNode().nodeGroupId(), data.responseJSON);
                            viewModel.permissionTree.updateCards(viewModel.selectedNode().nodeGroupId(), data.responseJSON);
                        }
                        viewModel.loading(false);
                    });
                }
            };

            viewModel.saveSelectedNode = function() {
                if (viewModel.selectedNode()) {
                    viewModel.saveNode(viewModel.selectedNode());
                }
            };

            viewModel.cardTree = new CardTreeViewModel({
                graph: viewModel.graph,
                appliedFunctions: viewModel.appliedFunctions,
                graphModel: viewModel.graphModel
            });

            viewModel.permissionTree = new CardTreeViewModel({
                graph: viewModel.graph,
                graphModel: viewModel.graphModel,
                appliedFunctions: viewModel.appliedFunctions,
                multiselect: true
            });

            viewModel.selectedCards = ko.computed(function() {
                var selection = viewModel.permissionTree.selection();
                if (selection) {
                    if (selection.widgets) {
                        return selection;
                    }
                    return selection.parent;
                } else {
                    return null;
                }
            });

            viewModel.selectedCard = ko.computed(function() {
                var selection = viewModel.cardTree.selection();
                if (selection) {
                    if (selection.widgets) {
                        return selection;
                    }
                    return selection.parent;
                } else {
                    return null;
                }
            });

            viewModel.nodeForm = new NodeFormView({
                graph: viewModel.graph,
                graphModel: viewModel.graphModel,
                loading: viewModel.loading,
                node: viewModel.selectedNode,
                appliedFunctions: viewModel.appliedFunctions,
                restrictedNodegroups: data.restrictedNodegroups
            });

            viewModel.branchListView = new BranchListView({
                el: $('#branch-library'),
                branches: data.branches,
                graphModel: viewModel.graphModel,
                loading: viewModel.loading,
                disableAppendButton: ko.computed(function() {
                    // self.node() && self.node().dirty();
                })
            });

            viewModel.permissionsDesigner = new PermissionDesigner({
                cardTree: viewModel.permissionTree
            });

            viewModel.graphSettingsViewModel = new GraphSettingsViewModel({
                designerViewModel: viewModel,
                graph: viewModel.graph,
                graphModel: viewModel.graphModel,
                ontologyClasses: viewModel.ontologyClasses,
                ontologies: viewModel.ontologies,
                ontologyClass: ko.observable(''),
                iconFilter: ko.observable(''),
                rootNodeColor: ko.observable(''),
                "ontology_namespaces": data.ontology_namespaces,
                onReset: function() {
                    var graph = koMapping.toJS(viewModel.graphSettingsViewModel.graph);
                    viewModel.report.resetConfigs(graph.config);
                    viewModel.report.get('template_id')(graph["template_id"]);
                }
            });

            viewModel.report = new ReportModel(_.extend(data, {
                graphModel: viewModel.graphModel,
                cards: viewModel.cardTree.topCards,
                preview: true
            }));

            viewModel.report.configJSON.subscribe(function(config) {
                var graph = koMapping.toJS(viewModel.graphSettingsViewModel.graph);
                graph.config = koMapping.toJS(config);
                koMapping.fromJS(graph, viewModel.graphSettingsViewModel.graph);
            });

            viewModel.report.configJSON.extend({deferred: true});

            viewModel.report.get('template_id').subscribe(function(val) {
                viewModel.graphSettingsViewModel.graph["template_id"](val);
            });

            viewModel.reportLookup = reportLookup;
            viewModel.reportTemplates = _.map(reportLookup, function(report, id) {
                report.id = id;
                return report;
            });

            viewModel.graphTree = new GraphTree({
                graphModel: viewModel.graphModel,
                graphSettings: viewModel.graphSettingsViewModel,
                cardTree: viewModel.cardTree,
                permissionTree: viewModel.permissionTree,
                appliedFunctions: viewModel.appliedFunctions,
                restrictedNodegroups: data.restrictedNodegroups
            });

            viewModel.graphTree.branchListVisible.subscribe(function(visible) {
                if (visible) {
                    viewModel.branchListView.loadDomainConnections();
                }
            }, this);

            viewModel.loadGraphSettings = function() {
                var self = this;
                viewModel.loading(true);
                $.ajax({
                    type: 'GET',
                    url: arches.urls.graph_settings(data.graphid),
                    data: {'search': true, 'csrfmiddlewaretoken': '{{ csrf_token }}'}})
                    .done(function(data) {
                        self.graphSettingsViewModel.resource_data(data.resources);
                        self.graphSettingsViewModel.icon_data(data.icons);
                        self.graphSettingsViewModel.jsonCache(self.graphSettingsViewModel.jsonData());
                        self.graphSettingsViewModel.contentLoading = viewModel.loading;
                        self.graphSettingsVisible(true);
                        viewModel.loading(false);
                    })
                    .fail(function() {
                        throw 'error loading graph settings';
                    });
            };

            var correspondingCard = function(item, cardTree){
                var cardList = cardTree.cachedFlatTree;
                if (cardList === undefined) {
                    var cardList = cardTree.flattenTree(cardTree.topCards(), []);
                    cardTree.cachedFlatTree = cardList;
                }
                var res;
                var matchingWidget;
                if (item && typeof item !== 'string') {
                    if (item.nodeGroupId) { //if the item is a node in graph tree
                        var matchingCards = _.filter(cardList, function(card){
                            return card.nodegroupid === item.nodeGroupId();
                        });
                        _.each(matchingCards, function(card){
                            var match;
                            match = _.find(card.widgets(), function(widget){
                                return widget.node_id() === item.nodeid;
                            });
                            if (match) {
                                matchingWidget = match;
                            }
                        });
                        if (matchingWidget) {
                            res = matchingWidget;
                        } else {
                            res = matchingCards[0];
                        }
                    } else { //if the item is a card or widget in the card tree
                        res = _.find(cardList, function(card){
                            if (item.nodegroupid) {
                                return card.nodegroupid === item.nodegroupid;
                            } else {
                                return card.nodegroupid === item.node.nodeGroupId();
                            }
                        });
                    }
                }
                return res;

            };

            var correspondingNode = function(card, graphTree){
                var nodeMatch;
                nodeMatch = _.find(graphTree.items(), function(node){
                    if (card) {
                        if (card.node) {
                            return node.nodeid === card.node_id();
                        } else {
                            return node.nodeGroupId() === card.nodegroupid && node.nodeid === node.nodeGroupId();
                        }
                    }
                });
                return nodeMatch;
            };

            var updateGraphSelection = function() {
                var matchingNode = correspondingNode(viewModel.cardTree.selection(), viewModel.graphTree);
                if (matchingNode) {
                    viewModel.graphTree.selectItem(matchingNode);
                }
            };

            var updateCardSelection = function() {
                var graphTreeSelection = viewModel.graphTree.selectedItems().length > 0 ? viewModel.graphTree.selectedItems()[0] : null;
                var matchingCard;
                if (graphTreeSelection) {
                    if (graphTreeSelection.istopnode === true) {
                        viewModel.cardTree.selection(viewModel.cardTree.topCards()[0]);
                    } else {
                        matchingCard = correspondingCard(graphTreeSelection, viewModel.cardTree);
                        if (matchingCard) {
                            viewModel.cardTree.selection(matchingCard);
                            viewModel.cardTree.expandToRoot(viewModel.cardTree.selection());
                        }
                    }
                }
            };

            var updatePermissionCardSelection = function() {
                var matchingCard = correspondingCard(viewModel.cardTree.selection(), viewModel.permissionTree);
                if (matchingCard) {
                    viewModel.permissionTree.expandToRoot(matchingCard);
                    viewModel.permissionTree.selection.removeAll();
                    matchingCard.selectChildCards();
                }
            };

            if (viewModel.activeTab() === 'graph') {
                viewModel.loadGraphSettings();
                // here we might load data/views asyncronously
            }

            var loadPermissionData = viewModel.activeTab.subscribe(function(tab) {
                // Loads identities and nodegroup permissions when the permissions tab is opened and then disposes the ko.subscribe.
                if (tab === 'permissions') {
                    viewModel.permissionsDesigner.getPermissionManagerData();
                    loadPermissionData.dispose();
                }
            });

            var helpContentLookup = {
                permissions: {
                    'title': 'xxxx', // dynamic title loading not implemented
                    'template': 'permissions-tab-help',
                },
                graph: {
                    'title': 'xxxx', // dynamic title loading not implemented
                    'template': 'graph-tab-help',
                },
                card: {
                    'title': 'xxxx', // dynamic title loading not implemented
                    'template': 'cards-tab-help',
                }
            };

            viewModel.activeTab.subscribe(function(tab) {
                viewModel.helpTemplate(helpContentLookup[tab]['template']);
                viewModel.getHelp();
                switch (tab) {
                case 'card':
                    updateCardSelection();
                    break;
                case 'graph':
                    updateGraphSelection();
                    break;
                case 'permissions':
                    updatePermissionCardSelection();
                    break;
                default:
                    return;
                }
            });

            viewModel.graphView = new GraphView({
                el: $('#graph'),
                graphModel: viewModel.graphModel,
                nodeSize: 15,
                nodeSizeOver: 20,
                labelOffset: 10,
                loading: this.loading
            });

            viewModel.graphModel.on('select-node', function(node) {
                viewModel.graphView.zoomTo(node);
                viewModel.graphTree.expandParentNode(node);
            });

            viewModel.showPreview = function() {
                viewModel.viewState('preview');
                viewModel.graphView.resize();
            };

            /**
            * update the sizing of elements on window resize
            */
            var resize = function() {
                $('.grid').height($(window).height() - 208);
                $('#graph').height($(window).height() - 100);
                if (!!viewModel.graphView) {
                    viewModel.graphView.resize();
                }
            };

            $(window).resize(resize);

            resize();

            BaseManagerView.prototype.initialize.apply(this, arguments);
        }
    });

    return new GraphDesignerView();
});
<|endoftext|>