Skip to content

Commit

Permalink
refactor(docker/switch/component): implement new design [EE-3688] (#1932
Browse files Browse the repository at this point in the history
)

* merge capabilities changes from Chaim

* refactor(docker/switch/component): implement new design [EE=3688]

* code review issues

* merge code

* feat(ui): UI improvements node details screen EE-3468 (#1926)

* merge code

* fix encode secret toggle bug on adding secret page

* fixed a bug for service webhook toggle
  • Loading branch information
Zhang Hao committed Jul 20, 2022
1 parent a98f3dc commit 77f9277
Show file tree
Hide file tree
Showing 16 changed files with 209 additions and 100 deletions.
@@ -0,0 +1,23 @@
export default class ContainerCapabilitiesController {
/* @ngInject */
constructor($scope) {
this.$scope = $scope;

this.oldCapabilities = [];
}

createOnChangeHandler(capability) {
return (checked) => {
this.$scope.$evalAsync(() => {
capability.allowed = checked;
});
};
}

$doCheck() {
if (this.oldCapabilities.length !== this.capabilities.length) {
this.oldCapabilities = this.capabilities;
this.capabilitiesOnChange = Object.fromEntries(this.capabilities.map((cap) => [cap.capability, this.createOnChangeHandler(cap)]));
}
}
}
@@ -1,6 +1,9 @@
import controller from './container-capabilities.controller';

angular.module('portainer.docker').component('containerCapabilities', {
templateUrl: './containerCapabilities.html',
bindings: {
capabilities: '=',
},
controller,
});
@@ -1,18 +1,15 @@
<form class="form-horizontal" style="margin-top: 15px">
<div class="col-sm-12 form-section-title"> Container capabilities </div>
<div class="form-group">
<div ng-repeat="cap in $ctrl.capabilities" class="col-xs-12 col-sm-6 col-md-4">
<div class="row">
<div class="col-xs-8">
<label for="capability" class="control-label text-left" style="display: flex; padding: 0">
{{ cap.capability }}
<portainer-tooltip message="cap.description"></portainer-tooltip>
</label>
</div>
<div class="col-xs-4">
<label class="switch"> <input type="checkbox" name="capability" ng-model="cap.allowed" /><i></i> </label>
</div>
</div>
<div class="form-group flex flex-wrap gap-y-2 px-5">
<div ng-repeat="cap in $ctrl.capabilities" class="w-1/3 text-center">
<por-switch-field
label-class="'col-sm-6'"
tooltip="cap.description"
checked="cap.allowed"
label="cap.capability"
name="'capability'"
on-change="($ctrl.capabilitiesOnChange[cap.capability])"
></por-switch-field>
</div>
</div>
</form>
8 changes: 4 additions & 4 deletions app/docker/components/imageRegistry/por-image-registry.html
Expand Up @@ -47,8 +47,8 @@
<div ng-if="!$ctrl.model.UseRegistry">
<div class="form-group">
<span class="small">
<p class="text-muted mb-5" style="margin-left: 15px">
<pr-icon icon="'alert-circle'" mode="'primary'" feather="true"></pr-icon>
<p class="text-muted" style="margin-left: 15px">
<i class="fa fa-exclamation-circle blue-icon" aria-hidden="true" style="margin-right: 2px"></i>
When using advanced mode, image and repository <b>must be</b> publicly available.
</p>
</span>
Expand All @@ -75,10 +75,10 @@
<div class="col-sm-12">
<p>
<a class="small interactive" ng-if="!$ctrl.model.UseRegistry" ng-click="$ctrl.model.UseRegistry = true;">
<i class="fa fa-database space-right" aria-hidden="true"></i> Simple mode
<pr-icon icon="'database'" feather="true"> </pr-icon> Simple mode
</a>
<a class="small interactive" ng-if="$ctrl.model.UseRegistry" ng-click="$ctrl.model.UseRegistry = false;">
<i class="fa fa-globe space-right" aria-hidden="true"></i> Advanced mode
<pr-icon icon="'globe'" feather="true"> </pr-icon> Advanced mode
</a>
</p>
</div>
Expand Down
42 changes: 42 additions & 0 deletions app/docker/views/containers/create/createContainerController.js
Expand Up @@ -110,6 +110,48 @@ angular.module('portainer.docker').controller('CreateContainerController', [
settingUnlimitedResources: false,
};

$scope.onAlwaysPullChange = onAlwaysPullChange;
$scope.handlePublishAllPortsChange = handlePublishAllPortsChange;
$scope.handleAutoRemoveChange = handleAutoRemoveChange;
$scope.handlePrivilegedChange = handlePrivilegedChange;
$scope.handleInitChange = handleInitChange;

function onAlwaysPullChange(checked) {
return $scope.$evalAsync(() => {
$scope.formValues.alwaysPull = checked;
});
}

function handlePublishAllPortsChange(checked) {
return $scope.$evalAsync(() => {
$scope.config.HostConfig.PublishAllPorts = checked;
});
}

function handleAutoRemoveChange(checked) {
return $scope.$evalAsync(() => {
$scope.config.HostConfig.AutoRemove = checked;
});
}

function handlePrivilegedChange(checked) {
return $scope.$evalAsync(() => {
$scope.config.HostConfig.Privileged = checked;
});
}

function handleInitChange(checked) {
return $scope.$evalAsync(() => {
$scope.config.HostConfig.Init = checked;
});
}

$scope.onEnableWebhookChange = function (checked) {
return $scope.$evalAsync(() => {
$scope.formValues.EnableWebhook = checked;
});
};

$scope.handleEnvVarChange = handleEnvVarChange;
function handleEnvVarChange(value) {
$scope.formValues.Env = value;
Expand Down
68 changes: 37 additions & 31 deletions app/docker/views/containers/create/createcontainer.html
Expand Up @@ -49,11 +49,15 @@
<!-- always-pull -->
<div class="form-group">
<div class="col-sm-12">
<label for="ownership" class="control-label text-left">
Always pull the image
<portainer-tooltip message="'When enabled, Portainer will automatically try to pull the specified image before creating the container.'"></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px"> <input type="checkbox" ng-model="formValues.alwaysPull" ng-disabled="!state.pullImageValidity" /><i></i> </label>
<por-switch-field
name="'alwaysPull'"
label-class="'col-sm-2'"
checked="formValues.alwaysPull"
disabled="!state.pullImageValidity"
label="'Always pull the image'"
on-change="(onAlwaysPullChange)"
tooltip="'When enabled, Portainer will automatically try to pull the specified image before creating the container.'"
></por-switch-field>
</div>
</div>
<!-- !always-pull -->
Expand All @@ -66,14 +70,13 @@
<div class="col-sm-12 form-section-title"> Webhooks </div>
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Create a container webhook
<portainer-tooltip
position="'top'"
message="'Create a webhook (or callback URI) to automate the recreate this container. Sending a POST request to this callback URI (without requiring any authentication) will pull the most up-to-date version of the associated image and recreate this container.'"
></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px"> <input type="checkbox" ng-model="formValues.EnableWebhook" /><i></i> </label>
<por-switch-field
checked="formValues.EnableWebhook"
on-change="(onEnableWebhookChange)"
label-class="'col-sm-2'"
label="'Create a container webhook'"
tooltip="'Create a webhook (or callback URI) to automate the recreate this container. Sending a POST request to this callback URI (without requiring any authentication) will pull the most up-to-date version of the associated image and recreate this container.'"
></por-switch-field>
</div>
</div>
</div>
Expand All @@ -83,13 +86,13 @@
<!-- publish-exposed-ports -->
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Publish all exposed network ports to random host ports
<portainer-tooltip
message="'When enabled, Portainer will let Docker automatically map a random port on the host to each one defined in the image Dockerfile.'"
></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px"> <input type="checkbox" ng-model="config.HostConfig.PublishAllPorts" /><i></i> </label>
<por-switch-field
label-class="'col-sm-2'"
checked="config.HostConfig.PublishAllPorts"
label="'Publish all exposed network ports to random host ports'"
on-change="(handlePublishAllPortsChange)"
tooltip="'When enabled, Portainer will let Docker automatically map a random port on the host to each one defined in the image Dockerfile.'"
></por-switch-field>
</div>
</div>
<!-- !publish-exposed-ports -->
Expand Down Expand Up @@ -154,13 +157,13 @@
<!-- autoremove -->
<div class="form-group">
<div class="col-sm-12">
<label for="ownership" class="control-label text-left">
Auto remove
<portainer-tooltip
message="'When enabled, Portainer will automatically remove the container when it exits. This is useful when you want to use the container only once.'"
></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px"> <input type="checkbox" ng-model="config.HostConfig.AutoRemove" /><i></i> </label>
<por-switch-field
label-class="'col-sm-2'"
checked="config.HostConfig.AutoRemove"
label="'Auto remove'"
on-change="(handleAutoRemoveChange)"
tooltip="'When enabled, Portainer will automatically remove the container when it exits. This is useful when you want to use the container only once.'"
></por-switch-field>
</div>
</div>
<!-- !autoremove -->
Expand Down Expand Up @@ -612,16 +615,19 @@
<!-- privileged-mode -->
<div class="form-group" ng-if="allowPrivilegedMode">
<div class="col-sm-12">
<label for="privileged_mode" class="control-label text-left"> Privileged mode </label>
<label class="switch" style="margin-left: 20px"> <input type="checkbox" name="privileged_mode" ng-model="config.HostConfig.Privileged" /><i></i> </label>
<por-switch-field
label-class="'col-sm-2'"
checked="config.HostConfig.Privileged"
label="'Privileged mode'"
on-change="(handlePrivilegedChange)"
></por-switch-field>
</div>
</div>
<!-- !privileged-mode -->
<!-- init -->
<div class="form-group" ng-if="applicationState.endpoint.apiVersion >= 1.37">
<div class="col-sm-12">
<label for="init" class="control-label text-left"> Init </label>
<label class="switch" style="margin-left: 20px"> <input type="checkbox" name="init" ng-model="config.HostConfig.Init" /><i></i> </label>
<por-switch-field label-class="'col-sm-2'" checked="config.HostConfig.Init" label="'Init'" on-change="(handleInitChange)"></por-switch-field>
</div>
</div>
<!-- !init -->
Expand Down
25 changes: 7 additions & 18 deletions app/docker/views/containers/edit/container.html
Expand Up @@ -113,20 +113,13 @@
"
>
<td colspan="{{ WebhookURL ? '1' : '2' }}">
Container webhook
<portainer-tooltip
position="'top'"
message="'Webhook (or callback URI) used to automate the recreation of this container. Sending a POST request to this callback URI (without requiring any authentication) will pull the most up-to-date version of the associated image and recreate this container.'"
></portainer-tooltip>
<label class="switch" style="margin-left: 20px">
<input
disable-authorization="DockerContainerUpdate"
type="checkbox"
ng-model="WebhookExists"
ng-click="updateWebhook(container, false)"
ng-disabled="disabledWebhookButton(WebhookExists)"
/><i></i>
</label>
<por-switch-field
tooltip="'Webhook (or callback URI) used to automate the recreation of this container. Sending a POST request to this callback URI (without requiring any authentication) will pull the most up-to-date version of the associated image and recreate this container.'"
checked="WebhookExists"
disabled="disabledWebhookButton(WebhookExists)"
on-change="(onWebhookChange)"
label="'Container webhook'"
></por-switch-field>
</td>
<td ng-if="WebhookExists && WebhookURL">
<span class="text-muted">{{ WebhookURL | truncatelr }}</span>
Expand Down Expand Up @@ -340,10 +333,6 @@
</table>
</td>
</tr>
<tr ng-if="container.HostConfig.DeviceRequests.length">
<td>GPUS</td>
<td>{{ computeDockerGPUCommand() }}</td>
</tr>
</tbody>
</table>
</rd-widget-body>
Expand Down
12 changes: 11 additions & 1 deletion app/docker/views/containers/edit/containerController.js
Expand Up @@ -82,6 +82,10 @@ angular.module('portainer.docker').controller('ContainerController', [
};

$scope.disabledWebhookButton = function (webhookExists) {
if (!Authentication.hasAuthorizations(['DockerContainerUpdate'])) {
return true;
}

if (webhookExists) {
return !$scope.hasAuthorizations(['PortainerWebhookDelete']);
}
Expand All @@ -93,6 +97,13 @@ angular.module('portainer.docker').controller('ContainerController', [
$scope.state.pullImageValidity = validity;
}

$scope.onWebhookChange = function (enabled) {
$scope.$evalAsync(() => {
$scope.updateWebhook($scope.container, false);
$scope.WebhookExists = enabled;
});
};

$scope.updateRestartPolicy = updateRestartPolicy;
$scope.updateWebhook = function updateWebhook(container, recreate) {
if (($scope.WebhookExists && recreate) || (!$scope.WebhookExists && !recreate)) {
Expand All @@ -102,7 +113,6 @@ angular.module('portainer.docker').controller('ContainerController', [
.then(function success() {
$scope.WebhookURL = null;
$scope.WebhookID = null;
$scope.WebhookExists = false;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to delete webhook');
Expand Down
8 changes: 8 additions & 0 deletions app/docker/views/secrets/create/createSecretController.js
Expand Up @@ -23,6 +23,14 @@ angular.module('portainer.docker').controller('CreateSecretController', [
actionInProgress: false,
};

$scope.handleEncodeSecretChange = handleEncodeSecretChange;

function handleEncodeSecretChange(checked) {
return $scope.$evalAsync(() => {
$scope.formValues.encodeSecret = checked;
});
}

$scope.addLabel = function () {
$scope.formValues.Labels.push({ key: '', value: '' });
};
Expand Down
12 changes: 7 additions & 5 deletions app/docker/views/secrets/create/createsecret.html
Expand Up @@ -24,11 +24,13 @@
<!-- encode-secret -->
<div class="form-group">
<div class="col-sm-12">
<label for="encode_secret" class="control-label text-left">
Encode secret
<portainer-tooltip message="'Secrets need to be base64 encoded. Disable this if your secret is already base64 encoded.'"></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px"> <input type="checkbox" name="encode_secret" ng-model="formValues.encodeSecret" /><i></i> </label>
<por-switch-field
label-class="'col-sm-2'"
checked="formValues.encodeSecret"
label="'Encode secret'"
on-change="(handleEncodeSecretChange)"
tooltip="'Secrets need to be base64 encoded. Disable this if your secret is already base64 encoded.'"
></por-switch-field>
</div>
</div>
<!-- !encode-secret -->
Expand Down
8 changes: 8 additions & 0 deletions app/docker/views/services/create/createServiceController.js
Expand Up @@ -111,6 +111,14 @@ angular.module('portainer.docker').controller('CreateServiceController', [

$scope.allowBindMounts = false;

$scope.handleWebHookChange = handleWebHookChange;

function handleWebHookChange(checked) {
return $scope.$evalAsync(() => {
$scope.formValues.Webhook = checked;
});
}

$scope.handleEnvVarChange = handleEnvVarChange;
function handleEnvVarChange(value) {
$scope.formValues.Env = value;
Expand Down
15 changes: 7 additions & 8 deletions app/docker/views/services/create/createservice.html
Expand Up @@ -96,14 +96,13 @@
<div class="col-sm-12 form-section-title"> Webhooks </div>
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Create a service webhook
<portainer-tooltip
position="'top'"
message="Create a webhook (or callback URI) to automate the update of this service. Sending a POST request to this callback URI (without requiring any authentication) will pull the most up-to-date version of the associated image and re-deploy this service."
></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px"> <input type="checkbox" ng-model="formValues.Webhook" /><i></i> </label>
<por-switch-field
label-class="'col-sm-2'"
checked="$ctrl.formValues.Webhook"
label="'Create a service webhook'"
on-change="(handleWebHookChange)"
tooltip="'Create a webhook (or callback URI) to automate the update of this service. Sending a POST request to this callback URI (without requiring any authentication) will pull the most up-to-date version of the associated image and re-deploy this service.'"
></por-switch-field>
</div>
</div>
</div>
Expand Down

0 comments on commit 77f9277

Please sign in to comment.