1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 13:55:21 +02:00

chore(project): add prettier for code format (#3645)

* chore(project): install prettier and lint-staged

* chore(project): apply prettier to html too

* chore(project): git ignore eslintcache

* chore(project): add a comment about format script

* chore(prettier): update printWidth

* chore(prettier): remove useTabs option

* chore(prettier): add HTML validation

* refactor(prettier): fix closing tags

* feat(prettier): define angular parser for html templates

* style(prettier): run prettier on codebase

Co-authored-by: Anthony Lapenna <lapenna.anthony@gmail.com>
This commit is contained in:
Chaim Lev-Ari 2020-04-11 00:54:53 +03:00 committed by GitHub
parent 6663073be1
commit cf5056d9c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
714 changed files with 31228 additions and 28305 deletions

View file

@ -1,3 +1 @@
angular.module('portainer.integrations', [
'portainer.integrations.storidge'
]);
angular.module('portainer.integrations', ['portainer.integrations.storidge']);

View file

@ -1,126 +1,128 @@
// TODO: legacy extension management
angular.module('portainer.integrations.storidge', [])
.config(['$stateRegistryProvider', function ($stateRegistryProvider) {
'use strict';
angular.module('portainer.integrations.storidge', []).config([
'$stateRegistryProvider',
function ($stateRegistryProvider) {
'use strict';
var storidge = {
name: 'storidge',
parent: 'root',
abstract: true,
url: '/storidge'
};
var storidge = {
name: 'storidge',
parent: 'root',
abstract: true,
url: '/storidge',
};
var profiles = {
name: 'storidge.profiles',
url: '/profiles',
views: {
'content@': {
templateUrl: './views/profiles/profiles.html',
controller: 'StoridgeProfilesController'
}
}
};
var profiles = {
name: 'storidge.profiles',
url: '/profiles',
views: {
'content@': {
templateUrl: './views/profiles/profiles.html',
controller: 'StoridgeProfilesController',
},
},
};
var profile = {
name: 'storidge.profiles.profile',
url: '/:id',
views: {
'content@': {
templateUrl: './views/profiles/edit/profile.html',
controller: 'StoridgeProfileController'
}
}
};
var profile = {
name: 'storidge.profiles.profile',
url: '/:id',
views: {
'content@': {
templateUrl: './views/profiles/edit/profile.html',
controller: 'StoridgeProfileController',
},
},
};
var drives = {
name: 'storidge.drives',
url: '/drives',
views: {
'content@': {
templateUrl: './views/drives/drives.html',
controller: 'StoridgeDrivesController'
}
}
};
var drives = {
name: 'storidge.drives',
url: '/drives',
views: {
'content@': {
templateUrl: './views/drives/drives.html',
controller: 'StoridgeDrivesController',
},
},
};
var drive = {
name: 'storidge.drives.drive',
url: '/:id',
views: {
'content@': {
templateUrl: './views/drives/inspect/drive.html',
controller: 'StoridgeDriveController'
}
}
};
var drive = {
name: 'storidge.drives.drive',
url: '/:id',
views: {
'content@': {
templateUrl: './views/drives/inspect/drive.html',
controller: 'StoridgeDriveController',
},
},
};
var snapshot = {
name: 'docker.volumes.volume.snapshot',
url: '/:snapshotId',
views: {
'content@': {
templateUrl: './views/snapshots/inspect/snapshot.html',
controller: 'StoridgeSnapshotController'
}
}
};
var snapshot = {
name: 'docker.volumes.volume.snapshot',
url: '/:snapshotId',
views: {
'content@': {
templateUrl: './views/snapshots/inspect/snapshot.html',
controller: 'StoridgeSnapshotController',
},
},
};
var profileCreation = {
name: 'storidge.profiles.new',
url: '/new',
params: {
profileName: ''
},
views: {
'content@': {
templateUrl: './views/profiles/create/createprofile.html',
controller: 'StoridgeCreateProfileController'
}
}
};
var profileCreation = {
name: 'storidge.profiles.new',
url: '/new',
params: {
profileName: '',
},
views: {
'content@': {
templateUrl: './views/profiles/create/createprofile.html',
controller: 'StoridgeCreateProfileController',
},
},
};
var cluster = {
name: 'storidge.cluster',
url: '/cluster',
views: {
'content@': {
templateUrl: './views/cluster/cluster.html',
controller: 'StoridgeClusterController'
}
}
};
var cluster = {
name: 'storidge.cluster',
url: '/cluster',
views: {
'content@': {
templateUrl: './views/cluster/cluster.html',
controller: 'StoridgeClusterController',
},
},
};
var node = {
name: 'storidge.cluster.node',
url: '/:name',
views: {
'content@': {
templateUrl: './views/nodes/inspect/node.html',
controller: 'StoridgeNodeController'
}
}
};
var node = {
name: 'storidge.cluster.node',
url: '/:name',
views: {
'content@': {
templateUrl: './views/nodes/inspect/node.html',
controller: 'StoridgeNodeController',
},
},
};
var monitor = {
name: 'storidge.monitor',
url: '/events',
views: {
'content@': {
templateUrl: './views/monitor/monitor.html',
controller: 'StoridgeMonitorController'
}
}
};
var monitor = {
name: 'storidge.monitor',
url: '/events',
views: {
'content@': {
templateUrl: './views/monitor/monitor.html',
controller: 'StoridgeMonitorController',
},
},
};
$stateRegistryProvider.register(storidge);
$stateRegistryProvider.register(drives);
$stateRegistryProvider.register(drive);
$stateRegistryProvider.register(snapshot);
$stateRegistryProvider.register(profiles);
$stateRegistryProvider.register(profile);
$stateRegistryProvider.register(profileCreation);
$stateRegistryProvider.register(cluster);
$stateRegistryProvider.register(node);
$stateRegistryProvider.register(monitor);
}]);
$stateRegistryProvider.register(storidge);
$stateRegistryProvider.register(drives);
$stateRegistryProvider.register(drive);
$stateRegistryProvider.register(snapshot);
$stateRegistryProvider.register(profiles);
$stateRegistryProvider.register(profile);
$stateRegistryProvider.register(profileCreation);
$stateRegistryProvider.register(cluster);
$stateRegistryProvider.register(node);
$stateRegistryProvider.register(monitor);
},
]);

View file

@ -2,13 +2,19 @@
<rd-widget>
<rd-widget-body classes="no-padding">
<div class="toolBar">
<div class="toolBarTitle">
<i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }}
</div>
<div class="toolBarTitle"> <i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }} </div>
</div>
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input type="text" class="searchInput" ng-model="$ctrl.state.textFilter" ng-change="$ctrl.onTextFilterChange()" placeholder="Search..." auto-focus ng-model-options="{ debounce: 300 }">
<input
type="text"
class="searchInput"
ng-model="$ctrl.state.textFilter"
ng-change="$ctrl.onTextFilterChange()"
placeholder="Search..."
auto-focus
ng-model-options="{ debounce: 300 }"
/>
</div>
<div class="table-responsive">
<table class="table table-hover">
@ -45,7 +51,10 @@
</tr>
</thead>
<tbody>
<tr dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" ng-class="{active: item.Checked}">
<tr
dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))"
ng-class="{ active: item.Checked }"
>
<td>{{ item.Time }}</td>
<td>{{ item.Category }}</td>
<td>{{ item.Module }}</td>

View file

@ -7,6 +7,6 @@ angular.module('portainer.integrations.storidge').component('storidgeClusterEven
dataset: '<',
tableKey: '@',
orderBy: '@',
reverseOrder: '<'
}
reverseOrder: '<',
},
});

View file

@ -2,18 +2,22 @@
<rd-widget>
<rd-widget-body classes="no-padding">
<div class="toolBar">
<div class="toolBarTitle">
<i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }}
</div>
<div class="toolBarTitle"> <i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }} </div>
</div>
<div class="actionBar">
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.rescanAction()">
<i class="fa fa-sync space-right" aria-hidden="true"></i>Rescan drives
</button>
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.rescanAction()"> <i class="fa fa-sync space-right" aria-hidden="true"></i>Rescan drives </button>
</div>
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input type="text" class="searchInput" ng-model="$ctrl.state.textFilter" ng-change="$ctrl.onTextFilterChange()" placeholder="Search..." auto-focus ng-model-options="{ debounce: 300 }">
<input
type="text"
class="searchInput"
ng-model="$ctrl.state.textFilter"
ng-change="$ctrl.onTextFilterChange()"
placeholder="Search..."
auto-focus
ng-model-options="{ debounce: 300 }"
/>
</div>
<div class="table-responsive">
<table class="table table-hover">
@ -74,7 +78,10 @@
</tr>
</thead>
<tbody>
<tr dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" ng-class="{active: item.Checked}">
<tr
dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))"
ng-class="{ active: item.Checked }"
>
<td>
<a ui-sref="storidge.drives.drive({id: item.Id})"> {{ item.Id }}</a>
</td>
@ -84,11 +91,17 @@
<td>{{ item.Use }}</td>
<td>{{ item.Type }}</td>
<td>
<span class="label label-{{ item.Status|drivestatusbadge }}">{{ item.Status|capitalize }}</span>
<span class="label label-{{ item.Status | drivestatusbadge }}">{{ item.Status | capitalize }}</span>
</td>
<td>
<button ng-if="item.Status === 'available'" type="button" class="btn btn-sm btn-primary btn-datatable"
ng-click="$ctrl.addAction(item, $index)" button-spinner="$ctrl.additionInProgress[$index]" ng-disabled="$ctrl.actionInProgress">
<button
ng-if="item.Status === 'available'"
type="button"
class="btn btn-sm btn-primary btn-datatable"
ng-click="$ctrl.addAction(item, $index)"
button-spinner="$ctrl.additionInProgress[$index]"
ng-disabled="$ctrl.actionInProgress"
>
<span ng-hide="$ctrl.additionInProgress[$index]"><i class="fa fa-plus space-right" aria-hidden="true"></i>Add to storage pool</span>
<span ng-show="$ctrl.additionInProgress[$index]">Addition in progress...</span>
</button>
@ -104,9 +117,7 @@
</table>
</div>
<div class="footer" ng-if="$ctrl.dataset">
<div class="infoBar" ng-if="$ctrl.state.selectedItemCount !== 0">
{{ $ctrl.state.selectedItemCount }} item(s) selected
</div>
<div class="infoBar" ng-if="$ctrl.state.selectedItemCount !== 0"> {{ $ctrl.state.selectedItemCount }} item(s) selected </div>
<div class="paginationControls">
<form class="form-inline">
<span class="limitSelector">

View file

@ -12,6 +12,6 @@ angular.module('portainer.integrations.storidge').component('storidgeDrivesDatat
addAction: '<',
rescanAction: '<',
actionInProgress: '<',
additionInProgress: '<'
}
additionInProgress: '<',
},
});

View file

@ -1,43 +1,45 @@
angular.module('portainer.docker')
.controller('StoridgeDrivesDatatableController', ['$scope', '$controller', 'DatatableService',
function ($scope, $controller, DatatableService) {
angular.extend(this, $controller('GenericDatatableController', {$scope: $scope}));
angular.module('portainer.docker').controller('StoridgeDrivesDatatableController', [
'$scope',
'$controller',
'DatatableService',
function ($scope, $controller, DatatableService) {
angular.extend(this, $controller('GenericDatatableController', { $scope: $scope }));
this.allowSelection = function (item) {
return item.Status !== 'normal';
};
this.allowSelection = function (item) {
return item.Status !== 'normal';
};
this.$onInit = function() {
this.setDefaults();
this.prepareTableFromDataset();
this.$onInit = function () {
this.setDefaults();
this.prepareTableFromDataset();
this.state.orderBy = this.orderBy;
var storedOrder = DatatableService.getDataTableOrder(this.tableKey);
if (storedOrder !== null) {
this.state.reverseOrder = storedOrder.reverse;
this.state.orderBy = storedOrder.orderBy;
}
this.state.orderBy = this.orderBy;
var storedOrder = DatatableService.getDataTableOrder(this.tableKey);
if (storedOrder !== null) {
this.state.reverseOrder = storedOrder.reverse;
this.state.orderBy = storedOrder.orderBy;
}
var textFilter = DatatableService.getDataTableTextFilters(this.tableKey);
if (textFilter !== null) {
this.state.textFilter = textFilter;
this.onTextFilterChange();
}
var textFilter = DatatableService.getDataTableTextFilters(this.tableKey);
if (textFilter !== null) {
this.state.textFilter = textFilter;
this.onTextFilterChange();
}
var storedFilters = DatatableService.getDataTableFilters(this.tableKey);
if (storedFilters !== null) {
this.filters = storedFilters;
}
if (this.filters && this.filters.state) {
this.filters.state.open = false;
}
var storedFilters = DatatableService.getDataTableFilters(this.tableKey);
if (storedFilters !== null) {
this.filters = storedFilters;
}
if (this.filters && this.filters.state) {
this.filters.state.open = false;
}
var storedSettings = DatatableService.getDataTableSettings(this.tableKey);
if (storedSettings !== null) {
this.settings = storedSettings;
this.settings.open = false;
}
this.onSettingsRepeaterChange();
};
}
]);
var storedSettings = DatatableService.getDataTableSettings(this.tableKey);
if (storedSettings !== null) {
this.settings = storedSettings;
this.settings.open = false;
}
this.onSettingsRepeaterChange();
};
},
]);

View file

@ -2,16 +2,12 @@
<rd-widget>
<rd-widget-body classes="no-padding">
<div class="toolBar">
<div class="toolBarTitle">
<i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }}
</div>
<div class="toolBarTitle"> <i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }} </div>
</div>
<div class="actionBar">
<div class="row">
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.addNodeAction()">
<i class="fa fa-plus space-right" aria-hidden="true"></i>Add node
</button>
<div style="margin-bottom: 0px;">
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.addNodeAction()"> <i class="fa fa-plus space-right" aria-hidden="true"></i>Add node </button>
<div style="margin-bottom: 0px;">
<span ng-if="$ctrl.addInfo" class="text-muted small">
To add a node to this cluster, run the following command on your new node
<code>
@ -27,7 +23,15 @@
</div>
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input type="text" class="searchInput" ng-model="$ctrl.state.textFilter" ng-change="$ctrl.onTextFilterChange()" placeholder="Search..." auto-focus ng-model-options="{ debounce: 300 }">
<input
type="text"
class="searchInput"
ng-model="$ctrl.state.textFilter"
ng-change="$ctrl.onTextFilterChange()"
placeholder="Search..."
auto-focus
ng-model-options="{ debounce: 300 }"
/>
</div>
<div class="table-responsive">
<table class="table table-hover">
@ -64,7 +68,10 @@
</tr>
</thead>
<tbody>
<tr dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" ng-class="{active: item.Checked}">
<tr
dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))"
ng-class="{ active: item.Checked }"
>
<td>
<a ui-sref="storidge.cluster.node({name: item.Name})"> {{ item.Name }}</a>
</td>

View file

@ -7,6 +7,6 @@ angular.module('portainer.integrations.storidge').component('storidgeNodesDatata
dataset: '<',
tableKey: '@',
orderBy: '@',
reverseOrder: '<'
}
reverseOrder: '<',
},
});

View file

@ -1,56 +1,62 @@
angular.module('portainer.integrations.storidge')
.controller('StoridgeNodesDatatableController', ['$scope', '$controller', 'clipboard', 'Notifications', 'StoridgeNodeService', 'DatatableService',
function($scope, $controller, clipboard, Notifications, StoridgeNodeService, DatatableService) {
angular.extend(this, $controller('GenericDatatableController', { $scope: $scope }));
angular.module('portainer.integrations.storidge').controller('StoridgeNodesDatatableController', [
'$scope',
'$controller',
'clipboard',
'Notifications',
'StoridgeNodeService',
'DatatableService',
function ($scope, $controller, clipboard, Notifications, StoridgeNodeService, DatatableService) {
angular.extend(this, $controller('GenericDatatableController', { $scope: $scope }));
var ctrl = this;
var ctrl = this;
this.addNodeAction = function() {
StoridgeNodeService.add()
.then(function sucess(data) {
ctrl.addInfo = data.content;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve the "add node" command');
});
};
this.addNodeAction = function () {
StoridgeNodeService.add()
.then(function sucess(data) {
ctrl.addInfo = data.content;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve the "add node" command');
});
};
this.copyAddNodeCommand = function() {
clipboard.copyText(ctrl.addInfo);
$('#copyNotification').show();
$('#copyNotification').fadeOut(2000);
};
this.copyAddNodeCommand = function () {
clipboard.copyText(ctrl.addInfo);
$('#copyNotification').show();
$('#copyNotification').fadeOut(2000);
};
this.$onInit = function() {
this.setDefaults();
this.prepareTableFromDataset();
this.$onInit = function () {
this.setDefaults();
this.prepareTableFromDataset();
this.state.orderBy = this.orderBy;
var storedOrder = DatatableService.getDataTableOrder(this.tableKey);
if (storedOrder !== null) {
this.state.reverseOrder = storedOrder.reverse;
this.state.orderBy = storedOrder.orderBy;
}
this.state.orderBy = this.orderBy;
var storedOrder = DatatableService.getDataTableOrder(this.tableKey);
if (storedOrder !== null) {
this.state.reverseOrder = storedOrder.reverse;
this.state.orderBy = storedOrder.orderBy;
}
var textFilter = DatatableService.getDataTableTextFilters(this.tableKey);
if (textFilter !== null) {
this.state.textFilter = textFilter;
this.onTextFilterChange();
}
var textFilter = DatatableService.getDataTableTextFilters(this.tableKey);
if (textFilter !== null) {
this.state.textFilter = textFilter;
this.onTextFilterChange();
}
var storedFilters = DatatableService.getDataTableFilters(this.tableKey);
if (storedFilters !== null) {
this.filters = storedFilters;
}
if (this.filters && this.filters.state) {
this.filters.state.open = false;
}
var storedFilters = DatatableService.getDataTableFilters(this.tableKey);
if (storedFilters !== null) {
this.filters = storedFilters;
}
if (this.filters && this.filters.state) {
this.filters.state.open = false;
}
var storedSettings = DatatableService.getDataTableSettings(this.tableKey);
if (storedSettings !== null) {
this.settings = storedSettings;
this.settings.open = false;
}
this.onSettingsRepeaterChange();
};
}]);
var storedSettings = DatatableService.getDataTableSettings(this.tableKey);
if (storedSettings !== null) {
this.settings = storedSettings;
this.settings.open = false;
}
this.onSettingsRepeaterChange();
};
},
]);

