<commit_before>Threadable.ComposeController = Ember.Controller.extend({
  needs: ['organization', 'group', 'topbar', 'conversations'],

  organization: Ember.computed.alias('controllers.organization'),
  conversations: Ember.computed.alias('controllers.conversations'),

  sending: false,
  conversation: null,
  message: null,
  groups: Ember.ArrayProxy.create({content:[]}),
  isTask: false,
  subject: null,
  body: null,
  error: null,

  unselectedGroups: function() {
    var groups = Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
      content:[],
      sortProperties: ['name'],
      sortAscending: true
    });
    groups.addObjects(this.get('organization.groups'));
    groups.removeObjects(this.get('groups'));
    return groups;
  }.property('allGroups.length', 'groups.length'),

  addGroup: function(group) {
    var group, groups = this.get('groups');
    if (typeof group === 'string') {
      if(group == 'my') {
        group = this.get('organization.groups').findBy('primary', true);
      } else {
        group = this.get('organization.groups').findBy('slug', group);
      }
    }
    if (!group) return;
    if (groups.indexOf(group) === -1) groups.pushObject(group);
  },

  hasSubject: function() {
    var subject = this.get('subject');
    return subject && !subject.match(/^(\s|\n)+$/);
  }.property('subject'),

  disabled: function(){
    return this.get('sending') || !this.get('hasSubject');
  }.property('sending', 'hasSubject'),

  actions: {
    reset: function() {
      this.get('groups').clear();
      this.addGroup(this.get('controllers.group.model'));
      this.set('subject', null);
      this.set('body', null);
      this.set('error', null);
    },
    composeTask: function() {
      this.set('isTask', true);
    },
    composeConversation: function() {
      this.set('isTask', false);
    },
    removeGroup: function(group) {
      this.get('groups').removeObject(group);
    },
    addGroup: function(group) {
      this.get('groups').addObject(group);
    },
    sendMessage: function() {
      if (this.get('disabled')) return;
      this.set('sending', true);
      var
        organization     = this.get('organization'),
        organizationSlug = organization.get('slug'),
        conversation     = Threadable.Conversation.create(),
        message          = Threadable.Message.create(),
        subject          = this.get('subject'),
        isTask           = this.get('isTask'),
        groups           = this.get('groups').toArray();

      conversation.set('subject', subject);
      conversation.set('organizationSlug', organizationSlug);
      conversation.set('groupIds', groups.mapBy('id'));
      conversation.set('task', isTask);

      message.set('organizationSlug', organizationSlug);
      message.set('subject', subject);
      message.set('body', this.get('body'));
      message.set('bodyPlain', this.get('body'));
      message.set('bodyHtml', message.get('bodyAsHtml'));

      conversation.saveRecord().then(
        conversationSaved.bind(this),
        conversationFailed.bind(this)
      );

      function conversationSaved(response) {
        message.set('conversationId',   conversation.get('id'));
        message.set('conversationSlug', conversation.get('slug'));
        if(conversation.get('isTask') && !message.get('body')) {
          // don't send messages for blank tasks.
          saveFinished.bind(this)();
          return;
        }

        message.saveRecord().then(
          messageSaved.bind(this),
          messageFailed.bind(this)
        );
      }

      function conversationFailed(xhr) {
        error.call(this, xhr);
        this.set('sending', false);
      }

      function messageSaved(response) {
        conversation.deserialize(response.message.conversation);
        saveFinished.bind(this)();
      }

      function saveFinished() {
        //TODO: move all of this into the spot in conversations_controller where we get the event from redis
        conversation.set('organization', organization);

        if(this.get('conversations').findBy('id', conversation.get('id'))) {
          Threadable.Conversation.cache(conversation);
        }

        this.send('reset');
        this.send('addConversation', conversation);
        this.send('transitionToConversation', conversation);
        this.set('sending', false);
      }

      function messageFailed(xhr) {
        error.call(this, xhr);
        conversation.deleteRecord();
        conversation.set('id', null);
        conversation.set('slug', null);
        conversation.set('isNew', true);
        this.set('sending', false);
      }

      function error(response) {
        var error = response && response.error || 'an unknown error occurred';
        this.set('error', error);
      }

    }
  }
});
<commit_msg>fix linter error<commit_after>Threadable.ComposeController = Ember.Controller.extend({
  needs: ['organization', 'group', 'topbar', 'conversations'],

  organization: Ember.computed.alias('controllers.organization'),
  conversations: Ember.computed.alias('controllers.conversations'),

  sending: false,
  conversation: null,
  message: null,
  groups: Ember.ArrayProxy.create({content:[]}),
  isTask: false,
  subject: null,
  body: null,
  error: null,

  unselectedGroups: function() {
    var groups = Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
      content:[],
      sortProperties: ['name'],
      sortAscending: true
    });
    groups.addObjects(this.get('organization.groups'));
    groups.removeObjects(this.get('groups'));
    return groups;
  }.property('allGroups.length', 'groups.length'),

  addGroup: function(group) {
    var group, groups = this.get('groups');
    if (typeof group === 'string') {
      if(group == 'my') {
        group = this.get('organization.groups').findBy('primary', true);
      } else {
        group = this.get('organization.groups').findBy('slug', group);
      }
    }
    if (!group) return;
    if (groups.indexOf(group) === -1) groups.pushObject(group);
  },

  hasSubject: function() {
    var subject = this.get('subject');
    return subject && !subject.match(/^(\s|\n)+$/);
  }.property('subject'),

  disabled: function(){
    return this.get('sending') || !this.get('hasSubject');
  }.property('sending', 'hasSubject'),

  actions: {
    reset: function() {
      this.get('groups').clear();
      this.addGroup(this.get('controllers.group.model'));
      this.set('subject', null);
      this.set('body', null);
      this.set('error', null);
    },
    composeTask: function() {
      this.set('isTask', true);
    },
    composeConversation: function() {
      this.set('isTask', false);
    },
    removeGroup: function(group) {
      this.get('groups').removeObject(group);
    },
    addGroup: function(group) {
      this.get('groups').addObject(group);
    },
    sendMessage: function() {
      if (this.get('disabled')) return;
      this.set('sending', true);
      var
        organization     = this.get('organization'),
        organizationSlug = organization.get('slug'),
        conversation     = Threadable.Conversation.create(),
        message          = Threadable.Message.create(),
        subject          = this.get('subject'),
        isTask           = this.get('isTask'),
        groups           = this.get('groups').toArray();

      conversation.set('subject', subject);
      conversation.set('organizationSlug', organizationSlug);
      conversation.set('groupIds', groups.mapBy('id'));
      conversation.set('task', isTask);

      message.set('organizationSlug', organizationSlug);
      message.set('subject', subject);
      message.set('body', this.get('body'));
      message.set('bodyPlain', this.get('body'));
      message.set('bodyHtml', message.get('bodyAsHtml'));

      conversation.saveRecord().then(
        conversationSaved.bind(this),
        conversationFailed.bind(this)
      );

      function conversationSaved(response) {
        message.set('conversationId',   conversation.get('id'));
        message.set('conversationSlug', conversation.get('slug'));
        if(conversation.get('isTask') && !message.get('body')) {
          // don't send messages for blank tasks.
          saveFinished.bind(this)();
          return;
        }

        message.saveRecord().then(
          messageSaved.bind(this),
          messageFailed.bind(this)
        );
      }

      function conversationFailed(xhr) {
        error.call(this, xhr);
        this.set('sending', false);
      }

      function messageSaved(response) {
        conversation.deserialize(response.message.conversation);
        saveFinished.bind(this)();
      }

      function saveFinished() {
        //TODO: move all of this into the spot in conversations_controller where we get the event from redis
        conversation.set('organization', organization);

        if(this.get('conversations').findBy('id', conversation.get('id'))) {
          Threadable.Conversation.cache(conversation);
        }

        this.send('reset');
        this.send('addConversation', conversation);
        this.send('transitionToConversation', conversation);
        this.set('sending', false);
      }

      function messageFailed(xhr) {
        error.call(this, xhr);
        conversation.deleteRecord();
        conversation.set('id', null);
        conversation.set('slug', null);
        conversation.set('isNew', true);
        this.set('sending', false);
      }

      function error(response) {
        var errorMessage = response && response.error || 'an unknown error occurred';
        this.set('error', errorMessage);
      }

    }
  }
});
<|endoftext|>


<commit_before>function applicable() {
  // This will apply hack on all iDevices
  return navigator.userAgent.match(/(iPad|iPhone|iPod)/g) &&
         navigator.userAgent.match(/Safari/g);
}

