Move app clone into app view

This commit is contained in:
Johannes Zellner
2019-09-13 17:18:37 +02:00
parent 849b9e0c80
commit c570e8b6fe
4 changed files with 133 additions and 138 deletions
+63
View File
@@ -50,6 +50,69 @@
</div>
</div>
<!-- Modal clone app -->
<div class="modal fade" id="cloneModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
Clone - {{ app.fqdn }}
</h4>
</div>
<div class="modal-body" style="padding: 0 15px">
<p>Using backup from <b>{{ clone.backup.creationTime | prettyDate }}</b> and version <b>v{{ clone.backup.version }}</b></p>
<fieldset>
<form role="form" ng-submit="clone.submit()" autocomplete="off">
<div class="form-group" ng-class="{ 'has-error': clone.error.location }">
<label class="control-label" for="cloneLocationInput">Location</label>
<div ng-show="clone.error.location"><small>{{ clone.error.location }}</small></div>
<div class="input-group form-inline">
<input type="text" class="form-control" ng-model="clone.location" id="cloneLocationInput" name="location" placeholder="Leave empty to use bare domain" autofocus>
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span>{{ (!clone.location ? '' : (clone.domain.config.hyphenatedSubdomains ? '-' : '.')) + clone.domain.domain }}</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<li ng-repeat="domain in domains">
<a href="" ng-click="clone.domain = domain">{{ domain.domain }}</a>
</li>
</ul>
</div>
</div>
</div>
<p class="text-center" ng-show="appClone.location && appClone.domain.provider === 'manual'">
<b>Add an A record manually for {{ appClone.location }} to this Cloudron's public IP</b>
<br>
</p>
<div class="has-error text-center" ng-show="appClone.error.port">{{ appClone.error.port }}</div>
<div ng-repeat="(env, info) in appClone.portBindingsInfo">
<ng-form name="portInfo_form">
<div class="form-group" ng-class="{ 'has-error': (!appClone.itemName{{$index}}.$dirty && appClone.error.port) || (portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid) }">
<label class="control-label" for="inputPortInfo{{env}}"><input type="checkbox" ng-model="appClone.portBindingsEnabled[env]">
{{ info.title }}
<sup>
<a popover-placement="top-right" popover-trigger="outsideClick" uib-popover="{{info.description}} ({{ HOST_PORT_MIN }} - {{ HOST_PORT_MAX }})"><i class="fa fa-question-circle"></i></a>
</sup>
</label>
<input type="number" class="form-control" ng-model="appClone.portBindings[env]" ng-disabled="!appClone.portBindingsEnabled[env]" id="inputPortInfo{{env}}" later-name="itemName{{$index}}" min="{{hostPortMin}}" max="{{hostPortMax}}" required>
</div>
</ng-form>
</div>
</form>
</fieldset>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-success" ng-click="appClone.submit()"><i class="far fa-clone"></i> Clone</button>
</div>
</div>
</div>
</div>
<div class="content">
+70
View File
@@ -515,6 +515,76 @@ angular.module('Application').controller('AppController', ['$scope', '$location'
}
};
$scope.clone = {
busy: true,
error: {},
backup: null,
location: '',
domain: null,
portBindings: {},
portBindingsInfo: {},
portBindingsEnabled: {},
show: function (backup) {
var app = $scope.app;
$scope.clone.backup = backup;
$scope.clone.domain = $scope.domains.find(function (d) { return app.domain === d.domain; }); // pre-select the app's domain
$scope.clone.portBindingsInfo = angular.extend({}, app.manifest.tcpPorts, app.manifest.udpPorts); // Portbinding map only for information
// set default ports
for (var env in $scope.clone.portBindingsInfo) {
$scope.clone.portBindings[env] = $scope.clone.portBindingsInfo[env].defaultValue || 0;
$scope.clone.portBindingsEnabled[env] = true;
}
$('#cloneModal').modal('show');
},
submit: function () {
$scope.clone.busy = true;
// only use enabled ports from portBindings
var finalPortBindings = {};
for (var env in $scope.clone.portBindings) {
if ($scope.clone.portBindingsEnabled[env]) {
finalPortBindings[env] = $scope.clone.portBindings[env];
}
}
var data = {
location: $scope.clone.location,
domain: $scope.clone.domain.domain,
portBindings: finalPortBindings,
backupId: $scope.clone.backup.id
};
Client.cloneApp($scope.app.id, data, function (error, clonedApp) {
$scope.clone.busy = false;
if (error) {
if (error.statusCode === 409) {
if (error.portName) {
$scope.clone.error.port = error.message;
} else if (error.domain) {
$scope.clone.error.location = 'This location is already taken.';
$('#cloneLocationInput').focus();
} else {
Client.error(error);
}
} else {
Client.error(error);
}
return;
}
$('#cloneModal').modal('hide');
$location.path('/apps');
});
}
}
function fetchUsers(callback) {
Client.getUsers(function (error, users) {
if (error) return callback(error);
-64
View File
@@ -1,67 +1,3 @@
<!-- Modal clone app -->
<div class="modal fade" id="appCloneModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
Clone - {{ appClone.app.fqdn }}
</h4>
</div>
<div class="modal-body" style="padding: 0 15px">
<p>Using backup from <b>{{ appClone.backup.creationTime | prettyDate }}</b> and version <b>v{{ appClone.backup.version }}</b></p>
<fieldset>
<form role="form" ng-submit="appClone.submit()" autocomplete="off">
<div class="form-group" ng-class="{ 'has-error': appClone.error.location }">
<label class="control-label" for="appCloneLocationInput">Location</label>
<div ng-show="appClone.error.location"><small>{{ appClone.error.location }}</small></div>
<div class="input-group form-inline">
<input type="text" class="form-control" ng-model="appClone.location" id="appCloneLocationInput" name="location" placeholder="Leave empty to use bare domain" autofocus>
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span>{{ (!appClone.location ? '' : (appClone.domain.config.hyphenatedSubdomains ? '-' : '.')) + appClone.domain.domain }}</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<li ng-repeat="domain in domains">
<a href="" ng-click="appClone.domain = domain">{{ domain.domain }}</a>
</li>
</ul>
</div>
</div>
</div>
<p class="text-center" ng-show="appClone.location && appClone.domain.provider === 'manual'">
<b>Add an A record manually for {{ appClone.location }} to this Cloudron's public IP</b>
<br>
</p>
<div class="has-error text-center" ng-show="appClone.error.port">{{ appClone.error.port }}</div>
<div ng-repeat="(env, info) in appClone.portBindingsInfo">
<ng-form name="portInfo_form">
<div class="form-group" ng-class="{ 'has-error': (!appClone.itemName{{$index}}.$dirty && appClone.error.port) || (portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid) }">
<label class="control-label" for="inputPortInfo{{env}}"><input type="checkbox" ng-model="appClone.portBindingsEnabled[env]">
{{ info.title }}
<sup>
<a popover-placement="top-right" popover-trigger="outsideClick" uib-popover="{{info.description}} ({{ HOST_PORT_MIN }} - {{ HOST_PORT_MAX }})"><i class="fa fa-question-circle"></i></a>
</sup>
</label>
<input type="number" class="form-control" ng-model="appClone.portBindings[env]" ng-disabled="!appClone.portBindingsEnabled[env]" id="inputPortInfo{{env}}" later-name="itemName{{$index}}" min="{{hostPortMin}}" max="{{hostPortMax}}" required>
</div>
</ng-form>
</div>
</form>
</fieldset>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-success" ng-click="appClone.submit()"><i class="far fa-clone"></i> Clone</button>
</div>
</div>
</div>
</div>
<!-- Modal postinstall confirm -->
<div class="modal fade" id="appPostInstallConfirmModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
-74
View File
@@ -21,80 +21,6 @@ angular.module('Application').controller('AppsController', ['$scope', '$location
$scope.backupsEnabled = true;
$scope.disableIndexingTemplate = '# Disable search engine indexing\n\nUser-agent: *\nDisallow: /';
$scope.appClone = {
busy: false,
error: {},
app: {},
backup: {},
// form
location: '',
domain: null,
portBindings: {},
portBindingsInfo: {},
portBindingsEnabled: {},
show: function (app, backup) {
$scope.appClone.busy = false;
$scope.appClone.error = {};
$scope.appClone.app = app;
$scope.appClone.backup = backup;
$scope.appClone.location = '';
$scope.appClone.domain = $scope.domains.find(function (d) { return app.domain === d.domain; }); // pre-select the app's domain
$scope.appClone.portBindingsInfo = angular.extend({}, $scope.appClone.app.manifest.tcpPorts, $scope.appClone.app.manifest.udpPorts); // Portbinding map only for information
// set default ports
for (var env in $scope.appClone.portBindingsInfo) {
$scope.appClone.portBindings[env] = $scope.appClone.portBindingsInfo[env].defaultValue || 0;
$scope.appClone.portBindingsEnabled[env] = true;
}
$('#appCloneModal').modal('show');
},
submit: function () {
$scope.appClone.busy = true;
// only use enabled ports from portBindings
var finalPortBindings = {};
for (var env in $scope.appClone.portBindings) {
if ($scope.appClone.portBindingsEnabled[env]) {
finalPortBindings[env] = $scope.appClone.portBindings[env];
}
}
var data = {
location: $scope.appClone.location,
domain: $scope.appClone.domain.domain,
portBindings: finalPortBindings,
backupId: $scope.appClone.backup.id
};
Client.cloneApp($scope.appClone.app.id, data, function (error, clonedApp) {
$scope.appClone.busy = false;
if (error) {
if (error.statusCode === 409) {
if (error.portName) {
$scope.appClone.error.port = error.message;
} else if (error.domain) {
$scope.appClone.error.location = 'This location is already taken.';
$('#appCloneLocationInput').focus();
} else {
Client.error(error);
}
} else {
Client.error(error);
}
return;
}
$('#appCloneModal').modal('hide');
Client.refreshAppCache(clonedApp.id); // reflect the new app state immediately
});
}
};
$scope.appPostInstallConfirm = {
app: {},
message: '',