View file

@ -2,6 +2,6 @@ angular.module('portainer.integrations.storidge').component('storidgeProfileSele
templateUrl: './storidgeProfileSelector.html',
controller: 'StoridgeProfileSelectorController',
bindings: {
'storidgeProfile': '='
}
storidgeProfile: '=',
},
});

View file

@ -1,17 +1,19 @@
angular.module('portainer.integrations.storidge')
.controller('StoridgeProfileSelectorController', ['StoridgeProfileService', 'Notifications',
function (StoridgeProfileService, Notifications) {
var ctrl = this;
angular.module('portainer.integrations.storidge').controller('StoridgeProfileSelectorController', [
'StoridgeProfileService',
'Notifications',
function (StoridgeProfileService, Notifications) {
var ctrl = this;
function initComponent() {
StoridgeProfileService.profiles()
.then(function success(data) {
ctrl.profiles = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve Storidge profiles');
});
}
function initComponent() {
StoridgeProfileService.profiles()
.then(function success(data) {
ctrl.profiles = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve Storidge profiles');
});
}
initComponent();
}]);
initComponent();
},
]);

View file

@ -2,19 +2,24 @@
<rd-widget>
<rd-widget-body classes="no-padding">
<div class="toolBar">
<div class="toolBarTitle">
<i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }}
</div>
<div class="toolBarTitle"> <i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }} </div>
</div>
<div class="actionBar">
<button type="button" class="btn btn-sm btn-danger"
ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.state.selectedItems)">
<button type="button" class="btn btn-sm btn-danger" ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.state.selectedItems)">
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
</button>
</div>
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input type="text" class="searchInput" ng-model="$ctrl.state.textFilter" ng-change="$ctrl.onTextFilterChange()" placeholder="Search..." auto-focus ng-model-options="{ debounce: 300 }">
<input
type="text"
class="searchInput"
ng-model="$ctrl.state.textFilter"
ng-change="$ctrl.onTextFilterChange()"
placeholder="Search..."
auto-focus
ng-model-options="{ debounce: 300 }"
/>
</div>
<div class="table-responsive">
<table class="table table-hover">
@ -34,10 +39,13 @@
</tr>
</thead>
<tbody>
<tr dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" ng-class="{active: item.Checked}">
<tr
dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))"
ng-class="{ active: item.Checked }"
>
<td>
<span class="md-checkbox">
<input id="select_{{ $index }}" type="checkbox" ng-model="item.Checked" ng-click="$ctrl.selectItem(item, $event)"/>
<input id="select_{{ $index }}" type="checkbox" ng-model="item.Checked" ng-click="$ctrl.selectItem(item, $event)" />
<label for="select_{{ $index }}"></label>
</span>
<a ui-sref="storidge.profiles.profile({id: item.Name})">{{ item.Name }}</a>
@ -53,9 +61,7 @@
</table>
</div>
<div class="footer" ng-if="$ctrl.dataset">
<div class="infoBar" ng-if="$ctrl.state.selectedItemCount !== 0">
{{ $ctrl.state.selectedItemCount }} item(s) selected
</div>
<div class="infoBar" ng-if="$ctrl.state.selectedItemCount !== 0"> {{ $ctrl.state.selectedItemCount }} item(s) selected </div>
<div class="paginationControls">
<form class="form-inline">
<span class="limitSelector">

View file

@ -8,6 +8,6 @@ angular.module('portainer.integrations.storidge').component('storidgeProfilesDat
tableKey: '@',
orderBy: '@',
reverseOrder: '<',
removeAction: '<'
}
removeAction: '<',
},
});

View file

@ -1,18 +1,22 @@
<rd-widget>
<rd-widget-header icon="fa-plus" title-text="Create snapshot">
</rd-widget-header>
<rd-widget-header icon="fa-plus" title-text="Create snapshot"> </rd-widget-header>
<rd-widget-body>
<form class="form-horizontal">
<div class="form-group">
<label for="description" class="col-sm-3 col-lg-2 control-label text-left">Description</label>
<div class="col-sm-9 col-lg-10">
<input type="text" class="form-control" id="description" ng-model="$ctrl.formValues.Description">
<input type="text" class="form-control" id="description" ng-model="$ctrl.formValues.Description" />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="$ctrl.state.actionInProgress"
ng-click="$ctrl.createSnapshot()" button-spinner="$ctrl.state.actionInProgress">
<button
type="button"
class="btn btn-primary btn-sm"
ng-disabled="$ctrl.state.actionInProgress"
ng-click="$ctrl.createSnapshot()"
button-spinner="$ctrl.state.actionInProgress"
>
<span ng-hide="$ctrl.state.actionInProgress">Create snapshot</span>
<span ng-show="$ctrl.state.actionInProgress">Creating snapshot...</span>
</button>

View file

@ -2,6 +2,6 @@ angular.module('portainer.docker').component('storidgeSnapshotCreation', {
templateUrl: './storidgeSnapshotCreation.html',
controller: 'StoridgeSnapshotCreationController',
bindings: {
volumeId: '<'
}
volumeId: '<',
},
});

View file

@ -1,26 +1,28 @@
angular.module('portainer.docker')
.controller('StoridgeSnapshotCreationController', ['StoridgeSnapshotService', 'Notifications', '$state',
function (StoridgeSnapshotService, Notifications, $state) {
var ctrl = this;
angular.module('portainer.docker').controller('StoridgeSnapshotCreationController', [
'StoridgeSnapshotService',
'Notifications',
'$state',
function (StoridgeSnapshotService, Notifications, $state) {
var ctrl = this;
this.formValues = {};
this.state = {
actionInProgress: false
};
this.formValues = {};
this.state = {
actionInProgress: false,
};
this.createSnapshot = function () {
ctrl.state.actionInProgress = true;
StoridgeSnapshotService.create(ctrl.volumeId, ctrl.formValues.Description)
.then(function success() {
Notifications.success('Success', 'Snapshot successfully created');
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to create snapshot');
})
.finally(function final() {
ctrl.state.actionInProgress = false;
});
};
}]);
this.createSnapshot = function () {
ctrl.state.actionInProgress = true;
StoridgeSnapshotService.create(ctrl.volumeId, ctrl.formValues.Description)
.then(function success() {
Notifications.success('Success', 'Snapshot successfully created');
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to create snapshot');
})
.finally(function final() {
ctrl.state.actionInProgress = false;
});
};
},
]);

View file

@ -2,19 +2,23 @@
<rd-widget>
<rd-widget-body classes="no-padding">
<div class="toolBar">
<div class="toolBarTitle">
<i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }}
</div>
<div class="toolBarTitle"> <i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }} </div>
</div>
<div class="actionBar">
<button type="button" class="btn btn-sm btn-danger"
ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.state.selectedItems)">
<button type="button" class="btn btn-sm btn-danger" ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.state.selectedItems)">
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
</button>
</div>
<div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
<input type="text" class="searchInput" ng-model="$ctrl.state.textFilter" ng-change="$ctrl.onTextFilterChange()" placeholder="Search..." ng-model-options="{ debounce: 300 }">
<input
type="text"
class="searchInput"
ng-model="$ctrl.state.textFilter"
ng-change="$ctrl.onTextFilterChange()"
placeholder="Search..."
ng-model-options="{ debounce: 300 }"
/>
</div>
<div class="table-responsive">
<table class="table table-hover">
@ -48,10 +52,13 @@
</tr>
</thead>
<tbody>
<tr dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" ng-class="{active: item.Checked}">
<tr
dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))"
ng-class="{ active: item.Checked }"
>
<td>
<span class="md-checkbox">
<input id="select_{{ $index }}" type="checkbox" ng-model="item.Checked" ng-click="$ctrl.selectItem(item, $event)" ng-disabled="item.Status === 'normal'"/>
<input id="select_{{ $index }}" type="checkbox" ng-model="item.Checked" ng-click="$ctrl.selectItem(item, $event)" ng-disabled="item.Status === 'normal'" />
<label for="select_{{ $index }}"></label>
</span>
<a ui-sref="docker.volumes.volume.snapshot({snapshotId: item.Id})"> {{ item.Id }}</a>
@ -69,9 +76,7 @@
</table>
</div>
<div class="footer" ng-if="$ctrl.dataset">
<div class="infoBar" ng-if="$ctrl.state.selectedItemCount !== 0">
{{ $ctrl.state.selectedItemCount }} item(s) selected
</div>
<div class="infoBar" ng-if="$ctrl.state.selectedItemCount !== 0"> {{ $ctrl.state.selectedItemCount }} item(s) selected </div>
<div class="paginationControls">
<form class="form-inline">
<span class="limitSelector">

View file

@ -8,6 +8,6 @@ angular.module('portainer.integrations.storidge').component('storidgeSnapshotsDa
tableKey: '@',
orderBy: '@',
reverseOrder: '<',
removeAction: '<'
}
removeAction: '<',
},
});

View file

@ -80,31 +80,31 @@
</tr>
<tr>
<td>IP</td>
<td>{{ $ctrl.volume.IP}}</td>
<td>{{ $ctrl.volume.IP }}</td>
</tr>
<tr>
<td>Drive Type</td>
<td>{{ $ctrl.volume.DriveType}}</td>
<td>{{ $ctrl.volume.DriveType }}</td>
</tr>
<tr>
<td>Encryption</td>
<td>{{ $ctrl.volume.Encryption}}</td>
<td>{{ $ctrl.volume.Encryption }}</td>
</tr>
<tr>
<td>Snapshot Enabled</td>
<td>{{ $ctrl.volume.SnapshotEnabled}}</td>
<td>{{ $ctrl.volume.SnapshotEnabled }}</td>
</tr>
<tr>
<td>Snapshot Interval</td>
<td>{{ $ctrl.volume.SnapshotInterval}} minute(s)</td>
<td>{{ $ctrl.volume.SnapshotInterval }} minute(s)</td>
</tr>
<tr>
<td>Max Snapshots</td>
<td>{{ $ctrl.volume.SnapshotMax}}</td>
<td>{{ $ctrl.volume.SnapshotMax }}</td>
</tr>
<tr>
<td>Filesystem</td>
<td>{{ $ctrl.volume.Filesystem}}</td>
<td>{{ $ctrl.volume.Filesystem }}</td>
</tr>
<tr ng-if="$ctrl.volume.Labels">
<td>Labels</td>
@ -126,7 +126,7 @@
<div class="form-group">
<label for="volume_node" class="col-sm-2 col-lg-1 control-label text-left">Node</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="$ctrl.formValues.Node" name="volume_node" placeholder="2">
<input type="text" class="form-control" ng-model="$ctrl.formValues.Node" name="volume_node" placeholder="2" />
</div>
</div>
<!-- !Node -->
@ -134,7 +134,7 @@
<div class="form-group">
<label for="volume_capacity" class="col-sm-2 col-lg-1 control-label text-left">Capacity</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="$ctrl.formValues.Capacity" name="volume_capacity" placeholder="2">
<input type="text" class="form-control" ng-model="$ctrl.formValues.Capacity" name="volume_capacity" placeholder="2" />
</div>
</div>
<!-- !Capacity -->
@ -142,13 +142,13 @@
<div class="form-group">
<label for="min_iops" class="col-sm-2 col-lg-1 control-label text-left">Min IOPS</label>
<div class="col-sm-10 col-lg-11">
<input type="number" class="form-control" ng-model="$ctrl.formValues.IOPSMin" name="min_iops" placeholder="100">
<input type="number" class="form-control" ng-model="$ctrl.formValues.IOPSMin" name="min_iops" placeholder="100" />
</div>
</div>
<div class="form-group">
<label for="max_iops" class="col-sm-2 col-lg-1 control-label text-left">Max IOPS</label>
<div class="col-sm-10 col-lg-11">
<input type="number" class="form-control" ng-model="$ctrl.formValues.IOPSMax" name="max_iops" placeholder="2000">
<input type="number" class="form-control" ng-model="$ctrl.formValues.IOPSMax" name="max_iops" placeholder="2000" />
</div>
</div>
<!-- !IOPS -->
@ -156,13 +156,13 @@
<div class="form-group">
<label for="min_bandwidth" class="col-sm-2 col-lg-1 control-label text-left">Min Bandwidth</label>
<div class="col-sm-10 col-lg-11">
<input type="number" class="form-control" ng-model="$ctrl.formValues.BandwidthMin" name="min_bandwidth" placeholder="100">
<input type="number" class="form-control" ng-model="$ctrl.formValues.BandwidthMin" name="min_bandwidth" placeholder="100" />
</div>
</div>
<div class="form-group">
<label for="max_bandwidth" class="col-sm-2 col-lg-1 control-label text-left">Max Bandwidth</label>
<div class="col-sm-10 col-lg-11">
<input type="number" class="form-control" ng-model="$ctrl.formValues.BandwidthMax" name="max_bandwidth" placeholder="2000">
<input type="number" class="form-control" ng-model="$ctrl.formValues.BandwidthMax" name="max_bandwidth" placeholder="2000" />
</div>
</div>
<!-- !Bandwidth -->
@ -179,11 +179,11 @@
<div ng-repeat="label in $ctrl.formValues.Labels" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="label.name" placeholder="e.g. com.example.foo">
<input type="text" class="form-control" ng-model="label.name" placeholder="e.g. com.example.foo" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar">
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="$ctrl.removeLabel($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
@ -195,4 +195,4 @@
<!-- !labels -->
</form>
</rd-widget-body>
</rd-widget>
</rd-widget>

View file

@ -2,6 +2,6 @@ angular.module('portainer.docker').component('volumeStoridgeInfo', {
templateUrl: './volumeStoridgeInfo.html',
controller: 'VolumeStoridgeInfoController',
bindings: {
volume: '<'
}
volume: '<',
},
});

View file