// per http://stackoverflow.com/questions/29001977/safari-in-ios8-is-scrolling-screen-when-fixed-elements-get-focus/29064810
function positioningWorkaround($fixedElement) {
  if (!applicable()) {
    return;
  }

  const fixedElement = $fixedElement[0];

  var done = false;
  var originalScrollTop = 0;

  var blurredNow = function(evt) {
    if (!done && _.include($(document.activeElement).parents(), fixedElement)) {
      // something in focus so skip
      return;
    }

    done = true;

    fixedElement.parentElement.style.height = '';
    $('#main-outlet').show();

    fixedElement.style.position = '';
    fixedElement.style.top = '';
    fixedElement.style.height = '';
    $(window).scrollTop(originalScrollTop);

    if (evt) {
      evt.target.removeEventListener('blur', blurred);
    }
  };

  var blurred = _.debounce(blurredNow, 250);

  var positioningHack = function(evt){

    const self = this;
    done = false;

    // we need this, otherwise changing focus means we never clear
    self.addEventListener('blur', blurred);

    if (fixedElement.style.position === 'absolute') {
      if (this !== document.activeElement) {
        evt.preventDefault();
        self.focus();
      }
      return;
    }

    originalScrollTop = $(window).scrollTop();

    // take care of body
    $('#main-outlet').hide();

    fixedElement.style.position = 'absolute';
    // get out of the way while opening keyboard
    fixedElement.style.top = '0px';
    fixedElement.style.height = parseInt(window.innerHeight*0.6) + "px";
    fixedElement.parentElement.style.height = window.innerHeight + "px";
    $(window).scrollTop(0);
    // great ... iOS positions this yet again
    // so lets take over if this happens
    setTimeout(()=>$(window).scrollTop(0),500);

    evt.preventDefault();
    self.focus();
  };

  function attachTouchStart(elem, fn) {
    if (!$(elem).data('listening')) {
        elem.addEventListener('touchstart', fn);
        $(elem).data('listening', true);
    }
  }

  const checkForInputs = _.debounce(function(){
    $fixedElement.find('button,a:not(.mobile-file-upload)').each(function(idx, elem){
      if ($(elem).parents('.autocomplete').length > 0) {
        return;
      }

      attachTouchStart(this, function(evt){
        done = true;
        $(document.activeElement).blur();
        evt.preventDefault();
        $(this).click();
      });
    });
    $fixedElement.find('input[type=text],textarea').each(function(){
      attachTouchStart(this, positioningHack);
    });
  }, 100);

  fixedElement.addEventListener('DOMNodeInserted', checkForInputs);
}

export default positioningWorkaround;
<commit_msg>we must hide the header for iPad<commit_after>function applicable() {
  // This will apply hack on all iDevices
  return navigator.userAgent.match(/(iPad|iPhone|iPod)/g) &&
         navigator.userAgent.match(/Safari/g);
}

// per http://stackoverflow.com/questions/29001977/safari-in-ios8-is-scrolling-screen-when-fixed-elements-get-focus/29064810
function positioningWorkaround($fixedElement) {
  if (!applicable()) {
    return;
  }

  const fixedElement = $fixedElement[0];

  var done = false;
  var originalScrollTop = 0;

  var blurredNow = function(evt) {
    if (!done && _.include($(document.activeElement).parents(), fixedElement)) {
      // something in focus so skip
      return;
    }

    done = true;

    fixedElement.parentElement.style.height = '';
    $('#main-outlet').show();
    $('header').show();

    fixedElement.style.position = '';
    fixedElement.style.top = '';
    fixedElement.style.height = '';
    $(window).scrollTop(originalScrollTop);

    if (evt) {
      evt.target.removeEventListener('blur', blurred);
    }
  };

  var blurred = _.debounce(blurredNow, 250);

  var positioningHack = function(evt){

    const self = this;
    done = false;

    // we need this, otherwise changing focus means we never clear
    self.addEventListener('blur', blurred);

    if (fixedElement.style.position === 'absolute') {
      if (this !== document.activeElement) {
        evt.preventDefault();
        self.focus();
      }
      return;
    }

    originalScrollTop = $(window).scrollTop();

    // take care of body
    $('#main-outlet').hide();
    $('header').hide();

    fixedElement.style.position = 'absolute';
    // get out of the way while opening keyboard
    fixedElement.style.top = '0px';
    fixedElement.style.height = parseInt(window.innerHeight*0.6) + "px";
    fixedElement.parentElement.style.height = window.innerHeight + "px";
    $(window).scrollTop(0);
    // great ... iOS positions this yet again
    // so lets take over if this happens
    setTimeout(()=>$(window).scrollTop(0),500);

    evt.preventDefault();
    self.focus();
  };

  function attachTouchStart(elem, fn) {
    if (!$(elem).data('listening')) {
        elem.addEventListener('touchstart', fn);
        $(elem).data('listening', true);
    }
  }

  const checkForInputs = _.debounce(function(){
    $fixedElement.find('button,a:not(.mobile-file-upload)').each(function(idx, elem){
      if ($(elem).parents('.autocomplete').length > 0) {
        return;
      }

      attachTouchStart(this, function(evt){
        done = true;
        $(document.activeElement).blur();
        evt.preventDefault();
        $(this).click();
      });
    });
    $fixedElement.find('input[type=text],textarea').each(function(){
      attachTouchStart(this, positioningHack);
    });
  }, 100);

  fixedElement.addEventListener('DOMNodeInserted', checkForInputs);
}

export default positioningWorkaround;
<|endoftext|>


<commit_before>define([
  'extensions/collections/filteredcollection',
  'extensions/views/filter'
], function (Collection, Filter) {
  return function () {
    var collection = new Collection(
      $.map($('#licences-list li'), function (li) {
        var $li = $(li);
        return {
          title: $li.text(),
          el: $li
        };
      })
    );

    var view = new Filter({
      el: $('#filter-wrapper'),
      listEl: $('#licences-list dl'),
      countEl: $('#licences-list .count'),
      label: 'Find an application, licence, notice or registration named:',
      placeholder: 'Example: Temporary Event Notice',
      collection: collection
    });
    view.render();
  };
});
<commit_msg>change example text to sentence case<commit_after>define([
  'extensions/collections/filteredcollection',
  'extensions/views/filter'
], function (Collection, Filter) {
  return function () {
    var collection = new Collection(
      $.map($('#licences-list li'), function (li) {
        var $li = $(li);
        return {
          title: $li.text(),
          el: $li
        };
      })
    );

    var view = new Filter({
      el: $('#filter-wrapper'),
      listEl: $('#licences-list dl'),
      countEl: $('#licences-list .count'),
      label: 'Find an application, licence, notice or registration named:',
      placeholder: 'Example: Temporary event notice',
      collection: collection
    });
    view.render();
  };
});
<|endoftext|>


<commit_before>
// Save and Export the file
// This function returns a file..
// #TODO why aren't we using .ajax call?
function saveAndExport(str, fileType){
    var date = new Date();
    var form_action = location.protocol + '//' + location.host + "/tagger/save_export/";
    $('<form></form>', { action: form_action, method: 'POST'}).append(
        $('<input></input>', { name: 'filename', type: 'hidden', value: fileType + "_" + ISODateString(date)+ fileType })
    ).append(
        $('<input></input>', { name: 'data', type: 'hidden', value: str })
    ).submit();
}

// Save the draft string (Items object stringified) to the server using a post xhr
// The successful response will be the items coming back and reloaded.
function saveDraft(str){
    $.ajax({
        type : "POST",
        dataType : 'json',
        url  : "/tagger/save_draft",
        data : { content : str },
        // On success update our items list to be what the server sends back
        // Really nothing should change other than now the items have a UUID
        success : function(xhr) {
            items = xhr
        },
        error : function(xhr, txtStatus, errThrown) {
            console.log(arguments);
        }
    })

}

function saveRemote(str) {

}<commit_msg>Load JS<commit_after>
// Save and Export the file
// This function returns a file..
// #TODO why aren't we using .ajax call?
function saveAndExport(str, fileType){
    var date = new Date();
    var form_action = location.protocol + '//' + location.host + "/tagger/save_export/";
    $('<form></form>', { action: form_action, method: 'POST'}).append(
        $('<input></input>', { name: 'filename', type: 'hidden', value: fileType + "_" + ISODateString(date)+ fileType })
    ).append(
        $('<input></input>', { name: 'data', type: 'hidden', value: str })
    ).submit();
}

// Save the draft string (Items object stringified) to the server using a post xhr
// The successful response will be the items coming back and reloaded.
function saveDraft(str){
    $.ajax({
        type : "POST",
        dataType : 'json',
        url  : "/tagger/save_draft",
        data : { content : str },
        // On success update our items list to be what the server sends back
        // Really nothing should change other than now the items have a UUID
        success : function(xhr) {
            items = xhr
        },
        error : function(xhr, txtStatus, errThrown) {
            // # TODO No. Add a real error modal
            console.log(arguments);
        }
    })
}

function saveRemote(str) {
// # TODO
}

