Refactoring views to use modals for create/edit instead of their own pages.

This commit is contained in:
kevgliss
2015-07-10 17:08:39 -07:00
parent 1e902750c3
commit c79905cd92
31 changed files with 533 additions and 529 deletions

View File

@ -1,18 +1,6 @@
'use strict';
angular.module('lemur')
.config(function config($routeProvider) {
$routeProvider.when('/certificates/create', {
templateUrl: '/angular/certificates/certificate/certificateWizard.tpl.html',
controller: 'CertificateCreateController'
});
$routeProvider.when('/certificates/:id/edit', {
templateUrl: '/angular/certificates/certificate/edit.tpl.html',
controller: 'CertificateEditController'
});
})
.controller('CertificateEditController', function ($scope, $routeParams, CertificateApi, CertificateService, MomentService) {
CertificateApi.get($routeParams.id).then(function (certificate) {
$scope.certificate = certificate;
@ -23,13 +11,14 @@ angular.module('lemur')
})
.controller('CertificateCreateController', function ($scope, $modal, CertificateApi, CertificateService, AccountService, ELBService, AuthorityService, MomentService, LemurRestangular) {
.controller('CertificateCreateController', function ($scope, $modalInstance, CertificateApi, CertificateService, DestinationService, ELBService, AuthorityService, PluginService, MomentService, WizardHandler, LemurRestangular) {
$scope.certificate = LemurRestangular.restangularizeElement(null, {}, 'certificates');
$scope.save = function (certificate) {
var loadingModal = $modal.open({backdrop: 'static', template: '<wave-spinner></wave-spinner>', windowTemplateUrl: 'angular/loadingModal.html', size: 'large'});
$scope.create = function (certificate) {
WizardHandler.wizard().context.loading = true;
CertificateService.create(certificate).then(function (response) {
loadingModal.close();
WizardHandler.wizard().context.loading = false;
$modalInstance.close();
});
};
@ -88,7 +77,11 @@ angular.module('lemur')
};
PluginService.get('destination').then(function (plugins) {
$scope.plugins = plugins;
});
$scope.elbService = ELBService;
$scope.authorityService = AuthorityService;
$scope.accountService = AccountService;
$scope.destinationService = DestinationService;
});

View File

@ -1,20 +0,0 @@
<h2 class="featurette-heading">Create a certificate <span class="text-muted"><small>encrypt all the things
</small></span></h2>
<div class="panel panel-default">
<div class="panel-heading">
<a href="/#/certificates/" class="btn btn-danger pull-right">Cancel</a>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form name="createForm" class="form-horizontal" role="form" ng-submit="submitCreate()" novalidate>
</form>
</div>
<div class="panel-footer">
<button type="submit" ng-disabled="createForm.$invalid" class="btn btn-success pull-right"><span
ng-show="!loading"> Create </span><span ng-show="loading">Creating <i ng-show="loading"
class="fa fa-cog fa-spin"></i></span>
</button>
<div class="clearfix"></div>
</div>
</div>

View File

@ -1,17 +1,23 @@
<h2 class="featurette-heading"><span ng-show="!certificate.id">Create</span><span ng-show="certificate.id">Edit</span> Certificate <span class="text-muted"><small>encrypt all the things
<div>
<wizard on-finish="save(certificate)" template="angular/wizard.html">
<wz-step title="Tracking" canexit="trackingForm.$valid">
<ng-include src="'angular/certificates/certificate/tracking.tpl.html'"></ng-include>
</wz-step>
<wz-step title="Distinguished Name" canenter="exitTracking" canexit="exitDN">
<ng-include src="'angular/certificates/certificate/distinguishedName.tpl.html'"></ng-include>
</wz-step>
<wz-step title="Options" canenter="enterValidation">
<ng-include src="'angular/certificates/certificate/options.tpl.html'"></ng-include>
</wz-step>
<wz-step title="Destinations" canenter="enterValidation">
<ng-include src="'angular/certificates/certificate/destinations.tpl.html'"></ng-include>
</wz-step>
</wizard>
</div>
<div class="modal-header">
<h3 class="modal-title"><span ng-show="!certificate.id">Create</span><span ng-show="certificate.id">Edit</span> Certificate <span class="text-muted"><small>encrypt all the things</small></h3>
</div>
<div class="modal-body">
<div>
<wizard on-finish="create(certificate)" template="angular/wizard.html">
<wz-step title="Tracking" canexit="trackingForm.$valid">
<ng-include src="'angular/certificates/certificate/tracking.tpl.html'"></ng-include>
</wz-step>
<wz-step title="Options" canenter="enterValidation">
<ng-include src="'angular/certificates/certificate/options.tpl.html'"></ng-include>
</wz-step>
<wz-step title="Distinguished Name" canenter="exitTracking" canexit="exitDN">
<ng-include src="'angular/certificates/certificate/distinguishedName.tpl.html'"></ng-include>
</wz-step>
<wz-step title="Destinations" canenter="enterValidation">
<ng-include src="'angular/certificates/certificate/destinations.tpl.html'"></ng-include>
</wz-step>
</wizard>
</div>
</div>

View File

@ -1,62 +1,28 @@
<p>Destinations are purely optional, if you think the created certificate will be used in AWS select one or more accounts and Lemur will upload it for you.</p>
<div class="form-horizontal">
<div class="form-group">
<div class="form-group">
<label class="control-label col-sm-2">
Accounts
Destinations
</label>
<div class="col-sm-10">
<div class="input-group">
<input type="text" ng-model="certificate.selectedAccount" placeholder="Account Name"
typeahead="account.label for account in accountService.findAccountsByName($viewValue)" typeahead-loading="loadingAccounts"
class="form-control input-md" typeahead-on-select="certificate.attachAccount($item)" typeahead-min-wait="50"
tooltip="Lemur can upload the certificate to any AWS account."
<input type="text" ng-model="certificate.selectedDestination" placeholder="AWS, TheSecret..."
typeahead="destination.label for destination in destinationService.findDestinationsByName($viewValue)" typeahead-loading="loadingDestinations"
class="form-control input-md" typeahead-on-select="certificate.attachDestination($item)" typeahead-min-wait="50"
tooltip="Lemur can upload certificates to any pre-defined destination"
tooltip-trigger="focus" tooltip-placement="top">
<span class="input-group-btn">
<button ng-model="accounts.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ certificate.accounts.length || 0 }}</span>
<button ng-model="destinations.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ certificate.destinations.length || 0 }}</span>
</button>
</span>
</div>
<table class="table">
<tr ng-repeat="account in certificate.accounts track by $index">
<td><a class="btn btn-sm btn-info" href="#/accounts/{{ account.id }}/certificates">{{ account.label }}</a></td>
<td><span class="text-muted">{{ account.comments }}</span></td>
<tr ng-repeat="destination in certificate.destinations track by $index">
<td><a class="btn btn-sm btn-info" href="#/destinations/{{ destination.id }}/certificates">{{ destination.label }}</a></td>
<td><span class="text-muted">{{ destination.description }}</span></td>
<td>
<button type="button" ng-click="certificate.removeAccount($index)" class="btn btn-danger btn-sm pull-right">Remove</button>
<button type="button" ng-click="certificate.removeDestination($index)" class="btn btn-danger btn-sm pull-right">Remove</button>
</td>
</tr>
</table>
</div>
</div>
<!--<div ng-show="certificate.accounts" class="form-group">
<label class="control-label col-sm-2">
ELBs
</label>
<div class="col-sm-10">
<div class="input-group">
<input type="text" ng-model="certificate.selectedELB" placeholder="ELB Name"
typeahead="elb.name for elb in elbService.findELBByName($viewValue)" typeahead-loading="loadingAccounts"
class="form-control col-md-4" typeahead-min-wait="50"
tooltip="Lemur can upload a certificate to one or more ELBs"
tooltip-trigger="focus" tooltip-placement="top"/>
<input class="form-control col-md-2" type="integer" ng-model="certificate.selectedPort" placeholder="Port"/>
<select class="form-control col-md-2" ng-options="item for item in ['https', 'tcp']"></select>
<span class="input-group-btn">
<button ng-click="certificate.attachELB()" class="btn btn-info">Add</button>
</span>
</div>
<table class="table">
<tr ng-repeat="elb in certificate.elbs track by $index">
<td><a class="btn btn-sm btn-info" href="#/accounts/{{ elb.id }}/elbs">{{ elb.name }}</a></td>
<td>{{ elb.region }}</td>
<td>{{ elb.scheme }}</td>
<td>{{ elb.vpcId }}</td>
<td>{{ elb.listener.scheme }}</td>
<td>{{ elb.listener.port }}</td>
<td>
<button type="button" ng-click="certificate.removeELB($index)" class="btn btn-danger btn-sm pull-right">remove</button>
</td>
</tr>
</table>
</div>-->
</div>

View File

@ -47,7 +47,7 @@
Common Name
</label>
<div class="col-sm-10">
<input name="commonName" tooltip="If you need a certificate with multiple domains enter your primary domain here and the rest under 'Subject Alternate Names' in the options panel" ng-model="certificate.commonName" placeholder="Common Name" class="form-control" required/>
<input name="commonName" tooltip="If you need a certificate with multiple domains enter your primary domain here and the rest under 'Subject Alternate Names' in the next panel" ng-model="certificate.commonName" placeholder="Common Name" class="form-control" required/>
<p ng-show="trackingForm.commonName.$invalid && !trackingForm.commonName.$pristine" class="help-block">You must enter a common name</p>
</div>
</div>
@ -65,7 +65,7 @@
</div>
</div>
</div>
<span class="text-center col-sm-2"><label><span class="glyphicon glyphicon-resize-horizontal"></span></label></span>
<span style="padding-top: 15px" class="text-center col-sm-2"><label><span class="glyphicon glyphicon-resize-horizontal"></span></label></span>
<div class="col-sm-4">
<div>
<div class="input-group">

View File

@ -2,20 +2,16 @@
angular.module('lemur')
.config(function config($routeProvider) {
$routeProvider.when('/certificates/upload', {
templateUrl: '/angular/certificates/certificate/upload.tpl.html',
controller: 'CertificatesUploadController'
});
})
.controller('CertificatesUploadController', function ($scope, CertificateService, LemurRestangular, AccountService, ELBService) {
.controller('CertificateUploadController', function ($scope, $modalInstance, CertificateService, LemurRestangular, DestinationService, ELBService, PluginService) {
$scope.certificate = LemurRestangular.restangularizeElement(null, {}, 'certificates');
$scope.upload = CertificateService.upload;
$scope.accountService = AccountService;
$scope.destinationService = DestinationService;
$scope.elbService = ELBService;
PluginService.get('destination').then(function (plugins) {
$scope.plugins = plugins;
});
$scope.attachELB = function (elb) {
$scope.certificate.attachELB(elb);
@ -23,4 +19,9 @@ angular.module('lemur')
$scope.certificate.elb.listeners = listeners;
});
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});

View File

@ -1,136 +1,71 @@
<h2 class="featurette-heading">Upload a certificate <span class="text-muted"><small>encrypt all the things
</small></span></h2>
<div class="panel panel-default">
<div class="panel-heading">
<a href="/#/certificates/" class="btn btn-danger pull-right">Cancel</a>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<form name="uploadForm" class="form-horizontal" role="form" novalidate>
<div class="form-group"
ng-class="{'has-error': uploadForm.owner.$invalid, 'has-success': !uploadForm.owner.$invalid&&uploadForm.owner.$dirty}">
<label class="control-label col-sm-2">
Owner
</label>
<div class="modal-header">
<div class="modal-title">
<h3 class="modal-header">Upload a certificate <span class="text-muted"><small>encrypt all the things</small></span></h3>
</div>
<div class="modal-body">
<form name="uploadForm" class="form-horizontal" role="form" novalidate>
<div class="form-group"
ng-class="{'has-error': uploadForm.owner.$invalid, 'has-success': !uploadForm.owner.$invalid&&uploadForm.owner.$dirty}">
<label class="control-label col-sm-2">
Owner
</label>
<div class="col-sm-10">
<input type="email" name="owner" ng-model="certificate.owner" placeholder="owner@netflix.com"
class="form-control" required/>
<div class="col-sm-10">
<input type="email" name="owner" ng-model="certificate.owner" placeholder="owner@netflix.com"
class="form-control" required/>
<p ng-show="uploadForm.owner.$invalid && !uploadForm.owner.$pristine" class="help-block">Enter a valid
email.</p>
</div>
</div>
<div class="form-group"
ng-class="{'has-error': uploadForm.publicCert.$invalid, 'has-success': !uploadForm.publicCert.$invalid&&uploadForm.publicCert.$dirty}">
<label class="control-label col-sm-2">
Public Certificate
</label>
<p ng-show="uploadForm.owner.$invalid && !uploadForm.owner.$pristine" class="help-block">Enter a valid
email.</p>
</div>
</div>
<div class="form-group"
ng-class="{'has-error': uploadForm.publicCert.$invalid, 'has-success': !uploadForm.publicCert.$invalid&&uploadForm.publicCert.$dirty}">
<label class="control-label col-sm-2">
Public Certificate
</label>
<div class="col-sm-10">
<div class="col-sm-10">
<textarea name="publicCert" ng-model="certificate.publicCert" placeholder="PEM encoded string..."
class="form-control" ng-pattern="/^-----BEGIN CERTIFICATE-----/" required></textarea>
<p ng-show="uploadForm.publicCert.$invalid && !uploadForm.publicCert.$pristine" class="help-block">Enter
a valid certificate.</p>
</div>
</div>
<div class="form-group"
ng-class="{'has-error': uploadForm.privateKey.$invalid&&uploadForm.privateKey.$dirty, 'has-success': !uploadForm.privateKey.$invalid&&uploadForm.privateKey.$dirty}">
<label class="control-label col-sm-2">
Private Key
</label>
<p ng-show="uploadForm.publicCert.$invalid && !uploadForm.publicCert.$pristine" class="help-block">Enter
a valid certificate.</p>
</div>
</div>
<div class="form-group"
ng-class="{'has-error': uploadForm.privateKey.$invalid&&uploadForm.privateKey.$dirty, 'has-success': !uploadForm.privateKey.$invalid&&uploadForm.privateKey.$dirty}">
<label class="control-label col-sm-2">
Private Key
</label>
<div class="col-sm-10">
<div class="col-sm-10">
<textarea name="privateKey" ng-model="certificate.privateKey" placeholder="PEM encoded string..."
class="form-control" ng-pattern="/^-----BEGIN RSA PRIVATE KEY-----/"></textarea>
<p ng-show="uploadForm.privateKey.$invalid && !uploadForm.privateKey.$pristine" class="help-block">Enter
a valid certificate.</p>
</div>
</div>
<div class="form-group"
ng-class="{'has-error': uploadForm.owner.$invalid&&uploadform.intermediateCert.$dirty, 'has-success': !uploadForm.intermediateCert.$invalid&&uploadForm.intermediateCert.$dirty}">
<label class="control-label col-sm-2">
Intermediate Certificate
</label>
<p ng-show="uploadForm.privateKey.$invalid && !uploadForm.privateKey.$pristine" class="help-block">Enter
a valid certificate.</p>
</div>
</div>
<div class="form-group"
ng-class="{'has-error': uploadForm.owner.$invalid&&uploadform.intermediateCert.$dirty, 'has-success': !uploadForm.intermediateCert.$invalid&&uploadForm.intermediateCert.$dirty}">
<label class="control-label col-sm-2">
Intermediate Certificate
</label>
<div class="col-sm-10">
<div class="col-sm-10">
<textarea name="intermediateCert" ng-model="certificate.intermediateCert"
placeholder="PEM encoded string..." class="form-control"
ng-pattern="/^-----BEGIN CERTIFICATE-----/"></textarea>
<p ng-show="uploadForm.intermediateCert.$invalid && !uploadForm.intemediateCert.$pristine"
class="help-block">Enter a valid certificate.</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Accounts
</label>
<div class="col-sm-10">
<div class="input-group">
<input type="text" ng-model="certificate.selectedAccount" placeholder="Account Name"
typeahead="account.label for account in accountService.findAccountsByName($viewValue)" typeahead-loading="loadingAccounts"
class="form-control" typeahead-on-select="certificate.attachAccount($item)" typeahead-min-wait="50"
tooltip="Lemur can upload the certificate to any AWS account."
tooltip-trigger="focus" tooltip-placement="top">
<span class="input-group-btn">
<button ng-model="certificate.accounts" class="btn btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ certificate.accounts.length || 0 }}</span>
</button>
</span>
</div>
<table ng-show="certificate.accounts" class="table">
<tr ng-repeat="account in certificate.accounts track by $index">
<td><a class="btn btn-sm btn-info" href="#/accounts/{{ account.id }}/certificates">{{ account.label }}</a></td>
<td><span class="text-muted">{{ account.comments }}</span></td>
<td>
<button type="button" ng-click="certificate.removeAccount($index)" class="btn btn-danger btn-sm pull-right">
Remove
</button>
</td>
</tr>
</table>
</div>
</div>
<!--<div class="form-group">
<label class="control-label col-sm-2">
ELBs
</label>
<div class="col-sm-10">
<div class="input-group">
<input type="text" ng-model="certificate.selectedELB" placeholder="ELB Name"
typeahead="elb.name for elb in elbService.findELBByName($viewValue)" typeahead-loading="loadingAccounts"
class="form-control" typeahead-on-select="attachELB($item)" typeahead-min-wait="50"
tooltip="Lemur can upload a certificate to one or more ELBs searching will be limited to the accounts selected above"
tooltip-trigger="focus" tooltip-placement="top">
<span class="input-group-btn">
<button ng-model="certificate.elbs" class="btn btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ certificate.elbs.length || 0 }}</span>
</button>
</span>
<p ng-show="uploadForm.intermediateCert.$invalid && !uploadForm.intemediateCert.$pristine"
class="help-block">Enter a valid certificate.</p>
</div>
</div>
<table ng-show="certificate.elbs" class="table">
<tr ng-repeat="elb in certificate.elbs track by $index">
<td><a class="btn btn-sm btn-info" href="#/accounts/{{ elb.id }}/elbs">{{ elb.name }}</a></td>
<td>{{ elb.region }}</td>
<td>{{ elb.scheme }}</td>
<td>{{ elb.vpcId }}</td>
<td><a class="btn btn-info" ng-model="elb.showListeners" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">View Listeners</a></td>
<td>
<button type="button" ng-click="certificate.removeAccount($index)" class="btn btn-danger btn-sm pull-right">
Remove
</button>
</td>
</tr>
</table>
</div>
</div>-->
</form>
</div>
<div class="panel-footer">
<button type="submit" ng-click="upload(certificate)" ng-disabled="uploadForm.$invalid" class="btn btn-success pull-right">Upload</button>
<div class="clearfix"></div>
</div>
<div ng-include="'angular/certificates/certificate/destinations.tpl.html'"></div>
</form>
</div>
<div class="modal-footer">
<button type="submit" ng-click="upload(certificate)" ng-disabled="uploadForm.$invalid" class="btn btn-success">Import</button>
<button ng-click="cancel()" class="btn btn-danger">Cancel</button>
</div>
</div>

View File

@ -58,15 +58,15 @@ angular.module('lemur')
removeCustom: function (index) {
this.extensions.custom.splice(index, 1);
},
attachAccount: function (account) {
this.selectedAccount = null;
if (this.accounts === undefined) {
this.accounts = [];
attachDestination: function (destination) {
this.selectedDestination = null;
if (this.destinations === undefined) {
this.destinations = [];
}
this.accounts.push(account);
this.destinations.push(destination);
},
removeAccount: function (index) {
this.accounts.splice(index, 1);
removeDestination: function (index) {
this.destinations.splice(index, 1);
},
attachELB: function (elb) {
this.selectedELB = null;
@ -99,13 +99,6 @@ angular.module('lemur')
});
};
CertificateService.getARNs = function (certificate) {
certificate.arns = [];
_.each(certificate.accounts, function (account) {
certificate.arns.push('arn:aws:iam::' + account.accountNumber + ':server-certificate/' + certificate.name);
});
};
CertificateService.create = function (certificate) {
certificate.attachSubAltName();
return CertificateApi.post(certificate).then(
@ -191,10 +184,9 @@ angular.module('lemur')
});
};
CertificateService.getAccounts = function (certificate) {
certificate.getList('accounts').then(function (accounts) {
certificate.accounts = accounts;
CertificateService.getARNs(certificate);
CertificateService.getDestinations = function (certificate) {
certificate.getList('destinations').then(function (destinations) {
certificate.destinations = destinations;
});
};

View File

@ -9,7 +9,7 @@ angular.module('lemur')
});
})
.controller('CertificatesViewController', function ($q, $scope, CertificateApi, CertificateService, MomentService, ngTableParams) {
.controller('CertificatesViewController', function ($q, $scope, $modal, CertificateApi, CertificateService, MomentService, ngTableParams) {
$scope.filter = {};
$scope.certificateTable = new ngTableParams({
page: 1, // show first page
@ -26,7 +26,7 @@ angular.module('lemur')
// TODO we should attempt to resolve all of these in parallel
_.each(data, function (certificate) {
CertificateService.getDomains(certificate);
CertificateService.getAccounts(certificate);
CertificateService.getDestinations(certificate);
CertificateService.getListeners(certificate);
CertificateService.getAuthority(certificate);
CertificateService.getCreator(certificate);
@ -60,4 +60,30 @@ angular.module('lemur')
$scope.toggleFilter = function (params) {
params.settings().$scope.show_filter = !params.settings().$scope.show_filter;
};
$scope.create = function () {
var modalInstance = $modal.open({
animation: true,
controller: 'CertificateCreateController',
templateUrl: '/angular/certificates/certificate/certificateWizard.tpl.html',
size: 'lg'
});
modalInstance.result.then(function () {
$scope.certificateTable.reload();
});
};
$scope.import = function () {
var modalInstance = $modal.open({
animation: true,
controller: 'CertificateUploadController',
templateUrl: '/angular/certificates/certificate/upload.tpl.html',
size: 'lg'
});
modalInstance.result.then(function () {
$scope.certificateTable.reload();
});
};
});

View File

@ -5,14 +5,14 @@
<div class="panel panel-default">
<div class="panel-heading">
<div class="btn-group pull-right">
<a data-placement="left" data-title="Create Certificate" bs-tooltip href="#/certificates/create"
<button data-placement="left" data-title="Create Certificate" bs-tooltip ng-click="create()"
class="btn btn-primary">
Create
</a>
<a data-placement="left" data-title="Upload Certificate" bs-tooltip href="#/certificates/upload"
</button>
<button data-placement="left" data-title="Import Certificate" bs-tooltip ng-click="import()"
class="btn btn-info">
Upload
</a>
Import
</button>
</div>
<div class="btn-group">
<button ng-click="toggleFilter(certificateTable)" class="btn btn-default">Filter</button>
@ -30,9 +30,9 @@
<li><span class="text-muted">{{ certificate.owner }}</span></li>
</ul>
</td>
<td data-title="'Accounts'" filter="{ 'account': 'select' }" filter-date="getAccountDropDown()">
<td data-title="'Destinations'" filter="{ 'destination': 'select' }" filter-date="getDestinationDropDown()">
<div class="btn-group">
<a href="#/accounts/{{ account.id }}/edit" class="btn btn-sm btn-default" ng-repeat="account in certificate.accounts">{{ account.label }}</a>
<a href="#/destinations/{{ destination.id }}/edit" class="btn btn-sm btn-default" ng-repeat="account in certificate.destinations">{{ destination.label }}</a>
</div>
</td>
<td data-title="'Active'" filter="{ 'active': 'select' }" filter-data="getCertificateStatus()">
@ -106,7 +106,7 @@
<div class="list-group">
<a href="#/domains/{{ domain.id }}" class="list-group-item" ng-repeat="domain in certificate.domains">{{ domain.name }}</a>
</div>
<h4 ng-show="certificate.accounts.total">ARNs</h4>
<h4 ng-show="certificate.destinations.total">ARNs</h4>
<ul class="list-group">
<li class="list-group-item" ng-repeat="arn in certificate.arns">{{ arn }}</li>
</ul>