@ -1,103 +1,105 @@
angular.module('portainer.docker')
.controller('VolumeStoridgeInfoController', ['$state', 'StoridgeVolumeService', 'Notifications',
function ($state, StoridgeVolumeService, Notifications) {
var ctrl = this;
angular.module('portainer.docker').controller('VolumeStoridgeInfoController', [
'$state',
'StoridgeVolumeService',
'Notifications',
function ($state, StoridgeVolumeService, Notifications) {
var ctrl = this;
this.state = {
updateInProgress: false,
isUpdating: false
};
this.addLabel = function() {
this.formValues.Labels.push({ name: '', value: ''});
};
this.removeLabel = function(index) {
this.formValues.Labels.splice(index, 1);
};
this.initLabels = function() {
var labels = this.volume.Labels;
if (labels) {
this.formValues.Labels = Object.keys(labels).map(function(key) {
return { name:key, value:labels[key] };
});
}
};
this.updateVolume = function() {
this.state.updateInProgress = true;
this.formValues = {
IOPSMin: this.volume.IOPSMin,
IOPSMax: this.volume.IOPSMax,
Node: this.volume.Node,
Capacity: this.volume.Capacity,
BandwidthMin: this.volume.BandwidthMin,
BandwidthMax: this.volume.BandwidthMax,
Labels: []
this.state = {
updateInProgress: false,
isUpdating: false,
};
this.initLabels();
};
this.cancelUpdate = function() {
this.state.updateInProgress = false;
this.formValues = {};
};
this.addLabel = function () {
this.formValues.Labels.push({ name: '', value: '' });
};
this.prepareLabels = function(volume) {
var labels = {};
this.formValues.Labels.forEach(function (label) {
if (label.name && label.value) {
labels[label.name] = label.value;
this.removeLabel = function (index) {
this.formValues.Labels.splice(index, 1);
};
this.initLabels = function () {
var labels = this.volume.Labels;
if (labels) {
this.formValues.Labels = Object.keys(labels).map(function (key) {
return { name: key, value: labels[key] };
});
}
});
volume.Labels = labels;
};
};
this.prepareVolume = function() {
var volume = angular.copy(this.formValues);
var data = this.volume;
if (volume.Node === data.Node || !volume.Node) {
delete volume.Node;
}
if (volume.Capacity === data.Capacity || !volume.Capacity) {
delete volume.Capacity;
}
if (volume.IOPSMin === data.IOPSMin || !volume.IOPSMin) {
delete volume.IOPSMin;
} else {
volume.IOPSMin = volume.IOPSMin.toString();
}
if (volume.IOPSMax === data.IOPSMax || !volume.IOPSMax) {
delete volume.IOPSMax;
} else {
volume.IOPSMax = volume.IOPSMax.toString();
}
if (volume.BandwidthMin === data.BandwidthMin || !volume.BandwidthMin) {
delete volume.BandwidthMin;
}
if (volume.BandwidthMax === data.BandwidthMax || !volume.BandwidthMax) {
delete volume.BandwidthMax;
}
this.prepareLabels(volume);
return volume;
};
this.updateVolume = function () {
this.state.updateInProgress = true;
this.formValues = {
IOPSMin: this.volume.IOPSMin,
IOPSMax: this.volume.IOPSMax,
Node: this.volume.Node,
Capacity: this.volume.Capacity,
BandwidthMin: this.volume.BandwidthMin,
BandwidthMax: this.volume.BandwidthMax,
Labels: [],
};
this.initLabels();
};
this.confirmUpdate = function() {
this.state.isUpdating = true;
this.cancelUpdate = function () {
this.state.updateInProgress = false;
this.formValues = {};
};
var volume = this.prepareVolume();
volume.Name = this.volume.Name;
StoridgeVolumeService.update(volume)
.then(function success() {
Notifications.success('Volume successfully updated');
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update volume');
ctrl.state.isUpdating = false;
});
};
this.prepareLabels = function (volume) {
var labels = {};
this.formValues.Labels.forEach(function (label) {
if (label.name && label.value) {
labels[label.name] = label.value;
}
});
volume.Labels = labels;
};
}]);
this.prepareVolume = function () {
var volume = angular.copy(this.formValues);
var data = this.volume;
if (volume.Node === data.Node || !volume.Node) {
delete volume.Node;
}
if (volume.Capacity === data.Capacity || !volume.Capacity) {
delete volume.Capacity;
}
if (volume.IOPSMin === data.IOPSMin || !volume.IOPSMin) {
delete volume.IOPSMin;
} else {
volume.IOPSMin = volume.IOPSMin.toString();
}
if (volume.IOPSMax === data.IOPSMax || !volume.IOPSMax) {
delete volume.IOPSMax;
} else {
volume.IOPSMax = volume.IOPSMax.toString();
}
if (volume.BandwidthMin === data.BandwidthMin || !volume.BandwidthMin) {
delete volume.BandwidthMin;
}
if (volume.BandwidthMax === data.BandwidthMax || !volume.BandwidthMax) {
delete volume.BandwidthMax;
}
this.prepareLabels(volume);
return volume;
};
this.confirmUpdate = function () {
this.state.isUpdating = true;
var volume = this.prepareVolume();
volume.Name = this.volume.Name;
StoridgeVolumeService.update(volume)
.then(function success() {
Notifications.success('Volume successfully updated');
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update volume');
ctrl.state.isUpdating = false;
});
};
},
]);

View file

@ -1,51 +1,53 @@
import _ from 'lodash-es';
angular.module('portainer.integrations.storidge')
.filter('drivestatusbadge', function () {
'use strict';
return function (text) {
var status = text ? _.toLower(text) : '';
if (status === 'available') {
return 'info';
} else if (status === 'faulty') {
return 'danger';
}
return 'success';
};
})
.filter('storidgeNodeStatusBadge', function () {
'use strict';
return function (text) {
var status = text ? _.toLower(text) : '';
if (status === 'cordoned' || status === 'maintenance') {
return 'orange-icon';
} else if (status === 'leaving' || status === 'failed') {
return 'red-icon'
}
return 'green-icon';
};
})
.filter('storidgeClusterConditionBadge', function () {
'use strict';
return function (text) {
var status = text ? _.toLower(text) : '';
if (status === 'alert') {
return 'red-icon';
} else if (status === 'warning') {
return 'orange-icon';
}
return 'green-icon';
};
}).filter('bytes', function() {
return function(bytes, precision) {
bytes = parseFloat(bytes);
if (isNaN(bytes) || !isFinite(bytes)) return '-';
if (!precision) precision = 1;
var units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'];
var number = Math.floor(Math.log(bytes) / Math.log(1024));
if (bytes === 0) {
return ('0 B');
}
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number];
}
});
angular
.module('portainer.integrations.storidge')
.filter('drivestatusbadge', function () {
'use strict';
return function (text) {
var status = text ? _.toLower(text) : '';
if (status === 'available') {
return 'info';
} else if (status === 'faulty') {
return 'danger';
}
return 'success';
};
})
.filter('storidgeNodeStatusBadge', function () {
'use strict';
return function (text) {
var status = text ? _.toLower(text) : '';
if (status === 'cordoned' || status === 'maintenance') {
return 'orange-icon';
} else if (status === 'leaving' || status === 'failed') {
return 'red-icon';
}
return 'green-icon';
};
})
.filter('storidgeClusterConditionBadge', function () {
'use strict';
return function (text) {
var status = text ? _.toLower(text) : '';
if (status === 'alert') {
return 'red-icon';
} else if (status === 'warning') {
return 'orange-icon';
}
return 'green-icon';
};
})
.filter('bytes', function () {
return function (bytes, precision) {
bytes = parseFloat(bytes);
if (isNaN(bytes) || !isFinite(bytes)) return '-';
if (!precision) precision = 1;
var units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'];
var number = Math.floor(Math.log(bytes) / Math.log(1024));
if (bytes === 0) {
return '0 B';
}
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number];
};
});

View file

@ -28,4 +28,4 @@ export function StoridgeNodeDetailedModel(name, properties) {
this.UsedCapacity = properties.usedCapacity;
this.UsedIOPS = properties.usedIOPS;
this.Vdisks = properties.vdisks;
}
}

View file

@ -88,25 +88,25 @@ export function StoridgeCreateProfileRequest(model) {
if (model.MinIOPS && model.MaxIOPS) {
this.iops = {
min: model.MinIOPS,
max: model.MaxIOPS
max: model.MaxIOPS,
};
}
if (model.MinBandwidth && model.MaxBandwidth) {
this.bandwidth = {
min: model.MinBandwidth,
max: model.MaxBandwidth
max: model.MaxBandwidth,
};
}
this.filesystem = {
type: model.Filesystem
type: model.Filesystem,
};
var service = {};
service.snapshot = {
enabled: model.SnapshotEnabled
enabled: model.SnapshotEnabled,
};
if (model.SnapshotEnabled) {
service.snapshot.interval = model.SnapshotInterval;
@ -114,7 +114,7 @@ export function StoridgeCreateProfileRequest(model) {
}
service.encryption = {
enabled: model.EncryptionEnabled
enabled: model.EncryptionEnabled,
};
this.service = service;
@ -122,7 +122,7 @@ export function StoridgeCreateProfileRequest(model) {
this.interface = {
driver: model.InterfaceDriver,
network: model.InterfaceNetwork,
conf: model.InterfaceConf
conf: model.InterfaceConf,
};
if (model.InterfaceType) {

View file

@ -34,7 +34,7 @@ export function StoridgeVolumeUpdateModel(data) {
iopsmin: data.IOPSMin,
iopsmax: data.IOPSMax,
bandwidthmin: data.BandwidthMin,
bandwidthmax: data.BandwidthMax
bandwidthmax: data.BandwidthMax,
};
this.labels = data.Labels;
}
}

View file

@ -1,45 +1,51 @@
angular.module('portainer.integrations.storidge')
.factory('Storidge', ['$resource', 'API_ENDPOINT_ENDPOINTS', 'EndpointProvider', function StoridgeFactory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider) {
'use strict';
return $resource(API_ENDPOINT_ENDPOINTS + '/:endpointId/storidge/:resource/:id/:action', {
endpointId: EndpointProvider.endpointID
angular.module('portainer.integrations.storidge').factory('Storidge', [
'$resource',
'API_ENDPOINT_ENDPOINTS',
'EndpointProvider',
function StoridgeFactory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider) {
'use strict';
return $resource(
API_ENDPOINT_ENDPOINTS + '/:endpointId/storidge/:resource/:id/:action',
{
endpointId: EndpointProvider.endpointID,
},
{
rebootCluster: { method: 'POST', params: { resource: 'clusters', action: 'reboot' } },
shutdownCluster: { method: 'POST', params: { resource: 'clusters', action: 'shutdown' } },
queryEvents: { method: 'GET', params: { resource: 'clusters', action: 'events' }, timeout: 4500, ignoreLoadingBar: true, isArray: true },
getVersion: { method: 'GET', params: { resource: 'clusters', action: 'version' } },
getInfo: { method: 'GET', params: { resource: 'clusters', action: 'info' }, timeout: 4500, ignoreLoadingBar: true },
queryNodes: { method: 'GET', params: { resource: 'nodes' } },
getNode: { method: 'GET', params: { resource: 'nodes', id: '@id' } },
addNode: { method: 'POST', params: { resource: 'nodes' } },
removeNode: { method: 'DELETE', params: { resource: 'nodes', id: '@id' } },
cordonNode: { method: 'POST', params: { resource: 'nodes', action: 'cordon', id: '@id' } },
uncordonNode: { method: 'POST', params: { resource: 'nodes', action: 'uncordon', id: '@id' } },
queryProfiles: { method: 'GET', params: { resource: 'profiles' } },
getProfile: { method: 'GET', params: { resource: 'profiles' } },
createProfile: { method: 'POST', params: { resource: 'profiles' } },
updateProfile: { method: 'PUT', params: { resource: 'profiles', id: '@name' } },
deleteProfile: { method: 'DELETE', params: { resource: 'profiles' } },
queryDrives: { method: 'GET', params: { resource: 'drives' } },
getDrive: { method: 'GET', params: { resource: 'drives', id: '@id' } },
addDrive: { method: 'POST', params: { resource: 'drives' } },
removeDrive: { method: 'DELETE', params: { resource: 'drives', id: '@id' } },
rescanDrives: { method: 'POST', params: { resource: 'drives', action: 'rescan' } },
queryVolumes: { method: 'GET', params: { resource: 'volumes' } },
createVolume: { method: 'POST', params: { resource: 'volumes' } },
getVolume: { method: 'GET', params: { resource: 'volumes', id: '@id' } },
updateVolume: { method: 'POST', params: { resource: 'volumes', id: '@name' } },
removeVolume: { method: 'DELETE', params: { resource: 'volumes', id: '@id' } },
querySnapshots: { method: 'GET', params: { resource: 'volumes', id: '@id', action: 'snapshots' } },
createSnapshot: { method: 'POST', params: { resource: 'volumes', id: '@id', action: 'snapshot' } },
getSnapshot: { method: 'GET', params: { resource: 'snapshots', id: '@id' } },
removeSnapshot: { method: 'DELETE', params: { resource: 'snapshots', id: '@id' } },
}
);
},
{
rebootCluster: { method: 'POST', params: { resource: 'clusters', action: 'reboot' } },
shutdownCluster: { method: 'POST', params: { resource: 'clusters', action: 'shutdown' } },
queryEvents: { method: 'GET', params: { resource: 'clusters', action: 'events' }, timeout: 4500, ignoreLoadingBar: true, isArray: true },
getVersion: { method: 'GET', params: { resource: 'clusters', action: 'version' } },
getInfo: { method: 'GET', params: { resource: 'clusters', action: 'info' }, timeout: 4500, ignoreLoadingBar: true },
queryNodes: { method: 'GET', params: { resource: 'nodes' } },
getNode: { method: 'GET', params: { resource: 'nodes', id: '@id' } },
addNode: { method: 'POST', params: { resource: 'nodes' } },
removeNode: { method: 'DELETE', params: { resource: 'nodes', id: '@id' } },
cordonNode: { method: 'POST', params : { resource: 'nodes', action:'cordon', id: '@id' } },
uncordonNode: { method: 'POST', params : { resource: 'nodes', action: 'uncordon', id:'@id' } },
queryProfiles: { method: 'GET', params: { resource: 'profiles' } },
getProfile: { method: 'GET', params: { resource: 'profiles' } },
createProfile: { method: 'POST', params: { resource: 'profiles' } },
updateProfile: { method: 'PUT', params: { resource: 'profiles', id: '@name' } },
deleteProfile: { method: 'DELETE', params: { resource: 'profiles' } },
queryDrives: { method: 'GET', params: { resource: 'drives' } },
getDrive: { method: 'GET', params: { resource: 'drives', id: '@id' } },
addDrive: { method: 'POST', params: { resource: 'drives' } },
removeDrive: { method: 'DELETE', params: { resource: 'drives', id: '@id' } },
rescanDrives: { method: 'POST', params: { resource: 'drives', action: 'rescan' } },
queryVolumes: { method: 'GET', params: { resource: 'volumes' } },
createVolume: { method: 'POST', params: { resource: 'volumes' } },
getVolume: { method: 'GET', params: { resource: 'volumes', id: '@id' } },
updateVolume: { method: 'POST', params: { resource: 'volumes', id: '@name' } },
removeVolume: { method: 'DELETE', params: { resource: 'volumes' , id: '@id' } },
querySnapshots: { method: 'GET', params: { resource: 'volumes', id: '@id', action: 'snapshots' } },
createSnapshot: { method: 'POST', params: { resource: 'volumes', id: '@id', action: 'snapshot' } },
getSnapshot: { method: 'GET', params: { resource: 'snapshots', id: '@id' } },
removeSnapshot: { method: 'DELETE', params: { resource: 'snapshots', id: '@id'} }
});
}]);
]);

View file

@ -1,192 +1,190 @@
import Chart from 'chart.js';
import filesize from 'filesize';
angular.module('portainer.integrations.storidge')
.factory('StoridgeChartService', [function StoridgeChartService() {
'use strict';
angular.module('portainer.integrations.storidge').factory('StoridgeChartService', [
function StoridgeChartService() {
'use strict';
// Max. number of items to display on a chart
var CHART_LIMIT = 600;
// Max. number of items to display on a chart
var CHART_LIMIT = 600;
var service = {};
var service = {};
service.CreateCapacityChart = function(context) {
return new Chart(context, {
type: 'doughnut',
data: {
datasets: [
{
data: [],
backgroundColor: [
'rgba(171, 213, 255, 0.7)',
'rgba(229, 57, 53, 0.7)'
]
}
],
labels: []
},
options: {
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var label = data.labels[tooltipItem.index];
var value = dataset.data[tooltipItem.index];
return label + ': ' + filesize(value, {base: 10, round: 1});
}
}
},
animation: {
duration: 0
},
responsiveAnimationDuration: 0,
responsive: true,
hover: {
animationDuration: 0
}
}
});
};
service.CreateIOPSChart = function(context) {
return new Chart(context, {
type: 'line',
data: {
labels: [],
datasets: [
{
label: 'IOPS',
data: [],
fill: true,
backgroundColor: 'rgba(151,187,205,0.4)',
borderColor: 'rgba(151,187,205,0.6)',
pointBackgroundColor: 'rgba(151,187,205,1)',
pointBorderColor: 'rgba(151,187,205,1)',
pointRadius: 2,
borderWidth: 2
}
]
},
options: {
animation: {
duration: 0
},
responsiveAnimationDuration: 0,
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
position: 'nearest'
},
hover: {
animationDuration: 0
},
scales: {
yAxes: [
service.CreateCapacityChart = function (context) {
return new Chart(context, {
type: 'doughnut',
data: {
datasets: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
});
};
data: [],
backgroundColor: ['rgba(171, 213, 255, 0.7)', 'rgba(229, 57, 53, 0.7)'],
},
],
labels: [],
},
options: {
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var label = data.labels[tooltipItem.index];
var value = dataset.data[tooltipItem.index];
return label + ': ' + filesize(value, { base: 10, round: 1 });
},
},
},
animation: {
duration: 0,
},
responsiveAnimationDuration: 0,
responsive: true,
hover: {
animationDuration: 0,
},
},
});
};
service.CreateBandwidthChart = function(context) {
return new Chart(context, {
type: 'line',
data: {
labels: [],
datasets: [
{
label: 'Bandwidth',
data: [],
fill: true,
backgroundColor: 'rgba(151,187,205,0.4)',
borderColor: 'rgba(151,187,205,0.6)',
pointBackgroundColor: 'rgba(151,187,205,1)',
pointBorderColor: 'rgba(151,187,205,1)',
pointRadius: 2,
borderWidth: 2
}
]
},
options: {
animation: {
duration: 0
},
responsiveAnimationDuration: 0,
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
position: 'nearest',
callbacks: {
label: function(tooltipItem, data) {
var datasetLabel = data.datasets[tooltipItem.datasetIndex].label;
return bytePerSecBasedTooltipLabel(datasetLabel, tooltipItem.yLabel);
}
}
},
hover: {
animationDuration: 0
},
scales: {
yAxes: [
service.CreateIOPSChart = function (context) {
return new Chart(context, {
type: 'line',
data: {
labels: [],
datasets: [
{
ticks: {
beginAtZero: true,
callback: bytePerSecBasedAxisLabel
}
}
]
}
}
});
};
label: 'IOPS',
data: [],
fill: true,
backgroundColor: 'rgba(151,187,205,0.4)',
borderColor: 'rgba(151,187,205,0.6)',
pointBackgroundColor: 'rgba(151,187,205,1)',
pointBorderColor: 'rgba(151,187,205,1)',
pointRadius: 2,
borderWidth: 2,
},
],
},
options: {
animation: {
duration: 0,
},
responsiveAnimationDuration: 0,
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
position: 'nearest',
},
hover: {
animationDuration: 0,
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
},
});
};
service.UpdateChart = function(label, value, chart) {
chart.data.labels.push(label);
chart.data.datasets[0].data.push(value);
service.CreateBandwidthChart = function (context) {
return new Chart(context, {
type: 'line',
data: {
labels: [],
datasets: [
{
label: 'Bandwidth',
data: [],
fill: true,
backgroundColor: 'rgba(151,187,205,0.4)',
borderColor: 'rgba(151,187,205,0.6)',
pointBackgroundColor: 'rgba(151,187,205,1)',
pointBorderColor: 'rgba(151,187,205,1)',
pointRadius: 2,
borderWidth: 2,
},
],
},
options: {
animation: {
duration: 0,
},
responsiveAnimationDuration: 0,
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
position: 'nearest',
callbacks: {
label: function (tooltipItem, data) {
var datasetLabel = data.datasets[tooltipItem.datasetIndex].label;
return bytePerSecBasedTooltipLabel(datasetLabel, tooltipItem.yLabel);
},
},
},
hover: {
animationDuration: 0,
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
callback: bytePerSecBasedAxisLabel,
},
},
],
},
},
});
};
if (chart.data.datasets[0].data.length > CHART_LIMIT) {
chart.data.labels.pop();
chart.data.datasets[0].data.pop();
}
chart.update(0);
};
service.UpdatePieChart = function(label, value, chart) {
var idx = chart.data.labels.indexOf(label);
if (idx > -1) {
chart.data.datasets[0].data[idx] = value;
} else {
service.UpdateChart = function (label, value, chart) {
chart.data.labels.push(label);
chart.data.datasets[0].data.push(value);
if (chart.data.datasets[0].data.length > CHART_LIMIT) {
chart.data.labels.pop();
chart.data.datasets[0].data.pop();
}
chart.update(0);
};
service.UpdatePieChart = function (label, value, chart) {
var idx = chart.data.labels.indexOf(label);
if (idx > -1) {
chart.data.datasets[0].data[idx] = value;
} else {
chart.data.labels.push(label);
chart.data.datasets[0].data.push(value);
}
chart.update(0);
};
function bytePerSecBasedTooltipLabel(label, value) {
var processedValue = 0;
if (value > 5) {
processedValue = filesize(value, { base: 10, round: 1 });
} else {
processedValue = value.toFixed(1) + 'B';
}
return label + ': ' + processedValue + '/s';
}
chart.update(0);
};
function bytePerSecBasedTooltipLabel(label, value) {
var processedValue = 0;
if (value > 5) {
processedValue = filesize(value, {base: 10, round: 1});
} else {
processedValue = value.toFixed(1) + 'B';
function bytePerSecBasedAxisLabel(value) {
if (value > 5) {
return filesize(value, { base: 10, round: 1 });
}
return value.toFixed(1) + 'B/s';
}
return label + ': ' + processedValue + '/s';
}
function bytePerSecBasedAxisLabel(value) {
if (value > 5) {
return filesize(value, {base: 10, round: 1});
}
return value.toFixed(1) + 'B/s';
}
return service;
}]);
return service;
},
]);

