<commit_before>

$(document).ready (function ()
{
	addEvents();
});

var text = "";
var counterMax = 10;
var counter = 0;
var quotes = [];

function addQuotes (item)
{
	$.tmpl( "quoteItemTmpl", item ).appendTo("#quotesList");
	$(".tag").on("click", function() {
		return $(this).hasClass('selected') ?  onTagFilter("") : onTagFilter(this.innerHTML);
	})
}

function addEvents ()
{
	var self = this;
	$(".searchField").keyup(function (e)
	{
		if (event.which == 13)
		{
			$("#quotesList").empty();
			quotes = [];
			self.doSearch($(this).val());
			counter = 0;
		}
	});

	$(".searchField").focus(function ()
	{
		$(this).val("");
	});
}

function doSearch (value, nextUrl)
{
	text = value;
	//$("#quotesList").empty();
	//$("#quotesList").append("
Searching...
");
	$("#progress").show();
	putSerch(text, onSearchResult, nextUrl);
}

function onSearchResult (result)
{
	for (var i=0; i<result.data.length; i++)
	{
		quotes.push(result.data[i]);
		if (!cxData) {
			$("#searchInfo").remove();
			$("#progress").hide();

			data = filterResult(quotes);
			addQuotes(data);

		} else {

			$("#searchInfo").remove();
			$("#progress").hide();

			data = filterAdd([result.data[i]]);
			addQuotes(data);

			$(".linkWrapper").empty();
			$(".linkWrapper").append("Quotes from this person");
			$(".linkWrapper").append("Quotes from other people in articles related to this person");

		}
	}

	if (result.next && counter < counterMax)
	{
		doSearch(text, result.next);
		counter++;
	}
	else
	{

		$("#searchInfo").remove();
		$("#progress").hide();

		//data = filterResult(quotes);
		addQuotes(data);

		$(".linkWrapper").empty();
		$(".linkWrapper").append("Quotes from this person");
		$(".linkWrapper").append("Quotes from other people in articles related to this person");

	}

}

function onRelatedLinks (useSpeaker)
{
	$("#quotesList").empty();
	filterBySpeaker(useSpeaker);

	var data = returnFilteredDataObj();
	addQuotes(data);

	if (useSpeaker) {
		$(".filterLinkOthers").removeClass('selected');
		$(".filterLinkSpeaker").addClass('selected');
	} else {
		$(".filterLinkSpeaker").removeClass('selected');
		$(".filterLinkOthers").addClass('selected');
	}

}

function onTagFilter (tag)
{
	$("#quotesList").empty();
	filterByTag(tag);
	var data = returnFilteredDataObj();
	addQuotes(data);
	if (!tag) {
		$(".tag").removeClass('selected')
	} else {
		$(".tag." + tag).addClass('selected');
	}
}<commit_msg>fix duplicates<commit_after>

$(document).ready (function ()
{
	addEvents();
});

var text = "";
var counterMax = 10;
var counter = 0;
var quotes = [];

function addQuotes (item)
{
	$.tmpl( "quoteItemTmpl", item ).appendTo("#quotesList");
	$(".tag").on("click", function() {
		return $(this).hasClass('selected') ?  onTagFilter("") : onTagFilter(this.innerHTML);
	})
}

function addEvents ()
{
	var self = this;
	$(".searchField").keyup(function (e)
	{
		if (event.which == 13)
		{
			$("#quotesList").empty();
			quotes = [];
			self.doSearch($(this).val());
			counter = 0;
		}
	});

	$(".searchField").focus(function ()
	{
		$(this).val("");
	});
}

function doSearch (value, nextUrl)
{
	text = value;
	//$("#quotesList").empty();
	//$("#quotesList").append("
Searching...
");
	$("#progress").show();
	putSerch(text, onSearchResult, nextUrl);
}

function onSearchResult (result)
{
	for (var i=0; i<result.data.length; i++)
	{
		quotes.push(result.data[i]);
		if (!cxData) {
			$("#searchInfo").remove();
			$("#progress").hide();
			$("#quotesList").empty();

			data = filterResult(quotes);
			addQuotes(data);

		} else {

			$("#searchInfo").remove();
			$("#progress").hide();
			$("#quotesList").empty();

			data = filterAdd([result.data[i]]);
			addQuotes(data);

			$(".linkWrapper").empty();
			$(".linkWrapper").append("Quotes from this person");
			$(".linkWrapper").append("Quotes from other people in articles related to this person");

		}
	}

	if (result.next && counter < counterMax)
	{
		doSearch(text, result.next);
		counter++;
	}
	else
	{

		$("#searchInfo").remove();
		$("#progress").hide();
		$("#quotesList").empty();

		//data = filterResult(quotes);
		addQuotes(data);

		$(".linkWrapper").empty();
		$(".linkWrapper").append("Quotes from this person");
		$(".linkWrapper").append("Quotes from other people in articles related to this person");

	}

}

function onRelatedLinks (useSpeaker)
{
	$("#quotesList").empty();
	filterBySpeaker(useSpeaker);

	var data = returnFilteredDataObj();
	addQuotes(data);

	if (useSpeaker) {
		$(".filterLinkOthers").removeClass('selected');
		$(".filterLinkSpeaker").addClass('selected');
	} else {
		$(".filterLinkSpeaker").removeClass('selected');
		$(".filterLinkOthers").addClass('selected');
	}

}

function onTagFilter (tag)
{
	$("#quotesList").empty();
	filterByTag(tag);
	var data = returnFilteredDataObj();
	addQuotes(data);
	if (!tag) {
		$(".tag").removeClass('selected')
	} else {
		$(".tag." + tag).addClass('selected');
	}
}<|endoftext|>


<commit_before>import angular from 'angular';
import _ from 'underscore';

angular.module('dimApp')
  .component('dimObjectives', Objectives())
  .directive('dimMoveItemProperties', MoveItemProperties);