// This should ONLY ever be the first thing done after the UI loads.
// Do it at anyother time and unexpected results could ensue.
function loadDrafts() {
    $.ajax({
        type : "POST",
        dataType : 'json',
        url  : "/tagger/load_drafts",
        // On success update our items list to be what the server sends back
        // Really nothing should change other than now the items have a UUID
        success : function(xhr) {
            items = xhr

            // Uncheck everything when you add a new tag
            jQuery("#multiItemSelector input[type=checkbox]").each(function(i,obj) {
                obj.checked = false;
            });
            // Update the form
            updateInputFields();

            if (itemCounter == 0){
                jQuery("#multiItemSelector").empty();
            }

            for (itemCounter in items) {

                jQuery("#multiItemSelector").append($("     <input id='"+itemCounter+"' type='checkbox' name='tagItem'/>"+items[itemCounter]['title']+""));

                for (objHash in items[itemCounter].educationalAlignments) {
                    // Create our object
                    var object = {
                        'educationalAlignment' : items[itemCounter].educationalAlignments[objHash]['educationAlignment'],
                        'alignmentType' : items[itemCounter].educationalAlignments[objHash]['alignmentType'],
                        'dotNotation' : items[itemCounter].educationalAlignments[objHash]['dotNotation'],
                        'description' : items[itemCounter].educationalAlignments[objHash]['description'],
                        'itemURL' : items[itemCounter].educationalAlignments[objHash]['itemUrl']
                    };

                    // Okay add it.
                    if (alignments[objHash] == undefined) {
                        $('.noAlignmentsYet').hide();
                        alignments[objHash] = object;
                        $('#currentAlignmentTable > tbody:last').append('
<input type="checkbox" class="alignment-checkbox" value="'+objHash+'" />'+ object.dotNotation +'	'+ capitalize(object.alignmentType) +'
');
                    }
                }

            }

            updateTextArea();

        },
        error : function(xhr, txtStatus, errThrown) {
            // # TODO No. Add a real error modal
            console.log(arguments);
        }
    })
}<|endoftext|>


<commit_before>'use strict';

angular.module('openolitor').directive('ooSaveButton', ['msgBus', function(msgBus) {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      entity: '@',
      model: '=',
      onSave: '=',
      onCancel: '=',
      form: '='
    },
    transclude: true,
    templateUrl: 'scripts/common/components/oo-savebutton.directive.html',
    controller: function($scope) {
      $scope.isNew = function() {
        return !$scope.model || $scope.model.id === undefined;
      };

      $scope.loading = false;
      msgBus.onMsg('EntityModified', $scope, function(event, msg) {
        if (msg.entity === $scope.entity && msg.data.id === $scope.model.id) {
          $scope.model = msg.data;
          $scope.loading = false;
          $scope.$apply();
        }
      });

      msgBus.onMsg('EntityCreated', $scope, function(event, msg) {
        if (msg.entity === $scope.entity && msg.data.id === $scope.model.id) {
          $scope.model = msg.data;
          $scope.loading = false;
          $scope.$apply();
        }
      });

      $scope.save = function() {
        $scope.loading = true;
        $scope.onSave();
      };

      $scope.cancel = function() {
        $scope.loading = true;
        $scope.onCancel();
      };
    }
  };
}]);
<commit_msg>check if we expected change from server side<commit_after>'use strict';

angular.module('openolitor').directive('ooSaveButton', ['msgBus', function(msgBus) {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      entity: '@',
      model: '=',
      onSave: '=',
      onCancel: '=',
      form: '='
    },
    transclude: true,
    templateUrl: 'scripts/common/components/oo-savebutton.directive.html',
    controller: function($scope) {
      $scope.isNew = function() {
        return !$scope.model || $scope.model.id === undefined;
      };

      $scope.loading = false;
      msgBus.onMsg('EntityModified', $scope, function(event, msg) {
        if (msg.entity === $scope.entity && msg.data.id === $scope.model.id) {
          if (!$scope.loading) {
            //TODO: Use alertservice to notify user to reload page before saving
          }
          else {
            //$scope.model = msg.data;
            $scope.loading = false;
            $scope.$apply();
          }
       }
      });

      msgBus.onMsg('EntityCreated', $scope, function(event, msg) {
        if (msg.entity === $scope.entity && msg.data.id === $scope.model.id) {
          $scope.model = msg.data;
          $scope.loading = false;
          $scope.$apply();
        }
      });

      $scope.save = function() {
        $scope.loading = true;
        $scope.onSave();
      };

      $scope.cancel = function() {
        $scope.loading = true;
        $scope.onCancel();
      };
    }
  };
}]);
<|endoftext|>


<commit_before>'use strict';