View file

@ -1,65 +1,68 @@
import { StoridgeInfoModel } from '../models/info';
import { StoridgeEventModel } from '../models/events';
angular.module('portainer.integrations.storidge')
.factory('StoridgeClusterService', ['$q', 'Storidge', function StoridgeClusterServiceFactory($q, Storidge) {
'use strict';
var service = {};
angular.module('portainer.integrations.storidge').factory('StoridgeClusterService', [
'$q',
'Storidge',
function StoridgeClusterServiceFactory($q, Storidge) {
'use strict';
var service = {};
service.reboot = function() {
return Storidge.rebootCluster().$promise;
};
service.reboot = function () {
return Storidge.rebootCluster().$promise;
};
service.shutdown = function() {
return Storidge.shutdownCluster().$promise;
};
service.shutdown = function () {
return Storidge.shutdownCluster().$promise;
};
service.info = function() {
var deferred = $q.defer();
service.info = function () {
var deferred = $q.defer();
Storidge.getInfo().$promise
.then(function success(data) {
var info = new StoridgeInfoModel(data);
deferred.resolve(info);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge information', err: err });
});
Storidge.getInfo()
.$promise.then(function success(data) {
var info = new StoridgeInfoModel(data);
deferred.resolve(info);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge information', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
service.version = function() {
var deferred = $q.defer();
service.version = function () {
var deferred = $q.defer();
Storidge.getVersion().$promise
.then(function success(data) {
var version = data.version;
deferred.resolve(version);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge version', err: err });
});
Storidge.getVersion()
.$promise.then(function success(data) {
var version = data.version;
deferred.resolve(version);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge version', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
service.events = function() {
var deferred = $q.defer();
service.events = function () {
var deferred = $q.defer();
Storidge.queryEvents().$promise
.then(function success(data) {
var events = data.map(function(item) {
return new StoridgeEventModel(item);
});
deferred.resolve(events);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge events', err: err });
});
Storidge.queryEvents()
.$promise.then(function success(data) {
var events = data.map(function (item) {
return new StoridgeEventModel(item);
});
deferred.resolve(events);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge events', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
return service;
}]);
return service;
},
]);

View file

@ -1,79 +1,81 @@
import { StoridgeDriveModel } from '../models/drive';
angular.module('portainer.integrations.storidge')
.factory('StoridgeDriveService', ['$q', 'Storidge', function StoridgeDriveServiceFactory($q, Storidge) {
'use strict';
var service = {};
angular.module('portainer.integrations.storidge').factory('StoridgeDriveService', [
'$q',
'Storidge',
function StoridgeDriveServiceFactory($q, Storidge) {
'use strict';
var service = {};
service.drives = function () {
var deferred = $q.defer();
service.drives = function () {
var deferred = $q.defer();
Storidge.queryDrives().$promise
.then(function success(data) {
var driveData = data.drives;
var drives = driveData.map(function (drive) {
return new StoridgeDriveModel(drive);
});
Storidge.queryDrives()
.$promise.then(function success(data) {
var driveData = data.drives;
var drives = driveData.map(function (drive) {
return new StoridgeDriveModel(drive);
});
deferred.resolve(drives);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge drives', err: err });
});
deferred.resolve(drives);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge drives', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
service.drive = function (id) {
var deferred = $q.defer();
Storidge.getDrive({ id: id }).$promise
.then(function success(data) {
var drive = new StoridgeDriveModel(data);
Storidge.getNode({ id: data.nodeid }).$promise
.then(function (data) {
drive.Node = data.name;
deferred.resolve(drive);
});
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge drive', err: err });
});
service.drive = function (id) {
var deferred = $q.defer();
return deferred.promise;
};
Storidge.getDrive({ id: id })
.$promise.then(function success(data) {
var drive = new StoridgeDriveModel(data);
Storidge.getNode({ id: data.nodeid }).$promise.then(function (data) {
drive.Node = data.name;
deferred.resolve(drive);
});
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge drive', err: err });
});
service.add = function (device, node) {
var deferred = $q.defer();
return deferred.promise;
};
Storidge.addDrive({ device: device, node: node }).$promise
.then(function success() {
deferred.resolve();
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to add Storidge drive', err: err });
});
service.add = function (device, node) {
var deferred = $q.defer();
return deferred.promise;
};
Storidge.addDrive({ device: device, node: node })
.$promise.then(function success() {
deferred.resolve();
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to add Storidge drive', err: err });
});
service.remove = function (id) {
var deferred = $q.defer();
return deferred.promise;
};
Storidge.removeDrive({ id: id }).$promise
.then(function success() {
deferred.resolve();
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to remove Storidge drive', err: err });
});
service.remove = function (id) {
var deferred = $q.defer();
return deferred.promise;
};
Storidge.removeDrive({ id: id })
.$promise.then(function success() {
deferred.resolve();
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to remove Storidge drive', err: err });
});
service.rescan = function () {
return Storidge.rescanDrives().$promise;
};
return deferred.promise;
};
return service;
}]);
service.rescan = function () {
return Storidge.rescanDrives().$promise;
};
return service;
},
]);

View file

@ -1,63 +1,66 @@
import { StoridgeNodeModel, StoridgeNodeDetailedModel } from '../models/node';
angular.module('portainer.integrations.storidge')
.factory('StoridgeNodeService', ['$q', 'Storidge', function StoridgeNodeServiceFactory($q, Storidge) {
'use strict';
var service = {};
angular.module('portainer.integrations.storidge').factory('StoridgeNodeService', [
'$q',
'Storidge',
function StoridgeNodeServiceFactory($q, Storidge) {
'use strict';
var service = {};
service.nodes = function() {
var deferred = $q.defer();
service.nodes = function () {
var deferred = $q.defer();
Storidge.queryNodes().$promise
.then(function success(data) {
var nodeData = data.nodes;
var nodes = [];
Storidge.queryNodes()
.$promise.then(function success(data) {
var nodeData = data.nodes;
var nodes = [];
for (var key in nodeData) {
if (nodeData.hasOwnProperty(key)) {
nodes.push(new StoridgeNodeModel(key, nodeData[key]));
}
}
for (var key in nodeData) {
if (nodeData.hasOwnProperty(key)) {
nodes.push(new StoridgeNodeModel(key, nodeData[key]));
}
}
deferred.resolve(nodes);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge nodes', err: err });
});
deferred.resolve(nodes);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge nodes', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
service.node = function (id) {
var deferred = $q.defer();
service.node = function (id) {
var deferred = $q.defer();
Storidge.getNode({id:id}).$promise
.then(function success(data) {
var node = new StoridgeNodeDetailedModel(data.name, data.properties);
deferred.resolve(node);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge node', err: err });
});
Storidge.getNode({ id: id })
.$promise.then(function success(data) {
var node = new StoridgeNodeDetailedModel(data.name, data.properties);
deferred.resolve(node);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge node', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
service.add = function () {
return Storidge.addNode().$promise;
};
service.add = function () {
return Storidge.addNode().$promise;
};
service.cordon = function (id) {
return Storidge.cordonNode({id: id}).$promise;
};
service.cordon = function (id) {
return Storidge.cordonNode({ id: id }).$promise;
};
service.uncordon = function (id) {
return Storidge.uncordonNode({id: id}).$promise;
};
service.uncordon = function (id) {
return Storidge.uncordonNode({ id: id }).$promise;
};
service.remove = function (id) {
return Storidge.removeNode({id:id}).$promise;
};
service.remove = function (id) {
return Storidge.removeNode({ id: id }).$promise;
};
return service;
}]);
return service;
},
]);

View file

@ -1,59 +1,58 @@
import {
StoridgeCreateProfileRequest,
StoridgeProfileListModel,
StoridgeProfileModel
} from '../models/profile';
import { StoridgeCreateProfileRequest, StoridgeProfileListModel, StoridgeProfileModel } from '../models/profile';
angular.module('portainer.integrations.storidge')
.factory('StoridgeProfileService', ['$q', 'Storidge', function StoridgeProfileServiceFactory($q, Storidge) {
'use strict';
var service = {};
angular.module('portainer.integrations.storidge').factory('StoridgeProfileService', [
'$q',
'Storidge',
function StoridgeProfileServiceFactory($q, Storidge) {
'use strict';
var service = {};
service.create = function(model) {
var payload = new StoridgeCreateProfileRequest(model);
return Storidge.createProfile(payload).$promise;
};
service.create = function (model) {
var payload = new StoridgeCreateProfileRequest(model);
return Storidge.createProfile(payload).$promise;
};
service.update = function(model) {
var payload = new StoridgeCreateProfileRequest(model);
return Storidge.updateProfile(payload).$promise;
};
service.update = function (model) {
var payload = new StoridgeCreateProfileRequest(model);
return Storidge.updateProfile(payload).$promise;
};
service.delete = function(profileName) {
return Storidge.deleteProfile({ id: profileName }).$promise;
};
service.delete = function (profileName) {
return Storidge.deleteProfile({ id: profileName }).$promise;
};
service.profile = function(profileName) {
var deferred = $q.defer();
service.profile = function (profileName) {
var deferred = $q.defer();
Storidge.getProfile({ id: profileName }).$promise
.then(function success(data) {
var profile = new StoridgeProfileModel(profileName, data);
deferred.resolve(profile);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge profile details', err: err });
});
Storidge.getProfile({ id: profileName })
.$promise.then(function success(data) {
var profile = new StoridgeProfileModel(profileName, data);
deferred.resolve(profile);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge profile details', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
service.profiles = function() {
var deferred = $q.defer();
service.profiles = function () {
var deferred = $q.defer();
Storidge.queryProfiles().$promise
.then(function success(data) {
var profiles = data.profiles.map(function (item) {
return new StoridgeProfileListModel(item);
});
deferred.resolve(profiles);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge profiles', err: err });
});
Storidge.queryProfiles()
.$promise.then(function success(data) {
var profiles = data.profiles.map(function (item) {
return new StoridgeProfileListModel(item);
});
deferred.resolve(profiles);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge profiles', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
return service;
}]);
return service;
},
]);

View file

@ -1,80 +1,83 @@
import { StoridgeSnapshotModel } from '../models/snapshot'
import { StoridgeSnapshotModel } from '../models/snapshot';
angular.module('portainer.integrations.storidge')
.factory('StoridgeSnapshotService', ['$q', 'Storidge', function StoridgeSnapshotServiceFactory($q, Storidge) {
'use strict';
var service = {};
angular.module('portainer.integrations.storidge').factory('StoridgeSnapshotService', [
'$q',
'Storidge',
function StoridgeSnapshotServiceFactory($q, Storidge) {
'use strict';
var service = {};
service.snapshots = snapshots;
service.snapshot = snapshot;
service.create = create;
service.remove = remove;
service.snapshots = snapshots;
service.snapshot = snapshot;
service.create = create;
service.remove = remove;
function snapshots(volumeId) {
var deferred = $q.defer();
function snapshots(volumeId) {
var deferred = $q.defer();
Storidge.querySnapshots({id: volumeId}).$promise
.then(function success(data) {
var snapshotsData = data.snapshots;
let snapshotsArray = [];
for (const key in snapshotsData) {
if (snapshotsData.hasOwnProperty(key)) {
snapshotsArray.push(snapshotsData[key]);
}
}
var snapshots = snapshotsArray.map(function (snapshot) {
return new StoridgeSnapshotModel(snapshot);
});
deferred.resolve(snapshots);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge snapshots', err: err });
});
Storidge.querySnapshots({ id: volumeId })
.$promise.then(function success(data) {
var snapshotsData = data.snapshots;
let snapshotsArray = [];
for (const key in snapshotsData) {
if (snapshotsData.hasOwnProperty(key)) {
snapshotsArray.push(snapshotsData[key]);
}
}
var snapshots = snapshotsArray.map(function (snapshot) {
return new StoridgeSnapshotModel(snapshot);
});
deferred.resolve(snapshots);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge snapshots', err: err });
});
return deferred.promise;
}
return deferred.promise;
}
function snapshot(id) {
var deferred = $q.defer();
function snapshot(id) {
var deferred = $q.defer();
Storidge.getSnapshot({id:id}).$promise
.then(function success(data) {
var snapshot = new StoridgeSnapshotModel(data.snapshot);
deferred.resolve(snapshot);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge snapshot', err: err });
});
Storidge.getSnapshot({ id: id })
.$promise.then(function success(data) {
var snapshot = new StoridgeSnapshotModel(data.snapshot);
deferred.resolve(snapshot);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge snapshot', err: err });
});
return deferred.promise;
}
function create(volumeId, description) {
var deferred = $q.defer();
Storidge.createSnapshot({id: volumeId, opts: {description: description}}).$promise
.then(function success(data) {
deferred.resolve(data);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to create Storidge volume snapshot', err: err });
});
return deferred.promise;
}
return deferred.promise;
}
function create(volumeId, description) {
var deferred = $q.defer();
Storidge.createSnapshot({ id: volumeId, opts: { description: description } })
.$promise.then(function success(data) {
deferred.resolve(data);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to create Storidge volume snapshot', err: err });
});
function remove(id) {
var deferred = $q.defer();
return deferred.promise;
}
Storidge.removeSnapshot({ id: id }).$promise
.then(function success() {
deferred.resolve();
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to remove Storidge volume snapshot', err: err });
});
function remove(id) {
var deferred = $q.defer();
return deferred.promise;
}
Storidge.removeSnapshot({ id: id })
.$promise.then(function success() {
deferred.resolve();
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to remove Storidge volume snapshot', err: err });
});
return service;
}]);
return deferred.promise;
}
return service;
},
]);

View file

@ -1,38 +1,41 @@
import { StoridgeVolumeModel, StoridgeVolumeUpdateModel } from '../models/volume';
angular.module('portainer.integrations.storidge')
.factory('StoridgeVolumeService', ['$q', 'Storidge', function StoridgeVolumeServiceFactory($q, Storidge) {
'use strict';
var service = {};
angular.module('portainer.integrations.storidge').factory('StoridgeVolumeService', [
'$q',
'Storidge',
function StoridgeVolumeServiceFactory($q, Storidge) {
'use strict';
var service = {};
service.volume = function(id) {
var deferred = $q.defer();
service.volume = function (id) {
var deferred = $q.defer();
Storidge.getVolume({id:id}).$promise
.then(function success(data) {
var volume = new StoridgeVolumeModel(data);
deferred.resolve(volume);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge volume', err: err });
});
Storidge.getVolume({ id: id })
.$promise.then(function success(data) {
var volume = new StoridgeVolumeModel(data);
deferred.resolve(volume);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve Storidge volume', err: err });
});
return deferred.promise;
};
service.update = function(data) {
var deferred = $q.defer();
var volume = new StoridgeVolumeUpdateModel(data);
Storidge.updateVolume(volume).$promise
.then(function success(data) {
deferred.resolve(data);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to update Storidge volume', err: err });
});
return deferred.promise;
};
return deferred.promise;
};
service.update = function (data) {
var deferred = $q.defer();
var volume = new StoridgeVolumeUpdateModel(data);
Storidge.updateVolume(volume)
.$promise.then(function success(data) {
deferred.resolve(data);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to update Storidge volume', err: err });
});
return service;
}]);
return deferred.promise;
};
return service;
},
]);

View file

@ -22,7 +22,8 @@
</tr>
<tr>
<td>Condition</td>
<td><i class="fa fa-heartbeat space-right {{ clusterInfo.Condition | storidgeClusterConditionBadge }}"></i>
<td
><i class="fa fa-heartbeat space-right {{ clusterInfo.Condition | storidgeClusterConditionBadge }}"></i>
{{ clusterInfo.Condition }}
</td>
</tr>
@ -56,10 +57,6 @@
<div class="row">
<div class="col-sm-12">
<storidge-nodes-datatable
title-text="Storage nodes" title-icon="fa-object-group"
dataset="clusterNodes" table-key="storidge_nodes"
order-by="Name"
></storidge-nodes-datatable>
<storidge-nodes-datatable title-text="Storage nodes" title-icon="fa-object-group" dataset="clusterNodes" table-key="storidge_nodes" order-by="Name"></storidge-nodes-datatable>
</div>
</div>

View file

@ -1,81 +1,89 @@
angular.module('portainer.integrations.storidge')
.controller('StoridgeClusterController', ['$q', '$scope', '$state', 'Notifications', 'StoridgeClusterService', 'StoridgeNodeService', 'ModalService',
function ($q, $scope, $state, Notifications, StoridgeClusterService, StoridgeNodeService, ModalService) {
angular.module('portainer.integrations.storidge').controller('StoridgeClusterController', [
'$q',
'$scope',
'$state',
'Notifications',
'StoridgeClusterService',
'StoridgeNodeService',
'ModalService',
function ($q, $scope, $state, Notifications, StoridgeClusterService, StoridgeNodeService, ModalService) {
$scope.state = {
shutdownInProgress: false,
rebootInProgress: false,
};
$scope.state = {
shutdownInProgress: false,
rebootInProgress: false
};
$scope.rebootCluster = function () {
ModalService.confirm({
title: 'Are you sure?',
message: 'All the nodes in the cluster will reboot during the process. Do you want to reboot the Storidge cluster?',
buttons: {
confirm: {
label: 'Reboot',
className: 'btn-danger',
},
},
callback: function onConfirm(confirmed) {
if (!confirmed) {
return;
}
rebootCluster();
},
});
};
$scope.rebootCluster = function() {
ModalService.confirm({
title: 'Are you sure?',
message: 'All the nodes in the cluster will reboot during the process. Do you want to reboot the Storidge cluster?',
buttons: {
confirm: {
label: 'Reboot',
className: 'btn-danger'
}
},
callback: function onConfirm(confirmed) {
if(!confirmed) { return; }
rebootCluster();
}
});
};
function rebootCluster() {
$scope.state.rebootInProgress = true;
StoridgeClusterService.reboot().finally(function final() {
$scope.state.rebootInProgress = false;
Notifications.success('Cluster successfully rebooted');
$state.reload();
});
}
function rebootCluster() {
$scope.state.rebootInProgress = true;
StoridgeClusterService.reboot()
.finally(function final() {
$scope.state.rebootInProgress = false;
Notifications.success('Cluster successfully rebooted');
$state.reload();
});
}
$scope.shutdownCluster = function () {
ModalService.confirm({
title: 'Are you sure?',
message: 'All the nodes in the cluster will shutdown. Do you want to shutdown the Storidge cluster?',
buttons: {
confirm: {
label: 'Shutdown',
className: 'btn-danger',
},
},
callback: function onConfirm(confirmed) {
if (!confirmed) {
return;
}
shutdownCluster();
},
});
};
$scope.shutdownCluster = function() {
ModalService.confirm({
title: 'Are you sure?',
message: 'All the nodes in the cluster will shutdown. Do you want to shutdown the Storidge cluster?',
buttons: {
confirm: {
label: 'Shutdown',
className: 'btn-danger'
}
},
callback: function onConfirm(confirmed) {
if(!confirmed) { return; }
shutdownCluster();
}
});
};
function shutdownCluster() {
$scope.state.shutdownInProgress = true;
StoridgeClusterService.shutdown().finally(function final() {
$scope.state.shutdownInProgress = false;
Notifications.success('Cluster successfully shutdown');
$state.go('docker.dashboard');
});
}
function shutdownCluster() {
$scope.state.shutdownInProgress = true;
StoridgeClusterService.shutdown()
.finally(function final() {
$scope.state.shutdownInProgress = false;
Notifications.success('Cluster successfully shutdown');
$state.go('docker.dashboard');
});
}
function initView() {
$q.all({
info: StoridgeClusterService.info(),
version: StoridgeClusterService.version(),
nodes: StoridgeNodeService.nodes(),
})
.then(function success(data) {
$scope.clusterInfo = data.info;
$scope.clusterVersion = data.version;
$scope.clusterNodes = data.nodes;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve cluster information');
});
}
function initView() {
$q.all({
info: StoridgeClusterService.info(),
version: StoridgeClusterService.version(),
nodes: StoridgeNodeService.nodes()
})
.then(function success(data) {
$scope.clusterInfo = data.info;
$scope.clusterVersion = data.version;
$scope.clusterNodes = data.nodes;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve cluster information');
});
}
initView();
}]);
initView();
},
]);

View file

@ -4,21 +4,21 @@
<i class="fa fa-sync" aria-hidden="true"></i>
</a>
</rd-header-title>
<rd-header-content>
<a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.drives">Drives</a>
</rd-header-content>
<rd-header-content> <a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.drives">Drives</a> </rd-header-content>
</rd-header>
<div class="row">
<div class="col-sm-12">
<storidge-drives-datatable
title-text="Drives" title-icon="fa-hdd"
dataset="drives" table-key="storidge_drives"
order-by="Id"
rescan-action="rescanAction"
add-action="addAction"
action-in-progress="state.actionInProgress"
addition-in-progress="state.additionInProgress"
title-text="Drives"
title-icon="fa-hdd"
dataset="drives"
table-key="storidge_drives"
order-by="Id"
rescan-action="rescanAction"
add-action="addAction"
action-in-progress="state.actionInProgress"
addition-in-progress="state.additionInProgress"
></storidge-drives-datatable>
</div>
</div>

View file

@ -1,48 +1,51 @@
angular.module('portainer.integrations.storidge')
.controller('StoridgeDrivesController', ['$scope', '$state', 'Notifications', 'StoridgeDriveService',
function ($scope, $state, Notifications, StoridgeDriveService) {
angular.module('portainer.integrations.storidge').controller('StoridgeDrivesController', [
'$scope',
'$state',
'Notifications',
'StoridgeDriveService',
function ($scope, $state, Notifications, StoridgeDriveService) {
$scope.state = {
additionInProgress: [],
actionInProgress: false,
};
$scope.state = {
additionInProgress: [],
actionInProgress: false
};
$scope.addAction = function (drive, idx) {
$scope.state.additionInProgress[idx] = true;
$scope.state.actionInProgress = true;
StoridgeDriveService.add(drive.Device, drive.Node)
.then(function success() {
Notifications.success('Drive ' + drive.Device + ' successfully added on node ' + drive.Node);
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to add drive');
})
.finally(function final() {
$scope.state.additionInProgress[idx] = false;
$scope.state.actionInProgress = false;
});
};
$scope.addAction = function (drive, idx) {
$scope.state.additionInProgress[idx] = true;
$scope.state.actionInProgress = true;
StoridgeDriveService.add(drive.Device, drive.Node)
.then(function success() {
Notifications.success('Drive ' + drive.Device + ' successfully added on node ' + drive.Node);
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to add drive');
})
.finally(function final() {
$scope.state.additionInProgress[idx] = false;
$scope.state.actionInProgress = false;
});
};
$scope.rescanAction = function () {
StoridgeDriveService.rescan()
.then(function sucess() {
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to scan drives');
});
};
$scope.rescanAction = function () {
StoridgeDriveService.rescan()
.then(function sucess() {
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to scan drives');
});
};
function initView() {
StoridgeDriveService.drives()
.then(function success(data) {
$scope.drives = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve drives');
});
}
function initView() {
StoridgeDriveService.drives()
.then(function success(data) {
$scope.drives = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve drives');
});
}
initView();
}]);
initView();
},
]);

View file

@ -4,7 +4,7 @@
<a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.drives">Drives</a> &gt; <a ui-sref="storidge.drives.drive({id: drive.Id})">{{ drive.Id }}</a>
</rd-header-content>
</rd-header>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
@ -45,7 +45,7 @@
<tr>
<td>Status</td>
<td>
<span class="label label-{{ drive.Status|drivestatusbadge }}">{{ drive.Status|capitalize }}</span>
<span class="label label-{{ drive.Status | drivestatusbadge }}">{{ drive.Status | capitalize }}</span>
</td>
</tr>
</tbody>
@ -53,4 +53,4 @@
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>

View file

@ -1,49 +1,55 @@
angular.module('portainer.integrations.storidge')
.controller('StoridgeDriveController', ['$scope', '$state', '$transition$', 'Notifications', 'ModalService', 'StoridgeDriveService',
function ($scope, $state, $transition$, Notifications, ModalService, StoridgeDriveService) {
angular.module('portainer.integrations.storidge').controller('StoridgeDriveController', [
'$scope',
'$state',
'$transition$',
'Notifications',
'ModalService',
'StoridgeDriveService',
function ($scope, $state, $transition$, Notifications, ModalService, StoridgeDriveService) {
$scope.actionInProgress = false;
$scope.actionInProgress = false;
$scope.removeDrive = function () {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to remove this drive from the storage pool?',
buttons: {
confirm: {
label: 'Remove',
className: 'btn-danger',
},
},
callback: function onConfirm(confirmed) {
if (!confirmed) {
return;
}
$scope.actionInProgress = true;
StoridgeDriveService.remove($scope.drive.Id)
.then(function () {
Notifications.success('Success', 'Drive removed from storage pool');
$state.go('storidge.drives', {}, { reload: true });
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove drive from storage pool');
})
.finally(function final() {
$scope.actionInProgress = false;
});
},
});
};
$scope.removeDrive = function () {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to remove this drive from the storage pool?',
buttons: {
confirm: {
label: 'Remove',
className: 'btn-danger'
}
},
callback: function onConfirm(confirmed) {
if(!confirmed) { return; }
$scope.actionInProgress = true;
StoridgeDriveService.remove($scope.drive.Id)
.then(function () {
Notifications.success('Success', 'Drive removed from storage pool');
$state.go('storidge.drives', {}, { reload:true });
function initView() {
$scope.id = $transition$.params().id;
StoridgeDriveService.drive($scope.id)
.then(function success(data) {
$scope.drive = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove drive from storage pool');
})
.finally(function final() {
$scope.actionInProgress = false;
Notifications.error('Failure', err, 'Unable to retrieve drive details');
});
}
});
};
}
function initView() {
$scope.id = $transition$.params().id;
StoridgeDriveService.drive($scope.id)
.then(function success(data) {
$scope.drive = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve drive details');
});
}
initView();
}]);
initView();
},
]);

View file

@ -4,9 +4,7 @@
<i class="fa fa-sync" aria-hidden="true"></i>
</a>
</rd-header-title>
<rd-header-content>
<a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.monitor">Cluster monitoring</a>
</rd-header-content>
<rd-header-content> <a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.monitor">Cluster monitoring</a> </rd-header-content>
</rd-header>
<div class="row">
@ -28,7 +26,7 @@
<td>Provisioned capacity</td>
<td>
{{ info.ProvisionedCapacity | humansize }}
<span ng-if="+(info.ProvisionedCapacity) >= +(info.TotalCapacity)">
<span ng-if="+info.ProvisionedCapacity >= +info.TotalCapacity">
<i class="fa fa-exclamation-triangle red-icon" aria-hidden="true" style="margin-left: 2px;"></i>
</span>
</td>
@ -61,7 +59,7 @@
<td>Provisioned IOPS</td>
<td>
{{ info.ProvisionedIOPS | number }}
<span ng-if="+(info.ProvisionedIOPS) >= +(info.TotalIOPS)">
<span ng-if="+info.ProvisionedIOPS >= +info.TotalIOPS">
<i class="fa fa-exclamation-triangle red-icon" aria-hidden="true" style="margin-left: 2px;"></i>
</span>
</td>
@ -94,7 +92,7 @@
<td>Provisioned bandwidth</td>
<td>
{{ info.ProvisionedBandwidth | humansize }}
<span ng-if="+(info.ProvisionedBandwidth) >= +(info.TotalBandwidth)">
<span ng-if="+info.ProvisionedBandwidth >= +info.TotalBandwidth">
<i class="fa fa-exclamation-triangle red-icon" aria-hidden="true" style="margin-left: 2px;"></i>
</span>
</td>
@ -114,9 +112,12 @@
<div class="row">
<div class="col-sm-12">
<storidge-cluster-events-datatable
title-text="Cluster events" title-icon="fa-history"
dataset="events" table-key="storidge_cluster_events"
order-by="Time" reverse-order="true"
title-text="Cluster events"
title-icon="fa-history"
dataset="events"
table-key="storidge_cluster_events"
order-by="Time"
reverse-order="true"
></storidge-cluster-events-datatable>
</div>
</div>

View file

@ -1,104 +1,109 @@
import moment from 'moment';
angular.module('portainer.integrations.storidge')
.controller('StoridgeMonitorController', ['$q', '$scope', '$interval', '$document', 'Notifications', 'StoridgeClusterService', 'StoridgeChartService',
function ($q, $scope, $interval, $document, Notifications, StoridgeClusterService, StoridgeChartService) {
angular.module('portainer.integrations.storidge').controller('StoridgeMonitorController', [
'$q',
'$scope',
'$interval',
'$document',
'Notifications',
'StoridgeClusterService',
'StoridgeChartService',
function ($q, $scope, $interval, $document, Notifications, StoridgeClusterService, StoridgeChartService) {
$scope.$on('$destroy', function () {
stopRepeater();
});
$scope.$on('$destroy', function() {
stopRepeater();
});
function stopRepeater() {
var repeater = $scope.repeater;
if (angular.isDefined(repeater)) {
$interval.cancel(repeater);
repeater = null;
function stopRepeater() {
var repeater = $scope.repeater;
if (angular.isDefined(repeater)) {
$interval.cancel(repeater);
repeater = null;
}
}
}
function updateIOPSChart(info, chart) {
var usedIOPS = info.UsedIOPS;
var label = moment(new Date()).format('HH:mm:ss');
function updateIOPSChart(info, chart) {
var usedIOPS = info.UsedIOPS;
var label = moment(new Date()).format('HH:mm:ss');
StoridgeChartService.UpdateChart(label, usedIOPS, chart);
}
StoridgeChartService.UpdateChart(label, usedIOPS, chart);
}
function updateBandwithChart(info, chart) {
var usedBandwidth = info.UsedBandwidth;
var label = moment(new Date()).format('HH:mm:ss');
function updateBandwithChart(info, chart) {
var usedBandwidth = info.UsedBandwidth;
var label = moment(new Date()).format('HH:mm:ss');
StoridgeChartService.UpdateChart(label, usedBandwidth, chart);
}
StoridgeChartService.UpdateChart(label, usedBandwidth, chart);
}
function updateCapacityChart(info, chart) {
var usedCapacity = info.UsedCapacity;
var freeCapacity = info.FreeCapacity;
function updateCapacityChart(info, chart) {
var usedCapacity = info.UsedCapacity;
var freeCapacity = info.FreeCapacity;
StoridgeChartService.UpdatePieChart('Free', freeCapacity, chart);
StoridgeChartService.UpdatePieChart('Used', usedCapacity, chart);
}
StoridgeChartService.UpdatePieChart('Free', freeCapacity, chart);
StoridgeChartService.UpdatePieChart('Used', usedCapacity, chart);
}
function setUpdateRepeater(iopsChart, bandwidthChart, capacityChart) {
var refreshRate = 5000;
$scope.repeater = $interval(function() {
function setUpdateRepeater(iopsChart, bandwidthChart, capacityChart) {
var refreshRate = 5000;
$scope.repeater = $interval(function () {
$q.all({
events: StoridgeClusterService.events(),
info: StoridgeClusterService.info(),
})
.then(function success(data) {
$scope.events = data.events;
var info = data.info;
$scope.info = info;
updateIOPSChart(info, iopsChart);
updateBandwithChart(info, bandwidthChart);
updateCapacityChart(info, capacityChart);
})
.catch(function error(err) {
stopRepeater();
Notifications.error('Failure', err, 'Unable to retrieve cluster information');
});
}, refreshRate);
}
function startViewUpdate(iopsChart, bandwidthChart, capacityChart) {
$q.all({
events: StoridgeClusterService.events(),
info: StoridgeClusterService.info()
info: StoridgeClusterService.info(),
})
.then(function success(data) {
$scope.events = data.events;
var info = data.info;
$scope.info = info;
updateIOPSChart(info, iopsChart);
updateBandwithChart(info, bandwidthChart);
updateCapacityChart(info, capacityChart);
})
.catch(function error(err) {
stopRepeater();
Notifications.error('Failure', err, 'Unable to retrieve cluster information');
.then(function success(data) {
$scope.events = data.events;
var info = data.info;
$scope.info = info;
updateIOPSChart(info, iopsChart);
updateBandwithChart(info, bandwidthChart);
updateCapacityChart(info, capacityChart);
setUpdateRepeater(iopsChart, bandwidthChart, capacityChart);
})
.catch(function error(err) {
stopRepeater();
Notifications.error('Failure', err, 'Unable to retrieve cluster information');
});
}
function initCharts() {
var iopsChartCtx = $('#iopsChart');
var iopsChart = StoridgeChartService.CreateIOPSChart(iopsChartCtx);
var bandwidthChartCtx = $('#bandwithChart');
var bandwidthChart = StoridgeChartService.CreateBandwidthChart(bandwidthChartCtx);
var capacityChartCtx = $('#capacityChart');
var capacityChart = StoridgeChartService.CreateCapacityChart(capacityChartCtx);
startViewUpdate(iopsChart, bandwidthChart, capacityChart);
}
function initView() {
$document.ready(function () {
initCharts();
});
}, refreshRate);
}
}
function startViewUpdate(iopsChart, bandwidthChart, capacityChart) {
$q.all({
events: StoridgeClusterService.events(),
info: StoridgeClusterService.info()
})
.then(function success(data) {
$scope.events = data.events;
var info = data.info;
$scope.info = info;
updateIOPSChart(info, iopsChart);
updateBandwithChart(info, bandwidthChart);
updateCapacityChart(info, capacityChart);
setUpdateRepeater(iopsChart, bandwidthChart, capacityChart);
})
.catch(function error(err) {
stopRepeater();
Notifications.error('Failure', err, 'Unable to retrieve cluster information');
});
}
function initCharts() {
var iopsChartCtx = $('#iopsChart');
var iopsChart = StoridgeChartService.CreateIOPSChart(iopsChartCtx);
var bandwidthChartCtx = $('#bandwithChart');
var bandwidthChart = StoridgeChartService.CreateBandwidthChart(bandwidthChartCtx);
var capacityChartCtx = $('#capacityChart');
var capacityChart = StoridgeChartService.CreateCapacityChart(capacityChartCtx);
startViewUpdate(iopsChart, bandwidthChart, capacityChart);
}
function initView() {
$document.ready(function() {
initCharts();
});
}
initView();
}]);
initView();
},
]);

View file

@ -1,8 +1,7 @@
<rd-header>
<rd-header-title title-text="Node details"></rd-header-title>
<rd-header-content>
<a ui-sref="storidge.cluster">Storidge</a> &gt; <a
ui-sref="storidge.cluster.node({id: node.Name})">{{ node.Name }}</a>
<a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.cluster.node({id: node.Name})">{{ node.Name }}</a>
</rd-header-content>
</rd-header>
@ -10,16 +9,13 @@
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-object-group" title-text="Node details">
<button type="button" class="btn btn-sm btn-danger"
ng-disabled="(node.Status | lowercase) !== 'normal'" ng-click="removeNodeAction()">
<button type="button" class="btn btn-sm btn-danger" ng-disabled="(node.Status | lowercase) !== 'normal'" ng-click="removeNodeAction()">
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove node
</button>
<button type="button" class="btn btn-sm btn-primary"
ng-disabled="(node.Status | lowercase) !== 'normal'" ng-click="cordonNodeAction()">
<button type="button" class="btn btn-sm btn-primary" ng-disabled="(node.Status | lowercase) !== 'normal'" ng-click="cordonNodeAction()">
<i class="fas fa-wrench space-right" aria-hidden="true"></i>Enter maintenance mode
</button>
<button type="button" class="btn btn-sm btn-primary"
ng-disabled="(node.Status | lowercase) !== 'cordoned'" ng-click="uncordonNodeAction()">
<button type="button" class="btn btn-sm btn-primary" ng-disabled="(node.Status | lowercase) !== 'cordoned'" ng-click="uncordonNodeAction()">
<i class="fa fa-power-off space-right" aria-hidden="true"></i>Exit maintenance mode
</button>
</rd-widget-header>
@ -167,4 +163,4 @@
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>

View file

@ -1,107 +1,117 @@
angular.module('portainer.integrations.storidge')
.controller('StoridgeNodeController', ['$scope', '$state', '$transition$', 'Notifications', 'StoridgeNodeService', 'ModalService',
function ($scope, $state, $transition$, Notifications, StoridgeNodeService, ModalService) {
angular.module('portainer.integrations.storidge').controller('StoridgeNodeController', [
'$scope',
'$state',
'$transition$',
'Notifications',
'StoridgeNodeService',
'ModalService',
function ($scope, $state, $transition$, Notifications, StoridgeNodeService, ModalService) {
$scope.removeNodeAction = function (selectedItems) {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to remove the node from the cluster?',
buttons: {
confirm: {
label: 'Remove',
className: 'btn-danger',
},
},
callback: function onConfirm(confirmed) {
if (!confirmed) {
return;
}
remove(selectedItems);
},
});
};
$scope.removeNodeAction = function(selectedItems) {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to remove the node from the cluster?',
buttons: {
confirm: {
label: 'Remove',
className: 'btn-danger'
}
},
callback: function onConfirm(confirmed) {
if(!confirmed) { return; }
remove(selectedItems);
}
});
};
function remove() {
StoridgeNodeService.remove($scope.node.Name)
.then(function success() {
Notifications.success('Node successfully removed', $scope.node.Name);
$state.go('storidge.cluster');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove node');
});
}
function remove() {
StoridgeNodeService.remove($scope.node.Name)
.then(function success() {
Notifications.success('Node successfully removed', $scope.node.Name);
$state.go('storidge.cluster');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove node');
});
}
$scope.cordonNodeAction = function (selectedItems) {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to put the node in maintenance mode?',
buttons: {
confirm: {
label: 'Enter maintenance',
className: 'btn-danger',
},
},
callback: function onConfirm(confirmed) {
if (!confirmed) {
return;
}
cordonNode(selectedItems);
},
});
};
$scope.cordonNodeAction = function(selectedItems) {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to put the node in maintenance mode?',
buttons: {
confirm: {
label: 'Enter maintenance',
className: 'btn-danger'
}
},
callback: function onConfirm(confirmed) {
if(!confirmed) { return; }
cordonNode(selectedItems);
}
});
};
function cordonNode() {
StoridgeNodeService.cordon($scope.node.Name)
.then(function success() {
Notifications.success('Node successfully put in maintenance');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to put node in maintenance mode');
})
.finally(function final() {
$state.reload();
});
}
function cordonNode() {
StoridgeNodeService.cordon($scope.node.Name)
.then(function success() {
Notifications.success('Node successfully put in maintenance');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to put node in maintenance mode');
})
.finally(function final() {
$state.reload();
});
}
$scope.uncordonNodeAction = function (selectedItems) {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to bring the nodes out of maintenance mode?',
buttons: {
confirm: {
label: 'Exit maintenance',
className: 'btn-danger',
},
},
callback: function onConfirm(confirmed) {
if (!confirmed) {
return;
}
uncordonNode(selectedItems);
},
});
};
$scope.uncordonNodeAction = function(selectedItems) {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to bring the nodes out of maintenance mode?',
buttons: {
confirm: {
label: 'Exit maintenance',
className: 'btn-danger'
}
},
callback: function onConfirm(confirmed) {
if(!confirmed) { return; }
uncordonNode(selectedItems);
}
});
};
function uncordonNode() {
StoridgeNodeService.uncordon($scope.node.Name)
.then(function success() {
Notifications.success('Node successfully bringed back');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to put node out of maintenance mode');
})
.finally(function final() {
$state.reload();
});
}
function uncordonNode() {
StoridgeNodeService.uncordon($scope.node.Name)
.then(function success() {
Notifications.success('Node successfully bringed back');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to put node out of maintenance mode');
})
.finally(function final() {
$state.reload();
});
}
function initView() {
$scope.name = $transition$.params().name;
function initView() {
$scope.name = $transition$.params().name;
StoridgeNodeService.node($scope.name)
.then(function success(data) {
$scope.node = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve node details');
});
}
StoridgeNodeService.node($scope.name)
.then(function success(data) {
$scope.node = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve node details');
});
}
initView();
}]);
initView();
},
]);

View file

@ -1,108 +1,112 @@
import _ from 'lodash-es';
import { StoridgeProfileDefaultModel } from '../../../models/profile';
angular.module('portainer.integrations.storidge')
.controller('StoridgeCreateProfileController', ['$scope', '$state', '$transition$', 'Notifications', 'StoridgeProfileService',
function ($scope, $state, $transition$, Notifications, StoridgeProfileService) {
angular.module('portainer.integrations.storidge').controller('StoridgeCreateProfileController', [
'$scope',
'$state',
'$transition$',
'Notifications',
'StoridgeProfileService',
function ($scope, $state, $transition$, Notifications, StoridgeProfileService) {
$scope.formValues = {
Labels: [],
};
$scope.formValues = {
Labels: []
};
$scope.state = {
NoLimit: true,
LimitIOPS: false,
LimitBandwidth: false,
ManualInputDirectory: false,
actionInProgress: false,
};
$scope.state = {
NoLimit: true,
LimitIOPS: false,
LimitBandwidth: false,
ManualInputDirectory: false,
actionInProgress: false
};
$scope.RedundancyOptions = [
{ value: 2, label: '2-copy' },
{ value: 3, label: '3-copy' },
];
$scope.RedundancyOptions = [
{ value: 2, label: '2-copy' },
{ value: 3, label: '3-copy' }
];
$scope.addLabel = function () {
$scope.formValues.Labels.push({ name: '', value: '' });
};
$scope.addLabel = function() {
$scope.formValues.Labels.push({ name: '', value: ''});
};
$scope.removeLabel = function (index) {
$scope.formValues.Labels.splice(index, 1);
};
$scope.removeLabel = function(index) {
$scope.formValues.Labels.splice(index, 1);
};
function prepareLabels(profile) {
var labels = {};
$scope.formValues.Labels.forEach(function (label) {
if (label.name && label.value) {
labels[label.name] = label.value;
}
});
profile.Labels = labels;
}
$scope.create = function () {
var profile = $scope.model;
if (!$scope.state.LimitIOPS) {
delete profile.MinIOPS;
delete profile.MaxIOPS;
function prepareLabels(profile) {
var labels = {};
$scope.formValues.Labels.forEach(function (label) {
if (label.name && label.value) {
labels[label.name] = label.value;
}
});
profile.Labels = labels;
}
if (!$scope.state.LimitBandwidth) {
delete profile.MinBandwidth;
delete profile.MaxBandwidth;
}
$scope.create = function () {
var profile = $scope.model;
if (profile.SnapshotEnabled) {
if (!profile.SnapshotMax || profile.SnapshotMax <= 0) {
profile.SnapshotMax = 1;
if (!$scope.state.LimitIOPS) {
delete profile.MinIOPS;
delete profile.MaxIOPS;
}
if (!$scope.state.RecurringSnapshotEnabled) {
if (!$scope.state.LimitBandwidth) {
delete profile.MinBandwidth;
delete profile.MaxBandwidth;
}
if (profile.SnapshotEnabled) {
if (!profile.SnapshotMax || profile.SnapshotMax <= 0) {
profile.SnapshotMax = 1;
}
if (!$scope.state.RecurringSnapshotEnabled) {
delete profile.SnapshotInterval;
}
if ($scope.state.RecurringSnapshotEnabled && (!profile.SnapshotInterval || profile.SnapshotInterval <= 0)) {
profile.SnapshotInterval = 1440;
}
} else {
delete profile.SnapshotMax;
delete profile.SnapshotInterval;
}
if ($scope.state.RecurringSnapshotEnabled && (!profile.SnapshotInterval || profile.SnapshotInterval <= 0)) {
profile.SnapshotInterval = 1440;
prepareLabels(profile);
$scope.state.actionInProgress = true;
StoridgeProfileService.create(profile)
.then(function success() {
Notifications.success('Profile successfully created');
$state.go('storidge.profiles');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to create profile');
})
.finally(function final() {
$scope.state.actionInProgress = false;
});
};
$scope.updatedName = function () {
if (!$scope.state.ManualInputDirectory) {
var profile = $scope.model;
profile.Directory = '/cio/' + (profile.Name ? _.toLower(profile.Name) : '');
}
} else {
delete profile.SnapshotMax;
delete profile.SnapshotInterval;
};
$scope.updatedDirectory = function () {
if (!$scope.state.ManualInputDirectory) {
$scope.state.ManualInputDirectory = true;
}
};
function initView() {
var profile = new StoridgeProfileDefaultModel();
profile.Name = $transition$.params().profileName;
profile.Directory = profile.Directory + _.toLower(profile.Name);
$scope.model = profile;
}
prepareLabels(profile);
$scope.state.actionInProgress = true;
StoridgeProfileService.create(profile)
.then(function success() {
Notifications.success('Profile successfully created');
$state.go('storidge.profiles');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to create profile');
})
.finally(function final() {
$scope.state.actionInProgress = false;
});
};
$scope.updatedName = function() {
if (!$scope.state.ManualInputDirectory) {
var profile = $scope.model;
profile.Directory = '/cio/' + (profile.Name ? _.toLower(profile.Name) : '');
}
};
$scope.updatedDirectory = function() {
if (!$scope.state.ManualInputDirectory) {
$scope.state.ManualInputDirectory = true;
}
};
function initView() {
var profile = new StoridgeProfileDefaultModel();
profile.Name = $transition$.params().profileName;
profile.Directory = profile.Directory + _.toLower(profile.Name);
$scope.model = profile;
}
initView();
}]);
initView();
},
]);

View file

@ -1,8 +1,6 @@
<rd-header>
<rd-header-title title-text="Create profile"></rd-header-title>
<rd-header-content>
<a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.profiles">Profiles</a> &gt; Add profile
</rd-header-content>
<rd-header-content> <a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.profiles">Profiles</a> &gt; Add profile </rd-header-content>
</rd-header>
<div class="row">
@ -14,7 +12,7 @@
<div class="form-group" ng-class="{ 'has-error': storidgeCreateProfileForm.profile_name.$invalid }">
<label for="profile_name" class="col-sm-2 col-lg-1 control-label text-left">Name</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="model.Name" name="profile_name" placeholder="e.g. myProfile" ng-change="updatedName()" required>
<input type="text" class="form-control" ng-model="model.Name" name="profile_name" placeholder="e.g. myProfile" ng-change="updatedName()" required />
</div>
</div>
<div class="form-group" ng-show="storidgeCreateProfileForm.profile_name.$invalid">
@ -32,7 +30,15 @@
<div class="form-group" ng-class="{ 'has-error': storidgeCreateProfileForm.profile_directory.$invalid }">
<label for="profile_directory" class="col-sm-2 col-lg-1 control-label text-left">Directory</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="model.Directory" name="profile_directory" placeholder="e.g. /cio/myProfile" ng-change="updatedDirectory()" required>
<input
type="text"
class="form-control"
ng-model="model.Directory"
name="profile_directory"
placeholder="e.g. /cio/myProfile"
ng-change="updatedDirectory()"
required
/>
</div>
</div>
<div class="form-group" ng-show="storidgeCreateProfileForm.profile_directory.$invalid">
@ -47,7 +53,7 @@
<div class="form-group" ng-class="{ 'has-error': storidgeCreateProfileForm.profile_capacity.$invalid }">
<label for="profile_capacity" class="col-sm-2 col-lg-1 control-label text-left">Capacity</label>
<div class="col-sm-10 col-lg-11">
<input type="number" class="form-control" ng-model="model.Capacity" name="profile_capacity" ng-min="1" ng-max="64000" placeholder="2" required>
<input type="number" class="form-control" ng-model="model.Capacity" name="profile_capacity" ng-min="1" ng-max="64000" placeholder="2" required />
</div>
</div>
<div class="form-group" ng-show="storidgeCreateProfileForm.profile_capacity.$invalid">
@ -64,8 +70,7 @@
<div class="form-group">
<label for="profile_redundancy" class="col-sm-2 col-lg-1 control-label text-left">Redundancy</label>
<div class="col-sm-10 col-lg-11">
<select name="profile_redundancy" ng-model="model.Redundancy" ng-options="+(opt.value) as opt.label for opt in RedundancyOptions" class="form-control">
</select>
<select name="profile_redundancy" ng-model="model.Redundancy" ng-options="+(opt.value) as opt.label for opt in RedundancyOptions" class="form-control"> </select>
</div>
</div>
<!-- !redudancy -->
@ -108,9 +113,7 @@
<label for="profile_snapshotEnabled" class="col-sm-2 col-lg-1 control-label text-left">
Enable snapshots
</label>
<label class="switch" style="margin-left: 20px;">
<input name="profile_snapshotEnabled" type="checkbox" ng-model="model.SnapshotEnabled"><i></i>
</label>
<label class="switch" style="margin-left: 20px;"> <input name="profile_snapshotEnabled" type="checkbox" ng-model="model.SnapshotEnabled" /><i></i> </label>
</div>
<!-- !snapshotEnabled -->
<!-- snapshotMax -->
@ -122,7 +125,7 @@
<slider model="model.SnapshotMax" floor="1" ceil="100" step="1"></slider>
</div>
<div class="col-sm-2">
<input type="number" min="1" class="form-control" ng-model="model.SnapshotMax" id="profile_snapshotMax">
<input type="number" min="1" class="form-control" ng-model="model.SnapshotMax" id="profile_snapshotMax" />
</div>
<div class="col-sm-4">
<p class="small text-muted" style="margin-top: 7px;">
@ -137,7 +140,7 @@
Enable periodic snapshots
</label>
<label class="switch" style="margin-left: 20px;">
<input name="profile_recurringSnapshotEnabled" type="checkbox" ng-model="state.RecurringSnapshotEnabled"><i></i>
<input name="profile_recurringSnapshotEnabled" type="checkbox" ng-model="state.RecurringSnapshotEnabled" /><i></i>
</label>
</div>
<!-- !snapshotEnabled -->
@ -150,7 +153,7 @@
<slider model="model.SnapshotInterval" floor="1" ceil="2880" step="1"></slider>
</div>
<div class="col-sm-2">
<input type="number" min="1" class="form-control" ng-model="model.SnapshotInterval" id="profile_snapshotInterval">
<input type="number" min="1" class="form-control" ng-model="model.SnapshotInterval" id="profile_snapshotInterval" />
</div>
<div class="col-sm-4">
<p class="small text-muted" style="margin-top: 7px;">
@ -164,9 +167,7 @@
<label for="profile_encryptionEnabled" class="col-sm-2 col-lg-1 control-label text-left">
Enable encryption
</label>
<label class="switch" style="margin-left: 20px;">
<input name="profile_encryptionEnabled" type="checkbox" ng-model="model.EncryptionEnabled"><i></i>
</label>
<label class="switch" style="margin-left: 20px;"> <input name="profile_encryptionEnabled" type="checkbox" ng-model="model.EncryptionEnabled" /><i></i> </label>
</div>
<!-- !encryptionEnabled -->
<!-- interfaceType -->
@ -196,7 +197,7 @@
<div class="form-group">
<label for="profile_interfaceNetwork" class="col-sm-2 col-lg-1 control-label text-left">Network name</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="model.InterfaceNetwork" name="profile_interfaceNetwork" pattern="[a-zA-Z0-9]+">
<input type="text" class="form-control" ng-model="model.InterfaceNetwork" name="profile_interfaceNetwork" pattern="[a-zA-Z0-9]+" />
</div>
</div>
<!-- !interfaceNetwork -->
@ -204,7 +205,7 @@
<div class="form-group">
<label for="profile_interfaceConf" class="col-sm-2 col-lg-1 control-label text-left">Interface conf</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="model.InterfaceConf" name="profile_interfaceConf">
<input type="text" class="form-control" ng-model="model.InterfaceConf" name="profile_interfaceConf" />
</div>
</div>
<!-- !interfaceConf -->
@ -212,20 +213,18 @@
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Labels</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addLabel()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add label
</span>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addLabel()"> <i class="fa fa-plus-circle" aria-hidden="true"></i> add label </span>
</div>
<!-- labels-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="label in formValues.Labels" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="label.name" placeholder="e.g. com.example.foo">
<input type="text" class="form-control" ng-model="label.name" placeholder="e.g. com.example.foo" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar">
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeLabel($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
@ -247,17 +246,17 @@
</label>
</div>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="state.LimitIOPS" ng-change="state.NoLimit = (!state.LimitBandwidth && !state.LimitIOPS)"><i></i>
<input type="checkbox" ng-model="state.LimitIOPS" ng-change="state.NoLimit = (!state.LimitBandwidth && !state.LimitIOPS)" /><i></i>
</label>
</div>
<div class="form-group" ng-if="state.LimitIOPS">
<label for="min_iops" class="col-sm-1 control-label text-left">Min</label>
<div class="col-sm-5" ng-class="{ 'has-error': storidgeCreateProfileForm.min_iops.$invalid }">
<input type="number" class="form-control" ng-model="model.MinIOPS" name="min_iops" ng-min="30" ng-max="999999" placeholder="100" required>
<input type="number" class="form-control" ng-model="model.MinIOPS" name="min_iops" ng-min="30" ng-max="999999" placeholder="100" required />
</div>
<label for="max_iops" class="col-sm-1 control-label text-left">Max</label>
<div class="col-sm-5" ng-class="{ 'has-error': storidgeCreateProfileForm.max_iops.$invalid }">
<input type="number" class="form-control" ng-model="model.MaxIOPS" name="max_iops" ng-min="30" ng-max="999999" placeholder="2000" required>
<input type="number" class="form-control" ng-model="model.MaxIOPS" name="max_iops" ng-min="30" ng-max="999999" placeholder="2000" required />
</div>
</div>
<div class="form-group" ng-show="storidgeCreateProfileForm.min_iops.$invalid">
@ -292,17 +291,17 @@
</label>
</div>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="state.LimitBandwidth" ng-change="state.NoLimit = (!state.LimitBandwidth && !state.LimitIOPS)"><i></i>
<input type="checkbox" ng-model="state.LimitBandwidth" ng-change="state.NoLimit = (!state.LimitBandwidth && !state.LimitIOPS)" /><i></i>
</label>
</div>
<div class="form-group" ng-if="state.LimitBandwidth">
<label for="min_bandwidth" class="col-sm-1 control-label text-left">Min</label>
<div class="col-sm-5" ng-class="{ 'has-error': storidgeCreateProfileForm.min_bandwidth.$invalid }">
<input type="number" class="form-control" ng-model="model.MinBandwidth" name="min_bandwidth" ng-min="1" ng-max="5000" placeholder="1" required>
<input type="number" class="form-control" ng-model="model.MinBandwidth" name="min_bandwidth" ng-min="1" ng-max="5000" placeholder="1" required />
</div>
<label for="max_bandwidth" class="col-sm-1 control-label text-left">Max</label>
<div class="col-sm-5" ng-class="{ 'has-error': storidgeCreateProfileForm.max_bandwidth.$invalid }">
<input type="number" class="form-control" ng-model="model.MaxBandwidth" name="max_bandwidth" ng-min="1" ng-max="5000" placeholder="100" required>
<input type="number" class="form-control" ng-model="model.MaxBandwidth" name="max_bandwidth" ng-min="1" ng-max="5000" placeholder="100" required />
</div>
</div>
<div class="form-group" ng-show="storidgeCreateProfileForm.min_bandwidth.$invalid">
@ -330,7 +329,13 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-click="create()" ng-disabled="state.actionInProgress || !storidgeCreateProfileForm.$valid" button-spinner="state.actionInProgress">
<button
type="button"
class="btn btn-primary btn-sm"
ng-click="create()"
ng-disabled="state.actionInProgress || !storidgeCreateProfileForm.$valid"
button-spinner="state.actionInProgress"
>
<span ng-hide="state.actionInProgress">Create the profile</span>
<span ng-show="state.actionInProgress">Creating profile...</span>
</button>

View file

@ -1,8 +1,6 @@
<rd-header>
<rd-header-title title-text="Profile details"></rd-header-title>
<rd-header-content>
<a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.profiles">Profiles</a> &gt; {{ profile.Name }}
</rd-header-content>
<rd-header-content> <a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.profiles">Profiles</a> &gt; {{ profile.Name }} </rd-header-content>
</rd-header>
<div class="row" ng-if="profile">
@ -14,7 +12,7 @@
<div class="form-group">
<label for="profile_name" class="col-sm-2 col-lg-1 control-label text-left">Name</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="profile.Name" name="profile_name" disabled>
<input type="text" class="form-control" ng-model="profile.Name" name="profile_name" disabled />
</div>
</div>
<!-- !name-input -->
@ -25,7 +23,7 @@
<div class="form-group" ng-class="{ 'has-error': storidgeUpdateProfileForm.profile_directory.$invalid }">
<label for="profile_directory" class="col-sm-2 col-lg-1 control-label text-left">Directory</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="profile.Directory" name="profile_directory" placeholder="e.g. /cio/myProfile" required>
<input type="text" class="form-control" ng-model="profile.Directory" name="profile_directory" placeholder="e.g. /cio/myProfile" required />
</div>
</div>
<div class="form-group" ng-show="storidgeUpdateProfileForm.profile_directory.$invalid">
@ -40,7 +38,7 @@
<div class="form-group" ng-class="{ 'has-error': storidgeUpdateProfileForm.profile_capacity.$invalid }">
<label for="profile_capacity" class="col-sm-2 col-lg-1 control-label text-left">Capacity</label>
<div class="col-sm-10 col-lg-11">
<input type="number" class="form-control" ng-model="profile.Capacity" name="profile_capacity" ng-min="1" ng-max="64000" placeholder="2" required>
<input type="number" class="form-control" ng-model="profile.Capacity" name="profile_capacity" ng-min="1" ng-max="64000" placeholder="2" required />
</div>
</div>
<div class="form-group" ng-show="storidgeUpdateProfileForm.profile_capacity.$invalid">
@ -57,8 +55,7 @@
<div class="form-group">
<label for="profile_redundancy" class="col-sm-2 col-lg-1 control-label text-left">Redundancy</label>
<div class="col-sm-10 col-lg-11">
<select name="profile_redundancy" ng-model="profile.Redundancy" ng-options="+(opt.value) as opt.label for opt in RedundancyOptions" class="form-control">
</select>
<select name="profile_redundancy" ng-model="profile.Redundancy" ng-options="+(opt.value) as opt.label for opt in RedundancyOptions" class="form-control"> </select>
</div>
</div>
<!-- !redudancy -->
@ -86,148 +83,142 @@
<!-- !type -->
<!-- Filesystem -->
<div class="form-group">
<label for="profile_filesystem" class="col-sm-2 col-lg-1 control-label text-left">Filesystem</label>
<div class="col-sm-10 col-lg-11">
<select name="profile_filesystem" ng-model="profile.Filesystem" class="form-control">
<option value="btrfs">btrfs</option>
<option value="ext4">ext4</option>
<option value="xfs">xfs</option>
</select>
</div>
<label for="profile_filesystem" class="col-sm-2 col-lg-1 control-label text-left">Filesystem</label>
<div class="col-sm-10 col-lg-11">
<select name="profile_filesystem" ng-model="profile.Filesystem" class="form-control">
<option value="btrfs">btrfs</option>
<option value="ext4">ext4</option>
<option value="xfs">xfs</option>
</select>
</div>
<!-- !Filesystem -->
<!-- snapshotEnabled -->
<div class="form-group">
<label for="profile_snapshotEnabled" class="col-sm-2 col-lg-1 control-label text-left">
Enable snapshots
</label>
<label class="switch" style="margin-left: 20px;">
<input name="profile_snapshotEnabled" type="checkbox" ng-model="profile.SnapshotEnabled"><i></i>
</label>
</div>
<!-- !Filesystem -->
<!-- snapshotEnabled -->
<div class="form-group">
<label for="profile_snapshotEnabled" class="col-sm-2 col-lg-1 control-label text-left">
Enable snapshots
</label>
<label class="switch" style="margin-left: 20px;"> <input name="profile_snapshotEnabled" type="checkbox" ng-model="profile.SnapshotEnabled" /><i></i> </label>
</div>
<!-- !snapshotEnabled -->
<!-- snapshotMax -->
<div class="form-group" ng-if="profile.SnapshotEnabled">
<label for="profile_snapshotMax" class="col-sm-2 col-lg-1 control-label text-left" style="margin-top: 20px;">
Snapshot max
</label>
<div class="col-sm-4">
<slider model="profile.SnapshotMax" floor="1" ceil="100" step="1"></slider>
</div>
<!-- !snapshotEnabled -->
<!-- snapshotMax -->
<div class="form-group" ng-if="profile.SnapshotEnabled">
<label for="profile_snapshotMax" class="col-sm-2 col-lg-1 control-label text-left" style="margin-top: 20px;">
Snapshot max
</label>
<div class="col-sm-4">
<slider model="profile.SnapshotMax" floor="1" ceil="100" step="1"></slider>
</div>
<div class="col-sm-2">
<input type="number" min="1" class="form-control" ng-model="profile.SnapshotMax" id="profile_snapshotMax">
</div>
<div class="col-sm-4">
<p class="small text-muted" style="margin-top: 7px;">
Snapshot max (<b>count</b>)
</p>
</div>
<div class="col-sm-2">
<input type="number" min="1" class="form-control" ng-model="profile.SnapshotMax" id="profile_snapshotMax" />
</div>
<!-- !snapshotMax -->
<!-- snapshotEnabled -->
<div class="form-group" ng-if="profile.SnapshotEnabled">
<label for="profile_recurringSnapshotEnabled" class="col-sm-2 col-lg-1 control-label text-left">
Enable periodic snapshots
</label>
<label class="switch" style="margin-left: 20px;">
<input name="profile_recurringSnapshotEnabled" type="checkbox" ng-model="state.RecurringSnapshotEnabled"><i></i>
</label>
<div class="col-sm-4">
<p class="small text-muted" style="margin-top: 7px;">
Snapshot max (<b>count</b>)
</p>
</div>
<!-- !snapshotEnabled -->
<!-- snapshotInterval -->
<div class="form-group" ng-if="profile.SnapshotEnabled && state.RecurringSnapshotEnabled">
<label for="profile_snapshotInterval" class="col-sm-2 col-lg-1 control-label text-left" style="margin-top: 20px;">
Snapshot interval
</label>
<div class="col-sm-4">
<slider model="profile.SnapshotInterval" floor="1" ceil="2880" step="1"></slider>
</div>
<div class="col-sm-2">
<input type="number" min="1" class="form-control" ng-model="profile.SnapshotInterval" id="profile_snapshotInterval">
</div>
<div class="col-sm-4">
<p class="small text-muted" style="margin-top: 7px;">
Snapshot interval (<b>minutes</b>)
</p>
</div>
</div>
<!-- !snapshotMax -->
<!-- snapshotEnabled -->
<div class="form-group" ng-if="profile.SnapshotEnabled">
<label for="profile_recurringSnapshotEnabled" class="col-sm-2 col-lg-1 control-label text-left">
Enable periodic snapshots
</label>
<label class="switch" style="margin-left: 20px;">
<input name="profile_recurringSnapshotEnabled" type="checkbox" ng-model="state.RecurringSnapshotEnabled" /><i></i>
</label>
</div>
<!-- !snapshotEnabled -->
<!-- snapshotInterval -->
<div class="form-group" ng-if="profile.SnapshotEnabled && state.RecurringSnapshotEnabled">
<label for="profile_snapshotInterval" class="col-sm-2 col-lg-1 control-label text-left" style="margin-top: 20px;">
Snapshot interval
</label>
<div class="col-sm-4">
<slider model="profile.SnapshotInterval" floor="1" ceil="2880" step="1"></slider>
</div>
<!-- !snapshotInterval -->
<!-- encryptionEnabled -->
<div class="form-group">
<label for="profile_encryptionEnabled" class="col-sm-2 col-lg-1 control-label text-left">
Enable encryption
</label>
<label class="switch" style="margin-left: 20px;">
<input name="profile_encryptionEnabled" type="checkbox" ng-model="profile.EncryptionEnabled"><i></i>
</label>
<div class="col-sm-2">
<input type="number" min="1" class="form-control" ng-model="profile.SnapshotInterval" id="profile_snapshotInterval" />
</div>
<!-- !encryptionEnabled -->
<!-- interfaceType -->
<div class="form-group">
<label for="profile_interfaceType" class="col-sm-2 col-lg-1 control-label text-left">Interface type</label>
<div class="col-sm-10 col-lg-11">
<select name="profile_interfaceType" ng-model="profile.InterfaceType" class="form-control">
<option value=""></option>
<option value="nfs">nfs</option>
</select>
</div>
<div class="col-sm-4">
<p class="small text-muted" style="margin-top: 7px;">
Snapshot interval (<b>minutes</b>)
</p>
</div>
<!-- !interfaceType -->
<!-- interfaceDriver -->
<div class="form-group">
<label for="profile_interfaceDriver" class="col-sm-2 col-lg-1 control-label text-left">Network driver</label>
<div class="col-sm-10 col-lg-11">
<select name="profile_interfaceDriver" ng-model="profile.InterfaceDriver" class="form-control">
<option value=""></option>
<option value="macvlan">macvlan</option>
<option value="overlay">overlay</option>
</select>
</div>
</div>
<!-- !snapshotInterval -->
<!-- encryptionEnabled -->
<div class="form-group">
<label for="profile_encryptionEnabled" class="col-sm-2 col-lg-1 control-label text-left">
Enable encryption
</label>
<label class="switch" style="margin-left: 20px;"> <input name="profile_encryptionEnabled" type="checkbox" ng-model="profile.EncryptionEnabled" /><i></i> </label>
</div>
<!-- !encryptionEnabled -->
<!-- interfaceType -->
<div class="form-group">
<label for="profile_interfaceType" class="col-sm-2 col-lg-1 control-label text-left">Interface type</label>
<div class="col-sm-10 col-lg-11">
<select name="profile_interfaceType" ng-model="profile.InterfaceType" class="form-control">
<option value=""></option>
<option value="nfs">nfs</option>
</select>
</div>
<!-- !interfaceDriver -->
<!-- interfaceNetwork -->
<div class="form-group">
<label for="profile_interfaceNetwork" class="col-sm-2 col-lg-1 control-label text-left">Network name</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="profile.InterfaceNetwork" name="profile_interfaceNetwork" pattern="[a-zA-Z0-9]+">
</div>
</div>
<!-- !interfaceType -->
<!-- interfaceDriver -->
<div class="form-group">
<label for="profile_interfaceDriver" class="col-sm-2 col-lg-1 control-label text-left">Network driver</label>
<div class="col-sm-10 col-lg-11">
<select name="profile_interfaceDriver" ng-model="profile.InterfaceDriver" class="form-control">
<option value=""></option>
<option value="macvlan">macvlan</option>
<option value="overlay">overlay</option>
</select>
</div>
<!-- !interfaceNetwork -->
<!-- interfaceConf -->
<div class="form-group">
<label for="profile_interfaceConf" class="col-sm-2 col-lg-1 control-label text-left">Interface conf</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="profile.InterfaceConf" name="profile_interfaceConf">
</div>
</div>
<!-- !interfaceDriver -->
<!-- interfaceNetwork -->
<div class="form-group">
<label for="profile_interfaceNetwork" class="col-sm-2 col-lg-1 control-label text-left">Network name</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="profile.InterfaceNetwork" name="profile_interfaceNetwork" pattern="[a-zA-Z0-9]+" />
</div>
<!-- !interfaceConf -->
<!-- labels -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Labels</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addLabel()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add label
</span>
</div>
<!-- labels-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="label in formValues.Labels" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="label.name" placeholder="e.g. com.example.foo">
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar">
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeLabel($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
<!-- !interfaceNetwork -->
<!-- interfaceConf -->
<div class="form-group">
<label for="profile_interfaceConf" class="col-sm-2 col-lg-1 control-label text-left">Interface conf</label>
<div class="col-sm-10 col-lg-11">
<input type="text" class="form-control" ng-model="profile.InterfaceConf" name="profile_interfaceConf" />
</div>
</div>
<!-- !interfaceConf -->
<!-- labels -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Labels</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addLabel()"> <i class="fa fa-plus-circle" aria-hidden="true"></i> add label </span>
</div>
<!-- labels-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="label in formValues.Labels" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="label.name" placeholder="e.g. com.example.foo" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeLabel($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
<!-- !labels-input-list -->
</div>
<!-- !labels -->
<!-- !labels-input-list -->
</div>
<!-- !labels -->
<!-- iops -->
<div ng-if="!state.LimitBandwidth || state.NoLimit">
<div class="col-sm-12 form-section-title">
@ -239,18 +230,18 @@
Limit IOPS
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="state.LimitIOPS" ng-change="state.NoLimit = (!state.LimitBandwidth && !state.LimitIOPS)"><i></i>
<input type="checkbox" ng-model="state.LimitIOPS" ng-change="state.NoLimit = (!state.LimitBandwidth && !state.LimitIOPS)" /><i></i>
</label>
</div>
</div>
<div class="form-group" ng-if="state.LimitIOPS">
<label for="min_iops" class="col-sm-1 control-label text-left">Min</label>
<div class="col-sm-5" ng-class="{ 'has-error': storidgeUpdateProfileForm.min_iops.$invalid }">
<input type="number" class="form-control" ng-model="profile.MinIOPS" name="min_iops" ng-min="30" ng-max="999999" placeholder="100" required>
<input type="number" class="form-control" ng-model="profile.MinIOPS" name="min_iops" ng-min="30" ng-max="999999" placeholder="100" required />
</div>
<label for="max_iops" class="col-sm-1 control-label text-left">Max</label>
<div class="col-sm-5" ng-class="{ 'has-error': storidgeUpdateProfileForm.max_iops.$invalid }">
<input type="number" class="form-control" ng-model="profile.MaxIOPS" name="max_iops" ng-min="30" ng-max="999999" placeholder="2000" required>
<input type="number" class="form-control" ng-model="profile.MaxIOPS" name="max_iops" ng-min="30" ng-max="999999" placeholder="2000" required />
</div>
</div>
<div class="form-group" ng-show="storidgeUpdateProfileForm.min_iops.$invalid">
@ -284,18 +275,18 @@
Limit bandwidth
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="state.LimitBandwidth" ng-change="state.NoLimit = (!state.LimitBandwidth && !state.LimitIOPS)"><i></i>
<input type="checkbox" ng-model="state.LimitBandwidth" ng-change="state.NoLimit = (!state.LimitBandwidth && !state.LimitIOPS)" /><i></i>
</label>
</div>
</div>
<div class="form-group" ng-if="state.LimitBandwidth">
<label for="min_bandwidth" class="col-sm-1 control-label text-left">Min</label>
<div class="col-sm-5" ng-class="{ 'has-error': storidgeUpdateProfileForm.min_bandwidth.$invalid }">
<input type="number" class="form-control" ng-model="profile.MinBandwidth" name="min_bandwidth" ng-min="1" ng-max="5000" placeholder="1" required>
<input type="number" class="form-control" ng-model="profile.MinBandwidth" name="min_bandwidth" ng-min="1" ng-max="5000" placeholder="1" required />
</div>
<label for="max_bandwidth" class="col-sm-1 control-label text-left">Max</label>
<div class="col-sm-5" ng-class="{ 'has-error': storidgeUpdateProfileForm.max_bandwidth.$invalid }">
<input type="number" class="form-control" ng-model="profile.MaxBandwidth" name="max_bandwidth" ng-min="1" ng-max="5000" placeholder="100" required>
<input type="number" class="form-control" ng-model="profile.MaxBandwidth" name="max_bandwidth" ng-min="1" ng-max="5000" placeholder="100" required />
</div>
</div>
<div class="form-group" ng-show="storidgeUpdateProfileForm.min_bandwidth.$invalid">
@ -324,7 +315,13 @@
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-click="update()" ng-disabled="state.updateInProgress || !storidgeUpdateProfileForm.$valid" button-spinner="state.updateInProgress">
<button
type="button"
class="btn btn-primary btn-sm"
ng-click="update()"
ng-disabled="state.updateInProgress || !storidgeUpdateProfileForm.$valid"
button-spinner="state.updateInProgress"
>
<span ng-hide="state.updateInProgress">Update the profile</span>
<span ng-show="state.updateInProgress">Updating profile...</span>
</button>

View file

@ -1,142 +1,145 @@
angular.module('portainer.integrations.storidge')
.controller('StoridgeProfileController', ['$scope', '$state', '$transition$', 'Notifications', 'StoridgeProfileService', 'ModalService',
function ($scope, $state, $transition$, Notifications, StoridgeProfileService, ModalService) {
angular.module('portainer.integrations.storidge').controller('StoridgeProfileController', [
'$scope',
'$state',
'$transition$',
'Notifications',
'StoridgeProfileService',
'ModalService',
function ($scope, $state, $transition$, Notifications, StoridgeProfileService, ModalService) {
$scope.formValues = {
Labels: [],
};
$scope.formValues = {
Labels: []
};
$scope.state = {
NoLimit: false,
LimitIOPS: false,
LimitBandwidth: false,
updateInProgress: false,
deleteInProgress: false,
RecurringSnapshotEnabled: false,
};
$scope.state = {
NoLimit: false,
LimitIOPS: false,
LimitBandwidth: false,
updateInProgress: false,
deleteInProgress: false,
RecurringSnapshotEnabled: false
};
$scope.addLabel = function () {
$scope.formValues.Labels.push({ name: '', value: '' });
};
$scope.addLabel = function() {
$scope.formValues.Labels.push({ name: '', value: ''});
};
$scope.removeLabel = function (index) {
$scope.formValues.Labels.splice(index, 1);
};
$scope.removeLabel = function(index) {
$scope.formValues.Labels.splice(index, 1);
};
function prepareLabels(profile) {
var labels = {};
$scope.formValues.Labels.forEach(function (label) {
if (label.name && label.value) {
labels[label.name] = label.value;
}
});
profile.Labels = labels;
}
function initLabels(labels) {
$scope.formValues.Labels = Object.keys(labels).map(function(key) {
return { name:key, value:labels[key] };
});
}
$scope.RedundancyOptions = [
{ value: 2, label: '2-copy' },
{ value: 3, label: '3-copy' }
];
$scope.update = function() {
var profile = $scope.profile;
if (!$scope.state.LimitIOPS) {
delete profile.MinIOPS;
delete profile.MaxIOPS;
function prepareLabels(profile) {
var labels = {};
$scope.formValues.Labels.forEach(function (label) {
if (label.name && label.value) {
labels[label.name] = label.value;
}
});
profile.Labels = labels;
}
if (!$scope.state.LimitBandwidth) {
delete profile.MinBandwidth;
delete profile.MaxBandwidth;
function initLabels(labels) {
$scope.formValues.Labels = Object.keys(labels).map(function (key) {
return { name: key, value: labels[key] };
});
}
if (profile.SnapshotEnabled) {
if (!profile.SnapshotMax || profile.SnapshotMax <= 0) {
profile.SnapshotMax = 1;
$scope.RedundancyOptions = [
{ value: 2, label: '2-copy' },
{ value: 3, label: '3-copy' },
];
$scope.update = function () {
var profile = $scope.profile;
if (!$scope.state.LimitIOPS) {
delete profile.MinIOPS;
delete profile.MaxIOPS;
}
if (!$scope.state.RecurringSnapshotEnabled) {
if (!$scope.state.LimitBandwidth) {
delete profile.MinBandwidth;
delete profile.MaxBandwidth;
}
if (profile.SnapshotEnabled) {
if (!profile.SnapshotMax || profile.SnapshotMax <= 0) {
profile.SnapshotMax = 1;
}
if (!$scope.state.RecurringSnapshotEnabled) {
delete profile.SnapshotInterval;
}
if ($scope.state.RecurringSnapshotEnabled && (!profile.SnapshotInterval || profile.SnapshotInterval <= 0)) {
profile.SnapshotInterval = 1440;
}
} else {
delete profile.SnapshotMax;
delete profile.SnapshotInterval;
}
if ($scope.state.RecurringSnapshotEnabled && (!profile.SnapshotInterval || profile.SnapshotInterval <= 0)) {
profile.SnapshotInterval = 1440;
}
} else {
delete profile.SnapshotMax;
delete profile.SnapshotInterval;
prepareLabels(profile);
$scope.state.updateInProgress = true;
StoridgeProfileService.update(profile)
.then(function success() {
Notifications.success('Profile successfully updated');
$state.go('storidge.profiles');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update profile');
})
.finally(function final() {
$scope.state.updateInProgress = false;
});
};
$scope.delete = function () {
ModalService.confirmDeletion('Do you want to remove this profile?', function onConfirm(confirmed) {
if (!confirmed) {
return;
}
deleteProfile();
});
};
function deleteProfile() {
var profile = $scope.profile;
$scope.state.deleteInProgress = true;
StoridgeProfileService.delete(profile.Name)
.then(function success() {
Notifications.success('Profile successfully deleted');
$state.go('storidge.profiles');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to delete profile');
})
.finally(function final() {
$scope.state.deleteInProgress = false;
});
}
prepareLabels(profile);
function initView() {
StoridgeProfileService.profile($transition$.params().id)
.then(function success(data) {
var profile = data;
if ((profile.MinIOPS && profile.MinIOPS !== 0) || (profile.MaxIOPS && profile.MaxIOPS !== 0)) {
$scope.state.LimitIOPS = true;
} else if ((profile.MinBandwidth && profile.MinBandwidth !== 0) || (profile.MaxBandwidth && profile.MaxBandwidth !== 0)) {
$scope.state.LimitBandwidth = true;
} else {
$scope.state.NoLimit = true;
}
if (profile.SnapshotEnabled && profile.SnapshotInterval !== 0) {
$scope.state.RecurringSnapshotEnabled = true;
}
initLabels(profile.Labels);
$scope.profile = profile;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve profile details');
});
}
$scope.state.updateInProgress = true;
StoridgeProfileService.update(profile)
.then(function success() {
Notifications.success('Profile successfully updated');
$state.go('storidge.profiles');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update profile');
})
.finally(function final() {
$scope.state.updateInProgress = false;
});
};
$scope.delete = function() {
ModalService.confirmDeletion(
'Do you want to remove this profile?',
function onConfirm(confirmed) {
if(!confirmed) { return; }
deleteProfile();
}
);
};
function deleteProfile() {
var profile = $scope.profile;
$scope.state.deleteInProgress = true;
StoridgeProfileService.delete(profile.Name)
.then(function success() {
Notifications.success('Profile successfully deleted');
$state.go('storidge.profiles');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to delete profile');
})
.finally(function final() {
$scope.state.deleteInProgress = false;
});
}
function initView() {
StoridgeProfileService.profile($transition$.params().id)
.then(function success(data) {
var profile = data;
if ((profile.MinIOPS && profile.MinIOPS !== 0) || (profile.MaxIOPS && profile.MaxIOPS !== 0)) {
$scope.state.LimitIOPS = true;
} else if ((profile.MinBandwidth && profile.MinBandwidth !== 0) || (profile.MaxBandwidth && profile.MaxBandwidth !== 0)) {
$scope.state.LimitBandwidth = true;
} else {
$scope.state.NoLimit = true;
}
if (profile.SnapshotEnabled && profile.SnapshotInterval !== 0) {
$scope.state.RecurringSnapshotEnabled = true;
}
initLabels(profile.Labels);
$scope.profile = profile;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve profile details');
});
}
initView();
}]);
initView();
},
]);

View file

@ -4,23 +4,20 @@
<i class="fa fa-sync" aria-hidden="true"></i>
</a>
</rd-header-title>
<rd-header-content>
<a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.profiles">Profiles</a>
</rd-header-content>
<rd-header-content> <a ui-sref="storidge.cluster">Storidge</a> &gt; <a ui-sref="storidge.profiles">Profiles</a> </rd-header-content>
</rd-header>
<div class="row">
<div class="col-md-12">
<rd-widget>
<rd-widget-header icon="fa-plus" title-text="Add a profile">
</rd-widget-header>
<rd-widget-header icon="fa-plus" title-text="Add a profile"> </rd-widget-header>
<rd-widget-body>
<form class="form-horizontal">
<!-- name-input -->
<div class="form-group">
<label for="profile_name" class="col-sm-1 control-label text-left">Name</label>
<div class="col-sm-11">
<input type="text" class="form-control" ng-model="formValues.Name" id="profile_name" placeholder="e.g. myProfile">
<input type="text" class="form-control" ng-model="formValues.Name" id="profile_name" placeholder="e.g. myProfile" />
</div>
</div>
<!-- !name-input -->
@ -33,11 +30,19 @@
<!-- !tag-note -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-click="create()" ng-disabled="state.actionInProgress || !formValues.Name" button-spinner="state.actionInProgress">
<button
type="button"
class="btn btn-primary btn-sm"
ng-click="create()"
ng-disabled="state.actionInProgress || !formValues.Name"
button-spinner="state.actionInProgress"
>
<span ng-hide="state.actionInProgress">Create the profile</span>
<span ng-show="state.actionInProgress">Creating profile...</span>
</button>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Name" ui-sref="storidge.profiles.new({ profileName: formValues.Name })">Modify defaults...</button>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Name" ui-sref="storidge.profiles.new({ profileName: formValues.Name })"
>Modify defaults...</button
>
</div>
</div>
</form>
@ -49,15 +54,16 @@
<div class="row">
<div class="col-sm-12">
<storidge-profiles-datatable
title-text="Profiles" title-icon="fa-sticky-note"
dataset="profiles" table-key="storidge_profiles"
order-by="Name"
remove-action="removeAction"
title-text="Profiles"
title-icon="fa-sticky-note"
dataset="profiles"
table-key="storidge_profiles"
order-by="Name"
remove-action="removeAction"
></storidge-profiles-datatable>
</div>
</div>
<!-- <div class="row">
<div class="col-md-12">
<rd-widget>

View file

@ -1,72 +1,76 @@
import _ from 'lodash-es';
import { StoridgeProfileDefaultModel } from '../../models/profile';
angular.module('portainer.integrations.storidge')
.controller('StoridgeProfilesController', ['$q', '$scope', '$state', 'Notifications', 'StoridgeProfileService',
function ($q, $scope, $state, Notifications, StoridgeProfileService) {
angular.module('portainer.integrations.storidge').controller('StoridgeProfilesController', [
'$q',
'$scope',
'$state',
'Notifications',
'StoridgeProfileService',
function ($q, $scope, $state, Notifications, StoridgeProfileService) {
$scope.state = {
actionInProgress: false,
};
$scope.state = {
actionInProgress: false
};
$scope.formValues = {
Name: '',
};
$scope.formValues = {
Name: ''
};
$scope.removeAction = function(selectedItems) {
var actionCount = selectedItems.length;
angular.forEach(selectedItems, function (profile) {
StoridgeProfileService.delete(profile.Name)
.then(function success() {
Notifications.success('Profile successfully removed', profile.Name);
var index = $scope.profiles.indexOf(profile);
$scope.profiles.splice(index, 1);
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove profile');
})
.finally(function final() {
--actionCount;
if (actionCount === 0) {
$state.reload();
}
$scope.removeAction = function (selectedItems) {
var actionCount = selectedItems.length;
angular.forEach(selectedItems, function (profile) {
StoridgeProfileService.delete(profile.Name)
.then(function success() {
Notifications.success('Profile successfully removed', profile.Name);
var index = $scope.profiles.indexOf(profile);
$scope.profiles.splice(index, 1);
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove profile');
})
.finally(function final() {
--actionCount;
if (actionCount === 0) {
$state.reload();
}
});
});
});
};
};
$scope.create = function() {
var model = new StoridgeProfileDefaultModel();
model.Labels = {};
model.Name = $scope.formValues.Name;
model.Directory = model.Directory + _.toLower(model.Name);
delete model.MinBandwidth;
delete model.MaxBandwidth;
delete model.MinIOPS;
delete model.MaxIOPS;
$scope.create = function () {
var model = new StoridgeProfileDefaultModel();
model.Labels = {};
model.Name = $scope.formValues.Name;
model.Directory = model.Directory + _.toLower(model.Name);
delete model.MinBandwidth;
delete model.MaxBandwidth;
delete model.MinIOPS;
delete model.MaxIOPS;
$scope.state.actionInProgress = true;
StoridgeProfileService.create(model)
.then(function success() {
Notifications.success('Profile successfully created');
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to create profile');
})
.finally(function final() {
$scope.state.actionInProgress = false;
});
};
$scope.state.actionInProgress = true;
StoridgeProfileService.create(model)
.then(function success() {
Notifications.success('Profile successfully created');
$state.reload();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to create profile');
})
.finally(function final() {
$scope.state.actionInProgress = false;
});
};
function initView() {
StoridgeProfileService.profiles()
.then(function success(data) {
$scope.profiles = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve profiles');
});
}
function initView() {
StoridgeProfileService.profiles()
.then(function success(data) {
$scope.profiles = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve profiles');
});
}
initView();
}]);
initView();
},
]);

View file

@ -1,7 +1,8 @@
<rd-header>
<rd-header-title title-text="Snasphot details"></rd-header-title>
<rd-header-content>
<a ui-sref="docker.volumes">Volumes</a> &gt; <a ui-sref="docker.volumes.volume({id: volumeId})">{{ volumeId }}</a> &gt; Snapshots &gt; <a ui-sref="docker.volumes.volume.snapshot({id: snapshot.Id})">{{ snapshot.Id }}</a>
<a ui-sref="docker.volumes">Volumes</a> &gt; <a ui-sref="docker.volumes.volume({id: volumeId})">{{ volumeId }}</a> &gt; Snapshots &gt;
<a ui-sref="docker.volumes.volume.snapshot({id: snapshot.Id})">{{ snapshot.Id }}</a>
</rd-header-content>
</rd-header>
@ -16,9 +17,7 @@
<td>ID</td>
<td>
{{ snapshot.Id }}
<button class="btn btn-xs btn-danger" ng-click="removeSnapshot()">
<i class="fa fa-trash space-right" aria-hidden="true"></i>Remove snapshot
</button>
<button class="btn btn-xs btn-danger" ng-click="removeSnapshot()"> <i class="fa fa-trash space-right" aria-hidden="true"></i>Remove snapshot </button>
</td>
</tr>
<tr>
@ -50,4 +49,4 @@
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>

View file

@ -1,44 +1,50 @@
angular.module('portainer.integrations.storidge')
.controller('StoridgeSnapshotController', ['$scope', '$state', '$transition$', 'Notifications', 'ModalService', 'StoridgeSnapshotService',
function ($scope, $state, $transition$, Notifications, ModalService, StoridgeSnapshotService) {
angular.module('portainer.integrations.storidge').controller('StoridgeSnapshotController', [
'$scope',
'$state',
'$transition$',
'Notifications',
'ModalService',
'StoridgeSnapshotService',
function ($scope, $state, $transition$, Notifications, ModalService, StoridgeSnapshotService) {
$scope.removeSnapshot = function () {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to remove this snapshot?',
buttons: {
confirm: {
label: 'Remove',
className: 'btn-danger',
},
},
callback: function onConfirm(confirmed) {
if (!confirmed) {
return;
}
StoridgeSnapshotService.remove($scope.snapshot.Id)
.then(function () {
Notifications.success('Success', 'Snapshot removed');
$state.go('portainer.volumes.volume', { id: $scope.volumeId });
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove snapshot');
});
},
});
};
$scope.removeSnapshot = function () {
ModalService.confirm({
title: 'Are you sure?',
message: 'Do you want really want to remove this snapshot?',
buttons: {
confirm: {
label: 'Remove',
className: 'btn-danger'
}
},
callback: function onConfirm(confirmed) {
if(!confirmed) { return; }
StoridgeSnapshotService.remove($scope.snapshot.Id)
.then(function () {
Notifications.success('Success', 'Snapshot removed');
$state.go('portainer.volumes.volume', {id: $scope.volumeId});
function initView() {
$scope.volumeId = $transition$.params().id;
$scope.snapshotId = $transition$.params().snapshotId;
StoridgeSnapshotService.snapshot($scope.snapshotId)
.then(function success(data) {
$scope.snapshot = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to remove snapshot');
Notifications.error('Failure', err, 'Unable to retrieve snapshot details');
});
}
});
};
}
function initView() {
$scope.volumeId = $transition$.params().id;
$scope.snapshotId = $transition$.params().snapshotId;
StoridgeSnapshotService.snapshot($scope.snapshotId)
.then(function success(data) {
$scope.snapshot = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve snapshot details');
});
}
initView();
}]);
initView();
},
]);