function Objectives() {
  return {
    bindings: {
      objectives: '<'
    },
    template: [
      '
',
      '
',
      '
',
      '      = objective.progress, \'wins\': objective.completionValue === 9}">',
      '       9"> + {{ objective.progress - 9 }}',
      '
',
      '

',
      '
',
      '

',
      '
{{ objective.displayName || (objective.complete ? \'Complete\' : \'Incomplete\') }}
',
      '
{{ objective.display || (objective.progress + "/" + objective.completionValue) }}
',
      '
',
      '
',
      '
'
    ].join('')
  };
}

function MoveItemProperties() {
  return {
    bindToController: true,
    controller: MoveItemPropertiesCtrl,
    controllerAs: 'vm',
    scope: {
      item: '=dimMoveItemProperties',
      compareItem: '=dimCompareItem',
      infuse: '=dimInfuse',
      changeDetails: '&'
    },
    restrict: 'A',
    replace: true,
    template: [
      '
',
      '
',
      '
',
      '
',
      '
',
      '          ',
      '
',
      '
',
      '          ',
      '
',
      '
',
      '
',
      '        ',
      '          {{vm.item.name}}',
      '        ',
      '
',
      '      ',
      '
',
      '        ',
      '        ',
      '
',
      '
',
      '
',
      '
',
      '

',
      '
',
      '
{{vm.light}} {{::vm.classType}} {{::vm.item.typeName}}
',
      '

',
      '      <dim-item-tag ng-if="vm.featureFlags.tagsEnabled && vm.item.taggable" item="vm.item"></dim-item-tag>',
      '
',
      '
',
      '
',
      '

',
      '
',
      '  <form ng-if="vm.featureFlags.tagsEnabled && vm.item.taggable" name="notes"><textarea name="data" translate-attr="{ placeholder: \'Notes.Help\' }" class="item-notes" ng-maxlength="120" ng-model="vm.item.dimInfo.notes" ng-model-options="{ debounce: 250 }" ng-change="vm.updateNote()"></textarea></form>',
      '  ',
      '

',
      '

',
      '
',
      '
',
      '       {{ stat.name }} ',
      '      ',
      '        ',
      '        <span ng-if="stat.bar && stat.value && stat.value < stat.equippedStatsValue && stat.comparable" class="stat-box-inner" dim-percent-width="stat.value / stat.maximumValue">',
      '        <span ng-if="stat.bar && stat.value < stat.equippedStatsValue && stat.comparable" class="stat-box-inner lower-stats" dim-percent-width="(stat.equippedStatsValue - stat.value) / stat.maximumValue">',
      '         stat.equippedStatsValue && stat.comparable" class="stat-box-inner" dim-percent-width="stat.equippedStatsValue / stat.maximumValue">',
      '         stat.equippedStatsValue && stat.comparable" class="stat-box-inner higher-stats" dim-percent-width="(stat.value - stat.equippedStatsValue) / stat.maximumValue">',
      '         stat.equippedStatsValue), \'lower-stats\': (stat.value < stat.equippedStatsValue)}">{{ stat.value }}',
      '      ',
      '       stat.equippedStatsValue && stat.comparable), \'lower-stats\': (stat.value < stat.equippedStatsValue && stat.comparable)}" ng-show="{{ stat.bar }}">{{ stat.value }}',
      '        ({{ stat.qualityPercentage.range }})',
      '      ',
      '
',
      '
',
      '      ',
      '      ',
      '
',
      '
',
      '
',
      '    <dim-talent-grid talent-grid="vm.item.talentGrid" dim-infuse="vm.infuse(vm.item, $event)"></dim-talent-grid>',
      '
',
      '  <dim-objectives class="item-details" ng-if="vm.itemDetails" objectives="vm.item.objectives"></dim-objectives>',
      '
',
      '    ',
      '    <button ng-click="vm.dumpDebugInfo()" translate=Debug.Dump>',
      '
',
      '
'
    ].join('')
  };
}

function MoveItemPropertiesCtrl($sce, $q, dimStoreService, dimItemService, dimSettingsService, ngDialog, $scope, $rootScope, dimFeatureFlags, dimDefinitions) {
  var vm = this;

  vm.featureFlags = dimFeatureFlags;

  vm.hasDetails = (vm.item.stats && vm.item.stats.length) ||
    vm.item.talentGrid ||
    vm.item.objectives;
  vm.showDescription = true;// || (vm.item.description.length &&
  //    (!vm.item.equipment || (vm.item.objectives && vm.item.objectives.length)));
  vm.locking = false;

  // The 'i' keyboard shortcut toggles full details
  $scope.$on('dim-toggle-item-details', function() {
    vm.itemDetails = !vm.itemDetails;
    vm.changeDetails();
  });

  vm.openCompare = function() {
    ngDialog.closeAll();
    $rootScope.$broadcast('dim-store-item-compare', {
      item: vm.item,
      dupes: true
    });
  };

  vm.updateNote = function() {
    if (angular.isDefined(vm.item.dimInfo.notes)) {
      vm.item.dimInfo.save();
    }
  };

  vm.setItemState = function setItemState(item, type) {
    if (vm.locking) {
      return;
    }

    var store;
    if (item.owner === 'vault') {
      store = dimStoreService.getStores()[0];
    } else {
      store = dimStoreService.getStore(item.owner);
    }

    vm.locking = true;

    var state = false;
    if (type === 'lock') {
      state = !item.locked;
    } else if (type === 'track') {
      state = !item.tracked;
    }

    dimItemService.setItemState(item, store, state, type)
      .then(function(lockState) {
        if (type === 'lock') {
          item.locked = lockState;
        } else if (type === 'track') {
          item.tracked = lockState;
        }
        $rootScope.$broadcast('dim-filter-invalidate');
      })
      .finally(function() {
        vm.locking = false;
      });
  };

  vm.classes = {
    'is-arc': false,
    'is-solar': false,
    'is-void': false
  };

  vm.light = '';
  vm.classType = '';
  vm.showDetailsByDefault = (!vm.item.equipment && vm.item.notransfer);
  vm.itemDetails = vm.showDetailsByDefault;
  vm.settings = dimSettingsService;
  $scope.$watch('vm.settings.itemDetails', function(show) {
    vm.itemDetails = vm.itemDetails || show;
  });

  if (vm.item.primStat) {
    vm.light = vm.item.primStat.value.toString();
    vm.light += ' ' + vm.item.primStat.stat.statName;
    if (vm.item.dmg) {
      vm.classes['is-' + vm.item.dmg] = true;
    }
  }

  if (vm.item.classTypeName !== 'unknown' &&
      // These already include the class name
      vm.item.type !== 'ClassItem' &&
      vm.item.type !== 'Artifact' &&
      vm.item.type !== 'Class') {
    vm.classType = vm.item.classTypeName[0].toUpperCase() + vm.item.classTypeName.slice(1);
  }

  function compareItems(item) {
    if (item && vm.item.stats) {
      for (var key in Object.getOwnPropertyNames(vm.item.stats)) {
        var itemStats = item.stats && item.stats[key];
        if (itemStats) {
          var vmItemStats = vm.item.stats[key];
          if (vmItemStats) {
            vmItemStats.equippedStatsValue = itemStats.value;
            vmItemStats.equippedStatsName = itemStats.name;
            vmItemStats.comparable = vmItemStats.equippedStatsName === vmItemStats.name ||
              (vmItemStats.name === 'Magazine' && vmItemStats.equippedStatsName === 'Energy') ||
              (vmItemStats.name === 'Energy' && vmItemStats.equippedStatsName === 'Magazine');
          }
        }
      }
    }
  }

  /*
   * Get the item stats and its stat name
   * of the equipped item for comparison
   */
  if (vm.item.equipment) {
    if (vm.compareItem) {
      $scope.$watch('vm.compareItem', compareItems);
    } else {
      $scope.$watch('$parent.$parent.vm.store.items', function(items) {
        var item = _.find(items, function(item) {
          return item.equipped && item.type === vm.item.type;
        });
        compareItems(item);
      });
    }
  }

  vm.dumpDebugInfo = function() {
    console.log("DEBUG INFO for '" + vm.item.name + "'");
    console.log("DIM Item", vm.item);
    console.log("Bungie API Item", vm.item.originalItem || "Enable debug mode (ctrl+alt+shift+d) and refresh items to see this.");
    dimDefinitions.getDefinitions().then((defs) => {
      console.log("Manifest Item Definition", defs.InventoryItem.get(vm.item.hash));
    });
  };
}
<commit_msg>dropped this somewhere<commit_after>import angular from 'angular';
import _ from 'underscore';

angular.module('dimApp')
  .component('dimObjectives', Objectives())
  .directive('dimMoveItemProperties', MoveItemProperties);

function Objectives() {
  return {
    bindings: {
      objectives: '<'
    },
    template: [
      '
',
      '
',
      '
',
      '      = objective.progress, \'wins\': objective.completionValue === 9}">',
      '       9"> + {{ objective.progress - 9 }}',
      '
',
      '

',
      '
',
      '

',
      '
{{ objective.displayName || (objective.complete ? \'Complete\' : \'Incomplete\') }}
',
      '
{{ objective.display || (objective.progress + "/" + objective.completionValue) }}
',
      '
',
      '
',
      '
'
    ].join('')
  };
}

function MoveItemProperties() {
  return {
    bindToController: true,
    controller: MoveItemPropertiesCtrl,
    controllerAs: 'vm',
    scope: {
      item: '=dimMoveItemProperties',
      compareItem: '=dimCompareItem',
      infuse: '=dimInfuse',
      changeDetails: '&'
    },
    restrict: 'A',
    replace: true,
    template: [
      '
',
      '
',
      '
',
      '
',
      '
',
      '          ',
      '
',
      '
',
      '          ',
      '
',
      '
',
      '
',
      '        ',
      '          {{vm.item.name}}',
      '        ',
      '
',
      '      ',
      '
',
      '        ',
      '        ',
      '
',
      '
',
      '
',
      '
',
      '

',
      '
',
      '
{{vm.light}} {{::vm.classType}} {{::vm.item.typeName}}
',
      '

',
      '      <dim-item-tag ng-if="vm.featureFlags.tagsEnabled && vm.item.taggable" item="vm.item"></dim-item-tag>',
      '
',
      '
',
      '
',
      '

',
      '
',
      '  <form ng-if="vm.featureFlags.tagsEnabled && vm.item.taggable" name="notes"><textarea name="data" translate-attr="{ placeholder: \'Notes.Help\' }" class="item-notes" ng-maxlength="120" ng-model="vm.item.dimInfo.notes" ng-model-options="{ debounce: 250 }" ng-change="vm.updateNote()"></textarea></form>',
      '  ',
      '

',
      '

',
      '
',
      '
',
      '       {{ stat.name }} ',
      '      ',
      '        ',
      '        <span ng-if="stat.bar && stat.value && stat.value < stat.equippedStatsValue && stat.comparable" class="stat-box-inner" dim-percent-width="stat.value / stat.maximumValue">',
      '        <span ng-if="stat.bar && stat.value < stat.equippedStatsValue && stat.comparable" class="stat-box-inner lower-stats" dim-percent-width="(stat.equippedStatsValue - stat.value) / stat.maximumValue">',
      '         stat.equippedStatsValue && stat.comparable" class="stat-box-inner" dim-percent-width="stat.equippedStatsValue / stat.maximumValue">',
      '         stat.equippedStatsValue && stat.comparable" class="stat-box-inner higher-stats" dim-percent-width="(stat.value - stat.equippedStatsValue) / stat.maximumValue">',
      '         stat.equippedStatsValue), \'lower-stats\': (stat.value < stat.equippedStatsValue)}">{{ stat.value }}',
      '      ',
      '       stat.equippedStatsValue && stat.comparable), \'lower-stats\': (stat.value < stat.equippedStatsValue && stat.comparable)}" ng-show="{{ stat.bar }}">{{ stat.value }}',
      '        ({{ stat.qualityPercentage.range }})',
      '      ',
      '
',
      '
',
      '      ',
      '      ',
      '
',
      '
',
      '
',
      '    <dim-talent-grid talent-grid="vm.item.talentGrid" dim-infuse="vm.infuse(vm.item, $event)"></dim-talent-grid>',
      '
',
      '  <dim-objectives class="item-details" ng-if="vm.itemDetails" objectives="vm.item.objectives"></dim-objectives>',
      '
',
      '    ',
      '    <button ng-click="vm.dumpDebugInfo()" translate=Debug.Dump>',
      '
',
      '
'
    ].join('')
  };
}

function MoveItemPropertiesCtrl($sce, $q, dimStoreService, dimItemService, dimSettingsService, ngDialog, $scope, $rootScope, dimFeatureFlags, dimDefinitions) {
  var vm = this;

  vm.featureFlags = dimFeatureFlags;

  vm.hasDetails = (vm.item.stats && vm.item.stats.length) ||
    vm.item.talentGrid ||
    vm.item.objectives;
  vm.showDescription = true;// || (vm.item.description.length &&
  //    (!vm.item.equipment || (vm.item.objectives && vm.item.objectives.length)));
  vm.locking = false;

  // The 'i' keyboard shortcut toggles full details
  $scope.$on('dim-toggle-item-details', function() {
    vm.itemDetails = !vm.itemDetails;
    vm.changeDetails();
  });

  vm.openCompare = function() {
    ngDialog.closeAll();
    $rootScope.$broadcast('dim-store-item-compare', {
      item: vm.item,
      dupes: true
    });
  };

  vm.updateNote = function() {
    if (angular.isDefined(vm.item.dimInfo.notes)) {
      vm.item.dimInfo.save();
    }
  };

  vm.setItemState = function setItemState(item, type) {
    if (vm.locking) {
      return;
    }

    var store;
    if (item.owner === 'vault') {
      store = dimStoreService.getStores()[0];
    } else {
      store = dimStoreService.getStore(item.owner);
    }

    vm.locking = true;

    var state = false;
    if (type === 'lock') {
      state = !item.locked;
    } else if (type === 'track') {
      state = !item.tracked;
    }

    dimItemService.setItemState(item, store, state, type)
      .then(function(lockState) {
        if (type === 'lock') {
          item.locked = lockState;
        } else if (type === 'track') {
          item.tracked = lockState;
        }
        $rootScope.$broadcast('dim-filter-invalidate');
      })
      .finally(function() {
        vm.locking = false;
      });
  };

  vm.classes = {
    'is-arc': false,
    'is-solar': false,
    'is-void': false
  };

  vm.light = '';
  vm.classType = '';
  vm.showDetailsByDefault = (!vm.item.equipment && vm.item.notransfer);
  vm.itemDetails = vm.showDetailsByDefault;
  vm.settings = dimSettingsService;
  $scope.$watch('vm.settings.itemDetails', function(show) {
    vm.itemDetails = vm.itemDetails || show;
  });

  if (vm.item.primStat) {
    vm.light = vm.item.primStat.value.toString();
    vm.light += ' ' + vm.item.primStat.stat.statName;
    if (vm.item.dmg) {
      vm.classes['is-' + vm.item.dmg] = true;
    }
  }

  if (vm.item.classTypeName !== 'unknown' &&
      // These already include the class name
      vm.item.type !== 'ClassItem' &&
      vm.item.type !== 'Artifact' &&
      vm.item.type !== 'Class') {
    vm.classType = vm.item.classTypeNameLocalized[0].toUpperCase() + vm.item.classTypeNameLocalized.slice(1);
  }

  function compareItems(item) {
    if (item && vm.item.stats) {
      for (var key in Object.getOwnPropertyNames(vm.item.stats)) {
        var itemStats = item.stats && item.stats[key];
        if (itemStats) {
          var vmItemStats = vm.item.stats[key];
          if (vmItemStats) {
            vmItemStats.equippedStatsValue = itemStats.value;
            vmItemStats.equippedStatsName = itemStats.name;
            vmItemStats.comparable = vmItemStats.equippedStatsName === vmItemStats.name ||
              (vmItemStats.name === 'Magazine' && vmItemStats.equippedStatsName === 'Energy') ||
              (vmItemStats.name === 'Energy' && vmItemStats.equippedStatsName === 'Magazine');
          }
        }
      }
    }
  }

  /*
   * Get the item stats and its stat name
   * of the equipped item for comparison
   */
  if (vm.item.equipment) {
    if (vm.compareItem) {
      $scope.$watch('vm.compareItem', compareItems);
    } else {
      $scope.$watch('$parent.$parent.vm.store.items', function(items) {
        var item = _.find(items, function(item) {
          return item.equipped && item.type === vm.item.type;
        });
        compareItems(item);
      });
    }
  }

  vm.dumpDebugInfo = function() {
    console.log("DEBUG INFO for '" + vm.item.name + "'");
    console.log("DIM Item", vm.item);
    console.log("Bungie API Item", vm.item.originalItem || "Enable debug mode (ctrl+alt+shift+d) and refresh items to see this.");
    dimDefinitions.getDefinitions().then((defs) => {
      console.log("Manifest Item Definition", defs.InventoryItem.get(vm.item.hash));
    });
  };
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2014 TWO SIGMA INVESTMENTS, LLC
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * M_bkApp
 * This is the main module for the beaker notebook application. The module has a directive that holds the menu bar as
 * well as the notebook view. The module also owns the centralized cell evaluation logic.
 */
(function () {
    'use strict';
    var module = angular.module('M_bkApp', [
        'ngRoute',
        'ui.bootstrap',
        'M_angularUtils',
        'M_bkUtils',
        'M_cometd',
        'M_commonUI',
        'M_TreeView',
        'M_bkCore',
        'M_bkSession',
        'M_bkNotebook',
        'M_evaluatorManager',
        'M_menuPlugin',
        'M_bkCellPluginManager'
    ]);

    /**
     * bkApp
     * - This is the beaker App
     * - menus + plugins + notebook(notebook model + evaluator)
     */
    module.directive('bkApp', function () {
        return {
            restrict: 'E',
            templateUrl: "./template/bkApp.html",
            scope: {},
            controller: function (
                $scope,
                $routeParams,
                $location,
                $q,
                cometd,
                bkUtils,
                bkSession,
                evaluatorManager,
                menuPluginManager,
                bkCellPluginManager,
                bkBaseSessionModel,
                bkCoreManager,
                bkAppEvaluate)
            {
                var _impl = (function () {
                    var showTransientMessage = function (message) {
                        $scope.message = message;
                        bkUtils.delay(500).then(function () {
                            $scope.message = "";
                        });
                    };
                    var defaultSaveFunc = function (notebookModel) {
                        // by default pop up the file chooser for saving as 'file'
                        var deferred = $q.defer();
                        var saveAsFile = function (path) {
                            if (!path) {
                                deferred.reject("file save cancelled");
                            } else {
                                var saveFunc = bkCoreManager.getSaveFunc("file");
                                saveFunc(path, notebookModel).then(function () {
                                    bkHelper.setSaveFunction(function (notebookModel) {
                                        return saveFunc(path, notebookModel);
                                    });
                                    document.title = path.replace(/^.*[\\\/]/, '');
                                    deferred.resolve();
                                });
                            }
                        };
                        bkHelper.showFileChooser(saveAsFile, 'template/saveAsMenuModal.html');
                        return deferred.promise;
                    };
                    var _saveFunc = defaultSaveFunc;
                    var _pathOpeners = {};

                    return {
                        loadNotebook: function (notebookModel, alwaysCreateNewEvaluators, notebookUri, sessionID) {
                            if (angular.isString(notebookModel)) {
                                try {
                                    notebookModel = angular.fromJson(notebookModel);
                                    // TODO, to be removed. Addressing loading a corrupted notebook.
                                    if (angular.isString(notebookModel)) {
                                        notebookModel = angular.fromJson(notebookModel);
                                        bkCoreManager.log("corrupted-notebook", { notebookUri: notebookUri });
                                    }
                                } catch (e) {
                                    console.error(e);
                                    console.error("This is not a valid Beaker notebook JSON");
                                    console.error(notebookModel);
                                    window.alert("Not a valid Beaker notebook");
                                    return;
                                }
                            }

                            // Backup current session if it's not empty.
                            if (bkBaseSessionModel.getSessionID() &&
                                Object.keys(bkBaseSessionModel.getNotebookModel()).length > 0) {
                                bkSession.backupSession(bkBaseSessionModel.getSessionData());
                            }

                            evaluatorManager.reset();
                            if (!sessionID) {
                                sessionID = bkUtils.generateID(6);
                            }
                            bkBaseSessionModel.setSessionID(sessionID);
                            if (notebookModel && notebookModel.evaluators) {
                                for (var i = 0; i < notebookModel.evaluators.length; ++i) {
                                    evaluatorManager.newEvaluator(notebookModel.evaluators[i], alwaysCreateNewEvaluators);
                                }
                            }
                            bkBaseSessionModel.setNotebookModel(notebookModel);
                            bkBaseSessionModel.setNotebookUrl(notebookUri);
                            bkCoreManager.recordRecentDocument(notebookUri);
                            $scope.loading = false;

                            // TODO, the following is a hacky solution to address the issue that
                            // somehow the notebook is scrolled to the middle
                            // this hack listens to the 'scroll' event and scrolls it to the top
                            // A better solution is to do this when Angular stops firing and DOM updates finish.
                            // A even better solution would be to get rid of the unwanted scrolling in the first place.
                            // A even even better solution is the session actually remembers where the scrolling was
                            // and scroll to there and in the case of starting a new session (i.e. loading a notebook from file)
                            // scroll to top.
                            var listener = function(ev) {
                                window.scrollTo(0, 0);
                                window.removeEventListener('scroll', listener, false);
                            };
                            window.addEventListener('scroll', listener, false);
                        },
                        closeNotebook: function () {
                            var self = this;
                            var sessionID = bkBaseSessionModel.getSessionID();
                            var closeSession = function () {
                                bkSession.closeSession(sessionID).then(function () {
                                    evaluatorManager.exitAllEvaluators();
                                    bkBaseSessionModel.clearSession();
                                    self.setSaveFunction(defaultSaveFunc);
                                    $location.path("/control");
                                    bkCoreManager.refreshRootScope();
                                });
                            };
                            if (bkBaseSessionModel.isEdited() === false) {
                                closeSession();
                            } else {
                                var notebookUri= bkBaseSessionModel.getSessionData().notebookurl;
                                var notebookName = notebookUri ? notebookUri.replace(/^.*[\\\/]/, '') : "[New Notebook]";
                                bkHelper.showYesNoCancelModal(
                                    "Do you want to save " + notebookName + "?",
                                    "Confirm close",
                                    function () {
                                        self.saveNotebook().then(closeSession);
                                    },
                                    function () {
                                        console.log("close without saving");
                                        closeSession();
                                    },
                                    null,
                                    "Save",
                                    "Don't save"
                                );
                            }
                        },
                        // Save
                        setSaveFunction: function (saveFunc) {
                            _saveFunc = saveFunc;
                        },
                        getSaveFunction: function () {
                            return _saveFunc ? _saveFunc : defaultSaveFunc;
                        },
                        saveNotebook: function () {
                            var deferred = $q.defer();
                            $scope.message = "Saving";
                            var saveFunc = this.getSaveFunction();
                            var notebookModel = bkBaseSessionModel.getNotebookModel();
                            saveFunc(notebookModel).then(
                                function () {
                                    bkBaseSessionModel.setEdited(false);
                                    showTransientMessage("Saved");
                                    deferred.resolve(arguments);
                                },
                                function (msg) {
                                    showTransientMessage("Cancelled");
                                    deferred.reject();
                                });
                            return deferred.promise;
                        },
                        // Open
                        setPathOpener: function (pathType, opener) {
                            _pathOpeners[pathType] = opener;
                        },
                        openPath: function (path, pathType, retry, timeout) {
                            if (!path) {
                                return;
                            }
                            $scope.loading = true;
                            if (timeout === undefined) {
                                timeout = 100;
                            }
                            var self = this;
                            // XXX BEAKER-516 pathtype should be saved
                            // explicitly so we don't have to deduce them.
                            if (!pathType) {
                                pathType = path.substring(0, path.indexOf(':/')) || "file";
                            }
                            if (_pathOpeners[pathType]) {
                                _pathOpeners[pathType].open(path);
                            } else {
                                if (retry) {
                                    setTimeout(function () {
                                        self.openPath(path, pathType, retry, timeout - 1);
                                    }, 100);
                                } else {
                                    alert("Failed to open " + path
                                        + " because path type " + pathType
                                        + " was not recognized.");
                                }
                            }
                        },
                        evaluate: function (toEval) {
                            var cellOp = bkBaseSessionModel.cellOp;
                            // toEval can be a tagName (string)
                            // or a cellID (string)
                            // or a cellModel
                            // or an array of cellModels
                            if (typeof toEval === "string") {
                                if (cellOp.getCell(toEval)) {
                                    // this is a cellID
                                    if (cellOp.isContainer(toEval)) {
                                        // this is a section cell, in this case toEval is going to be an array of cellModel
                                        var cellIDs = bkBaseSessionModel.hierachicalLayout.getAllCellsInOrder(toEval);
                                        toEval = _.map(cellIDs, function (cellID) {
                                            return cellOp.getCell(cellID);
                                        });
                                    } else {
                                        // single cell, just get the cell model from cellID
                                        toEval = cellOp.getCell(toEval);
                                    }
                                } else {
                                    // not a cellID, assuming it is a tagName
                                    // in this case toEval is going to be an array of cellModel
                                    var cellIDs = bkBaseSessionModel.hierachicalLayout.getTaggedCellsInOrder(toEval);
                                    toEval = _.map(cellIDs, function (cellID) {
                                        return cellOp.getCell(cellID);
                                    });
                                }
                            }
                            if (!_.isArray(toEval)) {
                                return bkAppEvaluate.evaluate(toEval);
                            } else {
                                return bkAppEvaluate.evaluateAll(toEval);
                            }
                        },
                        evaluateCode: function (evaluator, code) {
                            // TODO, this isn't able to give back the evaluate result right now.
                            return bkAppEvaluate.evaluate({
                                evaluator: evaluator,
                                input: { body: code },
                                output: {}
                            });
                        }
                    };
                })();
                $scope.isEdited = function () {
                    return bkBaseSessionModel.isEdited();
                };
                $scope.$watch('isEdited()', function (edited, oldValue) {
                    if (edited) {
                        if (document.title[0] !== '*') {
                            document.title = "*" + document.title;
                        }
                    } else {
                        if (document.title[0] === '*') {
                            document.title = document.title.substring(1, document.title.length - 1);
                        }
                    }
                });

                bkCoreManager.setBkAppImpl(_impl);
                var intervalID = null;
                var stopAutoBackup = function () {
                    if (intervalID) {
                        clearInterval(intervalID);
                    }
                    intervalID = null;
                };
                var startAutoBackup = function () {
                    stopAutoBackup();
                    intervalID = setInterval(function () {
                        bkSession.backupSession(bkBaseSessionModel.getSessionData());
                    }, 60 * 1000);
                };
                $scope.getMenus = function () {
                    return menuPluginManager.getMenus();
                };
                var keydownHandler = function (e) {
                    if (e.ctrlKey && (e.which === 83)) {
                        e.preventDefault();
                        _impl.saveNotebook();
                        return false;
                    }
                };
                $(document).bind('keydown', keydownHandler);
                var onDestroy = function () {
                    bkSession.backupSession(bkBaseSessionModel.getSessionData());
                    stopAutoBackup();
                    bkCoreManager.setBkAppImpl(null);
                    $(document).unbind('keydown', keydownHandler);
                };
                // TODO, when use setLocation and leave from bkApp (e.g. to control panel),
                // we should warn and cancel evals
                /*var onLeave = function () {
                    if (bkAppEvaluate.isAnyInProgress()) {
                        bkHelper.showOkCancelModal(
                            "All in-progress and pending eval will be cancelled.",
                            "Warning!",
                            function () {
                                bkAppEvaluate.cancel();
                            }
                        );
                    }
                };*/
                $scope.$on("$destroy", onDestroy);
                window.onbeforeunload = function (e) {
                    // TODO, we should warn users, but I can't find a way to properly perform cancel after warning
                    bkAppEvaluate.cancel();

                    onDestroy();

//                    if (bkAppEvaluate.isAnyInProgress()) {
//                        return "Are you sure? All in-progress and pending evaluation will be cancelled";
//                    }
                };
                startAutoBackup();
                $scope.gotoControlPanel = function (event) {
                    if (event.button === 1) {
                        window.open("./");
                    } else {
                        bkCoreManager.gotoControlPanel();
                    }
                };

                cometd.addStatusListener(function (msg) {
                    if (msg.successful !== !$scope.disconnected) {
                        $scope.disconnected = !msg.successful;
                        $scope.$apply();
                    }
                });
                $scope.message = "";

                menuPluginManager.reset();
                bkCellPluginManager.reset();

                $scope.loading = true;
                // set the notebook model to empty so the UI is blank instead of leftover from previous model
                bkBaseSessionModel.setNotebookModel({});
                bkBaseSessionModel.setEdited(false);
                var sessionID = $routeParams.sessionID;
                if (sessionID) {
                    if (sessionID === "new") {
                        bkCoreManager.newDefaultNotebook(function (notebookJSON) {
                            _impl.loadNotebook(notebookJSON, true);
                            document.title = "New Notebook";
                        });
                    } else if (sessionID === "none") {
                        // do nothing
                    } else {
                        bkSession.loadSession(sessionID).then(function (ret) {
                            var notebookJson = ret.content;
                            var notebookUri = ret.notebookurl;
                            var notebookUriType = notebookUri ? notebookUri.substring(0, notebookUri.indexOf(':/')) || "file" : "file";
                            _impl.loadNotebook(notebookJson, false, notebookUri, sessionID);
                            _impl.setSaveFunction(function (notebookModel) {
                                var saveFunc = bkCoreManager.getSaveFunc(notebookUriType);
                                return saveFunc(notebookUri, notebookModel);
                            });
                            if (!notebookUri) {
                                document.title = "New Notebook";
                            } else {
                                document.title = notebookUri.replace(/^.*[\\\/]/, '');
                            }
                            bkBaseSessionModel.setEdited(ret.edited);
                        });
                    }
                } else {
                    var pathType = "";
                    var path = decodeURIComponent($routeParams.path);
                    _impl.openPath(path, undefined, true);
                }
            }
        };
    });

    module.factory('bkAppEvaluate', function (bkUtils, evaluatorManager) {

        var setOutputCellText = function (cell, text) {
            if (!cell.output) {
                cell.output = {};
            }
            cell.output.result = text;
        };
        var _promise = bkUtils.newPromise();
        var _theEvaluator = null;
        var _evaluate = function (cell) {
            if (!cell.evaluator) {
                return;
            }
            var lastPromise = _promise;
            setOutputCellText(cell, "pending");
            var evaluateCell = function () {
                var evaluator = evaluatorManager.getEvaluator(cell.evaluator);
                bkUtils.log("evaluate", {plugin: evaluator.evaluator.pluginName,
                                         length: cell.input.body.length});
                if (evaluator) {
                    var evalP = lastPromise.then(function () {
                        _theEvaluator = evaluator.evaluator;
                        return _theEvaluator.evaluate(cell.input.body, cell.output);
                    });
                    evalP.catch(function (ret) {
                        if (cell.output && cell.output.result === "pending") {
                            cell.output.result = "";
                        }
                    });
                    evalP.finally(function () {
                        _theEvaluator = null;
                    });
                    return evalP;
                } else {
                    setOutputCellText(cell, "waiting for evaluator initialization ...");
                    return bkUtils.delay(500).then(function () {
                        return evaluateCell();
                    });
                }
            };
            _promise = evaluateCell();
            return _promise;
        };

        return {
            evaluate: function (cell) {
                return _evaluate(cell);
            },
            evaluateAll: function (cells) {
                _(cells).each(_evaluate);
                return _promise;
            },
            isCancellable: function () {
                return !!(_theEvaluator && _theEvaluator.cancelExecution);
            },
            cancel: function () {
                if (_theEvaluator) {
                    if (_theEvaluator.cancelExecution) {
                        _theEvaluator.cancelExecution();
                        _promise = bkUtils.newPromise();
                    } else {
                        throw "cancel is not supported for the current evaluator";
                    }
                }
            },
            isAnyInProgress: function () {
                //return _promise.isPending();
                return !!_theEvaluator;
            }
        };
    });
})();
<commit_msg>Make (ctrl/command+click) do the same as middle click for upper left logo<commit_after>/*
 *  Copyright 2014 TWO SIGMA INVESTMENTS, LLC
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * M_bkApp
 * This is the main module for the beaker notebook application. The module has a directive that holds the menu bar as
 * well as the notebook view. The module also owns the centralized cell evaluation logic.
 */
(function () {
    'use strict';
    var module = angular.module('M_bkApp', [
        'ngRoute',
        'ui.bootstrap',
        'M_angularUtils',
        'M_bkUtils',
        'M_cometd',
        'M_commonUI',
        'M_TreeView',
        'M_bkCore',
        'M_bkSession',
        'M_bkNotebook',
        'M_evaluatorManager',
        'M_menuPlugin',
        'M_bkCellPluginManager'
    ]);

    /**
     * bkApp
     * - This is the beaker App
     * - menus + plugins + notebook(notebook model + evaluator)
     */
    module.directive('bkApp', function () {
        return {
            restrict: 'E',
            templateUrl: "./template/bkApp.html",
            scope: {},
            controller: function (
                $scope,
                $routeParams,
                $location,
                $q,
                cometd,
                bkUtils,
                bkSession,
                evaluatorManager,
                menuPluginManager,
                bkCellPluginManager,
                bkBaseSessionModel,
                bkCoreManager,
                bkAppEvaluate)
            {
                var _impl = (function () {
                    var showTransientMessage = function (message) {
                        $scope.message = message;
                        bkUtils.delay(500).then(function () {
                            $scope.message = "";
                        });
                    };
                    var defaultSaveFunc = function (notebookModel) {
                        // by default pop up the file chooser for saving as 'file'
                        var deferred = $q.defer();
                        var saveAsFile = function (path) {
                            if (!path) {
                                deferred.reject("file save cancelled");
                            } else {
                                var saveFunc = bkCoreManager.getSaveFunc("file");
                                saveFunc(path, notebookModel).then(function () {
                                    bkHelper.setSaveFunction(function (notebookModel) {
                                        return saveFunc(path, notebookModel);
                                    });
                                    document.title = path.replace(/^.*[\\\/]/, '');
                                    deferred.resolve();
                                });
                            }
                        };
                        bkHelper.showFileChooser(saveAsFile, 'template/saveAsMenuModal.html');
                        return deferred.promise;
                    };
                    var _saveFunc = defaultSaveFunc;
                    var _pathOpeners = {};

                    return {
                        loadNotebook: function (notebookModel, alwaysCreateNewEvaluators, notebookUri, sessionID) {
                            if (angular.isString(notebookModel)) {
                                try {
                                    notebookModel = angular.fromJson(notebookModel);
                                    // TODO, to be removed. Addressing loading a corrupted notebook.
                                    if (angular.isString(notebookModel)) {
                                        notebookModel = angular.fromJson(notebookModel);
                                        bkCoreManager.log("corrupted-notebook", { notebookUri: notebookUri });
                                    }
                                } catch (e) {
                                    console.error(e);
                                    console.error("This is not a valid Beaker notebook JSON");
                                    console.error(notebookModel);
                                    window.alert("Not a valid Beaker notebook");
                                    return;
                                }
                            }

                            // Backup current session if it's not empty.
                            if (bkBaseSessionModel.getSessionID() &&
                                Object.keys(bkBaseSessionModel.getNotebookModel()).length > 0) {
                                bkSession.backupSession(bkBaseSessionModel.getSessionData());
                            }

                            evaluatorManager.reset();
                            if (!sessionID) {
                                sessionID = bkUtils.generateID(6);
                            }
                            bkBaseSessionModel.setSessionID(sessionID);
                            if (notebookModel && notebookModel.evaluators) {
                                for (var i = 0; i < notebookModel.evaluators.length; ++i) {
                                    evaluatorManager.newEvaluator(notebookModel.evaluators[i], alwaysCreateNewEvaluators);
                                }
                            }
                            bkBaseSessionModel.setNotebookModel(notebookModel);
                            bkBaseSessionModel.setNotebookUrl(notebookUri);
                            bkCoreManager.recordRecentDocument(notebookUri);
                            $scope.loading = false;

                            // TODO, the following is a hacky solution to address the issue that
                            // somehow the notebook is scrolled to the middle
                            // this hack listens to the 'scroll' event and scrolls it to the top
                            // A better solution is to do this when Angular stops firing and DOM updates finish.
                            // A even better solution would be to get rid of the unwanted scrolling in the first place.
                            // A even even better solution is the session actually remembers where the scrolling was
                            // and scroll to there and in the case of starting a new session (i.e. loading a notebook from file)
                            // scroll to top.
                            var listener = function(ev) {
                                window.scrollTo(0, 0);
                                window.removeEventListener('scroll', listener, false);
                            };
                            window.addEventListener('scroll', listener, false);
                        },
                        closeNotebook: function () {
                            var self = this;
                            var sessionID = bkBaseSessionModel.getSessionID();
                            var closeSession = function () {
                                bkSession.closeSession(sessionID).then(function () {
                                    evaluatorManager.exitAllEvaluators();
                                    bkBaseSessionModel.clearSession();
                                    self.setSaveFunction(defaultSaveFunc);
                                    $location.path("/control");
                                    bkCoreManager.refreshRootScope();
                                });
                            };
                            if (bkBaseSessionModel.isEdited() === false) {
                                closeSession();
                            } else {
                                var notebookUri= bkBaseSessionModel.getSessionData().notebookurl;
                                var notebookName = notebookUri ? notebookUri.replace(/^.*[\\\/]/, '') : "[New Notebook]";
                                bkHelper.showYesNoCancelModal(
                                    "Do you want to save " + notebookName + "?",
                                    "Confirm close",
                                    function () {
                                        self.saveNotebook().then(closeSession);
                                    },
                                    function () {
                                        console.log("close without saving");
                                        closeSession();
                                    },
                                    null,
                                    "Save",
                                    "Don't save"
                                );
                            }
                        },
                        // Save
                        setSaveFunction: function (saveFunc) {
                            _saveFunc = saveFunc;
                        },
                        getSaveFunction: function () {
                            return _saveFunc ? _saveFunc : defaultSaveFunc;
                        },
                        saveNotebook: function () {
                            var deferred = $q.defer();
                            $scope.message = "Saving";
                            var saveFunc = this.getSaveFunction();
                            var notebookModel = bkBaseSessionModel.getNotebookModel();
                            saveFunc(notebookModel).then(
                                function () {
                                    bkBaseSessionModel.setEdited(false);
                                    showTransientMessage("Saved");
                                    deferred.resolve(arguments);
                                },
                                function (msg) {
                                    showTransientMessage("Cancelled");
                                    deferred.reject();
                                });
                            return deferred.promise;
                        },
                        // Open
                        setPathOpener: function (pathType, opener) {
                            _pathOpeners[pathType] = opener;
                        },
                        openPath: function (path, pathType, retry, timeout) {
                            if (!path) {
                                return;
                            }
                            $scope.loading = true;
                            if (timeout === undefined) {
                                timeout = 100;
                            }
                            var self = this;
                            // XXX BEAKER-516 pathtype should be saved
                            // explicitly so we don't have to deduce them.
                            if (!pathType) {
                                pathType = path.substring(0, path.indexOf(':/')) || "file";
                            }
                            if (_pathOpeners[pathType]) {
                                _pathOpeners[pathType].open(path);
                            } else {
                                if (retry) {
                                    setTimeout(function () {
                                        self.openPath(path, pathType, retry, timeout - 1);
                                    }, 100);
                                } else {
                                    alert("Failed to open " + path
                                        + " because path type " + pathType
                                        + " was not recognized.");
                                }
                            }
                        },
                        evaluate: function (toEval) {
                            var cellOp = bkBaseSessionModel.cellOp;
                            // toEval can be a tagName (string)
                            // or a cellID (string)
                            // or a cellModel
                            // or an array of cellModels
                            if (typeof toEval === "string") {
                                if (cellOp.getCell(toEval)) {
                                    // this is a cellID
                                    if (cellOp.isContainer(toEval)) {
                                        // this is a section cell, in this case toEval is going to be an array of cellModel
                                        var cellIDs = bkBaseSessionModel.hierachicalLayout.getAllCellsInOrder(toEval);
                                        toEval = _.map(cellIDs, function (cellID) {
                                            return cellOp.getCell(cellID);
                                        });
                                    } else {
                                        // single cell, just get the cell model from cellID
                                        toEval = cellOp.getCell(toEval);
                                    }
                                } else {
                                    // not a cellID, assuming it is a tagName
                                    // in this case toEval is going to be an array of cellModel
                                    var cellIDs = bkBaseSessionModel.hierachicalLayout.getTaggedCellsInOrder(toEval);
                                    toEval = _.map(cellIDs, function (cellID) {
                                        return cellOp.getCell(cellID);
                                    });
                                }
                            }
                            if (!_.isArray(toEval)) {
                                return bkAppEvaluate.evaluate(toEval);
                            } else {
                                return bkAppEvaluate.evaluateAll(toEval);
                            }
                        },
                        evaluateCode: function (evaluator, code) {
                            // TODO, this isn't able to give back the evaluate result right now.
                            return bkAppEvaluate.evaluate({
                                evaluator: evaluator,
                                input: { body: code },
                                output: {}
                            });
                        }
                    };
                })();
                $scope.isEdited = function () {
                    return bkBaseSessionModel.isEdited();
                };
                $scope.$watch('isEdited()', function (edited, oldValue) {
                    if (edited) {
                        if (document.title[0] !== '*') {
                            document.title = "*" + document.title;
                        }
                    } else {
                        if (document.title[0] === '*') {
                            document.title = document.title.substring(1, document.title.length - 1);
                        }
                    }
                });

                bkCoreManager.setBkAppImpl(_impl);
                var intervalID = null;
                var stopAutoBackup = function () {
                    if (intervalID) {
                        clearInterval(intervalID);
                    }
                    intervalID = null;
                };
                var startAutoBackup = function () {
                    stopAutoBackup();
                    intervalID = setInterval(function () {
                        bkSession.backupSession(bkBaseSessionModel.getSessionData());
                    }, 60 * 1000);
                };
                $scope.getMenus = function () {
                    return menuPluginManager.getMenus();
                };
                var keydownHandler = function (e) {
                    if (e.ctrlKey && (e.which === 83)) {
                        e.preventDefault();
                        _impl.saveNotebook();
                        return false;
                    }
                };
                $(document).bind('keydown', keydownHandler);
                var onDestroy = function () {
                    bkSession.backupSession(bkBaseSessionModel.getSessionData());
                    stopAutoBackup();
                    bkCoreManager.setBkAppImpl(null);
                    $(document).unbind('keydown', keydownHandler);
                };
                // TODO, when use setLocation and leave from bkApp (e.g. to control panel),
                // we should warn and cancel evals
                /*var onLeave = function () {
                    if (bkAppEvaluate.isAnyInProgress()) {
                        bkHelper.showOkCancelModal(
                            "All in-progress and pending eval will be cancelled.",
                            "Warning!",
                            function () {
                                bkAppEvaluate.cancel();
                            }
                        );
                    }
                };*/
                $scope.$on("$destroy", onDestroy);
                window.onbeforeunload = function (e) {
                    // TODO, we should warn users, but I can't find a way to properly perform cancel after warning
                    bkAppEvaluate.cancel();

                    onDestroy();

//                    if (bkAppEvaluate.isAnyInProgress()) {
//                        return "Are you sure? All in-progress and pending evaluation will be cancelled";
//                    }
                };
                startAutoBackup();
                $scope.gotoControlPanel = function (event) {
                    if (event.button === 1 // middle click
                        || (event.button === 0 // left click
                            && (navigator.appVersion.indexOf("Mac")!= -1 ? event.metaKey : event.ctrlKey))) {
                        window.open("./");
                    } else {
                        bkCoreManager.gotoControlPanel();
                    }
                };

                cometd.addStatusListener(function (msg) {
                    if (msg.successful !== !$scope.disconnected) {
                        $scope.disconnected = !msg.successful;
                        $scope.$apply();
                    }
                });
                $scope.message = "";

                menuPluginManager.reset();
                bkCellPluginManager.reset();

                $scope.loading = true;
                // set the notebook model to empty so the UI is blank instead of leftover from previous model
                bkBaseSessionModel.setNotebookModel({});
                bkBaseSessionModel.setEdited(false);
                var sessionID = $routeParams.sessionID;
                if (sessionID) {
                    if (sessionID === "new") {
                        bkCoreManager.newDefaultNotebook(function (notebookJSON) {
                            _impl.loadNotebook(notebookJSON, true);
                            document.title = "New Notebook";
                        });
                    } else if (sessionID === "none") {
                        // do nothing
                    } else {
                        bkSession.loadSession(sessionID).then(function (ret) {
                            var notebookJson = ret.content;
                            var notebookUri = ret.notebookurl;
                            var notebookUriType = notebookUri ? notebookUri.substring(0, notebookUri.indexOf(':/')) || "file" : "file";
                            _impl.loadNotebook(notebookJson, false, notebookUri, sessionID);
                            _impl.setSaveFunction(function (notebookModel) {
                                var saveFunc = bkCoreManager.getSaveFunc(notebookUriType);
                                return saveFunc(notebookUri, notebookModel);
                            });
                            if (!notebookUri) {
                                document.title = "New Notebook";
                            } else {
                                document.title = notebookUri.replace(/^.*[\\\/]/, '');
                            }
                            bkBaseSessionModel.setEdited(ret.edited);
                        });
                    }
                } else {
                    var pathType = "";
                    var path = decodeURIComponent($routeParams.path);
                    _impl.openPath(path, undefined, true);
                }
            }
        };
    });

    module.factory('bkAppEvaluate', function (bkUtils, evaluatorManager) {

        var setOutputCellText = function (cell, text) {
            if (!cell.output) {
                cell.output = {};
            }
            cell.output.result = text;
        };
        var _promise = bkUtils.newPromise();
        var _theEvaluator = null;
        var _evaluate = function (cell) {
            if (!cell.evaluator) {
                return;
            }
            var lastPromise = _promise;
            setOutputCellText(cell, "pending");
            var evaluateCell = function () {
                var evaluator = evaluatorManager.getEvaluator(cell.evaluator);
                bkUtils.log("evaluate", {plugin: evaluator.evaluator.pluginName,
                                         length: cell.input.body.length});
                if (evaluator) {
                    var evalP = lastPromise.then(function () {
                        _theEvaluator = evaluator.evaluator;
                        return _theEvaluator.evaluate(cell.input.body, cell.output);
                    });
                    evalP.catch(function (ret) {
                        if (cell.output && cell.output.result === "pending") {
                            cell.output.result = "";
                        }
                    });
                    evalP.finally(function () {
                        _theEvaluator = null;
                    });
                    return evalP;
                } else {
                    setOutputCellText(cell, "waiting for evaluator initialization ...");
                    return bkUtils.delay(500).then(function () {
                        return evaluateCell();
                    });
                }
            };
            _promise = evaluateCell();
            return _promise;
        };

        return {
            evaluate: function (cell) {
                return _evaluate(cell);
            },
            evaluateAll: function (cells) {
                _(cells).each(_evaluate);
                return _promise;
            },
            isCancellable: function () {
                return !!(_theEvaluator && _theEvaluator.cancelExecution);
            },
            cancel: function () {
                if (_theEvaluator) {
                    if (_theEvaluator.cancelExecution) {
                        _theEvaluator.cancelExecution();
                        _promise = bkUtils.newPromise();
                    } else {
                        throw "cancel is not supported for the current evaluator";
                    }
                }
            },
            isAnyInProgress: function () {
                //return _promise.isPending();
                return !!_theEvaluator;
            }
        };
    });
})();
<|endoftext|>


<commit_before>import React                   from 'react';
import ButtonBar               from '../../../../../../panels/ButtonBar';
import defaultServerParameters from '../../../../../../panels/run/defaults';
import RunClusterFrom          from '../../../../../../panels/run';
import ClusterPayloads         from '../../../../../../utils/ClusterPayload';
import RuntimeBackend          from '../../../panels/RuntimeBackend';

import merge                   from 'mout/src/object/merge';

import { connect } from 'react-redux';
import get          from 'mout/src/object/get';
import { dispatch } from '../../../../../../redux';
import * as Actions from '../../../../../../redux/actions/taskflows';

const SimulationStart = React.createClass({

  displayName: 'pyfr/common/steps/Simulation/Start',

  propTypes: {
    location: React.PropTypes.object,
    project: React.PropTypes.object,
    simulation: React.PropTypes.object,
    step: React.PropTypes.string,
    taskFlowName: React.PropTypes.string,
    primaryJob: React.PropTypes.string,
    view: React.PropTypes.string,

    error: React.PropTypes.string,
    tradClusters: React.PropTypes.object,
    ec2Clusters: React.PropTypes.object,
    onRun: React.PropTypes.func,
  },

  getInitialState() {
    return {
      serverType: 'Traditional',
      EC2: defaultServerParameters.EC2,
      Traditional: defaultServerParameters.Traditional,
      OpenStack: defaultServerParameters.OpenStack,

      backend: {},
      error: '',
    };
  },

  dataChange(key, value, which) {
    var profile = this.state[which];
    profile[key] = value;
    this.setState({ [which]: profile });
  },

  runSimulation() {
    const meshFile = this.props.simulation.metadata.inputFolder.files.mesh || this.props.project.metadata.inputFolder.files.mesh;
    var clusterName,
      sessionId = btoa(new Float64Array(3).map(Math.random)).substring(0, 96),
      payload;

    if (this.state.serverType === 'Traditional') {
      clusterName = this.props.tradClusters[this.state[this.state.serverType].profile].name;
      payload = Object.assign({},
        this.state[this.state.serverType].runtime || {},
        {
          backend: this.state.backend,
          input: {
            folder: {
              id: this.props.simulation.metadata.inputFolder._id,
            },
            meshFile: {
              id: meshFile,
            },
            iniFile: {
              id: this.props.simulation.metadata.inputFolder.files.ini,
            },
          },
          output: {
            folder: {
              id: this.props.simulation.metadata.outputFolder._id,
            },
          },
          cluster: ClusterPayloads.tradClusterPayload(this.state[this.state.serverType].profile),
        });
    } else if (this.state.serverType === 'EC2') {
      payload = Object.assign({},
        this.state[this.state.serverType].runtime || {},
        {
          backend: this.state.backend,
          input: {
            folder: {
              id: this.props.simulation.metadata.inputFolder._id,
            },
            meshFile: {
              id: meshFile,
            },
            iniFile: {
              id: this.props.simulation.metadata.inputFolder.files.ini,
            },
          },
          output: {
            folder: {
              id: this.props.simulation.metadata.outputFolder._id,
            },
          },
          cluster: ClusterPayloads.ec2ClusterPayload(
            this.state[this.state.serverType].name,
            this.state[this.state.serverType].machine,
            this.state[this.state.serverType].clusterSize,
            this.state[this.state.serverType].profile._id
          ),
        });
    } else {
      console.log('unrecognized serverType: ', this.state.serverType);
      return;
    }

    this.props.onRun(
      this.props.taskFlowName,
      this.props.primaryJob,
      payload,
      {
        id: this.props.simulation._id,
        step: 'Simulation',
        data: {
          view: 'run',
          metadata: {
            sessionId,
            cluster: clusterName,
          },
        },
      },
      {
        pathname: this.props.location.pathname,
        query: merge(this.props.location.query, {
          view: 'run',
        }),
        state: this.props.location.state,
      });
  },

  formAction(action) {
    this[action]();
  },

  updateServerType(e) {
    this.setState({ serverType: e.target.value });
  },

  updateBackend(backend) {
    this.setState({ backend });
  },

  render() {
    var actions = [{ name: 'runSimulation', label: 'Run Simulation', icon: '' }],
      serverProfiles = { EC2: this.state.EC2, Traditional: this.state.Traditional, OpenStack: this.state.OpenStack },
      backendProfiles = { cuda: false, openmp: [], opencl: [] };
    if (this.state.serverType === 'Traditional') {
      const clusterId = this.state.Traditional.profile;
      if (this.props.tradClusters[clusterId] && this.props.tradClusters[clusterId].config && this.props.tradClusters[clusterId].config.pyfr) {
        backendProfiles = this.props.tradClusters[clusterId].config.pyfr;
      }
    }

    return (

          <RunClusterFrom serverType={this.state.serverType} serverTypeChange={this.updateServerType}
            profiles={serverProfiles} dataChange={this.dataChange}
          />
          <RuntimeBackend profiles={backendProfiles} onChange={ this.updateBackend } visible={this.state.serverType === 'Traditional'} />
          <ButtonBar
            visible={this.state[this.state.serverType].profile !== ''}
            onAction={this.formAction}
            actions={actions}
            error={ this.props.error || this.state.error }
          />

);
  },
});

// Binding --------------------------------------------------------------------
/* eslint-disable arrow-body-style */

export default connect(
  state => {
    return {
      error: get(state, 'network.error.create_taskflow.resp.data.message')
        || get(state, 'network.error.start_taskflow.resp.data.message'),
      ec2Clusters: state.preferences.aws.mapById,
      tradClusters: state.preferences.clusters.mapById,
    };
  },
  () => {
    return {
      onRun: (taskflowName, primaryJob, payload, simulationStep, location) =>
        dispatch(Actions.createTaskflow(taskflowName, primaryJob, payload, simulationStep, location)),
    };
  }
)(SimulationStart);
<commit_msg>profile is the profile id<commit_after>import React                   from 'react';
import ButtonBar               from '../../../../../../panels/ButtonBar';
import defaultServerParameters from '../../../../../../panels/run/defaults';
import RunClusterFrom          from '../../../../../../panels/run';
import ClusterPayloads         from '../../../../../../utils/ClusterPayload';
import RuntimeBackend          from '../../../panels/RuntimeBackend';

import merge                   from 'mout/src/object/merge';

import { connect } from 'react-redux';
import get          from 'mout/src/object/get';
import { dispatch } from '../../../../../../redux';
import * as Actions from '../../../../../../redux/actions/taskflows';

const SimulationStart = React.createClass({

  displayName: 'pyfr/common/steps/Simulation/Start',

  propTypes: {
    location: React.PropTypes.object,
    project: React.PropTypes.object,
    simulation: React.PropTypes.object,
    step: React.PropTypes.string,
    taskFlowName: React.PropTypes.string,
    primaryJob: React.PropTypes.string,
    view: React.PropTypes.string,

    error: React.PropTypes.string,
    tradClusters: React.PropTypes.object,
    ec2Clusters: React.PropTypes.object,
    onRun: React.PropTypes.func,
  },

  getInitialState() {
    return {
      serverType: 'Traditional',
      EC2: defaultServerParameters.EC2,
      Traditional: defaultServerParameters.Traditional,
      OpenStack: defaultServerParameters.OpenStack,

      backend: {},
      error: '',
    };
  },

  dataChange(key, value, which) {
    var profile = this.state[which];
    profile[key] = value;
    this.setState({ [which]: profile });
  },

  runSimulation() {
    const meshFile = this.props.simulation.metadata.inputFolder.files.mesh || this.props.project.metadata.inputFolder.files.mesh;
    var clusterName,
      sessionId = btoa(new Float64Array(3).map(Math.random)).substring(0, 96),
      payload;

    if (this.state.serverType === 'Traditional') {
      clusterName = this.props.tradClusters[this.state[this.state.serverType].profile].name;
      payload = Object.assign({},
        this.state[this.state.serverType].runtime || {},
        {
          backend: this.state.backend,
          input: {
            folder: {
              id: this.props.simulation.metadata.inputFolder._id,
            },
            meshFile: {
              id: meshFile,
            },
            iniFile: {
              id: this.props.simulation.metadata.inputFolder.files.ini,
            },
          },
          output: {
            folder: {
              id: this.props.simulation.metadata.outputFolder._id,
            },
          },
          cluster: ClusterPayloads.tradClusterPayload(this.state[this.state.serverType].profile),
        });
    } else if (this.state.serverType === 'EC2') {
      payload = Object.assign({},
        this.state[this.state.serverType].runtime || {},
        {
          backend: this.state.backend,
          input: {
            folder: {
              id: this.props.simulation.metadata.inputFolder._id,
            },
            meshFile: {
              id: meshFile,
            },
            iniFile: {
              id: this.props.simulation.metadata.inputFolder.files.ini,
            },
          },
          output: {
            folder: {
              id: this.props.simulation.metadata.outputFolder._id,
            },
          },
          cluster: ClusterPayloads.ec2ClusterPayload(
            this.state[this.state.serverType].name,
            this.state[this.state.serverType].machine,
            this.state[this.state.serverType].clusterSize,
            this.state[this.state.serverType].profile
          ),
        });
    } else {
      console.log('unrecognized serverType: ', this.state.serverType);
      return;
    }

    this.props.onRun(
      this.props.taskFlowName,
      this.props.primaryJob,
      payload,
      {
        id: this.props.simulation._id,
        step: 'Simulation',
        data: {
          view: 'run',
          metadata: {
            sessionId,
            cluster: clusterName,
          },
        },
      },
      {
        pathname: this.props.location.pathname,
        query: merge(this.props.location.query, {
          view: 'run',
        }),
        state: this.props.location.state,
      });
  },

  formAction(action) {
    this[action]();
  },

  updateServerType(e) {
    this.setState({ serverType: e.target.value });
  },

  updateBackend(backend) {
    this.setState({ backend });
  },

  render() {
    var actions = [{ name: 'runSimulation', label: 'Run Simulation', icon: '' }],
      serverProfiles = { EC2: this.state.EC2, Traditional: this.state.Traditional, OpenStack: this.state.OpenStack },
      backendProfiles = { cuda: false, openmp: [], opencl: [] };
    if (this.state.serverType === 'Traditional') {
      const clusterId = this.state.Traditional.profile;
      if (this.props.tradClusters[clusterId] && this.props.tradClusters[clusterId].config && this.props.tradClusters[clusterId].config.pyfr) {
        backendProfiles = this.props.tradClusters[clusterId].config.pyfr;
      }
    }

    return (

          <RunClusterFrom serverType={this.state.serverType} serverTypeChange={this.updateServerType}
            profiles={serverProfiles} dataChange={this.dataChange}
          />
          <RuntimeBackend profiles={backendProfiles} onChange={ this.updateBackend } visible={this.state.serverType === 'Traditional'} />
          <ButtonBar
            visible={this.state[this.state.serverType].profile !== ''}
            onAction={this.formAction}
            actions={actions}
            error={ this.props.error || this.state.error }
          />

);
  },
});

// Binding --------------------------------------------------------------------
/* eslint-disable arrow-body-style */

export default connect(
  state => {
    return {
      error: get(state, 'network.error.create_taskflow.resp.data.message')
        || get(state, 'network.error.start_taskflow.resp.data.message'),
      ec2Clusters: state.preferences.aws.mapById,
      tradClusters: state.preferences.clusters.mapById,
    };
  },
  () => {
    return {
      onRun: (taskflowName, primaryJob, payload, simulationStep, location) =>
        dispatch(Actions.createTaskflow(taskflowName, primaryJob, payload, simulationStep, location)),
    };
  }
)(SimulationStart);
<|endoftext|>


<commit_before>define([
    'q',
    'knockout',
    'util/galaxy',
    'util/form',
    'store/ProviderTypes',
    'store/Accounts',
    'store/Profiles',
    'store/Zones',
    'api/api'
],
function (Q, ko, $galaxy, formutils, ProviderTypeStore, AccountStore, ProfileStore, ZoneStore, API) {
    var vm = function () {
        var self = this;

        /*
         *  ==================================================================================
         *   V I E W   V A R I A B L E S
         *  ==================================================================================
         */
        self.selectedAccount = ko.observable(null);
        self.selectedProviderType = ko.observable(null);
        self.accountTitle = ko.observable(null);
        self.currentMode = ko.observable('create');
        self.$galaxy = $galaxy;

        self.ProviderTypeStore = ProviderTypeStore;
        self.AccountStore = AccountStore;
        self.ProfileStore = ProfileStore;
        self.ZoneStore = ZoneStore;

        /*
         *  ==================================================================================
         *   R E G I S T R A T I O N   S E C T I O N
         *  ==================================================================================
         */
        self.id = 'account.detail';
        self.templatePath = 'account.html';
        self.domBindingId = '#account-detail';

        try {
            $galaxy.join(self);
        } catch (ex) {
            console.log(ex);
        }

        /*
         *  ==================================================================================
         *   E V E N T   S U B S C R I P T I O N S
         *  ==================================================================================
         */
        $galaxy.network.subscribe(self.id + '.docked', function (data) {
            ZoneStore.populate();

            ProviderTypeStore.populate().then(function () {
                return AccountStore.populate();
            }).then(function () {
                return ProfileStore.populate();
            }).then(function () {
                self.init(data);
            });
        });

        /*
         *  ==================================================================================
         *   V I E W   M E T H O D S
         *  ==================================================================================
         */

        self.init = function (data) {
            var account = null;
            var provider_type = null;

            if (data.hasOwnProperty('account')) {
                account = AccountStore.collection().filter(function (a) {
                    return a.id === parseInt(data.account, 10);
                })[0];

                self.accountTitle(account.title);
                self.selectedAccount(account);
            } else {
                self.accountTitle('New Account');

                $('#account_title').val('');
                $('#account_description').val('');
                $('#account_id').val('');
                $('#access_key_id').val('');
                $('#secret_access_key').val('');
                $('#keypair').val('');
                $('#default_availability_zone').val('');
                $('#route53_domain').val('');
                $('#private_key_file').val('');
            }

            if (data.hasOwnProperty('type')) {
                provider_type = ProviderTypeStore.collection().filter(function (a) {
                    return a.id === parseInt(data.type, 10);
                })[0];

                self.selectedProviderType(provider_type);
            }

            if (account && account.hasOwnProperty('id')) {
                $('#account_provider').val(account.provider_type);
                $('#account_title').val(account.title);
                $('#account_description').val(account.description);
                $('#account_id').val(account.account_id);
                $('#account_id').attr('disabled', 'disabled');
                $('#access_key_id').val('protected');
                $('#access_key_id').attr('disabled', 'disabled');
                $('#secret_access_key').val('protected');
                $('#secret_access_key').attr('disabled', 'disabled');
                $('#keypair').val('protected');
                $('#keypair').attr('disabled', 'disabled');
                $('#default_availability_zone').val(account.default_availability_zone);
                $('#route53_domain').val('protected');
                $('#route53_domain').attr('disabled', 'disabled');
                $('#private_key_file').val(account.yaml);
                $('#private_key_file').attr('readonly', 'readonly');

                self.currentMode('edit');
            } else if (provider_type && provider_type.hasOwnProperty('id')) {
                $('#account_provider').val(provider_type.id);
            }
        };

        self.saveAccount = function (model, evt) {
            if (self.currentMode() === 'create') {
                self.createAccount(model, evt);
            } else {
                self.updateAccount(model, evt);
            }
        };

        self.createAccount = function (model, evt) {
            var record = formutils.collectFormFields(evt.target.form), account = {};

            account.provider_type = record.account_provider.value;
            account.title = record.account_title.value;
            account.description = record.account_description.value;
            account.default_availability_zone = record.default_availability_zone.value;
            account.account_id = record.account_id.value;
            account.access_key_id = record.access_key_id.value;
            account.secret_access_key = record.secret_access_key.value;
            account.keypair = record.keypair.value;
            account.route53_domain = record.route53_domain.value;
            account.private_key = record.private_key_file.value;

            API.Accounts.save(account).then(function (newAccount) {
                AccountStore.add(newAccount);
                $galaxy.transport('account.list');
            });
        };

        self.updateAccount = function (model, evt) {
            var record = formutils.collectFormFields(evt.target.form);
            var account = {};

            // Update property values with those submitted from form
            account.id = self.selectedAccount().id;
            account.url = self.selectedAccount().url;
            account.provider_type = record.account_provider.value;
            account.title = record.account_title.value;
            account.description = record.account_description.value;
            account.default_availability_zone = record.default_availability_zone.value;

            // PATCH the update, and on success, replace the current item in the store with new one
            API.Accounts.update(account).then(function () {
                $galaxy.transport('account.list');
            }).catch(function (err) {
                console.log(err);
            });
        };

        self.cancelChanges = function (model, evt) {
            $galaxy.transport('account.list');
        };
    };
    return new vm();
});
<commit_msg>Fixed issue for when new cloud account form is partially disabled<commit_after>define([
    'q',
    'knockout',
    'util/galaxy',
    'util/form',
    'store/ProviderTypes',
    'store/Accounts',
    'store/Profiles',
    'store/Zones',
    'api/api'
],
function (Q, ko, $galaxy, formutils, ProviderTypeStore, AccountStore, ProfileStore, ZoneStore, API) {
    var vm = function () {
        var self = this;

        /*
         *  ==================================================================================
         *   V I E W   V A R I A B L E S
         *  ==================================================================================
         */
        self.selectedAccount = ko.observable(null);
        self.selectedProviderType = ko.observable(null);
        self.accountTitle = ko.observable(null);
        self.currentMode = ko.observable('create');
        self.$galaxy = $galaxy;

        self.ProviderTypeStore = ProviderTypeStore;
        self.AccountStore = AccountStore;
        self.ProfileStore = ProfileStore;
        self.ZoneStore = ZoneStore;

        /*
         *  ==================================================================================
         *   R E G I S T R A T I O N   S E C T I O N
         *  ==================================================================================
         */
        self.id = 'account.detail';
        self.templatePath = 'account.html';
        self.domBindingId = '#account-detail';

        try {
            $galaxy.join(self);
        } catch (ex) {
            console.log(ex);
        }

        /*
         *  ==================================================================================
         *   E V E N T   S U B S C R I P T I O N S
         *  ==================================================================================
         */
        $galaxy.network.subscribe(self.id + '.docked', function (data) {
            ZoneStore.populate();

            ProviderTypeStore.populate().then(function () {
                return AccountStore.populate();
            }).then(function () {
                return ProfileStore.populate();
            }).then(function () {
                self.init(data);
            });
        });

        /*
         *  ==================================================================================
         *   V I E W   M E T H O D S
         *  ==================================================================================
         */

        self.init = function (data) {
            var account = null;
            var provider_type = null;

            if (data.hasOwnProperty('account')) {
                account = AccountStore.collection().filter(function (a) {
                    return a.id === parseInt(data.account, 10);
                })[0];

                self.accountTitle(account.title);
                self.selectedAccount(account);
            } else {
                self.accountTitle('New Account');

                $('#account_title').val('');
                $('#account_description').val('');
                $('#account_id').val('');
                $('#access_key_id').val('');
                $('#secret_access_key').val('');
                $('#keypair').val('');
                $('#default_availability_zone').val('');
                $('#route53_domain').val('');
                $('#private_key_file').val('');
            }

            if (data.hasOwnProperty('type')) {
                provider_type = ProviderTypeStore.collection().filter(function (a) {
                    return a.id === parseInt(data.type, 10);
                })[0];

                self.selectedProviderType(provider_type);
            }

            if (account && account.hasOwnProperty('id')) {
                $('#account_provider').val(account.provider_type);
                $('#account_title').val(account.title);
                $('#account_description').val(account.description);
                $('#account_id').val(account.account_id);
                $('#account_id').attr('disabled', 'disabled');
                $('#access_key_id').val('protected');
                $('#access_key_id').attr('disabled', 'disabled');
                $('#secret_access_key').val('protected');
                $('#secret_access_key').attr('disabled', 'disabled');
                $('#keypair').val('protected');
                $('#keypair').attr('disabled', 'disabled');
                $('#default_availability_zone').val(account.default_availability_zone);
                $('#route53_domain').val('protected');
                $('#route53_domain').attr('disabled', 'disabled');
                $('#private_key_file').val(account.yaml);
                $('#private_key_file').attr('readonly', 'readonly');

                self.currentMode('edit');
            } else if (provider_type && provider_type.hasOwnProperty('id')) {
                $('#account_id').attr('disabled', false);
                $('#access_key_id').attr('disabled', false);
                $('#secret_access_key').attr('disabled', false);
                $('#keypair').attr('disabled', false);
                $('#route53_domain').attr('disabled', false);
                $('#private_key_file').attr('readonly', false);

                $('#account_provider').val(provider_type.id);
            }
        };

        self.saveAccount = function (model, evt) {
            if (self.currentMode() === 'create') {
                self.createAccount(model, evt);
            } else {
                self.updateAccount(model, evt);
            }
        };

        self.createAccount = function (model, evt) {
            var record = formutils.collectFormFields(evt.target.form), account = {};

            account.provider_type = record.account_provider.value;
            account.title = record.account_title.value;
            account.description = record.account_description.value;
            account.default_availability_zone = record.default_availability_zone.value;
            account.account_id = record.account_id.value;
            account.access_key_id = record.access_key_id.value;
            account.secret_access_key = record.secret_access_key.value;
            account.keypair = record.keypair.value;
            account.route53_domain = record.route53_domain.value;
            account.private_key = record.private_key_file.value;

            API.Accounts.save(account).then(function (newAccount) {
                AccountStore.add(newAccount);
                $galaxy.transport('account.list');
            });
        };

        self.updateAccount = function (model, evt) {
            var record = formutils.collectFormFields(evt.target.form);
            var account = {};

            // Update property values with those submitted from form
            account.id = self.selectedAccount().id;
            account.url = self.selectedAccount().url;
            account.provider_type = record.account_provider.value;
            account.title = record.account_title.value;
            account.description = record.account_description.value;
            account.default_availability_zone = record.default_availability_zone.value;

            // PATCH the update, and on success, replace the current item in the store with new one
            API.Accounts.update(account).then(function () {
                $galaxy.transport('account.list');
            }).catch(function (err) {
                console.log(err);
            });
        };

        self.cancelChanges = function (model, evt) {
            $galaxy.transport('account.list');
        };
    };
    return new vm();
});
<|endoftext|>