Merge branch 'release/1.15.2'

pull/1388/head 1.15.2
Anthony Lapenna 2017-11-13 10:11:14 +01:00
commit b044aa9a84
137 changed files with 707 additions and 1067 deletions

View File

@ -389,7 +389,7 @@ type (
const (
// APIVersion is the version number of the Portainer API.
APIVersion = "1.15.1"
APIVersion = "1.15.2"
// DBVersion is the version number of the Portainer database.
DBVersion = 6
// DefaultTemplatesURL represents the default URL for the templates definitions.

View File

@ -56,7 +56,7 @@ info:
**NOTE**: You can find more information on how to query the Docker API in the [Docker official documentation](https://docs.docker.com/engine/api/v1.30/) as well as in [this Portainer example](https://gist.github.com/deviantony/77026d402366b4b43fa5918d41bc42f8).
version: "1.15.1"
version: "1.15.2"
title: "Portainer API"
contact:
email: "info@portainer.io"
@ -1869,7 +1869,7 @@ definitions:
description: "Is analytics enabled"
Version:
type: "string"
example: "1.15.1"
example: "1.15.2"
description: "Portainer API version"
PublicSettingsInspectResponse:
type: "object"

View File

@ -9,6 +9,7 @@ angular.module('portainer', [
'LocalStorageModule',
'angular-jwt',
'angular-google-analytics',
'angular-loading-bar',
'portainer.templates',
'portainer.filters',
'portainer.rest',

View File

@ -1,5 +1,5 @@
angular.module('portainer')
.run(['$rootScope', '$state', 'Authentication', 'authManager', 'StateManager', 'EndpointProvider', 'Notifications', 'Analytics', function ($rootScope, $state, Authentication, authManager, StateManager, EndpointProvider, Notifications, Analytics) {
.run(['$rootScope', '$state', 'Authentication', 'authManager', 'StateManager', 'EndpointProvider', 'Notifications', 'Analytics', 'cfpLoadingBar', function ($rootScope, $state, Authentication, authManager, StateManager, EndpointProvider, Notifications, Analytics, cfpLoadingBar) {
'use strict';
EndpointProvider.initialize();
@ -18,6 +18,15 @@ angular.module('portainer')
});
$rootScope.$state = $state;
// Workaround to prevent the loading bar from going backward
// https://github.com/chieffancypants/angular-loading-bar/issues/273
var originalSet = cfpLoadingBar.set;
cfpLoadingBar.set = function overrideSet(n) {
if (n > cfpLoadingBar.status()) {
originalSet.apply(cfpLoadingBar, arguments);
}
};
}]);

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="config({id: config.Id})" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-content>
<a ui-sref="configs">Configs</a> &gt; <a ui-sref="config({id: config.Id})">{{ config.Name }}</a>

View File

@ -3,7 +3,6 @@ angular.module('config', [])
function ($scope, $transition$, $state, $document, ConfigService, Notifications, CodeMirrorService) {
$scope.removeConfig = function removeConfig(configId) {
$('#loadingViewSpinner').show();
ConfigService.remove(configId)
.then(function success(data) {
Notifications.success('Config successfully removed');
@ -11,9 +10,6 @@ function ($scope, $transition$, $state, $document, ConfigService, Notifications,
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove config');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
@ -27,7 +23,6 @@ function ($scope, $transition$, $state, $document, ConfigService, Notifications,
}
function initView() {
$('#loadingViewSpinner').show();
ConfigService.config($transition$.params().id)
.then(function success(data) {
$scope.config = data;
@ -35,9 +30,6 @@ function ($scope, $transition$, $state, $document, ConfigService, Notifications,
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve config details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="configs" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Configs</rd-header-content>
</rd-header>

View File

@ -30,17 +30,8 @@ function ($scope, $stateParams, $state, ConfigService, Notifications, Pagination
};
$scope.removeAction = function () {
$('#loadingViewSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadingViewSpinner').hide();
}
};
angular.forEach($scope.configs, function (config) {
if (config.Checked) {
counter = counter + 1;
ConfigService.remove(config.Id)
.then(function success() {
Notifications.success('Config deleted', config.Id);
@ -49,16 +40,12 @@ function ($scope, $stateParams, $state, ConfigService, Notifications, Pagination
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove config');
})
.finally(function final() {
complete();
});
}
});
};
function initView() {
$('#loadingViewSpinner').show();
ConfigService.configs()
.then(function success(data) {
$scope.configs = data;
@ -66,9 +53,6 @@ function ($scope, $stateParams, $state, ConfigService, Notifications, Pagination
.catch(function error(err) {
$scope.configs = [];
Notifications.error('Failure', err, 'Unable to retrieve configs');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,330 +1,334 @@
<rd-header>
<rd-header-title title="Container details">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-content>
<a ui-sref="containers">Containers</a> &gt; <a ui-sref="container({id: container.Id})">{{ container.Name|trimcontainername }}</a>
</rd-header-content>
</rd-header>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-cogs" title="Actions"></rd-widget-header>
<rd-widget-body classes="padding">
<div class="btn-group" role="group" aria-label="...">
<button class="btn btn-success" ng-click="start()" ng-disabled="container.State.Running"><i class="fa fa-play space-right" aria-hidden="true"></i>Start</button>
<button class="btn btn-danger" ng-click="stop()" ng-disabled="!container.State.Running"><i class="fa fa-stop space-right" aria-hidden="true"></i>Stop</button>
<button class="btn btn-danger" ng-click="kill()" ng-disabled="!container.State.Running"><i class="fa fa-bomb space-right" aria-hidden="true"></i>Kill</button>
<button class="btn btn-primary" ng-click="restart()" ng-disabled="!container.State.Running"><i class="fa fa-refresh space-right" aria-hidden="true"></i>Restart</button>
<button class="btn btn-primary" ng-click="pause()" ng-disabled="!container.State.Running || container.State.Paused"><i class="fa fa-pause space-right" aria-hidden="true"></i>Pause</button>
<button class="btn btn-primary" ng-click="unpause()" ng-disabled="!container.State.Paused"><i class="fa fa-play space-right" aria-hidden="true"></i>Resume</button>
<button class="btn btn-danger" ng-click="confirmRemove()"><i class="fa fa-trash space-right" aria-hidden="true"></i>Remove</button>
<button class="btn btn-danger" ng-click="recreate()" ng-if="!container.Config.Labels['com.docker.swarm.service.id']"><i class="fa fa-refresh space-right" aria-hidden="true"></i>Recreate</button>
<button class="btn btn-primary" ng-click="duplicate()" ng-if="!container.Config.Labels['com.docker.swarm.service.id']"><i class="fa fa-files-o space-right" aria-hidden="true"></i>Duplicate/Edit</button>
</div>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-server" title="Container status"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<tbody>
<tr>
<td>ID</td>
<td>{{ container.Id }}</td>
</tr>
<tr>
<td>Name</td>
<td ng-if="!container.edit">
{{ container.Name|trimcontainername }}
<a href="" data-toggle="tooltip" title="Edit container name" ng-click="container.edit = true;"><i class="fa fa-edit"></i></a>
</td>
<td ng-if="container.edit">
<form ng-submit="renameContainer()">
<input type="text" class="containerNameInput" ng-model="container.newContainerName">
<a href="" ng-click="container.edit = false;"><i class="fa fa-times"></i></a>
<a href="" ng-click="renameContainer()"><i class="fa fa-check-square-o"></i></a>
</form>
</td>
</tr>
<tr ng-if="container.NetworkSettings.IPAddress">
<td>IP address</td>
<td>{{ container.NetworkSettings.IPAddress }}</td>
</tr>
<tr>
<td>Status</td>
<td>
<i class="fa fa-heartbeat space-right green-icon" ng-if="container.State.Running"></i>
<i class="fa fa-heartbeat space-right red-icon" ng-if="!container.State.Running && container.State.Status !== 'created'"></i>
{{ container.State|getstatetext }} since {{ activityTime }}<span ng-if="!container.State.Running && container.State.Status !== 'created'"> with exit code {{ container.State.ExitCode }}</span>
</td>
</tr>
<tr>
<td>Created</td>
<td>{{ container.Created|getisodate }}</td>
</tr>
<tr ng-if="container.State.Running">
<td>Start time</td>
<td>{{ container.State.StartedAt|getisodate }}</td>
</tr>
<tr ng-if="!container.State.Running && container.State.Status !== 'created'">
<td>Finished</td>
<td>{{ container.State.FinishedAt|getisodate }}</td>
</tr>
<tr>
<td colspan="2">
<div class="btn-group" role="group" aria-label="...">
<a class="btn btn-outline-secondary" type="button" ui-sref="stats({id: container.Id})"><i class="fa fa-area-chart space-right" aria-hidden="true"></i>Stats</a>
<a class="btn btn-outline-secondary" type="button" ui-sref="containerlogs({id: container.Id})"><i class="fa fa-exclamation-circle space-right" aria-hidden="true"></i>Logs</a>
<a class="btn btn-outline-secondary" type="button" ui-sref="console({id: container.Id})"><i class="fa fa-terminal space-right" aria-hidden="true"></i>Console</a>
<a class="btn btn-outline-secondary" type="button" ui-sref="inspect({id: container.Id})"><i class="fa fa-info-circle space-right" aria-hidden="true"></i>Inspect</a>
</div>
</td>
</tr>
</tbody>
</table>
</rd-widget-body>
</rd-widget>
</div>
</div>
<!-- access-control-panel -->
<por-access-control-panel
ng-if="container && applicationState.application.authentication"
resource-id="container.Id"
resource-control="container.ResourceControl"
resource-type="'container'">
</por-access-control-panel>
<!-- !access-control-panel -->
<div ng-if="container.State.Health" class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-server" title="Container health"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<tbody>
<tr>
<td>Status</td>
<td>
<i ng-class="{'healthy': 'fa fa-heartbeat space-right green-icon', 'unhealthy': 'fa fa-heartbeat space-right red-icon', 'starting': 'fa fa-heartbeat space-right orange-icon'}[container.State.Health.Status]"></i>
{{ container.State.Health.Status }}
</td>
</tr>
<tr>
<td>Failure count</td>
<td>{{ container.State.Health.FailingStreak }}</td>
</tr>
<tr>
<td>Last output</td>
<td>{{ container.State.Health.Log[container.State.Health.Log.length - 1].Output }}</td>
</tr>
</tbody>
</table>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-clone" title="Create image"></rd-widget-header>
<rd-widget-body>
<form class="form-horizontal">
<!-- tag-description -->
<div class="form-group">
<div class="col-sm-12">
<span class="small text-muted">
You can create an image from this container, this allows you to backup important data or save
helpful configurations. You'll be able to spin up another container based on this image afterward.
</span>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-cogs" title="Actions"></rd-widget-header>
<rd-widget-body classes="padding">
<div class="btn-group" role="group" aria-label="...">
<button class="btn btn-success" ng-click="start()" ng-disabled="container.State.Running"><i class="fa fa-play space-right" aria-hidden="true"></i>Start</button>
<button class="btn btn-danger" ng-click="stop()" ng-disabled="!container.State.Running"><i class="fa fa-stop space-right" aria-hidden="true"></i>Stop</button>
<button class="btn btn-danger" ng-click="kill()" ng-disabled="!container.State.Running"><i class="fa fa-bomb space-right" aria-hidden="true"></i>Kill</button>
<button class="btn btn-primary" ng-click="restart()" ng-disabled="!container.State.Running"><i class="fa fa-refresh space-right" aria-hidden="true"></i>Restart</button>
<button class="btn btn-primary" ng-click="pause()" ng-disabled="!container.State.Running || container.State.Paused"><i class="fa fa-pause space-right" aria-hidden="true"></i>Pause</button>
<button class="btn btn-primary" ng-click="unpause()" ng-disabled="!container.State.Paused"><i class="fa fa-play space-right" aria-hidden="true"></i>Resume</button>
<button class="btn btn-danger" ng-click="confirmRemove()"><i class="fa fa-trash space-right" aria-hidden="true"></i>Remove</button>
<button class="btn btn-danger" ng-click="recreate()" ng-if="!container.Config.Labels['com.docker.swarm.service.id']"><i class="fa fa-refresh space-right" aria-hidden="true"></i>Recreate</button>
<button class="btn btn-primary" ng-click="duplicate()" ng-if="!container.Config.Labels['com.docker.swarm.service.id']"><i class="fa fa-files-o space-right" aria-hidden="true"></i>Duplicate/Edit</button>
</div>
<!-- !tag-description -->
<!-- image-and-registry -->
<div class="form-group">
<por-image-registry image="config.Image" registry="config.Registry"></por-image-registry>
</div>
<!-- !image-and-registry -->
<!-- tag-note -->
<div class="form-group">
<div class="col-sm-12">
<span class="small text-muted">Note: if you don't specify the tag in the image name, <span class="label label-default">latest</span> will be used.</span>
</div>
</div>
<!-- !tag-note -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!config.Image" ng-click="commit()">Create</button>
<i id="createImageSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
</div>
</div>
</form>
</rd-widget-body>
</rd-widget>
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-server" title="Container details"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<tbody>
<tr>
<td>Image</td>
<td><a ui-sref="image({id: container.Image})">{{ container.Image }}</a></td>
</tr>
<tr ng-if="portBindings.length > 0">
<td>Port configuration</td>
<td>
<div ng-repeat="portMapping in portBindings">
{{ portMapping.container }} <i class="fa fa-long-arrow-right"></i> {{ portMapping.host }}
</div>
</td>
</tr>
<tr>
<td>CMD</td>
<td><code>{{ container.Config.Cmd|command }}</code></td>
</tr>
<tr>
<td>ENV</td>
<td>
<table class="table table-bordered table-condensed">
<tr ng-repeat="var in container.Config.Env track by $index">
<td>{{ var|key: '=' }}</td>
<td>{{ var|value: '=' }}</td>
</tr>
</table>
</td>
</tr>
<tr ng-if="!(container.Config.Labels | emptyobject)">
<td>Labels</td>
<td>
<table class="table table-bordered table-condensed">
<tr ng-repeat="(k, v) in container.Config.Labels">
<td>{{ k }}</td>
<td>{{ v }}</td>
</tr>
</table>
</td>
</tr>
<tr ng-if="container.HostConfig.RestartPolicy.Name !== 'no'">
<td>Restart policies</td>
<td>
<table class="table table-bordered table-condensed">
<tr>
<td class="col-md-3">Name</td>
<td>{{ container.HostConfig.RestartPolicy.Name }}</td>
</tr>
<tr>
<td class="col-md-3">MaximumRetryCount</td>
<td>
{{ container.HostConfig.RestartPolicy.MaximumRetryCount }}
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</rd-widget-body>
</rd-widget>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-server" title="Container status"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<tbody>
<tr>
<td>ID</td>
<td>{{ container.Id }}</td>
</tr>
<tr>
<td>Name</td>
<td ng-if="!container.edit">
{{ container.Name|trimcontainername }}
<a href="" data-toggle="tooltip" title="Edit container name" ng-click="container.edit = true;"><i class="fa fa-edit"></i></a>
</td>
<td ng-if="container.edit">
<form ng-submit="renameContainer()">
<input type="text" class="containerNameInput" ng-model="container.newContainerName">
<a href="" ng-click="container.edit = false;"><i class="fa fa-times"></i></a>
<a href="" ng-click="renameContainer()"><i class="fa fa-check-square-o"></i></a>
</form>
</td>
</tr>
<tr ng-if="container.NetworkSettings.IPAddress">
<td>IP address</td>
<td>{{ container.NetworkSettings.IPAddress }}</td>
</tr>
<tr>
<td>Status</td>
<td>
<i class="fa fa-heartbeat space-right green-icon" ng-if="container.State.Running"></i>
<i class="fa fa-heartbeat space-right red-icon" ng-if="!container.State.Running && container.State.Status !== 'created'"></i>
{{ container.State|getstatetext }} since {{ activityTime }}<span ng-if="!container.State.Running && container.State.Status !== 'created'"> with exit code {{ container.State.ExitCode }}</span>
</td>
</tr>
<tr>
<td>Created</td>
<td>{{ container.Created|getisodate }}</td>
</tr>
<tr ng-if="container.State.Running">
<td>Start time</td>
<td>{{ container.State.StartedAt|getisodate }}</td>
</tr>
<tr ng-if="!container.State.Running && container.State.Status !== 'created'">
<td>Finished</td>
<td>{{ container.State.FinishedAt|getisodate }}</td>
</tr>
<tr>
<td colspan="2">
<div class="btn-group" role="group" aria-label="...">
<a class="btn btn-outline-secondary" type="button" ui-sref="stats({id: container.Id})"><i class="fa fa-area-chart space-right" aria-hidden="true"></i>Stats</a>
<a class="btn btn-outline-secondary" type="button" ui-sref="containerlogs({id: container.Id})"><i class="fa fa-exclamation-circle space-right" aria-hidden="true"></i>Logs</a>
<a class="btn btn-outline-secondary" type="button" ui-sref="console({id: container.Id})"><i class="fa fa-terminal space-right" aria-hidden="true"></i>Console</a>
<a class="btn btn-outline-secondary" type="button" ui-sref="inspect({id: container.Id})"><i class="fa fa-info-circle space-right" aria-hidden="true"></i>Inspect</a>
</div>
</td>
</tr>
</tbody>
</table>
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>
<div class="row" ng-if="container.Mounts.length > 0">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-cubes" title="Volumes"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<thead>
<tr>
<th>Host/volume</th>
<th>Path in container</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="vol in container.Mounts">
<td ng-if="vol.Type === 'bind'">{{ vol.Source }}</td>
<td ng-if="vol.Type === 'volume'"><a ui-sref="volume({id: vol.Name})">{{ vol.Name }}</a></td>
<td>{{ vol.Destination }}</td>
</tr>
</tbody>
</table>
</rd-widget-body>
</rd-widget>
<!-- access-control-panel -->
<por-access-control-panel
ng-if="container && applicationState.application.authentication"
resource-id="container.Id"
resource-control="container.ResourceControl"
resource-type="'container'">
</por-access-control-panel>
<!-- !access-control-panel -->
<div ng-if="container.State.Health" class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-server" title="Container health"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<tbody>
<tr>
<td>Status</td>
<td>
<i ng-class="{'healthy': 'fa fa-heartbeat space-right green-icon', 'unhealthy': 'fa fa-heartbeat space-right red-icon', 'starting': 'fa fa-heartbeat space-right orange-icon'}[container.State.Health.Status]"></i>
{{ container.State.Health.Status }}
</td>
</tr>
<tr>
<td>Failure count</td>
<td>{{ container.State.Health.FailingStreak }}</td>
</tr>
<tr>
<td>Last output</td>
<td>{{ container.State.Health.Log[container.State.Health.Log.length - 1].Output }}</td>
</tr>
</tbody>
</table>
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-sitemap" title="Connected networks">
<div class="pull-right">
Items per page:
<select ng-model="state.pagination_count" ng-change="changePaginationCount()">
<option value="0">All</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<thead>
<th>Network Name</th>
<th>IP Address</th>
<th>Gateway</th>
<th>MacAddress</th>
<th>Actions</th>
</thead>
<tbody>
<tr dir-paginate="(key, value) in container.NetworkSettings.Networks | itemsPerPage: state.pagination_count">
<td><a ui-sref="network({id: value.NetworkID})">{{ key }}</a></td>
<td>{{ value.IPAddress || '-' }}</td>
<td>{{ value.Gateway || '-' }}</td>
<td>{{ value.MacAddress || '-' }}</td>
<td>
<button type="button" class="btn btn-xs btn-danger" ng-click="containerLeaveNetwork(container, value.NetworkID)"><i class="fa fa-trash space-right" aria-hidden="true"></i>Leave Network</button>
</td>
</tr>
<tr ng-if="(container.NetworkSettings.Networks | emptyobject)">
<td colspan="5" class="text-center text-muted">No networks connected.</td>
</tr>
</tbody>
</table>
<div class="pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
<hr />
<form class="form-horizontal">
<!-- network-input -->
<div class="row">
<label for="container_network" class="col-sm-3 col-lg-2 control-label text-left">Join a Network</label>
<div class="col-sm-5 col-lg-4">
<select class="form-control" ng-model="selectedNetwork" id="container_network">
<option selected disabled hidden value="">Select a network</option>
<option ng-repeat="net in availableNetworks" ng-value="net.Id">{{ net.Name }}</option>
</select>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-clone" title="Create image"></rd-widget-header>
<rd-widget-body>
<form class="form-horizontal">
<!-- tag-description -->
<div class="form-group">
<div class="col-sm-12">
<span class="small text-muted">
You can create an image from this container, this allows you to backup important data or save
helpful configurations. You'll be able to spin up another container based on this image afterward.
</span>
</div>
</div>
<div class="col-sm-1">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!selectedNetwork" ng-click="containerJoinNetwork(container, selectedNetwork)">Join Network</button>
<!-- !tag-description -->
<!-- image-and-registry -->
<div class="form-group">
<por-image-registry image="config.Image" registry="config.Registry"></por-image-registry>
</div>
<!-- !image-and-registry -->
<!-- tag-note -->
<div class="form-group">
<div class="col-sm-12">
<span class="small text-muted">Note: if you don't specify the tag in the image name, <span class="label label-default">latest</span> will be used.</span>
</div>
</div>
<!-- !tag-note -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!config.Image" ng-click="commit()">Create</button>
</div>
</div>
</form>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-server" title="Container details"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<tbody>
<tr>
<td>Image</td>
<td><a ui-sref="image({id: container.Image})">{{ container.Image }}</a></td>
</tr>
<tr ng-if="portBindings.length > 0">
<td>Port configuration</td>
<td>
<div ng-repeat="portMapping in portBindings">
{{ portMapping.container }} <i class="fa fa-long-arrow-right"></i> {{ portMapping.host }}
</div>
</td>
</tr>
<tr>
<td>CMD</td>
<td><code>{{ container.Config.Cmd|command }}</code></td>
</tr>
<tr>
<td>ENV</td>
<td>
<table class="table table-bordered table-condensed">
<tr ng-repeat="var in container.Config.Env track by $index">
<td>{{ var|key: '=' }}</td>
<td>{{ var|value: '=' }}</td>
</tr>
</table>
</td>
</tr>
<tr ng-if="!(container.Config.Labels | emptyobject)">
<td>Labels</td>
<td>
<table class="table table-bordered table-condensed">
<tr ng-repeat="(k, v) in container.Config.Labels">
<td>{{ k }}</td>
<td>{{ v }}</td>
</tr>
</table>
</td>
</tr>
<tr ng-if="container.HostConfig.RestartPolicy.Name !== 'no'">
<td>Restart policies</td>
<td>
<table class="table table-bordered table-condensed">
<tr>
<td class="col-md-3">Name</td>
<td>{{ container.HostConfig.RestartPolicy.Name }}</td>
</tr>
<tr>
<td class="col-md-3">MaximumRetryCount</td>
<td>
{{ container.HostConfig.RestartPolicy.MaximumRetryCount }}
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row" ng-if="container.Mounts.length > 0">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-cubes" title="Volumes"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<thead>
<tr>
<th>Host/volume</th>
<th>Path in container</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="vol in container.Mounts">
<td ng-if="vol.Type === 'bind'">{{ vol.Source }}</td>
<td ng-if="vol.Type === 'volume'"><a ui-sref="volume({id: vol.Name})">{{ vol.Name }}</a></td>
<td>{{ vol.Destination }}</td>
</tr>
</tbody>
</table>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-sitemap" title="Connected networks">
<div class="pull-right">
Items per page:
<select ng-model="state.pagination_count" ng-change="changePaginationCount()">
<option value="0">All</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</form>
</rd-widget-body>
</rd-widget>
</rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<thead>
<th>Network Name</th>
<th>IP Address</th>
<th>Gateway</th>
<th>MacAddress</th>
<th>Actions</th>
</thead>
<tbody>
<tr dir-paginate="(key, value) in container.NetworkSettings.Networks | itemsPerPage: state.pagination_count">
<td><a ui-sref="network({id: value.NetworkID})">{{ key }}</a></td>
<td>{{ value.IPAddress || '-' }}</td>
<td>{{ value.Gateway || '-' }}</td>
<td>{{ value.MacAddress || '-' }}</td>
<td>
<button type="button" class="btn btn-xs btn-danger" ng-disabled="state.leaveNetworkInProgress" button-spinner="state.leaveNetworkInProgress" ng-click="containerLeaveNetwork(container, value.NetworkID)">
<span ng-hide="state.leaveNetworkInProgress"><i class="fa fa-trash space-right" aria-hidden="true"></i> Leave network</span>
<span ng-show="state.leaveNetworkInProgress">Leaving network...</span>
</button>
</td>
</tr>
<tr ng-if="(container.NetworkSettings.Networks | emptyobject)">
<td colspan="5" class="text-center text-muted">No networks connected.</td>
</tr>
</tbody>
</table>
<div class="pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
<hr />
<form class="form-horizontal">
<!-- network-input -->
<div class="row">
<label for="container_network" class="col-sm-3 col-lg-2 control-label text-left">Join a Network</label>
<div class="col-sm-5 col-lg-4">
<select class="form-control" ng-model="selectedNetwork" id="container_network">
<option selected disabled hidden value="">Select a network</option>
<option ng-repeat="net in availableNetworks" ng-value="net.Id">{{ net.Name }}</option>
</select>
</div>
<div class="col-sm-1">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.joinNetworkInProgress || !selectedNetwork" ng-click="containerJoinNetwork(container, selectedNetwork)" button-spinner="state.joinNetworkInProgress">
<span ng-hide="state.joinNetworkInProgress">Join network</span>
<span ng-show="state.joinNetworkInProgress">Joining network...</span>
</button>
</div>
</div>
</form>
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>

View File

@ -7,15 +7,17 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
Image: '',
Registry: ''
};
$scope.state = {};
$scope.state.pagination_count = Pagination.getPaginationCount('container_networks');
$scope.state = {
joinNetworkInProgress: false,
leaveNetworkInProgress: false,
pagination_count: Pagination.getPaginationCount('container_networks')
};
$scope.changePaginationCount = function() {
Pagination.setPaginationCount('container_networks', $scope.state.pagination_count);
};
var update = function () {
$('#loadingViewSpinner').show();
Container.get({id: $transition$.params().id}, function (d) {
var container = new ContainerDetailsViewModel(d);
$scope.container = container;
@ -41,15 +43,12 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
}
});
}
$('#loadingViewSpinner').hide();
}, function (e) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', e, 'Unable to retrieve container info');
});
};
$scope.start = function () {
$('#loadingViewSpinner').show();
Container.start({id: $scope.container.Id}, {}, function (d) {
update();
Notifications.success('Container started', $transition$.params().id);
@ -60,7 +59,6 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
};
$scope.stop = function () {
$('#loadingViewSpinner').show();
Container.stop({id: $transition$.params().id}, function (d) {
update();
Notifications.success('Container stopped', $transition$.params().id);
@ -71,7 +69,6 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
};
$scope.kill = function () {
$('#loadingViewSpinner').show();
Container.kill({id: $transition$.params().id}, function (d) {
update();
Notifications.success('Container killed', $transition$.params().id);
@ -82,23 +79,19 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
};
$scope.commit = function () {
$('#createImageSpinner').show();
var image = $scope.config.Image;
var registry = $scope.config.Registry;
var imageConfig = ImageHelper.createImageConfigForCommit(image, registry.URL);
ContainerCommit.commit({id: $transition$.params().id, tag: imageConfig.tag, repo: imageConfig.repo}, function (d) {
$('#createImageSpinner').hide();
update();
Notifications.success('Container commited', $transition$.params().id);
}, function (e) {
$('#createImageSpinner').hide();
update();
Notifications.error('Failure', e, 'Unable to commit container');
});
};
$scope.pause = function () {
$('#loadingViewSpinner').show();
Container.pause({id: $transition$.params().id}, function (d) {
update();
Notifications.success('Container paused', $transition$.params().id);
@ -109,7 +102,6 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
};
$scope.unpause = function () {
$('#loadingViewSpinner').show();
Container.unpause({id: $transition$.params().id}, function (d) {
update();
Notifications.success('Container unpaused', $transition$.params().id);
@ -138,7 +130,6 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
};
$scope.remove = function(cleanAssociatedVolumes) {
$('#loadingViewSpinner').show();
ContainerService.remove($scope.container, cleanAssociatedVolumes)
.then(function success() {
Notifications.success('Container successfully removed');
@ -146,14 +137,10 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove container');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.restart = function () {
$('#loadingViewSpinner').show();
Container.restart({id: $transition$.params().id}, function (d) {
update();
Notifications.success('Container restarted', $transition$.params().id);
@ -180,19 +167,18 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
};
$scope.containerLeaveNetwork = function containerLeaveNetwork(container, networkId) {
$('#loadingViewSpinner').show();
$scope.state.leaveNetworkInProgress = true;
Network.disconnect({id: networkId}, { Container: $transition$.params().id, Force: false }, function (d) {
if (container.message) {
$('#loadingViewSpinner').hide();
Notifications.error('Error', d, 'Unable to disconnect container from network');
} else {
$('#loadingViewSpinner').hide();
Notifications.success('Container left network', $transition$.params().id);
$state.go('container', {id: $transition$.params().id}, {reload: true});
}
$scope.state.leaveNetworkInProgress = false;
}, function (e) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', e, 'Unable to disconnect container from network');
$scope.state.leaveNetworkInProgress = false;
});
};
@ -219,7 +205,6 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
};
function recreateContainer(pullImage) {
$('#loadingViewSpinner').show();
var container = $scope.container;
var config = ContainerHelper.configFromContainer(container.Model);
ContainerService.remove(container, true)
@ -254,9 +239,6 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to re-create container');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}
@ -272,19 +254,18 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerCommit,
};
$scope.containerJoinNetwork = function containerJoinNetwork(container, networkId) {
$('#joinNetworkSpinner').show();
$scope.state.joinNetworkInProgress = true;
Network.connect({id: networkId}, { Container: $transition$.params().id }, function (d) {
if (container.message) {
$('#joinNetworkSpinner').hide();
Notifications.error('Error', d, 'Unable to connect container to network');
} else {
$('#joinNetworkSpinner').hide();
Notifications.success('Container joined network', $transition$.params().id);
$state.go('container', {id: $transition$.params().id}, {reload: true});
}
$scope.state.joinNetworkInProgress = false;
}, function (e) {
$('#joinNetworkSpinner').hide();
Notifications.error('Failure', e, 'Unable to connect container to network');
$scope.state.joinNetworkInProgress = false;
});
};

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Container console">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Container console"></rd-header-title>
<rd-header-content ng-if="state.loaded">
<a ui-sref="containers">Containers</a> &gt; <a ui-sref="container({id: container.Id})">{{ container.Name|trimcontainername }}</a> &gt; Console
</rd-header-content>
@ -10,11 +8,7 @@
<div class="row" ng-if="state.loaded">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-terminal" title="Console">
<div class="pull-right">
<i id="loadConsoleSpinner" class="fa fa-cog fa-2x fa-spin" style="margin-top: 5px; display: none;"></i>
</div>
</rd-widget-header>
<rd-widget-header icon="fa-terminal" title="Console"></rd-widget-header>
<rd-widget-body>
<form class="form-horizontal">
<div ng-if="!state.connected">
@ -54,8 +48,11 @@
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-1 col-sm-offset-2 col-lg-11 col-sm-10">
<button type="button" class="btn btn-primary" ng-click="connect()">Connect</button>
<div class="col-sm-12">
<button type="button" class="btn btn-primary" ng-disabled="state.connected" button-spinner="state.connected" ng-click="connect()">
<span ng-hide="state.leaveNetworkInProgress">Connect</span>
<span ng-show="state.leaveNetworkInProgress">Connecting...</span>
</button>
</div>
</div>
</div>

View File

@ -1,9 +1,11 @@
angular.module('containerConsole', [])
.controller('ContainerConsoleController', ['$scope', '$transition$', 'Container', 'Image', 'EndpointProvider', 'Notifications', 'ContainerHelper', 'ContainerService', 'ExecService',
function ($scope, $transition$, Container, Image, EndpointProvider, Notifications, ContainerHelper, ContainerService, ExecService) {
$scope.state = {};
$scope.state.loaded = false;
$scope.state.connected = false;
$scope.state = {
loaded: false,
connected: false
};
$scope.formValues = {};
var socket, term;
@ -19,25 +21,20 @@ function ($scope, $transition$, Container, Image, EndpointProvider, Notification
$scope.container = d;
if (d.message) {
Notifications.error('Error', d, 'Unable to retrieve container details');
$('#loadingViewSpinner').hide();
} else {
Image.get({id: d.Image}, function(imgData) {
$scope.imageOS = imgData.Os;
$scope.formValues.command = imgData.Os === 'windows' ? 'powershell' : 'bash';
$scope.state.loaded = true;
$('#loadingViewSpinner').hide();
}, function (e) {
Notifications.error('Failure', e, 'Unable to retrieve image details');
$('#loadingViewSpinner').hide();
});
}
}, function (e) {
Notifications.error('Failure', e, 'Unable to retrieve container details');
$('#loadingViewSpinner').hide();
});
$scope.connect = function() {
$('#loadConsoleSpinner').show();
var termWidth = Math.floor(($('#terminal-container').width() - 20) / 8.39);
var termHeight = 30;
var command = $scope.formValues.isCustomCommand ?
@ -67,9 +64,6 @@ function ($scope, $transition$, Container, Image, EndpointProvider, Notification
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to exec into container');
})
.finally(function final() {
$('#loadConsoleSpinner').hide();
});
};
@ -88,7 +82,6 @@ function ($scope, $transition$, Container, Image, EndpointProvider, Notification
$scope.state.connected = true;
socket.onopen = function(evt) {
$('#loadConsoleSpinner').hide();
term = new Terminal();
term.on('data', function (data) {

View File

@ -2,21 +2,18 @@ angular.module('containerInspect', ['angular-json-tree'])
.controller('ContainerInspectController', ['$scope', '$transition$', 'Notifications', 'ContainerService',
function ($scope, $transition$, Notifications, ContainerService) {
$scope.state = { DisplayTextView: false };
$scope.state = {
DisplayTextView: false
};
$scope.containerInfo = {};
function initView() {
$('#loadingViewSpinner').show();
ContainerService.inspect($transition$.params().id)
.then(function success(d) {
$scope.containerInfo = d;
})
.catch(function error(e) {
Notifications.error('Failure', e, 'Unable to inspect container');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -8,20 +8,15 @@ function ($scope, $transition$, $anchorScroll, ContainerLogs, Container) {
$scope.stderr = '';
$scope.tailLines = 2000;
$('#loadingViewSpinner').show();
Container.get({id: $transition$.params().id}, function (d) {
$scope.container = d;
$('#loadingViewSpinner').hide();
}, function (e) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', e, 'Unable to retrieve container info');
});
function getLogs() {
$('#loadingViewSpinner').show();
getLogsStdout();
getLogsStderr();
$('#loadingViewSpinner').hide();
}
function getLogsStderr() {

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Container logs">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Container logs"></rd-header-title>
<rd-header-content>
<a ui-sref="containers">Containers</a> &gt; <a ui-sref="container({id: container.Id})">{{ container.Name|trimcontainername }}</a> &gt; Logs
</rd-header-content>

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Container statistics">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Container statistics"></rd-header-title>
<rd-header-content>
<a ui-sref="containers">Containers</a> &gt; <a ui-sref="container({id: container.Id})">{{ container.Name|trimcontainername }}</a> &gt; Stats
</rd-header-content>

View File

@ -80,7 +80,6 @@ function ($q, $scope, $transition$, $document, $interval, ContainerService, Char
};
function startChartUpdate(networkChart, cpuChart, memoryChart) {
$('#loadingViewSpinner').show();
$q.all({
stats: ContainerService.containerStats($transition$.params().id),
top: ContainerService.containerTop($transition$.params().id)
@ -99,9 +98,6 @@ function ($q, $scope, $transition$, $document, $interval, ContainerService, Char
.catch(function error(err) {
stopRepeater();
Notifications.error('Failure', err, 'Unable to retrieve container statistics');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}
@ -143,17 +139,12 @@ function ($q, $scope, $transition$, $document, $interval, ContainerService, Char
}
function initView() {
$('#loadingViewSpinner').show();
ContainerService.container($transition$.params().id)
.then(function success(data) {
$scope.container = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve container information');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
$document.ready(function() {

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="containers" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadContainersSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Containers</rd-header-content>
</rd-header>

View File

@ -1,6 +1,6 @@
angular.module('containers', [])
.controller('ContainersController', ['$q', '$scope', '$filter', 'Container', 'ContainerService', 'ContainerHelper', 'SystemService', 'Notifications', 'Pagination', 'EntityListService', 'ModalService', 'ResourceControlService', 'EndpointProvider', 'LocalStorage',
function ($q, $scope, $filter, Container, ContainerService, ContainerHelper, SystemService, Notifications, Pagination, EntityListService, ModalService, ResourceControlService, EndpointProvider, LocalStorage) {
.controller('ContainersController', ['$q', '$scope', '$state', '$filter', 'Container', 'ContainerService', 'ContainerHelper', 'SystemService', 'Notifications', 'Pagination', 'EntityListService', 'ModalService', 'ResourceControlService', 'EndpointProvider', 'LocalStorage',
function ($q, $scope, $state, $filter, Container, ContainerService, ContainerHelper, SystemService, Notifications, Pagination, EntityListService, ModalService, ResourceControlService, EndpointProvider, LocalStorage) {
$scope.state = {};
$scope.state.pagination_count = Pagination.getPaginationCount('containers');
$scope.state.displayAll = LocalStorage.getFilterContainerShowAll();
@ -24,7 +24,6 @@ angular.module('containers', [])
$scope.cleanAssociatedVolumes = false;
var update = function (data) {
$('#loadContainersSpinner').show();
$scope.state.selectedItemCount = 0;
Container.query(data, function (d) {
var containers = d;
@ -45,21 +44,17 @@ angular.module('containers', [])
return model;
});
updateSelectionFlags();
$('#loadContainersSpinner').hide();
}, function (e) {
$('#loadContainersSpinner').hide();
Notifications.error('Failure', e, 'Unable to retrieve containers');
$scope.containers = [];
});
};
var batch = function (items, action, msg) {
$('#loadContainersSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadContainersSpinner').hide();
update({all: $scope.state.displayAll ? 1 : 0});
}
};
@ -78,12 +73,13 @@ angular.module('containers', [])
else if (action === Container.remove) {
ContainerService.remove(c, $scope.cleanAssociatedVolumes)
.then(function success() {
var index = items.indexOf(c);
items.splice(index, 1);
Notifications.success('Container successfully removed');
complete();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove container');
})
.finally(function final() {
complete();
});
}
@ -108,13 +104,9 @@ angular.module('containers', [])
Notifications.error('Failure', e, 'An error occured');
complete();
});
}
}
});
if (counter === 0) {
$('#loadContainersSpinner').hide();
}
};
$scope.selectItems = function (allSelected) {

View File

@ -58,14 +58,11 @@ function ($scope, $state, $document, Notifications, ConfigService, Authenticatio
}
$scope.create = function () {
$('#createResourceSpinner').show();
var accessControlData = $scope.formValues.AccessControlData;
var userDetails = Authentication.getUserDetails();
var isAdmin = userDetails.role === 1 ? true : false;
if (!validateForm(accessControlData, isAdmin)) {
$('#createResourceSpinner').hide();
return;
}
@ -83,9 +80,6 @@ function ($scope, $state, $document, Notifications, ConfigService, Authenticatio
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to create config');
})
.finally(function final() {
$('#createResourceSpinner').hide();
});
};

View File

@ -62,8 +62,6 @@
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Name" ng-click="create()">Create config</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="configs">Cancel</a>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
</div>
</div>
<!-- !actions -->

View File

@ -20,7 +20,8 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
};
$scope.state = {
formValidationError: ''
formValidationError: '',
actionInProgress: false
};
$scope.refreshSlider = function () {
@ -570,16 +571,16 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
if (!confirm) {
return false;
}
$('#createContainerSpinner').show();
var accessControlData = $scope.formValues.AccessControlData;
var userDetails = Authentication.getUserDetails();
var isAdmin = userDetails.role === 1 ? true : false;
if (!validateForm(accessControlData, isAdmin)) {
$('#createContainerSpinner').hide();
return;
}
$scope.state.actionInProgress = true;
var config = prepareConfiguration();
createContainer(config, accessControlData);
})
@ -605,7 +606,7 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
Notifications.error('Failure', err, 'Unable to create container');
})
.finally(function final() {
$('#createContainerSpinner').hide();
$scope.state.actionInProgress = false;
});
});
}

View File

@ -112,9 +112,10 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!config.Image || (!formValues.Registry && fromContainer)" ng-click="create()">Start container</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="containers">Cancel</a>
<i id="createContainerSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !config.Image || (!formValues.Registry && fromContainer)" ng-click="create()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Deploy the container</span>
<span ng-show="state.actionInProgress">Deployment in progress...</span>
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
<span ng-if="fromContainerMultipleNetworks" style="margin-left: 10px">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>

View File

@ -11,7 +11,8 @@ function ($q, $scope, $state, PluginService, Notifications, NetworkService, Labe
};
$scope.state = {
formValidationError: ''
formValidationError: '',
actionInProgress: false
};
$scope.availableNetworkDrivers = [];
@ -89,18 +90,16 @@ function ($q, $scope, $state, PluginService, Notifications, NetworkService, Labe
}
$scope.create = function () {
$('#createResourceSpinner').show();
var networkConfiguration = prepareConfiguration();
var accessControlData = $scope.formValues.AccessControlData;
var userDetails = Authentication.getUserDetails();
var isAdmin = userDetails.role === 1 ? true : false;
if (!validateForm(accessControlData, isAdmin)) {
$('#createResourceSpinner').hide();
return;
}
$scope.state.actionInProgress = true;
NetworkService.create(networkConfiguration)
.then(function success(data) {
var networkIdentifier = data.Id;
@ -115,12 +114,11 @@ function ($q, $scope, $state, PluginService, Notifications, NetworkService, Labe
Notifications.error('Failure', err, 'An error occured during network creation');
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
};
function initView() {
$('#loadingViewSpinner').show();
var endpointProvider = $scope.applicationState.endpoint.mode.provider;
var apiVersion = $scope.applicationState.endpoint.apiVersion;
if(endpointProvider !== 'DOCKER_SWARM') {
@ -130,9 +128,6 @@ function ($q, $scope, $state, PluginService, Notifications, NetworkService, Labe
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve network drivers');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Create network">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Create network"></rd-header-title>
<rd-header-content>
<a ui-sref="networks">Networks</a> &gt; Add network
</rd-header-content>
@ -130,8 +128,10 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!config.Name" ng-click="create()">Create network</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="networks">Cancel</a>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !config.Name" ng-click="create()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Create the network</span>
<span ng-show="state.actionInProgress">Creating network...</span>
</button>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>

View File

@ -3,7 +3,8 @@ angular.module('createRegistry', [])
function ($scope, $state, RegistryService, Notifications) {
$scope.state = {
RegistryType: 'quay'
RegistryType: 'quay',
actionInProgress: false
};
$scope.formValues = {
@ -27,13 +28,13 @@ function ($scope, $state, RegistryService, Notifications) {
};
$scope.addRegistry = function() {
$('#createRegistrySpinner').show();
var registryName = $scope.formValues.Name;
var registryURL = $scope.formValues.URL.replace(/^https?\:\/\//i, '');
var authentication = $scope.formValues.Authentication;
var username = $scope.formValues.Username;
var password = $scope.formValues.Password;
$scope.state.actionInProgress = true;
RegistryService.createRegistry(registryName, registryURL, authentication, username, password)
.then(function success(data) {
Notifications.success('Registry successfully created');
@ -43,7 +44,7 @@ function ($scope, $state, RegistryService, Notifications) {
Notifications.error('Failure', err, 'Unable to create registry');
})
.finally(function final() {
$('#createRegistrySpinner').hide();
$scope.state.actionInProgress = false;
});
};
}]);

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Create registry">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="display:none"></i>
</rd-header-title>
<rd-header-title title="Create registry"></rd-header-title>
<rd-header-content>
<a ui-sref="registries">Registries</a> &gt; Add registry
</rd-header-content>
@ -104,10 +102,15 @@
<!-- !credentials-password -->
</div>
<!-- !authentication-credentials -->
<div class="col-sm-12 form-section-title">
Actions
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Name || !formValues.URL || (formValues.Authentication && (!formValues.Username || !formValues.Password))" ng-click="addRegistry()">Add registry</button>
<i id="createRegistrySpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !formValues.Name || !formValues.URL || (formValues.Authentication && (!formValues.Username || !formValues.Password))" ng-click="addRegistry()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Add registry</span>
<span ng-show="state.actionInProgress">Adding registry...</span>
</button>
</div>
</div>
</form>

View File

@ -11,7 +11,8 @@ function ($scope, $state, Notifications, SecretService, LabelHelper, Authenticat
};
$scope.state = {
formValidationError: ''
formValidationError: '',
actionInProgress: false
};
$scope.addLabel = function() {
@ -55,17 +56,16 @@ function ($scope, $state, Notifications, SecretService, LabelHelper, Authenticat
}
$scope.create = function () {
$('#createResourceSpinner').show();
var accessControlData = $scope.formValues.AccessControlData;
var userDetails = Authentication.getUserDetails();
var isAdmin = userDetails.role === 1 ? true : false;
if (!validateForm(accessControlData, isAdmin)) {
$('#createResourceSpinner').hide();
return;
}
$scope.state.actionInProgress = true;
var secretConfiguration = prepareConfiguration();
SecretService.create(secretConfiguration)
.then(function success(data) {
@ -81,7 +81,7 @@ function ($scope, $state, Notifications, SecretService, LabelHelper, Authenticat
Notifications.error('Failure', err, 'Unable to create secret');
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
};
}]);

View File

@ -75,9 +75,10 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Name || !formValues.Data" ng-click="create()">Create secret</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="secrets">Cancel</a>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !formValues.Name || !formValues.Data" ng-click="create()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Create the secret</span>
<span ng-show="state.actionInProgress">Creating secret...</span>
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>
</div>

View File

@ -39,7 +39,8 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
};
$scope.state = {
formValidationError: ''
formValidationError: '',
actionInProgress: false
};
$scope.refreshSlider = function () {
@ -366,7 +367,7 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
Notifications.error('Failure', err, 'Unable to create service');
})
.finally(function final() {
$('#createServiceSpinner').hide();
$scope.state.actionInProgress = false;
});
}
@ -383,17 +384,16 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
}
$scope.create = function createService() {
$('#createServiceSpinner').show();
var accessControlData = $scope.formValues.AccessControlData;
var userDetails = Authentication.getUserDetails();
var isAdmin = userDetails.role === 1 ? true : false;
if (!validateForm(accessControlData, isAdmin)) {
$('#createServiceSpinner').hide();
return;
}
$scope.state.actionInProgress = true;
var config = prepareConfiguration();
createNewService(config, accessControlData);
};
@ -422,7 +422,6 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
}
function initView() {
$('#loadingViewSpinner').show();
var apiVersion = $scope.applicationState.endpoint.apiVersion;
var provider = $scope.applicationState.endpoint.mode.provider;
@ -448,9 +447,6 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to initialize view');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Create service">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-title title="Create service"></rd-header-title>
<rd-header-content>
<a ui-sref="services">Services</a> &gt; Add service
</rd-header-content>
@ -109,9 +107,10 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Image" ng-click="create()">Create service</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="services">Cancel</a>
<i id="createServiceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !formValues.Image" ng-click="create()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Create the service</span>
<span ng-show="state.actionInProgress">Creating service...</span>
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>
</div>

View File

@ -18,7 +18,8 @@ function ($scope, $state, $document, StackService, CodeMirrorService, Authentica
$scope.state = {
Method: 'editor',
formValidationError: ''
formValidationError: '',
actionInProgress: false
};
$scope.addEnvironmentVariable = function() {
@ -62,8 +63,6 @@ function ($scope, $state, $document, StackService, CodeMirrorService, Authentica
}
$scope.deployStack = function () {
$('#createResourceSpinner').show();
var name = $scope.formValues.Name;
var accessControlData = $scope.formValues.AccessControlData;
@ -72,10 +71,10 @@ function ($scope, $state, $document, StackService, CodeMirrorService, Authentica
var userId = userDetails.ID;
if (!validateForm(accessControlData, isAdmin)) {
$('#createResourceSpinner').hide();
return;
}
$scope.state.actionInProgress = true;
createStack(name)
.then(function success(data) {
Notifications.success('Stack successfully deployed');
@ -93,7 +92,7 @@ function ($scope, $state, $document, StackService, CodeMirrorService, Authentica
Notifications.error('Failure', err, 'Unable to apply resource control on the stack');
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
};

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Create stack">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="display: none;"></i>
</rd-header-title>
<rd-header-title title="Create stack"></rd-header-title>
<rd-header-content>
<a ui-sref="stacks">Stacks</a> > Add stack
</rd-header-content>
@ -169,12 +167,13 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="(state.Method === 'editor' && !formValues.StackFileContent)
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || (state.Method === 'editor' && !formValues.StackFileContent)
|| (state.Method === 'upload' && !formValues.StackFile)
|| (state.Method === 'repository' && (!formValues.RepositoryURL || !formValues.RepositoryPath))
|| !formValues.Name" ng-click="deployStack()">Deploy the stack</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="stacks">Cancel</a>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
|| !formValues.Name" ng-click="deployStack()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Deploy the stack</span>
<span ng-show="state.actionInProgress">Deployment in progress...</span>
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>
</div>

View File

@ -9,7 +9,8 @@ function ($q, $scope, $state, VolumeService, PluginService, ResourceControlServi
};
$scope.state = {
formValidationError: ''
formValidationError: '',
actionInProgress: false
};
$scope.availableVolumeDrivers = [];
@ -35,7 +36,6 @@ function ($q, $scope, $state, VolumeService, PluginService, ResourceControlServi
}
$scope.create = function () {
$('#createVolumeSpinner').show();
var name = $scope.formValues.Name;
var driver = $scope.formValues.Driver;
@ -46,10 +46,10 @@ function ($q, $scope, $state, VolumeService, PluginService, ResourceControlServi
var isAdmin = userDetails.role === 1 ? true : false;
if (!validateForm(accessControlData, isAdmin)) {
$('#createVolumeSpinner').hide();
return;
}
$scope.state.actionInProgress = true;
VolumeService.createVolume(volumeConfiguration)
.then(function success(data) {
var volumeIdentifier = data.Id;
@ -64,12 +64,11 @@ function ($q, $scope, $state, VolumeService, PluginService, ResourceControlServi
Notifications.error('Failure', err, 'An error occured during volume creation');
})
.finally(function final() {
$('#createVolumeSpinner').hide();
$scope.state.actionInProgress = false;
});
};
function initView() {
$('#loadingViewSpinner').show();
var endpointProvider = $scope.applicationState.endpoint.mode.provider;
var apiVersion = $scope.applicationState.endpoint.apiVersion;
if (endpointProvider !== 'DOCKER_SWARM') {
@ -79,9 +78,6 @@ function ($q, $scope, $state, VolumeService, PluginService, ResourceControlServi
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve volume drivers');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Create volume">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Create volume"></rd-header-title>
<rd-header-content>
<a ui-sref="volumes">Volumes</a> &gt; Add volume
</rd-header-content>
@ -73,9 +71,10 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-click="create()">Create volume</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="volumes">Cancel</a>
<i id="createVolumeSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-click="create()" ng-disabled="state.actionInProgress" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Create the volume</span>
<span ng-show="state.actionInProgress">Creating volume...</span>
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>
</div>

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Home">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Home"></rd-header-title>
<rd-header-content>Dashboard</rd-header-content>
</rd-header>
@ -171,6 +169,3 @@
</a>
</div>
</div>
<div class="row">
</div>

View File

@ -65,8 +65,6 @@ function ($scope, $q, Container, ContainerHelper, Image, Network, Volume, System
}
function initView() {
$('#loadingViewSpinner').show();
var endpointProvider = $scope.applicationState.endpoint.mode.provider;
var endpointRole = $scope.applicationState.endpoint.mode.role;
@ -86,9 +84,7 @@ function ($scope, $q, Container, ContainerHelper, Image, Network, Volume, System
prepareInfoData(d[4]);
$scope.serviceCount = d[5].length;
$scope.stackCount = d[6].length;
$('#loadingViewSpinner').hide();
}, function(e) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', e, 'Unable to load dashboard data');
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Endpoint details">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Endpoint details"></rd-header-title>
<rd-header-content>
<a ui-sref="endpoints">Endpoints</a> &gt; <a ui-sref="endpoint({id: endpoint.Id})">{{ endpoint.Name }}</a>
</rd-header-content>
@ -55,9 +53,11 @@
<!-- !endpoint-security -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!endpoint.Name || !endpoint.URL || (endpoint.TLS && ((endpoint.TLSVerify && !formValues.TLSCACert) || (endpoint.TLSClientCert && (!formValues.TLSCert || !formValues.TLSKey))))" ng-click="updateEndpoint()">Update endpoint</button>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !endpoint.Name || !endpoint.URL || (endpoint.TLS && ((endpoint.TLSVerify && !formValues.TLSCACert) || (endpoint.TLSClientCert && (!formValues.TLSCert || !formValues.TLSKey))))" ng-click="updateEndpoint()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Update endpoint</span>
<span ng-show="state.actionInProgress">Updating endpoint...</span>
</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="endpoints">Cancel</a>
<i id="updateResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
</div>
</div>
</form>

View File

@ -7,7 +7,8 @@ function ($scope, $state, $transition$, $filter, EndpointService, Notifications)
}
$scope.state = {
uploadInProgress: false
uploadInProgress: false,
actionInProgress: false
};
$scope.formValues = {
@ -35,13 +36,14 @@ function ($scope, $state, $transition$, $filter, EndpointService, Notifications)
type: $scope.endpointType
};
$('updateResourceSpinner').show();
$scope.state.actionInProgress = true;
EndpointService.updateEndpoint(endpoint.Id, endpointParams)
.then(function success(data) {
Notifications.success('Endpoint updated', $scope.endpoint.Name);
$state.go('endpoints');
}, function error(err) {
Notifications.error('Failure', err, 'Unable to update endpoint');
$scope.state.actionInProgress = false;
}, function update(evt) {
if (evt.upload) {
$scope.state.uploadInProgress = evt.upload;
@ -50,7 +52,6 @@ function ($scope, $state, $transition$, $filter, EndpointService, Notifications)
};
function initView() {
$('#loadingViewSpinner').show();
EndpointService.endpoint($transition$.params().id)
.then(function success(data) {
var endpoint = data;
@ -64,9 +65,6 @@ function ($scope, $state, $transition$, $filter, EndpointService, Notifications)
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve endpoint details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Endpoint access">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Endpoint access"></rd-header-title>
<rd-header-content>
<a ui-sref="endpoints">Endpoints</a> &gt; <a ui-sref="endpoint({id: endpoint.Id})">{{ endpoint.Name }}</a> &gt; Access management
</rd-header-content>

View File

@ -7,16 +7,12 @@ function ($scope, $transition$, EndpointService, Notifications) {
};
function initView() {
$('#loadingViewSpinner').show();
EndpointService.endpoint($transition$.params().id)
.then(function success(data) {
$scope.endpoint = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve endpoint details');
})
.finally(function final(){
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="endpoints" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadEndpointsSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Endpoint management</rd-header-content>
</rd-header>
@ -66,8 +65,11 @@
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="!formValues.Name || !formValues.URL || (formValues.TLS && ((formValues.TLSVerify && !formValues.TLSCACert) || (formValues.TLSClientCert && (!formValues.TLSCert || !formValues.TLSKey))))" ng-click="addEndpoint()"><i class="fa fa-plus" aria-hidden="true"></i> Add endpoint</button>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !formValues.Name || !formValues.URL || (formValues.TLS && ((formValues.TLSVerify && !formValues.TLSCACert) || (formValues.TLSClientCert && (!formValues.TLSCert || !formValues.TLSKey))))" ng-click="addEndpoint()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress"><i class="fa fa-plus" aria-hidden="true"></i> Add endpoint</span>
<span ng-show="state.actionInProgress">Creating endpoint...</span>
</button>
</div>
</div>
<!-- !actions -->

View File

@ -4,7 +4,8 @@ function ($scope, $state, $filter, EndpointService, EndpointProvider, Notificati
$scope.state = {
uploadInProgress: false,
selectedItemCount: 0,
pagination_count: Pagination.getPaginationCount('endpoints')
pagination_count: Pagination.getPaginationCount('endpoints'),
actionInProgress: false
};
$scope.sortType = 'Name';
$scope.sortReverse = true;
@ -59,11 +60,13 @@ function ($scope, $state, $filter, EndpointService, EndpointProvider, Notificati
var TLSCertFile = TLSSkipClientVerify ? null : securityData.TLSCert;
var TLSKeyFile = TLSSkipClientVerify ? null : securityData.TLSKey;
$scope.state.actionInProgress = true;
EndpointService.createRemoteEndpoint(name, URL, PublicURL, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile).then(function success(data) {
Notifications.success('Endpoint created', name);
$state.reload();
}, function error(err) {
$scope.state.uploadInProgress = false;
$scope.state.actionInProgress = false;
Notifications.error('Failure', err, 'Unable to create endpoint');
}, function update(evt) {
if (evt.upload) {
@ -73,32 +76,20 @@ function ($scope, $state, $filter, EndpointService, EndpointProvider, Notificati
};
$scope.removeAction = function () {
$('#loadEndpointsSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadEndpointsSpinner').hide();
}
};
angular.forEach($scope.endpoints, function (endpoint) {
if (endpoint.Checked) {
counter = counter + 1;
EndpointService.deleteEndpoint(endpoint.Id).then(function success(data) {
Notifications.success('Endpoint deleted', endpoint.Name);
var index = $scope.endpoints.indexOf(endpoint);
$scope.endpoints.splice(index, 1);
complete();
}, function error(err) {
Notifications.error('Failure', err, 'Unable to remove endpoint');
complete();
});
}
});
};
function fetchEndpoints() {
$('#loadEndpointsSpinner').show();
EndpointService.endpoints()
.then(function success(data) {
$scope.endpoints = data;
@ -106,9 +97,6 @@ function ($scope, $state, $filter, EndpointService, EndpointProvider, Notificati
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve endpoints');
$scope.endpoints = [];
})
.finally(function final() {
$('#loadEndpointsSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="engine" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-content>Docker</rd-header-content>
</rd-header>

View File

@ -1,9 +1,8 @@
angular.module('engine', [])
.controller('EngineController', ['$q', '$scope', 'SystemService', 'Notifications',
function ($q, $scope, SystemService, Notifications) {
function initView() {
$('#loadingViewSpinner').show();
$q.all({
version: SystemService.version(),
info: SystemService.info()
@ -16,9 +15,6 @@ function ($q, $scope, SystemService, Notifications) {
$scope.info = {};
$scope.version = {};
Notifications.error('Failure', err, 'Unable to retrieve engine details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="events" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadEventsSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Events</rd-header-content>
</rd-header>

View File

@ -19,16 +19,12 @@ function ($scope, Notifications, SystemService, Pagination) {
var from = moment().subtract(24, 'hour').unix();
var to = moment().unix();
$('#loadEventsSpinner').show();
SystemService.events(from, to)
.then(function success(data) {
$scope.events = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to load events');
})
.finally(function final() {
$('#loadEventsSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Image details">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Image details"></rd-header-title>
<rd-header-content>
<a ui-sref="images">Images</a> &gt; <a ui-sref="image({id: image.Id})">{{ image.Id }}</a>
</rd-header-content>
@ -41,6 +39,16 @@
or on the trash icon <span class="fa fa-trash-o" aria-hidden="true"></span> to delete a tag.
</span>
</div>
<div class="col-sm-12">
<span id="downloadResourceHint" class="createResource" style="display: none; margin-left: 0;">
Download in progress...
<i class="fa fa-circle-o-notch fa-spin" aria-hidden="true" style="margin-left: 2px;"></i>
</span>
<span id="uploadResourceHint" class="createResource" style="display: none; margin-left: 0;">
Upload in progress...
<i class="fa fa-circle-o-notch fa-spin" aria-hidden="true" style="margin-left: 2px;"></i>
</span>
</div>
</div>
</form>
</rd-widget-body>
@ -69,7 +77,6 @@
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Image" ng-click="tagImage()">Tag</button>
<i id="pullImageSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
</div>
</div>
</form>

View File

@ -21,7 +21,6 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
};
$scope.tagImage = function() {
$('#loadingViewSpinner').show();
var image = $scope.formValues.Image;
var registry = $scope.formValues.Registry;
@ -32,14 +31,11 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to tag image');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.pushTag = function(repository) {
$('#loadingViewSpinner').show();
$('#uploadResourceHint').show();
RegistryService.retrieveRegistryFromRepository(repository)
.then(function success(data) {
var registry = data;
@ -52,12 +48,12 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
Notifications.error('Failure', err, 'Unable to push image to repository');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
$('#uploadResourceHint').hide();
});
};
$scope.pullTag = function(repository) {
$('#loadingViewSpinner').show();
$('#downloadResourceHint').show();
RegistryService.retrieveRegistryFromRepository(repository)
.then(function success(data) {
var registry = data;
@ -70,12 +66,11 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
Notifications.error('Failure', err, 'Unable to pull image');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
$('#downloadResourceHint').hide();
});
};
$scope.removeTag = function(repository) {
$('#loadingViewSpinner').show();
ImageService.deleteImage(repository, false)
.then(function success() {
if ($scope.image.RepoTags.length === 1) {
@ -88,14 +83,10 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove image');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.removeImage = function (id) {
$('#loadingViewSpinner').show();
ImageService.deleteImage(id, false)
.then(function success() {
Notifications.success('Image successfully deleted', id);
@ -103,14 +94,10 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove image');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
function initView() {
$('#loadingViewSpinner').show();
var endpointProvider = $scope.applicationState.endpoint.mode.provider;
$q.all({
image: ImageService.image($transition$.params().id),
@ -123,9 +110,6 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve image details');
$state.go('images');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="images" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadImagesSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Images</rd-header-content>
</rd-header>
@ -29,8 +28,10 @@
<!-- !tag-note -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Image" ng-click="pullImage()">Pull</button>
<i id="pullImageSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !formValues.Image" ng-click="pullImage()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Pull the image</span>
<span ng-show="state.actionInProgress">Download in progress...</span>
</button>
</div>
</div>
</form>

View File

@ -1,11 +1,14 @@
angular.module('images', [])
.controller('ImagesController', ['$scope', '$state', 'ImageService', 'Notifications', 'Pagination', 'ModalService',
function ($scope, $state, ImageService, Notifications, Pagination, ModalService) {
$scope.state = {};
$scope.state.pagination_count = Pagination.getPaginationCount('images');
$scope.state = {
pagination_count: Pagination.getPaginationCount('images'),
actionInProgress: false,
selectedItemCount: 0
};
$scope.sortType = 'RepoTags';
$scope.sortReverse = true;
$scope.state.selectedItemCount = 0;
$scope.formValues = {
Image: '',
@ -39,9 +42,10 @@ function ($scope, $state, ImageService, Notifications, Pagination, ModalService)
};
$scope.pullImage = function() {
$('#pullImageSpinner').show();
var image = $scope.formValues.Image;
var registry = $scope.formValues.Registry;
$scope.state.actionInProgress = true;
ImageService.pullImage(image, registry, false)
.then(function success(data) {
Notifications.success('Image successfully pulled', image);
@ -51,7 +55,7 @@ function ($scope, $state, ImageService, Notifications, Pagination, ModalService)
Notifications.error('Failure', err, 'Unable to pull image');
})
.finally(function final() {
$('#pullImageSpinner').hide();
$scope.state.actionInProgress = false;
});
};
@ -64,17 +68,8 @@ function ($scope, $state, ImageService, Notifications, Pagination, ModalService)
$scope.removeAction = function (force) {
force = !!force;
$('#loadImagesSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadImagesSpinner').hide();
}
};
angular.forEach($scope.images, function (i) {
if (i.Checked) {
counter = counter + 1;
ImageService.deleteImage(i.Id, force)
.then(function success(data) {
Notifications.success('Image deleted', i.Id);
@ -83,16 +78,12 @@ function ($scope, $state, ImageService, Notifications, Pagination, ModalService)
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove image');
})
.finally(function final() {
complete();
});
}
});
};
function fetchImages() {
$('#loadImagesSpinner').show();
var endpointProvider = $scope.applicationState.endpoint.mode.provider;
var apiVersion = $scope.applicationState.endpoint.apiVersion;
ImageService.images(true)
@ -102,9 +93,6 @@ function ($scope, $state, ImageService, Notifications, Pagination, ModalService)
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve images');
$scope.images = [];
})
.finally(function final() {
$('#loadImagesSpinner').hide();
});
}

View File

@ -64,8 +64,10 @@
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="formValues.Password.length < 8 || formValues.Password !== formValues.ConfirmPassword" ng-click="createAdminUser()"><i class="fa fa-user-plus" aria-hidden="true"></i> Create user</button>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || formValues.Password.length < 8 || formValues.Password !== formValues.ConfirmPassword" ng-click="createAdminUser()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress"><i class="fa fa-user-plus" aria-hidden="true"></i> Create user</span>
<span ng-show="state.actionInProgress">Creating user...</span>
</button>
</div>
</div>
<!-- !actions -->

View File

@ -10,11 +10,15 @@ function ($scope, $state, $sanitize, Notifications, Authentication, StateManager
ConfirmPassword: ''
};
$scope.state = {
actionInProgress: false
};
$scope.createAdminUser = function() {
$('#createResourceSpinner').show();
var username = $sanitize($scope.formValues.Username);
var password = $sanitize($scope.formValues.Password);
$scope.state.actionInProgress = true;
UserService.initAdministrator(username, password)
.then(function success() {
return Authentication.login(username, password);
@ -41,7 +45,7 @@ function ($scope, $state, $sanitize, Notifications, Authentication, StateManager
Notifications.error('Failure', err, 'Unable to create administrator user');
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
};

View File

@ -66,8 +66,10 @@
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-primary btn-sm" ng-click="createLocalEndpoint()"><i class="fa fa-bolt" aria-hidden="true"></i> Connect</button>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress" ng-click="createLocalEndpoint()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress"><i class="fa fa-bolt" aria-hidden="true"></i> Connect</span>
<span ng-show="state.actionInProgress">Connecting...</span>
</button>
</div>
</div>
<!-- !actions -->
@ -184,8 +186,10 @@
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="!formValues.Name || !formValues.URL || (formValues.TLS && ((formValues.TLSVerify && !formValues.TLSCACert) || (!formValues.TLSSKipClientVerify && (!formValues.TLSCert || !formValues.TLSKey))))" ng-click="createRemoteEndpoint()"><i class="fa fa-plug" aria-hidden="true"></i> Connect</button>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !formValues.Name || !formValues.URL || (formValues.TLS && ((formValues.TLSVerify && !formValues.TLSCACert) || (!formValues.TLSSKipClientVerify && (!formValues.TLSCert || !formValues.TLSKey))))" ng-click="createRemoteEndpoint()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress"><i class="fa fa-bolt" aria-hidden="true"></i> Connect</span>
<span ng-show="state.actionInProgress">Connecting...</span>
</button>
</div>
</div>
<!-- !actions -->

View File

@ -9,7 +9,8 @@ function ($scope, $state, EndpointService, StateManager, EndpointProvider, Notif
$scope.logo = StateManager.getState().application.logo;
$scope.state = {
uploadInProgress: false
uploadInProgress: false,
actionInProgress: false
};
$scope.formValues = {
@ -25,11 +26,11 @@ function ($scope, $state, EndpointService, StateManager, EndpointProvider, Notif
};
$scope.createLocalEndpoint = function() {
$('#createResourceSpinner').show();
var name = 'local';
var URL = 'unix:///var/run/docker.sock';
var endpointID = 1;
$scope.state.actionInProgress = true;
EndpointService.createLocalEndpoint(name, URL, false, true)
.then(function success(data) {
endpointID = data.Id;
@ -44,12 +45,11 @@ function ($scope, $state, EndpointService, StateManager, EndpointProvider, Notif
EndpointService.deleteEndpoint(endpointID);
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
};
$scope.createRemoteEndpoint = function() {
$('#createResourceSpinner').show();
var name = $scope.formValues.Name;
var URL = $scope.formValues.URL;
var PublicURL = URL.split(':')[0];
@ -59,8 +59,9 @@ function ($scope, $state, EndpointService, StateManager, EndpointProvider, Notif
var TLSCAFile = TLSSkipVerify ? null : $scope.formValues.TLSCACert;
var TLSCertFile = TLSSKipClientVerify ? null : $scope.formValues.TLSCert;
var TLSKeyFile = TLSSKipClientVerify ? null : $scope.formValues.TLSKey;
var endpointID = 1;
$scope.state.actionInProgress = true;
EndpointService.createRemoteEndpoint(name, URL, PublicURL, TLS, TLSSkipVerify, TLSSKipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile)
.then(function success(data) {
endpointID = data.Id;
@ -75,7 +76,7 @@ function ($scope, $state, EndpointService, StateManager, EndpointProvider, Notif
EndpointService.deleteEndpoint(endpointID);
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
};
}]);

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Network details">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Network details"></rd-header-title>
<rd-header-content>
<a ui-sref="networks">Networks</a> &gt; <a ui-sref="network({id: network.Id})">{{ network.Name }}</a>
</rd-header-content>

View File

@ -3,35 +3,27 @@ angular.module('network', [])
function ($scope, $state, $transition$, $filter, Network, NetworkService, Container, ContainerHelper, Notifications) {
$scope.removeNetwork = function removeNetwork(networkId) {
$('#loadingViewSpinner').show();
Network.remove({id: $transition$.params().id}, function (d) {
if (d.message) {
$('#loadingViewSpinner').hide();
Notifications.error('Error', d, 'Unable to remove network');
} else {
$('#loadingViewSpinner').hide();
Notifications.success('Network removed', $transition$.params().id);
$state.go('networks', {});
}
}, function (e) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', e, 'Unable to remove network');
});
};
$scope.containerLeaveNetwork = function containerLeaveNetwork(network, containerId) {
$('#loadingViewSpinner').show();
Network.disconnect({id: $transition$.params().id}, { Container: containerId, Force: false }, function (d) {
if (d.message) {
$('#loadingViewSpinner').hide();
Notifications.error('Error', d, 'Unable to disconnect container from network');
} else {
$('#loadingViewSpinner').hide();
Notifications.success('Container left network', $transition$.params().id);
$state.go('network', {id: network.Id}, {reload: true});
}
}, function (e) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', e, 'Unable to disconnect container from network');
});
};
@ -63,9 +55,7 @@ function ($scope, $state, $transition$, $filter, Network, NetworkService, Contai
}
});
filterContainersInNetwork(network, containersInNetwork);
$('#loadingViewSpinner').hide();
}, function error(err) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', err, 'Unable to retrieve containers in network');
});
} else {
@ -73,9 +63,7 @@ function ($scope, $state, $transition$, $filter, Network, NetworkService, Contai
filters: { network: [$transition$.params().id] }
}, function success(data) {
filterContainersInNetwork(network, data);
$('#loadingViewSpinner').hide();
}, function error(err) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', err, 'Unable to retrieve containers in network');
});
}
@ -83,7 +71,6 @@ function ($scope, $state, $transition$, $filter, Network, NetworkService, Contai
}
function initView() {
$('#loadingViewSpinner').show();
NetworkService.network($transition$.params().id)
.then(function success(data) {
$scope.network = data;
@ -93,11 +80,7 @@ function ($scope, $state, $transition$, $filter, Network, NetworkService, Contai
}
})
.catch(function error(err) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', err, 'Unable to retrieve network info');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="networks" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadNetworksSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Networks</rd-header-content>
</rd-header>

View File

@ -35,17 +35,8 @@ function ($scope, $state, Network, NetworkService, Notifications, Pagination) {
};
$scope.removeAction = function () {
$('#loadNetworksSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadNetworksSpinner').hide();
}
};
angular.forEach($scope.networks, function (network) {
if (network.Checked) {
counter = counter + 1;
Network.remove({id: network.Id}, function (d) {
if (d.message) {
Notifications.error('Error', d, 'Unable to remove network');
@ -54,18 +45,14 @@ function ($scope, $state, Network, NetworkService, Notifications, Pagination) {
var index = $scope.networks.indexOf(network);
$scope.networks.splice(index, 1);
}
complete();
}, function (e) {
Notifications.error('Failure', e, 'Unable to remove network');
complete();
});
}
});
};
function initView() {
$('#loadNetworksSpinner').show();
NetworkService.networks(true, true, true, true)
.then(function success(data) {
$scope.networks = data;
@ -73,9 +60,6 @@ function ($scope, $state, Network, NetworkService, Notifications, Pagination) {
.catch(function error(err) {
$scope.networks = [];
Notifications.error('Failure', err, 'Unable to retrieve networks');
})
.finally(function final() {
$('#loadNetworksSpinner').hide();
});
}

View File

@ -68,11 +68,9 @@ function ($scope, $state, $transition$, LabelHelper, Node, NodeHelper, Task, Pag
config.Labels = LabelHelper.fromKeyValueToLabelHash(node.Labels);
Node.update({ id: node.Id, version: node.Version }, config, function (data) {
$('#loadServicesSpinner').hide();
Notifications.success('Node successfully updated', 'Node updated');
$state.go('node', {id: node.Id}, {reload: true});
}, function (e) {
$('#loadServicesSpinner').hide();
Notifications.error('Failure', e, 'Failed to update node');
});
};

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="registries" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Registry management</rd-header-content>
</rd-header>
@ -57,8 +56,10 @@
<!-- !authentication-credentials -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="dockerhub.Authentication && (!dockerhub.Username || !dockerhub.Password)" ng-click="updateDockerHub()">Update</button>
<i id="updateDockerhubSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || dockerhub.Authentication && (!dockerhub.Username || !dockerhub.Password)" ng-click="updateDockerHub()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Update</span>
<span ng-show="state.actionInProgress">Updating DockerHub settings...</span>
</button>
</div>
</div>
</form>

View File

@ -4,14 +4,15 @@ function ($q, $scope, $state, RegistryService, DockerHubService, ModalService, N
$scope.state = {
selectedItemCount: 0,
pagination_count: Pagination.getPaginationCount('registries')
pagination_count: Pagination.getPaginationCount('registries'),
actionInProgress: false
};
$scope.sortType = 'Name';
$scope.sortReverse = true;
$scope.updateDockerHub = function() {
$('#updateDockerhubSpinner').show();
var dockerhub = $scope.dockerhub;
$scope.state.actionInProgress = true;
DockerHubService.update(dockerhub)
.then(function success(data) {
Notifications.success('DockerHub registry updated');
@ -20,7 +21,7 @@ function ($q, $scope, $state, RegistryService, DockerHubService, ModalService, N
Notifications.error('Failure', err, 'Unable to update DockerHub details');
})
.finally(function final() {
$('#updateDockerhubSpinner').hide();
$scope.state.actionInProgress = false;
});
};
@ -61,19 +62,9 @@ function ($q, $scope, $state, RegistryService, DockerHubService, ModalService, N
};
function removeRegistries() {
$('#loadingViewSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadingViewSpinner').hide();
}
};
var registries = $scope.registries;
angular.forEach(registries, function (registry) {
if (registry.Checked) {
counter = counter + 1;
RegistryService.deleteRegistry(registry.Id)
.then(function success(data) {
var index = registries.indexOf(registry);
@ -82,16 +73,12 @@ function ($q, $scope, $state, RegistryService, DockerHubService, ModalService, N
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove registry');
})
.finally(function final() {
complete();
});
}
});
}
function initView() {
$('#loadingViewSpinner').show();
$q.all({
registries: RegistryService.registries(),
dockerhub: DockerHubService.dockerhub()
@ -103,9 +90,6 @@ function ($q, $scope, $state, RegistryService, DockerHubService, ModalService, N
.catch(function error(err) {
$scope.registries = [];
Notifications.error('Failure', err, 'Unable to retrieve registries');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Registry details">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Registry details"></rd-header-title>
<rd-header-content>
<a ui-sref="registries">Registries</a> &gt; <a ui-sref="registry({id: registry.Id})">{{ registry.Name }}</a>
</rd-header-content>
@ -66,9 +64,11 @@
<!-- !authentication-credentials -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!registry.Name || !registry.URL || (registry.Authentication && (!registry.Username || !registry.Password))" ng-click="updateRegistry()">Update registry</button>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !registry.Name || !registry.URL || (registry.Authentication && (!registry.Username || !registry.Password))" ng-click="updateRegistry()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Update registry</span>
<span ng-show="state.actionInProgress">Updating registry...</span>
</button>
<a type="button" class="btn btn-default btn-sm" ui-sref="registries">Cancel</a>
<i id="updateRegistrySpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
</div>
</div>
</form>

View File

@ -2,9 +2,13 @@ angular.module('registry', [])
.controller('RegistryController', ['$scope', '$state', '$transition$', '$filter', 'RegistryService', 'Notifications',
function ($scope, $state, $transition$, $filter, RegistryService, Notifications) {
$scope.state = {
actionInProgress: false
};
$scope.updateRegistry = function() {
$('#updateRegistrySpinner').show();
var registry = $scope.registry;
$scope.state.actionInProgress = true;
RegistryService.updateRegistry(registry)
.then(function success(data) {
Notifications.success('Registry successfully updated');
@ -14,12 +18,11 @@ function ($scope, $state, $transition$, $filter, RegistryService, Notifications)
Notifications.error('Failure', err, 'Unable to update registry');
})
.finally(function final() {
$('#updateRegistrySpinner').hide();
$scope.state.actionInProgress = false;
});
};
function initView() {
$('#loadingViewSpinner').show();
var registryID = $transition$.params().id;
RegistryService.registry(registryID)
.then(function success(data) {
@ -27,9 +30,6 @@ function ($scope, $state, $transition$, $filter, RegistryService, Notifications)
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve registry details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Registry access">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Registry access"></rd-header-title>
<rd-header-content>
<a ui-sref="registries">Registries</a> &gt; <a ui-sref="registry({id: registry.Id})">{{ registry.Name }}</a> &gt; Access management
</rd-header-content>

View File

@ -7,16 +7,12 @@ function ($scope, $transition$, RegistryService, Notifications) {
};
function initView() {
$('#loadingViewSpinner').show();
RegistryService.registry($transition$.params().id)
.then(function success(data) {
$scope.registry = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve registry details');
})
.finally(function final(){
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="secret({id: secret.Id})" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-content>
<a ui-sref="secrets">Secrets</a> &gt; <a ui-sref="secret({id: secret.Id})">{{ secret.Name }}</a>

View File

@ -3,7 +3,6 @@ angular.module('secret', [])
function ($scope, $transition$, $state, SecretService, Notifications) {
$scope.removeSecret = function removeSecret(secretId) {
$('#loadingViewSpinner').show();
SecretService.remove(secretId)
.then(function success(data) {
Notifications.success('Secret successfully removed');
@ -11,23 +10,16 @@ function ($scope, $transition$, $state, SecretService, Notifications) {
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove secret');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
function initView() {
$('#loadingViewSpinner').show();
SecretService.secret($transition$.params().id)
.then(function success(data) {
$scope.secret = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve secret details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="secrets" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Secrets</rd-header-content>
</rd-header>

View File

@ -30,17 +30,8 @@ function ($scope, $state, SecretService, Notifications, Pagination) {
};
$scope.removeAction = function () {
$('#loadingViewSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadingViewSpinner').hide();
}
};
angular.forEach($scope.secrets, function (secret) {
if (secret.Checked) {
counter = counter + 1;
SecretService.remove(secret.Id)
.then(function success() {
Notifications.success('Secret deleted', secret.Id);
@ -49,16 +40,12 @@ function ($scope, $state, SecretService, Notifications, Pagination) {
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove secret');
})
.finally(function final() {
complete();
});
}
});
};
function initView() {
$('#loadingViewSpinner').show();
SecretService.secrets()
.then(function success(data) {
$scope.secrets = data;
@ -66,9 +53,6 @@ function ($scope, $state, SecretService, Notifications, Pagination) {
.catch(function error(err) {
$scope.secrets = [];
Notifications.error('Failure', err, 'Unable to retrieve secrets');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="service({id: service.Id})" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-content>
<a ui-sref="services">Services</a> &gt; <a ui-sref="service({id: service.Id})">{{ service.Name }}</a>

View File

@ -200,7 +200,6 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
};
$scope.updateService = function updateService(service) {
$('#loadingViewSpinner').show();
var config = ServiceHelper.serviceToConfig(service.Model);
config.Name = service.Name;
config.Labels = LabelHelper.fromKeyValueToLabelHash(service.ServiceLabels);
@ -264,7 +263,6 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
};
Service.update({ id: service.Id, version: service.Version }, config, function (data) {
$('#loadingViewSpinner').hide();
if (data.message && data.message.match(/^rpc error:/)) {
Notifications.error(data.message, 'Error');
} else {
@ -273,7 +271,6 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
$scope.cancelChanges({});
initView();
}, function (e) {
$('#loadingViewSpinner').hide();
Notifications.error('Failure', e, 'Unable to update service');
});
};
@ -289,7 +286,6 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
};
function removeService() {
$('#loadingViewSpinner').show();
ServiceService.remove($scope.service)
.then(function success(data) {
Notifications.success('Service successfully deleted');
@ -297,9 +293,6 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove service');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}
@ -322,7 +315,6 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
}
function initView() {
$('#loadingViewSpinner').show();
var apiVersion = $scope.applicationState.endpoint.apiVersion;
ServiceService.service($transition$.params().id)
.then(function success(data) {
@ -371,9 +363,6 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
$scope.secrets = [];
$scope.configs = [];
Notifications.error('Failure', err, 'Unable to retrieve service details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -9,10 +9,8 @@ function ($scope, $transition$, $anchorScroll, ServiceLogs, Service) {
$scope.tailLines = 2000;
function getLogs() {
$('#loadingViewSpinner').show();
getLogsStdout();
getLogsStderr();
$('#loadingViewSpinner').hide();
}
function getLogsStderr() {
@ -48,13 +46,10 @@ function ($scope, $transition$, $anchorScroll, ServiceLogs, Service) {
}
function getService() {
$('#loadingViewSpinner').show();
Service.get({id: $transition$.params().id}, function (d) {
$scope.service = d;
$('#loadingViewSpinner').hide();
}, function (e) {
Notifications.error('Failure', e, 'Unable to retrieve service info');
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Service logs">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Service logs"></rd-header-title>
<rd-header-content>
<a ui-sref="services">Services</a> > <a ui-sref="service({id: service.ID})">{{ service.Spec.Name }}</a> > Logs
</rd-header-content>

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="services" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadServicesSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Services</rd-header-content>
</rd-header>

View File

@ -25,15 +25,12 @@ function ($q, $scope, $transition$, $state, Service, ServiceService, ServiceHelp
};
$scope.scaleService = function scaleService(service) {
$('#loadServicesSpinner').show();
var config = ServiceHelper.serviceToConfig(service.Model);
config.Mode.Replicated.Replicas = service.Replicas;
Service.update({ id: service.Id, version: service.Version }, config, function (data) {
$('#loadServicesSpinner').hide();
Notifications.success('Service successfully scaled', 'New replica count: ' + service.Replicas);
$state.reload();
}, function (e) {
$('#loadServicesSpinner').hide();
service.Scale = false;
service.Replicas = service.ReplicaCount;
Notifications.error('Failure', e, 'Unable to scale service');
@ -51,17 +48,8 @@ function ($q, $scope, $transition$, $state, Service, ServiceService, ServiceHelp
};
function removeServices() {
$('#loadServicesSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadServicesSpinner').hide();
}
};
angular.forEach($scope.services, function (service) {
if (service.Checked) {
counter = counter + 1;
ServiceService.remove(service)
.then(function success(data) {
Notifications.success('Service successfully deleted');
@ -70,9 +58,6 @@ function ($q, $scope, $transition$, $state, Service, ServiceService, ServiceHelp
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove service');
})
.finally(function final() {
complete();
});
}
});
@ -94,7 +79,6 @@ function ($q, $scope, $transition$, $state, Service, ServiceService, ServiceHelp
}
function initView() {
$('#loadServicesSpinner').show();
$q.all({
services: Service.query({}).$promise,
tasks: Task.query({filters: {'desired-state': ['running','accepted']}}).$promise,
@ -118,9 +102,6 @@ function ($q, $scope, $transition$, $state, Service, ServiceService, ServiceHelp
.catch(function error(err) {
$scope.services = [];
Notifications.error('Failure', err, 'Unable to retrieve services');
})
.finally(function final() {
$('#loadServicesSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Settings">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-title title="Settings"></rd-header-title>
<rd-header-content>Settings</rd-header-content>
</rd-header>
@ -112,9 +110,10 @@
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-click="saveApplicationSettings()">Save</button>
<i id="updateSettingsSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<!-- <span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span> -->
<button type="button" class="btn btn-primary btn-sm" ng-click="saveApplicationSettings()" ng-disabled="state.actionInProgress" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Save settings</span>
<span ng-show="state.actionInProgress">Saving...</span>
</button>
</div>
</div>
<!-- !actions -->

View File

@ -2,6 +2,10 @@ angular.module('settings', [])
.controller('SettingsController', ['$scope', '$state', 'Notifications', 'SettingsService', 'StateManager', 'DEFAULT_TEMPLATES_URL',
function ($scope, $state, Notifications, SettingsService, StateManager, DEFAULT_TEMPLATES_URL) {
$scope.state = {
actionInProgress: false
};
$scope.formValues = {
customLogo: false,
customTemplates: false,
@ -45,6 +49,7 @@ function ($scope, $state, Notifications, SettingsService, StateManager, DEFAULT_
settings.AllowBindMountsForRegularUsers = !$scope.formValues.restrictBindMounts;
settings.AllowPrivilegedModeForRegularUsers = !$scope.formValues.restrictPrivilegedMode;
$scope.state.actionInProgress = true;
updateSettings(settings, false);
};
@ -54,8 +59,6 @@ function ($scope, $state, Notifications, SettingsService, StateManager, DEFAULT_
}
function updateSettings(settings, resetForm) {
$('#loadingViewSpinner').show();
SettingsService.update(settings)
.then(function success(data) {
Notifications.success('Settings updated');
@ -69,12 +72,11 @@ function ($scope, $state, Notifications, SettingsService, StateManager, DEFAULT_
Notifications.error('Failure', err, 'Unable to update settings');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
$scope.state.actionInProgress = false;
});
}
function initView() {
$('#loadingViewSpinner').show();
SettingsService.settings()
.then(function success(data) {
var settings = data;
@ -91,9 +93,6 @@ function ($scope, $state, Notifications, SettingsService, StateManager, DEFAULT_
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve application settings');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Authentication settings">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-title title="Authentication settings"></rd-header-title>
<rd-header-content>
<a ui-sref="settings">Settings</a> &gt; Authentication
</rd-header-content>
@ -100,8 +98,10 @@
<i class="fa fa-times red-icon" style="margin-left: 5px;" ng-if="state.failedConnectivityCheck"></i>
</label>
<div class="col-sm-9 col-lg-10">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!LDAPSettings.URL || !LDAPSettings.ReaderDN || !LDAPSettings.Password" ng-click="LDAPConnectivityCheck()">Test connectivity</button>
<i id="connectivityCheckSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.connectivityCheckInProgress || !LDAPSettings.URL || !LDAPSettings.ReaderDN || !LDAPSettings.Password" ng-click="LDAPConnectivityCheck()" button-spinner="state.connectivityCheckInProgress">
<span ng-hide="state.connectivityCheckInProgress">Test connectivity</span>
<span ng-show="state.connectivityCheckInProgress">Testing connectivity...</span>
</button>
</div>
</div>
@ -240,9 +240,10 @@
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-click="saveSettings()">Save</button>
<i id="updateSettingsSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<!-- <span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span> -->
<button type="button" class="btn btn-primary btn-sm" ng-click="saveSettings()" ng-disabled="state.actionInProgress" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Save settings</span>
<span ng-show="state.actionInProgress">Saving...</span>
</button>
</div>
</div>
<!-- !actions -->

View File

@ -5,7 +5,9 @@ function ($q, $scope, Notifications, SettingsService, FileUploadService) {
$scope.state = {
successfulConnectivityCheck: false,
failedConnectivityCheck: false,
uploadInProgress: false
uploadInProgress: false,
connectivityCheckInProgress: false,
actionInProgress: false
};
$scope.formValues = {
@ -21,13 +23,13 @@ function ($q, $scope, Notifications, SettingsService, FileUploadService) {
};
$scope.LDAPConnectivityCheck = function() {
$('#connectivityCheckSpinner').show();
var settings = $scope.settings;
var TLSCAFile = $scope.formValues.TLSCACert !== settings.LDAPSettings.TLSConfig.TLSCACert ? $scope.formValues.TLSCACert : null;
var uploadRequired = ($scope.LDAPSettings.TLSConfig.TLS || $scope.LDAPSettings.StartTLS) && !$scope.LDAPSettings.TLSConfig.TLSSkipVerify;
$scope.state.uploadInProgress = uploadRequired;
$scope.state.connectivityCheckInProgress = true;
$q.when(!uploadRequired || FileUploadService.uploadLDAPTLSFiles(TLSCAFile, null, null))
.then(function success(data) {
return SettingsService.checkLDAPConnectivity(settings);
@ -44,18 +46,18 @@ function ($q, $scope, Notifications, SettingsService, FileUploadService) {
})
.finally(function final() {
$scope.state.uploadInProgress = false;
$('#connectivityCheckSpinner').hide();
$scope.state.connectivityCheckInProgress = false;
});
};
$scope.saveSettings = function() {
$('#updateSettingsSpinner').show();
var settings = $scope.settings;
var TLSCAFile = $scope.formValues.TLSCACert !== settings.LDAPSettings.TLSConfig.TLSCACert ? $scope.formValues.TLSCACert : null;
var uploadRequired = ($scope.LDAPSettings.TLSConfig.TLS || $scope.LDAPSettings.StartTLS) && !$scope.LDAPSettings.TLSConfig.TLSSkipVerify;
$scope.state.uploadInProgress = uploadRequired;
$scope.state.actionInProgress = true;
$q.when(!uploadRequired || FileUploadService.uploadLDAPTLSFiles(TLSCAFile, null, null))
.then(function success(data) {
return SettingsService.update(settings);
@ -68,12 +70,11 @@ function ($q, $scope, Notifications, SettingsService, FileUploadService) {
})
.finally(function final() {
$scope.state.uploadInProgress = false;
$('#updateSettingsSpinner').hide();
$scope.state.actionInProgress = false;
});
};
function initView() {
$('#loadingViewSpinner').show();
SettingsService.settings()
.then(function success(data) {
var settings = data;
@ -83,9 +84,6 @@ function ($q, $scope, Notifications, SettingsService, FileUploadService) {
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve application settings');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="stack({id: stack.Id})" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-content>
<a ui-sref="stacks">Stacks</a> > <a ui-sref="stack({id: stack.Id})">{{ stack.Name }}</a>
@ -73,8 +72,10 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-sm btn-primary" ng-click="deployStack()">Update stack</button>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-sm btn-primary" ng-disabled="state.actionInProgress" ng-click="deployStack()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Update the stack</span>
<span ng-show="state.actionInProgress">Deployment in progress...</span>
</button>
</div>
</div>
</form>

View File

@ -2,14 +2,17 @@ angular.module('stack', [])
.controller('StackController', ['$q', '$scope', '$state', '$stateParams', '$document', 'StackService', 'NodeService', 'ServiceService', 'TaskService', 'ServiceHelper', 'CodeMirrorService', 'Notifications', 'FormHelper',
function ($q, $scope, $state, $stateParams, $document, StackService, NodeService, ServiceService, TaskService, ServiceHelper, CodeMirrorService, Notifications, FormHelper) {
$scope.deployStack = function () {
$('#createResourceSpinner').show();
$scope.state = {
actionInProgress: false
};
$scope.deployStack = function () {
// The codemirror editor does not work with ng-model so we need to retrieve
// the value directly from the editor.
var stackFile = $scope.editor.getValue();
var env = FormHelper.removeInvalidEnvVars($scope.stack.Env);
$scope.state.actionInProgress = true;
StackService.updateStack($scope.stack.Id, stackFile, env)
.then(function success(data) {
Notifications.success('Stack successfully deployed');
@ -19,7 +22,7 @@ function ($q, $scope, $state, $stateParams, $document, StackService, NodeService
Notifications.error('Failure', err, 'Unable to create stack');
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
};
@ -32,7 +35,6 @@ function ($q, $scope, $state, $stateParams, $document, StackService, NodeService
};
function initView() {
$('#loadingViewSpinner').show();
var stackId = $stateParams.id;
StackService.stack(stackId)
@ -77,9 +79,6 @@ function ($q, $scope, $state, $stateParams, $document, StackService, NodeService
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve tasks details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="stacks" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Stacks</rd-header-content>
</rd-header>

View File

@ -46,19 +46,8 @@ function ($scope, Notifications, Pagination, StackService, ModalService) {
};
function deleteSelectedStacks() {
$('#loadingViewSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadingViewSpinner').hide();
}
};
angular.forEach($scope.stacks, function (stack) {
if (stack.Checked) {
counter = counter + 1;
StackService.remove(stack)
.then(function success() {
Notifications.success('Stack deleted', stack.Name);
@ -67,17 +56,12 @@ function ($scope, Notifications, Pagination, StackService, ModalService) {
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove stack ' + stack.Name);
})
.finally(function final() {
complete();
});
}
});
}
function initView() {
$('#loadingViewSpinner').show();
StackService.stacks(true)
.then(function success(data) {
var stacks = data;
@ -93,9 +77,6 @@ function ($scope, Notifications, Pagination, StackService, ModalService) {
.catch(function error(err) {
$scope.stacks = [];
Notifications.error('Failure', err, 'Unable to retrieve stacks');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="swarm" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Swarm</rd-header-content>
</rd-header>

View File

@ -72,8 +72,6 @@ function ($q, $scope, SystemService, NodeService, Pagination, Notifications, Sta
}
function initView() {
$('#loadingViewSpinner').show();
if (StateManager.getState().application.authentication) {
var userDetails = Authentication.getUserDetails();
var isAdmin = userDetails.role === 1 ? true: false;
@ -99,9 +97,6 @@ function ($q, $scope, SystemService, NodeService, Pagination, Notifications, Sta
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve cluster details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="swarm.visualizer" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
</rd-header-title>
<rd-header-content>
<a ui-sref="swarm">Swarm</a> &gt; <a ui-sref="swarm.visualizer">Cluster visualizer</a>

View File

@ -47,7 +47,6 @@ function ($q, $scope, $document, NodeService, ServiceService, TaskService, Notif
}
function initView() {
$('#loadingViewSpinner').show();
$q.all({
nodes: NodeService.nodes(),
services: ServiceService.services(),
@ -64,9 +63,6 @@ function ($q, $scope, $document, NodeService, ServiceService, TaskService, Notif
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to initialize cluster visualizer');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Task details">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Task details"></rd-header-title>
<rd-header-content ng-if="task && service">
<a ui-sref="services">Services</a> &gt; <a ui-sref="service({id: service.Id })">{{ service.Name }}</a> &gt; {{ task.Id }}
</rd-header-content>

View File

@ -3,7 +3,6 @@ angular.module('task', [])
function ($scope, $transition$, TaskService, Service, Notifications) {
function initView() {
$('#loadingViewSpinner').show();
TaskService.task($transition$.params().id)
.then(function success(data) {
var task = data;
@ -16,9 +15,6 @@ function ($scope, $transition$, TaskService, Service, Notifications) {
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve task details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="Team details">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="Team details"></rd-header-title>
<rd-header-content>
<a ui-sref="teams">Teams</a> &gt; <a ui-sref="team({id: team.Id})">{{ team.Name }}</a>
</rd-header-content>

View File

@ -44,7 +44,6 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
};
$scope.promoteToLeader = function(user) {
$('#loadingViewSpinner').show();
TeamMembershipService.updateMembership(user.MembershipId, user.Id, $scope.team.Id, 1)
.then(function success(data) {
$scope.leaderCount++;
@ -53,14 +52,10 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update user role');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.demoteToMember = function(user) {
$('#loadingViewSpinner').show();
TeamMembershipService.updateMembership(user.MembershipId, user.Id, $scope.team.Id, 2)
.then(function success(data) {
user.TeamRole = 'Member';
@ -69,14 +64,10 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update user role');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.addAllUsers = function() {
$('#loadingViewSpinner').show();
var teamMembershipQueries = [];
angular.forEach($scope.users, function (user) {
teamMembershipQueries.push(TeamMembershipService.createMembership(user.Id, $scope.team.Id, 2));
@ -95,14 +86,10 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update team members');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.addUser = function(user) {
$('#loadingViewSpinner').show();
TeamMembershipService.createMembership(user.Id, $scope.team.Id, 2)
.then(function success(data) {
removeUserFromArray(user.Id, $scope.users);
@ -113,14 +100,10 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update team members');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.removeAllUsers = function() {
$('#loadingViewSpinner').show();
var teamMembershipQueries = [];
angular.forEach($scope.teamMembers, function (user) {
teamMembershipQueries.push(TeamMembershipService.deleteMembership(user.MembershipId));
@ -133,14 +116,10 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update team members');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.removeUser = function(user) {
$('#loadingViewSpinner').show();
TeamMembershipService.deleteMembership(user.MembershipId)
.then(function success() {
removeUserFromArray(user.Id, $scope.teamMembers);
@ -149,14 +128,10 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update team members');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
function deleteTeam() {
$('#loadingViewSpinner').show();
TeamService.deleteTeam($scope.team.Id)
.then(function success(data) {
Notifications.success('Team successfully deleted', $scope.team.Name);
@ -164,9 +139,6 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove team');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}
@ -205,7 +177,6 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
}
function initView() {
$('#loadingViewSpinner').show();
$scope.isAdmin = Authentication.getUserDetails().role === 1 ? true: false;
$q.all({
team: TeamService.team($transition$.params().id),
@ -219,9 +190,6 @@ function ($q, $scope, $state, $transition$, TeamService, UserService, TeamMember
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve team details');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="teams" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Teams management</rd-header-content>
</rd-header>
@ -50,8 +49,10 @@
<!-- !team-leaders -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!state.validName || formValues.Name === ''" ng-click="addTeam()"><i class="fa fa-plus" aria-hidden="true"></i> Add team</button>
<i id="createTeamSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !state.validName || formValues.Name === ''" ng-click="addTeam()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress"><i class="fa fa-plus" aria-hidden="true"></i> Create team</span>
<span ng-show="state.actionInProgress">Creating team...</span>
</button>
<span class="text-danger" ng-if="state.teamCreationError" style="margin: 5px;">
<i class="fa fa-exclamation-circle" aria-hidden="true"></i> {{ state.teamCreationError }}
</span>

View File

@ -5,7 +5,8 @@ function ($q, $scope, $state, TeamService, UserService, TeamMembershipService, M
userGroupGroupCreationError: '',
selectedItemCount: 0,
validName: false,
pagination_count: Pagination.getPaginationCount('teams')
pagination_count: Pagination.getPaginationCount('teams'),
actionInProgress: false
};
$scope.sortType = 'Name';
$scope.sortReverse = false;
@ -54,7 +55,7 @@ function ($q, $scope, $state, TeamService, UserService, TeamMembershipService, M
};
$scope.addTeam = function() {
$('#createTeamSpinner').show();
$scope.state.actionInProgress = true;
$scope.state.teamCreationError = '';
var teamName = $scope.formValues.Name;
var leaderIds = [];
@ -71,22 +72,13 @@ function ($q, $scope, $state, TeamService, UserService, TeamMembershipService, M
Notifications.error('Failure', err, 'Unable to create team');
})
.finally(function final() {
$('#createTeamSpinner').hide();
$scope.state.actionInProgress = false;
});
};
function deleteSelectedTeams() {
$('#loadingViewSpinner').show();
var counter = 0;
var complete = function () {
counter = counter - 1;
if (counter === 0) {
$('#loadingViewSpinner').hide();
}
};
angular.forEach($scope.teams, function (team) {
if (team.Checked) {
counter = counter + 1;
TeamService.deleteTeam(team.Id)
.then(function success(data) {
var index = $scope.teams.indexOf(team);
@ -95,9 +87,6 @@ function ($q, $scope, $state, TeamService, UserService, TeamMembershipService, M
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove team');
})
.finally(function final() {
complete();
});
}
});
@ -114,7 +103,6 @@ function ($q, $scope, $state, TeamService, UserService, TeamMembershipService, M
};
function initView() {
$('#loadingViewSpinner').show();
var userDetails = Authentication.getUserDetails();
var isAdmin = userDetails.role === 1 ? true: false;
$scope.isAdmin = isAdmin;
@ -130,9 +118,6 @@ function ($q, $scope, $state, TeamService, UserService, TeamMembershipService, M
$scope.teams = [];
$scope.users = [];
Notifications.error('Failure', err, 'Unable to retrieve teams');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -3,7 +3,6 @@
<a data-toggle="tooltip" title="Refresh" ui-sref="templates" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Templates</rd-header-content>
</rd-header>
@ -60,10 +59,15 @@
<por-access-control-form form-data="formValues.AccessControlData" ng-if="applicationState.application.authentication"></por-access-control-form>
<!-- !access-control -->
<!-- actions -->
<div class="col-sm-12 form-section-title">
Actions
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.name" ng-click="createTemplate()">Create</button>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !formValues.name" ng-click="createTemplate()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Deploy the stack</span>
<span ng-show="state.actionInProgress">Deployment in progress...</span>
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>
</div>
@ -287,10 +291,15 @@
</div>
<!-- !advanced-options -->
<!-- actions -->
<div class="col-sm-12 form-section-title">
Actions
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.network" ng-click="createTemplate()">Create</button>
<i id="createResourceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !formValues.network" ng-click="createTemplate()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Deploy the container</span>
<span ng-show="state.actionInProgress">Deployment in progress...</span>
</button>
<span class="small text-muted" style="margin-left: 10px" ng-if="globalNetworkCount === 0 && applicationState.endpoint.mode.provider === 'DOCKER_SWARM' && !state.formValidationError">
When using Swarm, we recommend deploying containers in a shared network. Looks like you don't have any shared network, head over the <a ui-sref="networks">networks view</a> to create one.
</span>

View File

@ -7,6 +7,7 @@ function ($scope, $q, $state, $transition$, $anchorScroll, $filter, ContainerSer
hideDescriptions: $transition$.params().hide_descriptions,
formValidationError: '',
showDeploymentSelector: false,
actionInProgress: false,
filters: {
Categories: '!',
Platform: '!',
@ -85,7 +86,7 @@ function ($scope, $q, $state, $transition$, $anchorScroll, $filter, ContainerSer
Notifications.error('Failure', err, err.msg);
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
}
@ -113,26 +114,24 @@ function ($scope, $q, $state, $transition$, $anchorScroll, $filter, ContainerSer
$state.go('stacks', {}, {reload: true});
})
.finally(function final() {
$('#createResourceSpinner').hide();
$scope.state.actionInProgress = false;
});
}
$scope.createTemplate = function() {
$('#createResourceSpinner').show();
var userDetails = Authentication.getUserDetails();
var userId = userDetails.ID;
var accessControlData = $scope.formValues.AccessControlData;
var isAdmin = userDetails.role === 1 ? true : false;
if (!validateForm(accessControlData, isAdmin)) {
$('#createResourceSpinner').hide();
return;
}
var template = $scope.state.selectedTemplate;
var templatesKey = $scope.templatesKey;
$scope.state.actionInProgress = true;
if (template.Type === 'stack') {
createStackFromTemplate(template, userId, accessControlData);
} else {
@ -234,9 +233,6 @@ function ($scope, $q, $state, $transition$, $anchorScroll, $filter, ContainerSer
.catch(function error(err) {
$scope.templates = [];
Notifications.error('Failure', err, 'An error occured during apps initialization.');
})
.finally(function final(){
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="User details">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin"></i>
</rd-header-title>
<rd-header-title title="User details"></rd-header-title>
<rd-header-content>
<a ui-sref="users">Users</a> &gt; <a ui-sref="user({id: user.Id})">{{ user.Username }}</a>
</rd-header-content>

View File

@ -23,7 +23,6 @@ function ($q, $scope, $state, $transition$, UserService, ModalService, Notificat
};
$scope.updatePermissions = function() {
$('#loadingViewSpinner').show();
var role = $scope.formValues.Administrator ? 1 : 2;
UserService.updateUser($scope.user.Id, undefined, role)
.then(function success(data) {
@ -33,14 +32,10 @@ function ($q, $scope, $state, $transition$, UserService, ModalService, Notificat
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update user permissions');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
$scope.updatePassword = function() {
$('#loadingViewSpinner').show();
UserService.updateUser($scope.user.Id, $scope.formValues.newPassword, undefined)
.then(function success(data) {
Notifications.success('Password successfully updated');
@ -48,14 +43,10 @@ function ($q, $scope, $state, $transition$, UserService, ModalService, Notificat
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update user password');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
};
function deleteUser() {
$('#loadingViewSpinner').show();
UserService.deleteUser($scope.user.Id)
.then(function success(data) {
Notifications.success('User successfully deleted', $scope.user.Username);
@ -63,14 +54,10 @@ function ($q, $scope, $state, $transition$, UserService, ModalService, Notificat
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove user');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}
function initView() {
$('#loadingViewSpinner').show();
$q.all({
user: UserService.user($transition$.params().id),
settings: SettingsService.publicSettings()
@ -83,9 +70,6 @@ function ($q, $scope, $state, $transition$, UserService, ModalService, Notificat
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve user information');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View File

@ -1,7 +1,5 @@
<rd-header>
<rd-header-title title="User settings">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-title title="User settings"></rd-header-title>
<rd-header-content>User settings</rd-header-content>
</rd-header>

View File

@ -34,9 +34,6 @@ function ($scope, $state, $sanitize, Authentication, UserService, Notifications,
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve application settings');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

Some files were not shown because too many files have changed in this diff Show More