angular.module('deckApp.aws')
  .controller('awsCloneServerGroupCtrl', function($scope, $modalInstance, _, $q, $exceptionHandler, $state,
                                               accountService, orcaService, mortService, oortService, searchService, serverGroupService,
                                               instanceTypeService, modalWizardService, securityGroupService, taskMonitorService,
                                               serverGroup, application, title) {
    $scope.title = title;
    $scope.healthCheckTypes = ['EC2', 'ELB'];
    $scope.terminationPolicies = ['OldestInstance', 'NewestInstance', 'OldestLaunchConfiguration', 'ClosestToNextInstanceHour', 'Default'];

    $scope.applicationName = application.name;

    $scope.state = {
      loaded: false,
      queryAllImages: false
    };

    $scope.taskMonitor = taskMonitorService.buildTaskMonitor({
      application: application,
      title: 'Creating your server group',
      forceRefreshMessage: 'Getting your new server group from Amazon...',
      modalInstance: $modalInstance,
      forceRefreshEnabled: true
    });

    var accountLoader = accountService.getRegionsKeyedByAccount().then(function(regionsKeyedByAccount) {
      $scope.accounts = _.keys(regionsKeyedByAccount);
      $scope.regionsKeyedByAccount = regionsKeyedByAccount;
    });

    var securityGroupLoader = securityGroupService.getAllSecurityGroups().then(function(securityGroups) {
      $scope.securityGroups = securityGroups;
    });

    var loadBalancerLoader = oortService.listLoadBalancers().then(function(loadBalancers) {
      $scope.loadBalancers = loadBalancers;
    });

    var subnetLoader = mortService.listSubnets().then(function(subnets) {
      $scope.subnets = subnets;
    });

    var preferredZonesLoader = accountService.getPreferredZonesByAccount().then(function(preferredZones) {
      $scope.preferredZones = preferredZones;
    });

    var imageLoader = searchService.search('oort', {q: application.name, type: 'namedImages', pageSize: 100000000}).then(function(searchResults) {
      $scope.packageImages = searchResults.results;
      if ($scope.packageImages.length === 0) {
        if (serverGroup) {
          searchService.search('oort', {q: serverGroup.launchConfig.imageId, type: 'namedImages'}).then(function (searchResults) {
            if (searchResults.results.length > 0) {
              var packageRegex = /(\w+)-?\w+/;
              $scope.imageName = searchResults.results[0].imageName;
              var match = packageRegex.exec($scope.imageName);
              $scope.applicationName = match[1];
              searchService.search('oort', {q: $scope.applicationName, type: 'namedImages', pageSize: 100000000}).then(function(searchResults) {
                $scope.packageImages = searchResults.results;
              });
            }
          });
        } else {
          $scope.state.queryAllImages = true;
        }
      }
    });

    $q.all([accountLoader, securityGroupLoader, loadBalancerLoader, subnetLoader, imageLoader, preferredZonesLoader]).then(function() {
      $scope.state.loaded = true;
      initializeCommand();
      initializeWizardState();
      initializeSelectOptions();
      initializeWatches();
    });

    function initializeWizardState() {
      if (serverGroup) {
        modalWizardService.getWizard().markComplete('location');
        modalWizardService.getWizard().markComplete('load-balancers');
        modalWizardService.getWizard().markComplete('security-groups');
        modalWizardService.getWizard().markComplete('instance-profile');
        modalWizardService.getWizard().markComplete('capacity');
        modalWizardService.getWizard().markComplete('advanced');
      }
    }

    function initializeWatches() {
      $scope.$watch('command.credentials', credentialsChanged);
      $scope.$watch('command.region', regionChanged);
      $scope.$watch('command.subnetType', subnetChanged);
      $scope.$watch('command.usePreferredZones', usePreferredZonesToggled);
    }

    function initializeSelectOptions() {
      credentialsChanged();
      regionChanged();
      configureSubnetPurposes();
      configureSecurityGroupOptions();
    }

    function credentialsChanged() {
      if ($scope.command.credentials) {
        $scope.regions = $scope.regionsKeyedByAccount[$scope.command.credentials].regions;
        if (!_($scope.regions).some({name: $scope.command.region})) {
          $scope.command.region = null;
        } else {
          regionChanged();
        }
      } else {
        $scope.command.region = null;
      }
    }

    function regionChanged() {
      var command = $scope.command;
      configureSubnetPurposes();
      var currentZoneCount = command.availabilityZones ? command.availabilityZones.length : 0;
      if (command.region) {
        if (!_($scope.regionSubnetPurposes).some({purpose: command.subnetType})) {
          command.subnetType = null;
        }
        subnetChanged();
        configureInstanceTypes();
        configureAvailabilityZones();
        configureImages();
      } else {
        $scope.regionalAvailabilityZones = null;
      }

      usePreferredZonesToggled();
      if (!command.usePreferredZones) {
        command.availabilityZones = _.intersection(command.availabilityZones, $scope.regionalAvailabilityZones);
        var newZoneCount = command.availabilityZones ? command.availabilityZones.length : 0;
        if (currentZoneCount !== newZoneCount) {
          modalWizardService.getWizard().markDirty('capacity');
        }
      }
    }

    function usePreferredZonesToggled() {
      var command = $scope.command;
      if (command.usePreferredZones) {
        command.availabilityZones = $scope.preferredZones[command.credentials][command.region].sort();
      }
    }

    function subnetChanged() {
      var subnet = _($scope.subnets)
        .find({'purpose': $scope.command.subnetType, 'account': $scope.command.credentials, 'region': $scope.command.region});
      $scope.command.vpcId = subnet ? subnet.vpcId : null;
      configureSecurityGroupOptions();
      configureLoadBalancerOptions();
    }

    function configureAvailabilityZones() {
      $scope.regionalAvailabilityZones = _.find($scope.regionsKeyedByAccount[$scope.command.credentials].regions,
        {'name': $scope.command.region}).availabilityZones;
    }

    function configureSubnetPurposes() {
      if ($scope.command.region === null) {
        $scope.regionSubnetPurposes = null;
      }
      $scope.regionSubnetPurposes = _($scope.subnets)
        .filter({'account': $scope.command.credentials, 'region': $scope.command.region, 'target': 'ec2'})
        .pluck('purpose')
        .uniq()
        .map(function(purpose) { return { purpose: purpose, label: purpose };})
        .valueOf();
    }

    function configureSecurityGroupOptions() {
      var newRegionalSecurityGroups = _($scope.securityGroups[$scope.command.credentials].aws[$scope.command.region])
        .filter({'vpcId': $scope.command.vpcId || null})
        .valueOf();
      if ($scope.regionalSecurityGroups && $scope.command.securityGroups) {
        var previousCount = $scope.command.securityGroups.length;
        // not initializing - we are actually changing groups
        var matchedGroupNames = $scope.command.securityGroups.map(function(groupId) {
          return _($scope.regionalSecurityGroups).find({id: groupId}).name;
        }).map(function(groupName) {
          return _(newRegionalSecurityGroups).find({name: groupName});
        }).filter(function(group) {
          return group;
        }).map(function(group) {
          return group.id;
        });
        $scope.command.securityGroups = matchedGroupNames;
        if (matchedGroupNames.length !== previousCount) {
          modalWizardService.getWizard().markDirty('security-groups');
        }

      }

      $scope.regionalSecurityGroups = newRegionalSecurityGroups;
    }

    function configureLoadBalancerOptions() {
      var newLoadBalancers = _($scope.loadBalancers)
        .pluck('accounts')
        .flatten(true)
        .filter({'name': $scope.command.credentials})
        .pluck('regions')
        .flatten(true)
        .filter({'name': $scope.command.region})
        .pluck('loadBalancers')
        .flatten(true)
        .pluck('elb')
        .remove(undefined)
        .filter({'vpcid': $scope.command.vpcId})
        .pluck('loadBalancerName')
        .unique()
        .valueOf();

      if ($scope.regionalLoadBalancers && $scope.command.loadBalancers) {
        var previousCount = $scope.command.loadBalancers.length;
        $scope.command.loadBalancers = _.intersection(newLoadBalancers, $scope.command.loadBalancers);
        if ($scope.command.loadBalancers.length !== previousCount) {
          modalWizardService.getWizard().markDirty('load-balancers');
        }
      }

      $scope.regionalLoadBalancers = newLoadBalancers;
    }

    function configureImages() {
      if ($scope.command.region) {
        $scope.regionalImages = _.filter($scope.packageImages, {region: $scope.command.region});
        if ($scope.command.amiName && !_($scope.regionalImages).some({imageName: $scope.command.amiName})) {
          $scope.command.amiName = null;
        }
      } else {
        $scope.regionalImages = null;
        $scope.command.amiName = null;
      }
    }

    function configureInstanceTypes() {
      if ($scope.command.region) {
        instanceTypeService.getAvailableTypesForRegions([$scope.command.region]).then(function (result) {
          $scope.regionalInstanceTypes = result;
          if ($scope.command.instanceType && result.indexOf($scope.command.instanceType) === -1) {
            $scope.regionalInstanceTypes.push($scope.command.instanceType);
          }
        });
      }
    }

    function buildCommandFromExisting(serverGroup) {
      var serverGroupName = serverGroupService.parseServerGroupName(serverGroup.asg.autoScalingGroupName);
      var zones = serverGroup.asg.availabilityZones.sort();
      var preferredZones = $scope.preferredZones[serverGroup.account][serverGroup.region].sort();
      var usePreferredZones = zones.join(',') === preferredZones.join(',');
      var command = {
        'application': serverGroupName.application,
        'stack': serverGroupName.stack,
        'freeFormDetails': serverGroupName.freeFormDetails,
        'credentials': serverGroup.account,
        'cooldown': serverGroup.asg.defaultCooldown,
        'healthCheckGracePeriod': serverGroup.asg.healthCheckGracePeriod,
        'healthCheckType': serverGroup.asg.healthCheckType,
        'terminationPolicies': serverGroup.asg.terminationPolicies,
        'loadBalancers': serverGroup.asg.loadBalancerNames,
        'region': serverGroup.region,
        'availabilityZones': zones,
        'usePreferredZones': usePreferredZones,
        'capacity': {
          'min': serverGroup.asg.minSize,
          'max': serverGroup.asg.maxSize,
          'desired': serverGroup.asg.desiredCapacity
        },
        'allImageSelection': null,
        'instanceProfile': 'custom'
      };
      if (serverGroup.launchConfig) {
        var amiName = null;
        if (serverGroup.launchConfig.imageId) {
          var foundImage = _($scope.packageImages).find({'imageId': serverGroup.launchConfig.imageId});
          if (foundImage) {
            amiName = foundImage.imageName;
          }
        }
        angular.extend(command, {
          'instanceType': serverGroup.launchConfig.instanceType,
          'iamRole': serverGroup.launchConfig.iamInstanceProfile,
          'keyPair': serverGroup.launchConfig.keyName,
          'associatePublicIpAddress': serverGroup.launchConfig.associatePublicIpAddress,
          'ramdiskId': serverGroup.launchConfig.ramdiskId,
          'instanceMonitoring': serverGroup.launchConfig.instanceMonitoring.enabled,
          'ebsOptimized': serverGroup.launchConfig.ebsOptimized,
          'amiName': amiName
        });
      }
      var vpcZoneIdentifier = serverGroup.asg.vpczoneIdentifier;
      if (vpcZoneIdentifier !== '') {
        var subnetId = vpcZoneIdentifier.split(',')[0];
        var subnet = _($scope.subnets).find({'id': subnetId});
        command.subnetType = subnet.purpose;
        command.vpcId = subnet.vpcId;
      } else {
        command.subnetType = '';
        command.vpcId = null;
      }
      if (serverGroup.launchConfig && serverGroup.launchConfig.securityGroups.length) {
        command.securityGroups = serverGroup.launchConfig.securityGroups;
      }
      return command;
    }

    function createCommandTemplate() {
      var defaultCredentials = 'test';
      var defaultRegion = 'us-east-1';
      return {
        'application': application.name,
        'credentials': defaultCredentials,
        'region': defaultRegion,
        'usePreferredZones': true,
        'availabilityZones': $scope.preferredZones[defaultCredentials][defaultRegion],
        'capacity': {
          'min': 0,
          'max': 0,
          'desired': 0
        },
        'cooldown': 10,
        'healthCheckType': 'EC2',
        'healthCheckGracePeriod': 600,
        'instanceMonitoring': false,
        'ebsOptimized': false,

        //These two should not be hard coded here, and keyPair options should be loaded from AWS
        'iamRole': 'BaseIAMRole',
        'keyPair': 'nf-test-keypair-a',

        'terminationPolicies': ['Default'],
        'vpcId': null,
        allImageSelection: null
      };
    }

    function initializeCommand() {
      if (serverGroup) {
        $scope.command = buildCommandFromExisting(serverGroup);
      } else {
        $scope.command = createCommandTemplate();
      }
    }

    this.isValid = function () {
      return $scope.command && ($scope.command.amiName !== null) && ($scope.command.application !== null) &&
        ($scope.command.credentials !== null) && ($scope.command.instanceType !== null) &&
        ($scope.command.region !== null) && ($scope.command.availabilityZones !== null) &&
        ($scope.command.capacity.min !== null) && ($scope.command.capacity.max !== null) &&
        ($scope.command.capacity.desired !== null) &&
        modalWizardService.getWizard().isComplete();
    };

    this.showSubmitButton = function () {
      return modalWizardService.getWizard().allPagesVisited();
    };

    $scope.taskMonitor.onApplicationRefresh = function handleApplicationRefreshComplete() {
      $scope.taskMonitor.task.getCompletedKatoTask().then(function(katoTask) {
        if (katoTask.resultObjects && katoTask.resultObjects.length && katoTask.resultObjects[0].serverGroupNames) {
          var newStateParams = {
            serverGroup: katoTask.resultObjects[0].serverGroupNames[0].split(':')[1],
            accountId: $scope.command.credentials,
            region: $scope.command.region
          };
          var transitionTo = '^.^.^.clusters.serverGroup';
          if ($state.includes('**.clusters.serverGroup')) {  // clone via details, all view
            transitionTo = '^.serverGroup';
          }
          if ($state.includes('**.clusters.cluster.serverGroup')) { // clone or create with details open
            transitionTo = '^.^.serverGroup';
          }
          if ($state.includes('**.clusters')) { // create new, no details open
            transitionTo = '.serverGroup';
          }
          $state.go(transitionTo, newStateParams);
        }
      });
    };

    this.clone = function () {

      var command = angular.copy($scope.command);
      var description;
      if (serverGroup) {
        description = 'Create Cloned Server Group from ' + serverGroup.asg.autoScalingGroupName;
        command.type = 'copyLastAsg';
        command.source = {
          'account': serverGroup.account,
          'region': serverGroup.region,
          'asgName': serverGroup.asg.autoScalingGroupName
        };
      } else {
        command.type = 'deploy';
        var asgName = application.name;
        if (command.stack) {
          asgName += '-' + command.stack;
        }
        if (!command.stack && command.freeFormDetails) {
          asgName += '-';
        }
        if (command.freeFormDetails) {
          asgName += '-' + command.freeFormDetails;
        }
        description = 'Create New Server Group in cluster ' + asgName;
      }
      command.availabilityZones = {};
      command.availabilityZones[command.region] = $scope.command.availabilityZones;
      delete command.region;
      delete command.allImageSelection;
      delete command.instanceProfile;
      delete command.vpcId;

      $scope.taskMonitor.submit(
        function() {
          return orcaService.cloneServerGroup(command, application.name, description);
        }
      );
    };

    this.cancel = function () {
      $modalInstance.dismiss();
    };
  });
<commit_msg>do not send usePreferredZone flag<commit_after>'use strict';

angular.module('deckApp.aws')
  .controller('awsCloneServerGroupCtrl', function($scope, $modalInstance, _, $q, $exceptionHandler, $state,
                                               accountService, orcaService, mortService, oortService, searchService, serverGroupService,
                                               instanceTypeService, modalWizardService, securityGroupService, taskMonitorService,
                                               serverGroup, application, title) {
    $scope.title = title;
    $scope.healthCheckTypes = ['EC2', 'ELB'];
    $scope.terminationPolicies = ['OldestInstance', 'NewestInstance', 'OldestLaunchConfiguration', 'ClosestToNextInstanceHour', 'Default'];

    $scope.applicationName = application.name;

    $scope.state = {
      loaded: false,
      queryAllImages: false
    };

    $scope.taskMonitor = taskMonitorService.buildTaskMonitor({
      application: application,
      title: 'Creating your server group',
      forceRefreshMessage: 'Getting your new server group from Amazon...',
      modalInstance: $modalInstance,
      forceRefreshEnabled: true
    });

    var accountLoader = accountService.getRegionsKeyedByAccount().then(function(regionsKeyedByAccount) {
      $scope.accounts = _.keys(regionsKeyedByAccount);
      $scope.regionsKeyedByAccount = regionsKeyedByAccount;
    });

    var securityGroupLoader = securityGroupService.getAllSecurityGroups().then(function(securityGroups) {
      $scope.securityGroups = securityGroups;
    });

    var loadBalancerLoader = oortService.listLoadBalancers().then(function(loadBalancers) {
      $scope.loadBalancers = loadBalancers;
    });

    var subnetLoader = mortService.listSubnets().then(function(subnets) {
      $scope.subnets = subnets;
    });

    var preferredZonesLoader = accountService.getPreferredZonesByAccount().then(function(preferredZones) {
      $scope.preferredZones = preferredZones;
    });

    var imageLoader = searchService.search('oort', {q: application.name, type: 'namedImages', pageSize: 100000000}).then(function(searchResults) {
      $scope.packageImages = searchResults.results;
      if ($scope.packageImages.length === 0) {
        if (serverGroup) {
          searchService.search('oort', {q: serverGroup.launchConfig.imageId, type: 'namedImages'}).then(function (searchResults) {
            if (searchResults.results.length > 0) {
              var packageRegex = /(\w+)-?\w+/;
              $scope.imageName = searchResults.results[0].imageName;
              var match = packageRegex.exec($scope.imageName);
              $scope.applicationName = match[1];
              searchService.search('oort', {q: $scope.applicationName, type: 'namedImages', pageSize: 100000000}).then(function(searchResults) {
                $scope.packageImages = searchResults.results;
              });
            }
          });
        } else {
          $scope.state.queryAllImages = true;
        }
      }
    });

    $q.all([accountLoader, securityGroupLoader, loadBalancerLoader, subnetLoader, imageLoader, preferredZonesLoader]).then(function() {
      $scope.state.loaded = true;
      initializeCommand();
      initializeWizardState();
      initializeSelectOptions();
      initializeWatches();
    });

    function initializeWizardState() {
      if (serverGroup) {
        modalWizardService.getWizard().markComplete('location');
        modalWizardService.getWizard().markComplete('load-balancers');
        modalWizardService.getWizard().markComplete('security-groups');
        modalWizardService.getWizard().markComplete('instance-profile');
        modalWizardService.getWizard().markComplete('capacity');
        modalWizardService.getWizard().markComplete('advanced');
      }
    }

    function initializeWatches() {
      $scope.$watch('command.credentials', credentialsChanged);
      $scope.$watch('command.region', regionChanged);
      $scope.$watch('command.subnetType', subnetChanged);
      $scope.$watch('command.usePreferredZones', usePreferredZonesToggled);
    }

    function initializeSelectOptions() {
      credentialsChanged();
      regionChanged();
      configureSubnetPurposes();
      configureSecurityGroupOptions();
    }

    function credentialsChanged() {
      if ($scope.command.credentials) {
        $scope.regions = $scope.regionsKeyedByAccount[$scope.command.credentials].regions;
        if (!_($scope.regions).some({name: $scope.command.region})) {
          $scope.command.region = null;
        } else {
          regionChanged();
        }
      } else {
        $scope.command.region = null;
      }
    }

    function regionChanged() {
      var command = $scope.command;
      configureSubnetPurposes();
      var currentZoneCount = command.availabilityZones ? command.availabilityZones.length : 0;
      if (command.region) {
        if (!_($scope.regionSubnetPurposes).some({purpose: command.subnetType})) {
          command.subnetType = null;
        }
        subnetChanged();
        configureInstanceTypes();
        configureAvailabilityZones();
        configureImages();
      } else {
        $scope.regionalAvailabilityZones = null;
      }

      usePreferredZonesToggled();
      if (!command.usePreferredZones) {
        command.availabilityZones = _.intersection(command.availabilityZones, $scope.regionalAvailabilityZones);
        var newZoneCount = command.availabilityZones ? command.availabilityZones.length : 0;
        if (currentZoneCount !== newZoneCount) {
          modalWizardService.getWizard().markDirty('capacity');
        }
      }
    }

    function usePreferredZonesToggled() {
      var command = $scope.command;
      if (command.usePreferredZones) {
        command.availabilityZones = $scope.preferredZones[command.credentials][command.region].sort();
      }
    }

    function subnetChanged() {
      var subnet = _($scope.subnets)
        .find({'purpose': $scope.command.subnetType, 'account': $scope.command.credentials, 'region': $scope.command.region});
      $scope.command.vpcId = subnet ? subnet.vpcId : null;
      configureSecurityGroupOptions();
      configureLoadBalancerOptions();
    }

    function configureAvailabilityZones() {
      $scope.regionalAvailabilityZones = _.find($scope.regionsKeyedByAccount[$scope.command.credentials].regions,
        {'name': $scope.command.region}).availabilityZones;
    }

    function configureSubnetPurposes() {
      if ($scope.command.region === null) {
        $scope.regionSubnetPurposes = null;
      }
      $scope.regionSubnetPurposes = _($scope.subnets)
        .filter({'account': $scope.command.credentials, 'region': $scope.command.region, 'target': 'ec2'})
        .pluck('purpose')
        .uniq()
        .map(function(purpose) { return { purpose: purpose, label: purpose };})
        .valueOf();
    }

    function configureSecurityGroupOptions() {
      var newRegionalSecurityGroups = _($scope.securityGroups[$scope.command.credentials].aws[$scope.command.region])
        .filter({'vpcId': $scope.command.vpcId || null})
        .valueOf();
      if ($scope.regionalSecurityGroups && $scope.command.securityGroups) {
        var previousCount = $scope.command.securityGroups.length;
        // not initializing - we are actually changing groups
        var matchedGroupNames = $scope.command.securityGroups.map(function(groupId) {
          return _($scope.regionalSecurityGroups).find({id: groupId}).name;
        }).map(function(groupName) {
          return _(newRegionalSecurityGroups).find({name: groupName});
        }).filter(function(group) {
          return group;
        }).map(function(group) {
          return group.id;
        });
        $scope.command.securityGroups = matchedGroupNames;
        if (matchedGroupNames.length !== previousCount) {
          modalWizardService.getWizard().markDirty('security-groups');
        }

      }

      $scope.regionalSecurityGroups = newRegionalSecurityGroups;
    }

    function configureLoadBalancerOptions() {
      var newLoadBalancers = _($scope.loadBalancers)
        .pluck('accounts')
        .flatten(true)
        .filter({'name': $scope.command.credentials})
        .pluck('regions')
        .flatten(true)
        .filter({'name': $scope.command.region})
        .pluck('loadBalancers')
        .flatten(true)
        .pluck('elb')
        .remove(undefined)
        .filter({'vpcid': $scope.command.vpcId})
        .pluck('loadBalancerName')
        .unique()
        .valueOf();

      if ($scope.regionalLoadBalancers && $scope.command.loadBalancers) {
        var previousCount = $scope.command.loadBalancers.length;
        $scope.command.loadBalancers = _.intersection(newLoadBalancers, $scope.command.loadBalancers);
        if ($scope.command.loadBalancers.length !== previousCount) {
          modalWizardService.getWizard().markDirty('load-balancers');
        }
      }

      $scope.regionalLoadBalancers = newLoadBalancers;
    }

    function configureImages() {
      if ($scope.command.region) {
        $scope.regionalImages = _.filter($scope.packageImages, {region: $scope.command.region});
        if ($scope.command.amiName && !_($scope.regionalImages).some({imageName: $scope.command.amiName})) {
          $scope.command.amiName = null;
        }
      } else {
        $scope.regionalImages = null;
        $scope.command.amiName = null;
      }
    }

    function configureInstanceTypes() {
      if ($scope.command.region) {
        instanceTypeService.getAvailableTypesForRegions([$scope.command.region]).then(function (result) {
          $scope.regionalInstanceTypes = result;
          if ($scope.command.instanceType && result.indexOf($scope.command.instanceType) === -1) {
            $scope.regionalInstanceTypes.push($scope.command.instanceType);
          }
        });
      }
    }

    function buildCommandFromExisting(serverGroup) {
      var serverGroupName = serverGroupService.parseServerGroupName(serverGroup.asg.autoScalingGroupName);
      var zones = serverGroup.asg.availabilityZones.sort();
      var preferredZones = $scope.preferredZones[serverGroup.account][serverGroup.region].sort();
      var usePreferredZones = zones.join(',') === preferredZones.join(',');
      var command = {
        'application': serverGroupName.application,
        'stack': serverGroupName.stack,
        'freeFormDetails': serverGroupName.freeFormDetails,
        'credentials': serverGroup.account,
        'cooldown': serverGroup.asg.defaultCooldown,
        'healthCheckGracePeriod': serverGroup.asg.healthCheckGracePeriod,
        'healthCheckType': serverGroup.asg.healthCheckType,
        'terminationPolicies': serverGroup.asg.terminationPolicies,
        'loadBalancers': serverGroup.asg.loadBalancerNames,
        'region': serverGroup.region,
        'availabilityZones': zones,
        'usePreferredZones': usePreferredZones,
        'capacity': {
          'min': serverGroup.asg.minSize,
          'max': serverGroup.asg.maxSize,
          'desired': serverGroup.asg.desiredCapacity
        },
        'allImageSelection': null,
        'instanceProfile': 'custom'
      };
      if (serverGroup.launchConfig) {
        var amiName = null;
        if (serverGroup.launchConfig.imageId) {
          var foundImage = _($scope.packageImages).find({'imageId': serverGroup.launchConfig.imageId});
          if (foundImage) {
            amiName = foundImage.imageName;
          }
        }
        angular.extend(command, {
          'instanceType': serverGroup.launchConfig.instanceType,
          'iamRole': serverGroup.launchConfig.iamInstanceProfile,
          'keyPair': serverGroup.launchConfig.keyName,
          'associatePublicIpAddress': serverGroup.launchConfig.associatePublicIpAddress,
          'ramdiskId': serverGroup.launchConfig.ramdiskId,
          'instanceMonitoring': serverGroup.launchConfig.instanceMonitoring.enabled,
          'ebsOptimized': serverGroup.launchConfig.ebsOptimized,
          'amiName': amiName
        });
      }
      var vpcZoneIdentifier = serverGroup.asg.vpczoneIdentifier;
      if (vpcZoneIdentifier !== '') {
        var subnetId = vpcZoneIdentifier.split(',')[0];
        var subnet = _($scope.subnets).find({'id': subnetId});
        command.subnetType = subnet.purpose;
        command.vpcId = subnet.vpcId;
      } else {
        command.subnetType = '';
        command.vpcId = null;
      }
      if (serverGroup.launchConfig && serverGroup.launchConfig.securityGroups.length) {
        command.securityGroups = serverGroup.launchConfig.securityGroups;
      }
      return command;
    }

    function createCommandTemplate() {
      var defaultCredentials = 'test';
      var defaultRegion = 'us-east-1';
      return {
        'application': application.name,
        'credentials': defaultCredentials,
        'region': defaultRegion,
        'usePreferredZones': true,
        'availabilityZones': $scope.preferredZones[defaultCredentials][defaultRegion],
        'capacity': {
          'min': 0,
          'max': 0,
          'desired': 0
        },
        'cooldown': 10,
        'healthCheckType': 'EC2',
        'healthCheckGracePeriod': 600,
        'instanceMonitoring': false,
        'ebsOptimized': false,

        //These two should not be hard coded here, and keyPair options should be loaded from AWS
        'iamRole': 'BaseIAMRole',
        'keyPair': 'nf-test-keypair-a',

        'terminationPolicies': ['Default'],
        'vpcId': null,
        allImageSelection: null
      };
    }

    function initializeCommand() {
      if (serverGroup) {
        $scope.command = buildCommandFromExisting(serverGroup);
      } else {
        $scope.command = createCommandTemplate();
      }
    }

    this.isValid = function () {
      return $scope.command && ($scope.command.amiName !== null) && ($scope.command.application !== null) &&
        ($scope.command.credentials !== null) && ($scope.command.instanceType !== null) &&
        ($scope.command.region !== null) && ($scope.command.availabilityZones !== null) &&
        ($scope.command.capacity.min !== null) && ($scope.command.capacity.max !== null) &&
        ($scope.command.capacity.desired !== null) &&
        modalWizardService.getWizard().isComplete();
    };

    this.showSubmitButton = function () {
      return modalWizardService.getWizard().allPagesVisited();
    };

    $scope.taskMonitor.onApplicationRefresh = function handleApplicationRefreshComplete() {
      $scope.taskMonitor.task.getCompletedKatoTask().then(function(katoTask) {
        if (katoTask.resultObjects && katoTask.resultObjects.length && katoTask.resultObjects[0].serverGroupNames) {
          var newStateParams = {
            serverGroup: katoTask.resultObjects[0].serverGroupNames[0].split(':')[1],
            accountId: $scope.command.credentials,
            region: $scope.command.region
          };
          var transitionTo = '^.^.^.clusters.serverGroup';
          if ($state.includes('**.clusters.serverGroup')) {  // clone via details, all view
            transitionTo = '^.serverGroup';
          }
          if ($state.includes('**.clusters.cluster.serverGroup')) { // clone or create with details open
            transitionTo = '^.^.serverGroup';
          }
          if ($state.includes('**.clusters')) { // create new, no details open
            transitionTo = '.serverGroup';
          }
          $state.go(transitionTo, newStateParams);
        }
      });
    };

    this.clone = function () {

      var command = angular.copy($scope.command);
      var description;
      if (serverGroup) {
        description = 'Create Cloned Server Group from ' + serverGroup.asg.autoScalingGroupName;
        command.type = 'copyLastAsg';
        command.source = {
          'account': serverGroup.account,
          'region': serverGroup.region,
          'asgName': serverGroup.asg.autoScalingGroupName
        };
      } else {
        command.type = 'deploy';
        var asgName = application.name;
        if (command.stack) {
          asgName += '-' + command.stack;
        }
        if (!command.stack && command.freeFormDetails) {
          asgName += '-';
        }
        if (command.freeFormDetails) {
          asgName += '-' + command.freeFormDetails;
        }
        description = 'Create New Server Group in cluster ' + asgName;
      }
      command.availabilityZones = {};
      command.availabilityZones[command.region] = $scope.command.availabilityZones;
      delete command.region;
      delete command.allImageSelection;
      delete command.instanceProfile;
      delete command.vpcId;
      delete command.usePreferredZones;

      $scope.taskMonitor.submit(
        function() {
          return orcaService.cloneServerGroup(command, application.name, description);
        }
      );
    };

    this.cancel = function () {
      $modalInstance.dismiss();
    };
  });
<|endoftext|>


<commit_before>import { observes } from 'ember-addons/ember-computed-decorators';
import computed from 'ember-addons/ember-computed-decorators';
import Post from 'discourse/models/post';
import PreferencesController from 'discourse/controllers/preferences';
import UserCardController from 'discourse/controllers/user-card';
import UserController from 'discourse/controllers/user';
import { withPluginApi } from 'discourse/lib/plugin-api';

function isSameDay(date, opts) {
  let formatString = 'YYYY';
  const current = moment();
  const currentDate = moment(date, 'YYYY-MM-DD');

  if (opts && opts.anniversary) {
    if (current.format(formatString) <= currentDate.format(formatString)) return false;
  }

  formatString = 'MMDD';

  return current.format(formatString) === currentDate.format(formatString);
}

function cakeday(createdAt) {
  if (Ember.isEmpty(createdAt)) return false;
  return isSameDay(createdAt, { anniversary: true });
}

function cakedayBirthday(dateOfBirth) {
  if (Ember.isEmpty(dateOfBirth)) return false;
  return isSameDay(dateOfBirth);
}

function oldPluginCode() {
  Post.reopen({
    @computed('user_created_at')
    isCakeday(createdAt) {
      return cakeday(createdAt);
    },

    @computed('user_custom_fields.date_of_birth')
    isUserBirthday(dateOfBirth) {
      return cakedayBirthday(dateOfBirth);
    },
  });
}

function initializeCakeday(api, siteSettings) {
  const emojiEnabled = siteSettings.enable_emoji;
  const cakedayEnabled = siteSettings.cakeday_enabled;
  const cakedayBirthdayEnabled = siteSettings.cakeday_birthday_enabled;

  if (cakedayEnabled) {
    api.includePostAttributes('user_created_at');

    api.addPosterIcon((cfs, attrs) => {
      const createdAt = attrs.user_created_at;
      if (!Ember.isEmpty(createdAt) && isSameDay(createdAt, { anniversary: true })) {
        if (emojiEnabled) {
          return { emoji: siteSettings.cakeday_emoji };
        } else {
          return { icon: 'birthday-cake', title: I18n.t("user.anniversary.title") };
        }
      }
    });
  }

  if (cakedayBirthdayEnabled) {
    api.addPosterIcon(cfs => {
      const dob = cfs.date_of_birth;
      if (!Ember.isEmpty(dob) && isSameDay(dob)) {
        if (emojiEnabled) {
          return { emoji: siteSettings.cakeday_birthday_emoji };
        } else {
          return { icon: 'birthday-cake', title: I18n.t("user.date_of_birth.title") };
        }
      }
    });
  }

  if (cakedayEnabled || cakedayBirthdayEnabled) {
    api.decorateWidget("hamburger-menu:generalLinks", () => {
      let route;

      if (cakedayEnabled) {
        route = 'cakeday.anniversaries';
      } else if (cakedayBirthdayEnabled) {
        route = 'cakeday.birthdays';
      }

      return { route: route, label: 'cakeday.title' };
    });
  }
}

export default {
  name: 'cakeday',

  initialize(container) {
    const siteSettings = container.lookup('site-settings:main');
    const store = container.lookup('store:main');

    store.addPluralization('anniversary', 'anniversaries');

    PreferencesController.reopen({
      days: _.range(1, 32),

      @computed
      months() {
        return moment.months().map((month, index) => {
          return { name: month, value: index + 1 };
        });
      },

      @observes("userBirthdayMonth", "userBirthdayDay")
      _setUserDateOfBirth() {
        const userBirthdayMonth = this.get("userBirthdayMonth");
        const userBirthdayDay = this.get("userBirthdayDay");
        const user = this.get("model");
        var date = '';

        if (userBirthdayMonth !== '' && userBirthdayDay !== '') {
          date = `1904-${this.get('userBirthdayMonth')}-${this.get('userBirthdayDay')}`;
        }

        user.set("custom_fields.date_of_birth", date);
      },

      @computed("model.custom_fields.date_of_birth")
      userBirthdayMonth(dateOfBirth) {
        return moment(dateOfBirth, 'YYYY-MM-DD').month() + 1;
      },

      @computed("model.custom_fields.date_of_birth")
      userBirthdayDay(dateOfBirth) {
        return moment(dateOfBirth, 'YYYY-MM-DD').date();
      }
    });

    UserCardController.reopen({
      @computed('user.created_at')
      isCakeday(createdAt) {
        return cakeday(createdAt);
      },

      @computed('user.custom_fields.date_of_birth')
      isUserBirthday(dateOfBirth) {
        return cakedayBirthday(dateOfBirth);
      },
    });

    UserController.reopen({
      @computed('model.created_at')
      isCakeday(createdAt) {
        return cakeday(createdAt);
      },

      @computed('model.custom_fields.date_of_birth')
      isUserBirthday(dateOfBirth) {
        return cakedayBirthday(dateOfBirth);
      },
    });

    withPluginApi('0.1', api => initializeCakeday(api, siteSettings), { noApi: oldPluginCode });
  }
};
<commit_msg>Set title attribute for birthday icons.<commit_after>import { observes } from 'ember-addons/ember-computed-decorators';
import computed from 'ember-addons/ember-computed-decorators';
import Post from 'discourse/models/post';
import PreferencesController from 'discourse/controllers/preferences';
import UserCardController from 'discourse/controllers/user-card';
import UserController from 'discourse/controllers/user';
import { withPluginApi } from 'discourse/lib/plugin-api';

function isSameDay(date, opts) {
  let formatString = 'YYYY';
  const current = moment();
  const currentDate = moment(date, 'YYYY-MM-DD');

  if (opts && opts.anniversary) {
    if (current.format(formatString) <= currentDate.format(formatString)) return false;
  }

  formatString = 'MMDD';

  return current.format(formatString) === currentDate.format(formatString);
}

function cakeday(createdAt) {
  if (Ember.isEmpty(createdAt)) return false;
  return isSameDay(createdAt, { anniversary: true });
}

function cakedayBirthday(dateOfBirth) {
  if (Ember.isEmpty(dateOfBirth)) return false;
  return isSameDay(dateOfBirth);
}

function oldPluginCode() {
  Post.reopen({
    @computed('user_created_at')
    isCakeday(createdAt) {
      return cakeday(createdAt);
    },

    @computed('user_custom_fields.date_of_birth')
    isUserBirthday(dateOfBirth) {
      return cakedayBirthday(dateOfBirth);
    },
  });
}

function initializeCakeday(api, siteSettings) {
  const emojiEnabled = siteSettings.enable_emoji;
  const cakedayEnabled = siteSettings.cakeday_enabled;
  const cakedayBirthdayEnabled = siteSettings.cakeday_birthday_enabled;

  if (cakedayEnabled) {
    api.includePostAttributes('user_created_at');

    api.addPosterIcon((cfs, attrs) => {
      const createdAt = attrs.user_created_at;
      if (!Ember.isEmpty(createdAt) && isSameDay(createdAt, { anniversary: true })) {
        let result = {};

        if (emojiEnabled) {
          result.emoji = siteSettings.cakeday_emoji;
        } else {
          result.icon = 'birthday-cake';
        }

        result.title = I18n.t("user.anniversary.title");
        return result;
      }
    });
  }

  if (cakedayBirthdayEnabled) {
    api.addPosterIcon(cfs => {
      const dob = cfs.date_of_birth;
      if (!Ember.isEmpty(dob) && isSameDay(dob)) {
        let result = {};

        if (emojiEnabled) {
          result.emoji = siteSettings.cakeday_birthday_emoji;
        } else {
          result.icon = 'birthday-cake';
        }

        result.title = I18n.t("user.date_of_birth.title");
        return result;
      }
    });
  }

  if (cakedayEnabled || cakedayBirthdayEnabled) {
    api.decorateWidget("hamburger-menu:generalLinks", () => {
      let route;

      if (cakedayEnabled) {
        route = 'cakeday.anniversaries';
      } else if (cakedayBirthdayEnabled) {
        route = 'cakeday.birthdays';
      }

      return { route: route, label: 'cakeday.title' };
    });
  }
}

export default {
  name: 'cakeday',

  initialize(container) {
    const siteSettings = container.lookup('site-settings:main');
    const store = container.lookup('store:main');

    store.addPluralization('anniversary', 'anniversaries');

    PreferencesController.reopen({
      days: _.range(1, 32),

      @computed
      months() {
        return moment.months().map((month, index) => {
          return { name: month, value: index + 1 };
        });
      },

      @observes("userBirthdayMonth", "userBirthdayDay")
      _setUserDateOfBirth() {
        const userBirthdayMonth = this.get("userBirthdayMonth");
        const userBirthdayDay = this.get("userBirthdayDay");
        const user = this.get("model");
        var date = '';

        if (userBirthdayMonth !== '' && userBirthdayDay !== '') {
          date = `1904-${this.get('userBirthdayMonth')}-${this.get('userBirthdayDay')}`;
        }

        user.set("custom_fields.date_of_birth", date);
      },

      @computed("model.custom_fields.date_of_birth")
      userBirthdayMonth(dateOfBirth) {
        return moment(dateOfBirth, 'YYYY-MM-DD').month() + 1;
      },

      @computed("model.custom_fields.date_of_birth")
      userBirthdayDay(dateOfBirth) {
        return moment(dateOfBirth, 'YYYY-MM-DD').date();
      }
    });

    UserCardController.reopen({
      @computed('user.created_at')
      isCakeday(createdAt) {
        return cakeday(createdAt);
      },

      @computed('user.custom_fields.date_of_birth')
      isUserBirthday(dateOfBirth) {
        return cakedayBirthday(dateOfBirth);
      },
    });

    UserController.reopen({
      @computed('model.created_at')
      isCakeday(createdAt) {
        return cakeday(createdAt);
      },

      @computed('model.custom_fields.date_of_birth')
      isUserBirthday(dateOfBirth) {
        return cakedayBirthday(dateOfBirth);
      },
    });

    withPluginApi('0.1', api => initializeCakeday(api, siteSettings), { noApi: oldPluginCode });
  }
};
<|endoftext|>


<commit_before>import PostView from "discourse/views/post";

function createSignupView(container, post, signup, vote) {
  const controller = container.lookup("controller:signup", { singleton: false }),
        view = container.lookup("view:signup");

  controller.set("vote", vote);
  controller.setProperties({ model: Em.Object.create(signup), post });
  view.set("controller", controller);

  return view;
}

export default {
  name: "extend-for-signup",

  initialize(container) {
    // Add button to markdown editor
    // const composer = container.lookup("controller:composer");
    // window.PagedownCustom.appendButtons.push({
    //   id: 'wmd-signup-button',
    //   description: 'Add a signup form to your post',
    //   execute: function() {
    //     return composer.appendTextAtCursor("\n[signup type=multiple]\n- option 1\n- option 2\n[/signup]\n");
    //   }
    // });

    const messageBus = container.lookup("message-bus:main");

    // listen for back-end to tell us when a post has a signup
    messageBus.subscribe("/signups", data => {
      const post = container.lookup("controller:topic").get('model.postStream').findLoadedPost(data.post_id);
      // HACK to trigger the "postViewUpdated" event
      Em.run.next(_ => post.set("cooked", post.get("cooked") + " "));
    });

    // overwrite signups
    PostView.reopen({
      _createSignupViews: function($post) {
        const post = this.get("post"),
              signups = post.get("signups"),
              votes = post.get("signups_votes") || {};

        // don't even bother when there's no signup
        if (!signups) { return; }

        // clean-up if needed
        this._cleanUpSignupViews();

        const signupViews = {};

        // iterate over all signups
        $(".signup", $post).each(function() {
          const $div = $("<div>"),
                $signup = $(this),
                signupName = $signup.data("signup-name"),
                signupView = createSignupView(container, post, signups[signupName], votes[signupName]);

          $signup.replaceWith($div);
          Em.run.next(_ => signupView.renderer.replaceIn(signupView, $div[0]));
          signupViews[signupName] = signupView;
        });

        messageBus.subscribe("/signups/" + this.get("post.id"), results => {
          if (results && results.signups) {
            _.forEach(results.signups, signup => {
              if (signupViews[signup.name]) {
                signupViews[signup.name].get("controller").set("model", Em.Object.create(signup));
              }
            });
          }
        });

        this.set("signupViews", signupViews);
      }.on("postViewInserted", "postViewUpdated"),

      _cleanUpSignupViews: function() {
        messageBus.unsubscribe("/signups/" + this.get("post.id"));

        if (this.get("signupViews")) {
          _.forEach(this.get("signupViews"), v => v.destroy());
        }
      }.on("willClearRender")
    });
  }
};
<commit_msg>Might have gotten the signup button back<commit_after>import PostView from "discourse/views/post";
import { onToolbarCreate } from 'discourse/components/d-editor';

function createSignupView(container, post, signup, vote) {
  const controller = container.lookup("controller:signup", { singleton: false }),
        view = container.lookup("view:signup");

  controller.set("vote", vote);
  controller.setProperties({ model: Em.Object.create(signup), post });
  view.set("controller", controller);

  return view;
}

export default {
  name: "extend-for-signup",

  initialize(container) {
    // Add button to markdown editor
    const composer = container.lookup("controller:composer");
    onToolbarCreate(toolbar => {
      toolbar.addButton({
        id: 'wmd-signup-button',
        group: "extras",
        description: 'Add a signup form to your post',
        execute: function() {
          return composer.appendTextAtCursor("\n[signup type=multiple]\n- option 1\n- option 2\n[/signup]\n");
        }
      });
    });

    const messageBus = container.lookup("message-bus:main");

    // listen for back-end to tell us when a post has a signup
    messageBus.subscribe("/signups", data => {
      const post = container.lookup("controller:topic").get('model.postStream').findLoadedPost(data.post_id);
      // HACK to trigger the "postViewUpdated" event
      Em.run.next(_ => post.set("cooked", post.get("cooked") + " "));
    });

    // overwrite signups
    PostView.reopen({
      _createSignupViews: function($post) {
        const post = this.get("post"),
              signups = post.get("signups"),
              votes = post.get("signups_votes") || {};

        // don't even bother when there's no signup
        if (!signups) { return; }

        // clean-up if needed
        this._cleanUpSignupViews();

        const signupViews = {};

        // iterate over all signups
        $(".signup", $post).each(function() {
          const $div = $("<div>"),
                $signup = $(this),
                signupName = $signup.data("signup-name"),
                signupView = createSignupView(container, post, signups[signupName], votes[signupName]);

          $signup.replaceWith($div);
          Em.run.next(_ => signupView.renderer.replaceIn(signupView, $div[0]));
          signupViews[signupName] = signupView;
        });

        messageBus.subscribe("/signups/" + this.get("post.id"), results => {
          if (results && results.signups) {
            _.forEach(results.signups, signup => {
              if (signupViews[signup.name]) {
                signupViews[signup.name].get("controller").set("model", Em.Object.create(signup));
              }
            });
          }
        });

        this.set("signupViews", signupViews);
      }.on("postViewInserted", "postViewUpdated"),

      _cleanUpSignupViews: function() {
        messageBus.unsubscribe("/signups/" + this.get("post.id"));

        if (this.get("signupViews")) {
          _.forEach(this.get("signupViews"), v => v.destroy());
        }
      }.on("willClearRender")
    });
  }
};
<|endoftext|>


<commit_before>/**
 * `modules/idea-hub` data store: draft-post-ideas.
 *
 * Site Kit by Google, Copyright 2021 Google 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
 *
 *     https://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.
 */

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME } from './constants';
import { createFetchStore } from '../../../googlesitekit/data/create-fetch-store';

const fetchGetDraftPostIdeasStore = createFetchStore( {
	baseName: 'getDraftPostIdeas',
	controlCallback: () => {
		return API.get( 'modules', 'idea-hub', 'draft-post-ideas' );
	},
	reducerCallback: ( state, draftPostIdeas ) => {
		return {
			...state,
			draftPostIdeas,
		};
	},
} );

const baseInitialState = {
	draftPostIdeas: undefined,
};

const baseResolvers = {
	*getDraftPostIdeas( options = {} ) {
		const registry = yield Data.commonActions.getRegistry();
		const draftPostIdeas = registry.select( STORE_NAME ).getDraftPostIdeas( options );

		// If there are already draft ideas in state, don't make an API request.
		if ( draftPostIdeas === undefined ) {
			yield fetchGetDraftPostIdeasStore.actions.fetchGetDraftPostIdeas();
		}
	},
};

const baseSelectors = {
	/**
	 * Gets Draft Post Ideas from the Idea Hub.
	 *
	 * @since 1.34.0
	 *
	 * @param {Object} state            Data store's state.
	 * @param {Object} options          Options for getting draft post ideas.
	 * @param {number} [options.offset] Optional. From which array index to get ideas.
	 * @param {number} [options.length] Optional. Amount of draft post ideas to return.
	 * @return {(Array.<Object>|undefined)} A list of idea hub ideas; `undefined` if not loaded.
	 */
	getDraftPostIdeas( state, options = {} ) {
		const { draftPostIdeas } = state;

		if ( draftPostIdeas === undefined ) {
			return undefined;
		}

		const offset = options?.offset || 0;
		const length = options.length ? offset + options.length : draftPostIdeas.length;
		return ( 'offset' in options || 'length' in options ) ? draftPostIdeas.slice( offset, length ) : draftPostIdeas;
	},
};

const store = Data.combineStores(
	fetchGetDraftPostIdeasStore,
	{
		initialState: baseInitialState,
		resolvers: baseResolvers,
		selectors: baseSelectors,
	}
);

export const initialState = store.initialState;
export const actions = store.actions;
export const controls = store.controls;
export const reducer = store.reducer;
export const resolvers = store.resolvers;
export const selectors = store.selectors;

export default store;
<commit_msg>Address cache issue on Idea Hub draft posts.<commit_after>/**
 * `modules/idea-hub` data store: draft-post-ideas.
 *
 * Site Kit by Google, Copyright 2021 Google 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
 *
 *     https://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.
 */

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME } from './constants';
import { createFetchStore } from '../../../googlesitekit/data/create-fetch-store';

const fetchGetDraftPostIdeasStore = createFetchStore( {
	baseName: 'getDraftPostIdeas',
	controlCallback: () => {
		return API.get( 'modules', 'idea-hub', 'draft-post-ideas', undefined, { useCache: false } );
	},
	reducerCallback: ( state, draftPostIdeas ) => {
		return {
			...state,
			draftPostIdeas,
		};
	},
} );

const baseInitialState = {
	draftPostIdeas: undefined,
};

const baseResolvers = {
	*getDraftPostIdeas( options = {} ) {
		const registry = yield Data.commonActions.getRegistry();
		const draftPostIdeas = registry.select( STORE_NAME ).getDraftPostIdeas( options );

		// If there are already draft ideas in state, don't make an API request.
		if ( draftPostIdeas === undefined ) {
			yield fetchGetDraftPostIdeasStore.actions.fetchGetDraftPostIdeas();
		}
	},
};

const baseSelectors = {
	/**
	 * Gets Draft Post Ideas from the Idea Hub.
	 *
	 * @since 1.34.0
	 *
	 * @param {Object} state            Data store's state.
	 * @param {Object} options          Options for getting draft post ideas.
	 * @param {number} [options.offset] Optional. From which array index to get ideas.
	 * @param {number} [options.length] Optional. Amount of draft post ideas to return.
	 * @return {(Array.<Object>|undefined)} A list of idea hub ideas; `undefined` if not loaded.
	 */
	getDraftPostIdeas( state, options = {} ) {
		const { draftPostIdeas } = state;

		if ( draftPostIdeas === undefined ) {
			return undefined;
		}

		const offset = options?.offset || 0;
		const length = options.length ? offset + options.length : draftPostIdeas.length;
		return ( 'offset' in options || 'length' in options ) ? draftPostIdeas.slice( offset, length ) : draftPostIdeas;
	},
};

const store = Data.combineStores(
	fetchGetDraftPostIdeasStore,
	{
		initialState: baseInitialState,
		resolvers: baseResolvers,
		selectors: baseSelectors,
	}
);

export const initialState = store.initialState;
export const actions = store.actions;
export const controls = store.controls;
export const reducer = store.reducer;
export const resolvers = store.resolvers;
export const selectors = store.selectors;

export default store;
<|endoftext|>