mirror of https://github.com/portainer/portainer
fix(service): service related UI issues [EE-4062] (#7943)
parent
93866644c6
commit
a2f734051c
|
@ -8,7 +8,7 @@
|
|||
<!-- name-input -->
|
||||
<div class="form-group">
|
||||
<label for="service_name" class="col-sm-2 control-label text-left">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" ng-model="formValues.Name" id="service_name" placeholder="e.g. myService" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -18,8 +18,8 @@
|
|||
<por-image-registry
|
||||
model="formValues.RegistryModel"
|
||||
auto-complete="true"
|
||||
label-class="col-sm-1"
|
||||
input-class="col-sm-11"
|
||||
label-class="col-sm-2"
|
||||
input-class="col-sm-8"
|
||||
endpoint="endpoint"
|
||||
is-admin="isAdmin"
|
||||
check-rate-limits="true"
|
||||
|
@ -30,29 +30,29 @@
|
|||
<div class="col-sm-12 form-section-title"> Scheduling </div>
|
||||
<!-- scheduling-mode -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left"> Scheduling mode </label>
|
||||
<div class="btn-group btn-group-sm" style="margin-left: 20px">
|
||||
<div>
|
||||
<label class="control-label col-sm-2 text-left"> Scheduling mode </label>
|
||||
<div class="btn-group btn-group-sm col-sm-8">
|
||||
<label class="btn btn-light" ng-model="formValues.Mode" uib-btn-radio="'global'">Global</label>
|
||||
<label class="btn btn-light" ng-model="formValues.Mode" uib-btn-radio="'replicated'">Replicated</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group form-inline" ng-if="formValues.Mode === 'replicated'">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left"> Replicas </label>
|
||||
<input type="number" class="form-control" ng-model="formValues.Replicas" id="replicas" placeholder="e.g. 3" style="margin-left: 20px" />
|
||||
<div>
|
||||
<label class="control-label col-sm-2 text-left"> Replicas </label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" ng-model="formValues.Replicas" id="replicas" placeholder="e.g. 3" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !scheduling-mode -->
|
||||
<div class="col-sm-12 form-section-title"> Ports configuration </div>
|
||||
<!-- port-mapping -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12" style="margin-top: 5px">
|
||||
<label class="control-label text-left">Port mapping</label>
|
||||
<span class="label label-default interactive vertical-center" style="margin-left: 10px" ng-click="addPortBinding()">
|
||||
<pr-icon icon="'plus'" mode="'alt'"></pr-icon> map additional port
|
||||
</span>
|
||||
<label class="control-label col-sm-2 text-left">Port mapping</label>
|
||||
<div class="col-sm-8 pt-2">
|
||||
<span class="label label-default interactive vertical-center" ng-click="addPortBinding()"> <pr-icon icon="'plus'" mode="'alt'"></pr-icon> map additional port </span>
|
||||
</div>
|
||||
<div class="col-sm-12 form-inline mt-2">
|
||||
<div ng-repeat="portBinding in formValues.Ports" class="mt-1">
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<rd-widget-body classes="no-padding">
|
||||
<div class="form-inline" style="padding: 10px" authorization="DockerServiceUpdate">
|
||||
Add a config:
|
||||
<select class="form-control" ng-options="config.Name for config in configs | orderBy: 'Name'" ng-model="newConfig">
|
||||
<select class="form-control !h-[30px] !text-[13px]" ng-options="config.Name for config in configs | orderBy: 'Name'" ng-model="newConfig">
|
||||
<option selected disabled hidden value="">Select a config</option>
|
||||
</select>
|
||||
<a class="btn btn-default btn-sm" ng-click="addConfig(service, newConfig)"> <pr-icon icon="'plus'"></pr-icon> add config </a>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<rd-widget>
|
||||
<rd-widget-header icon="list" title-text="Container spec"></rd-widget-header>
|
||||
<rd-widget-body classes="no-padding">
|
||||
<table class="table">
|
||||
<table class="!mb-0 table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>CMD</td>
|
||||
<td class="w-1/5">CMD</td>
|
||||
<td
|
||||
><code ng-if="service.Command">{{ service.Command | command }}</code></td
|
||||
>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<rd-widget-body classes="no-padding">
|
||||
<div class="form-inline" style="padding: 10px" authorization="DockerServiceUpdate">
|
||||
Driver:
|
||||
<select class="form-control" ng-model="service.LogDriverName" ng-change="updateLogDriverName(service)" ng-disabled="isUpdating">
|
||||
<select class="form-control !h-[30px] !text-[13px]" ng-model="service.LogDriverName" ng-change="updateLogDriverName(service)" ng-disabled="isUpdating">
|
||||
<option selected value="">Default logging driver</option>
|
||||
<option ng-repeat="driver in availableLoggingDrivers" ng-value="driver">{{ driver }}</option>
|
||||
<option value="none">none</option>
|
||||
|
@ -22,7 +22,7 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="option in service.LogDriverOpts">
|
||||
<td>
|
||||
<td class="w-1/2">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon fit-text-size">name</span>
|
||||
<input type="text" class="form-control" ng-model="option.key" ng-disabled="option.added || isUpdating" placeholder="e.g. FOO" />
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<p>There are no mounts for this service.</p>
|
||||
</rd-widget-body>
|
||||
<rd-widget-body ng-if="service.ServiceMounts.length > 0" classes="no-padding">
|
||||
<table class="table">
|
||||
<table class="mb-0 table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th ng-if="isAdmin || allowBindMounts">Type</th>
|
||||
|
@ -20,11 +20,11 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="mount in service.ServiceMounts">
|
||||
<td ng-if="isAdmin || allowBindMounts">
|
||||
<tr ng-repeat="(index, mount) in service.ServiceMounts">
|
||||
<td class="!pt-6 !align-top" ng-if="isAdmin || allowBindMounts">
|
||||
<select
|
||||
name="mountType"
|
||||
class="form-control"
|
||||
class="form-control !h-[30px] !text-[13px]"
|
||||
ng-model="mount.Type"
|
||||
ng-change="onChangeMountType(service, mount)"
|
||||
ng-disabled="isUpdating"
|
||||
|
@ -34,47 +34,53 @@
|
|||
<option value="bind">Bind</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<select
|
||||
class="form-control"
|
||||
ng-model="mount.Source"
|
||||
ng-change="updateMount(service, mount)"
|
||||
ng-options="vol.Id as ((vol.Id|truncate:30) + ' - ' + (vol.Driver|truncate:30)) for vol in availableVolumes"
|
||||
ng-if="mount.Type === 'volume'"
|
||||
disable-authorization="DockerServiceUpdate"
|
||||
<td class="!pt-6 !pb-0 !align-top">
|
||||
<div class="mb-6">
|
||||
<select
|
||||
class="form-control !h-[30px] !text-[13px]"
|
||||
ng-model="mount.Source"
|
||||
ng-change="updateMount(service, mount)"
|
||||
ng-options="vol.Id as ((vol.Id|truncate:30) + ' - ' + (vol.Driver|truncate:30)) for vol in availableVolumes"
|
||||
ng-if="mount.Type === 'volume'"
|
||||
disable-authorization="DockerServiceUpdate"
|
||||
>
|
||||
<option selected disabled hidden value="">Select a volume</option>
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control !h-[30px] !text-[13px]"
|
||||
name=""
|
||||
ng-model="mount.Source"
|
||||
placeholder="e.g. /tmp/portainer/data"
|
||||
ng-change="updateMount(service, mount)"
|
||||
ng-disabled="isUpdating || (!isAdmin && !allowBindMounts && mount.Type === 'bind')"
|
||||
ng-if="mount.Type === 'bind'"
|
||||
/>
|
||||
</div>
|
||||
<div class="small text-warning !-mt-6" ng-show="!mount.Source">
|
||||
<div class="vertical-center"><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Source is required. </div></div
|
||||
>
|
||||
<option selected disabled hidden value="">Select a volume</option>
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name=""
|
||||
ng-model="mount.Source"
|
||||
placeholder="e.g. /tmp/portainer/data"
|
||||
ng-change="updateMount(service, mount)"
|
||||
ng-disabled="isUpdating || (!isAdmin && !allowBindMounts && mount.Type === 'bind')"
|
||||
ng-if="mount.Type === 'bind'"
|
||||
/>
|
||||
<div class="col-sm-12 small text-warning" ng-show="!mount.Source"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Source is required. </div>
|
||||
</td>
|
||||
<td>
|
||||
<td class="!pt-6 !pb-0 !align-top">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
class="form-control mb-6 !h-[30px] !text-[13px]"
|
||||
ng-model="mount.Target"
|
||||
placeholder="e.g. /tmp/portainer/data"
|
||||
ng-change="updateMount(service, mount)"
|
||||
ng-disabled="isUpdating"
|
||||
disable-authorization="DockerServiceUpdate"
|
||||
/>
|
||||
<div class="col-sm-12 small text-warning" ng-show="!mount.Target"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Target is required. </div>
|
||||
<div class="small text-warning !-mt-6" ng-show="!mount.Target">
|
||||
<div class="vertical-center"><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Target is required. </div></div
|
||||
>
|
||||
</td>
|
||||
<td authorization="DockerServiceUpdate">
|
||||
<input type="checkbox" class="form-control" ng-model="mount.ReadOnly" ng-change="updateMount(service, mount)" ng-disabled="isUpdating" />
|
||||
<por-switch-field checked="mount.ReadOnly" disabled="isUpdating" on-change="(toggleMountReadOnly)" index="index"></por-switch-field>
|
||||
</td>
|
||||
<td authorization="DockerServiceUpdate">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-dangerlight" type="button" ng-click="removeMount(service, $index)" ng-disabled="isUpdating">
|
||||
<button class="btn btn-dangerlight btn-sm" type="button" ng-click="removeMount(service, $index)" ng-disabled="isUpdating">
|
||||
<pr-icon icon="'trash-2'" size="'md'"></pr-icon>
|
||||
</button>
|
||||
</span>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<td>
|
||||
<select
|
||||
ng-if="network.Editable"
|
||||
class="form-control"
|
||||
class="form-control !h-[30px] !rounded !text-[13px]"
|
||||
ng-model="network.Id"
|
||||
ng-change="updateNetwork(service)"
|
||||
ng-options="net.Id as net.Name for net in filterNetworks(swarmNetworks, network)"
|
||||
|
@ -42,7 +42,7 @@
|
|||
</td>
|
||||
<td ng-if="network.Editable" authorization="DockerServiceUpdate">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-dangerlight" type="button" ng-click="removeNetwork(service, $index)" ng-disabled="isUpdating">
|
||||
<button class="btn btn-sm btn-dangerlight" type="button" ng-click="removeNetwork(service, $index)" ng-disabled="isUpdating">
|
||||
<pr-icon icon="'trash-2'" size="'md'"></pr-icon>
|
||||
</button>
|
||||
</span>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<tr ng-repeat="portBinding in service.Ports">
|
||||
<td>
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon">host</span>
|
||||
<span class="input-group-addon !leading-none">host</span>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
|
@ -39,7 +39,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon">container</span>
|
||||
<span class="input-group-addon !leading-none">container</span>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
|
@ -54,7 +54,7 @@
|
|||
<td>
|
||||
<div class="input-group input-group-sm">
|
||||
<select
|
||||
class="selectpicker form-control"
|
||||
class="selectpicker form-control !rounded"
|
||||
ng-model="portBinding.Protocol"
|
||||
ng-change="updatePublishedPort(service, mapping)"
|
||||
ng-disabled="isUpdating"
|
||||
|
@ -68,7 +68,7 @@
|
|||
<td>
|
||||
<div class="input-group input-group-sm">
|
||||
<select
|
||||
class="selectpicker form-control"
|
||||
class="selectpicker form-control !rounded"
|
||||
ng-model="portBinding.PublishMode"
|
||||
ng-change="updatePublishedPort(service, mapping)"
|
||||
ng-disabled="isUpdating"
|
||||
|
@ -81,7 +81,7 @@
|
|||
</td>
|
||||
<td authorization="DockerServiceUpdate">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-dangerlight" type="button" ng-click="removePortPublishedBinding(service, $index)" ng-disabled="isUpdating">
|
||||
<button class="btn btn-sm btn-dangerlight" type="button" ng-click="removePortPublishedBinding(service, $index)" ng-disabled="isUpdating">
|
||||
<pr-icon icon="'trash-2'" size="'md'"></pr-icon>
|
||||
</button>
|
||||
</span>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<td>
|
||||
<div class="input-group input-group-sm">
|
||||
<select
|
||||
class="selectpicker form-control"
|
||||
class="selectpicker form-control !rounded"
|
||||
ng-model="service.RestartCondition"
|
||||
ng-change="updateServiceAttribute(service, 'RestartCondition')"
|
||||
disable-authorization="DockerServiceUpdate"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<rd-widget-body classes="no-padding">
|
||||
<div class="form-inline" style="padding: 10px" authorization="DockerServiceUpdate">
|
||||
Add a secret:
|
||||
<select class="form-control" ng-options="secret.Name for secret in secrets | orderBy: 'Name'" ng-model="state.addSecret.secret">
|
||||
<select class="form-control !h-[30px] !text-[13px]" ng-options="secret.Name for secret in secrets | orderBy: 'Name'" ng-model="state.addSecret.secret">
|
||||
<option selected disabled hidden value="">Select a secret</option>
|
||||
</select>
|
||||
<div class="form-group" ng-if="applicationState.endpoint.apiVersion >= 1.3 && state.addSecret.override">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<rd-widget>
|
||||
<rd-widget-header icon="list" title-text="Update configuration"> </rd-widget-header>
|
||||
<rd-widget-body classes="no-padding">
|
||||
<table class="table">
|
||||
<table class="mb-0 table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Update Parallelism</td>
|
||||
|
@ -38,8 +38,8 @@
|
|||
<tr>
|
||||
<td>Update Failure Action</td>
|
||||
<td>
|
||||
<div class="form-group">
|
||||
<label class="radio-inline">
|
||||
<div class="form-group !mb-0">
|
||||
<label class="radio-inline align-baseline">
|
||||
<input
|
||||
type="radio"
|
||||
name="failure_action"
|
||||
|
@ -50,7 +50,7 @@
|
|||
/>
|
||||
Continue
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<label class="radio-inline align-baseline">
|
||||
<input
|
||||
type="radio"
|
||||
name="failure_action"
|
||||
|
@ -70,7 +70,7 @@
|
|||
<tr ng-if="applicationState.endpoint.apiVersion >= 1.29">
|
||||
<td>Order</td>
|
||||
<td>
|
||||
<div class="form-group">
|
||||
<div class="form-group !mb-0">
|
||||
<label class="radio-inline">
|
||||
<input
|
||||
type="radio"
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-9 col-md-9 col-xs-9">
|
||||
<rd-widget>
|
||||
|
@ -17,7 +16,7 @@
|
|||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td class="w-1/5">Name</td>
|
||||
<td ng-if="applicationState.endpoint.apiVersion <= 1.24">
|
||||
<input type="text" class="form-control" ng-model="service.Name" ng-change="updateServiceAttribute(service, 'Name')" ng-disabled="isUpdating" />
|
||||
</td>
|
||||
|
@ -66,26 +65,29 @@
|
|||
<td>{{ service.Image }}</td>
|
||||
</tr>
|
||||
<tr ng-if="isAdmin && applicationState.endpoint.type !== 4">
|
||||
<td colspan="{{ webhookURL ? '1' : '2' }}">
|
||||
<por-switch-field
|
||||
tooltip="'Webhook (or callback URI) used 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.'"
|
||||
checked="WebhookExists"
|
||||
disabled="!isAdmin"
|
||||
on-change="(onWebhookChange)"
|
||||
label="'Service webhook'"
|
||||
></por-switch-field>
|
||||
</td>
|
||||
<td ng-if="webhookURL">
|
||||
<span class="text-muted">{{ webhookURL | truncatelr }}</span>
|
||||
<button type="button" class="btn btn-sm btn-primary btn-sm space-left" ng-if="webhookURL" ng-click="copyWebhook()">
|
||||
<span>
|
||||
<pr-icon icon="'copy'" class-name="'mr-1'"></pr-icon>
|
||||
Copy link</span
|
||||
<td>
|
||||
<div class="inline-flex items-center">
|
||||
<div> Service webhook </div>
|
||||
<portainer-tooltip
|
||||
message="'Webhook (or callback URI) used 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.'"
|
||||
>
|
||||
</button>
|
||||
<span>
|
||||
<pr-icon id="copyNotification" icon="'check'" mode="'success'" style="display: none"></pr-icon>
|
||||
</span>
|
||||
</portainer-tooltip>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex flex-wrap items-center">
|
||||
<por-switch-field label-class="'!mr-0'" checked="WebhookExists" disabled="disabledWebhookButton(WebhookExists)" on-change="(onWebhookChange)"></por-switch-field>
|
||||
<span ng-if="webhookURL">
|
||||
<span class="text-muted">{{ webhookURL | truncatelr }}</span>
|
||||
<button type="button" class="btn btn-sm btn-primary btn-sm space-left" ng-if="webhookURL" ng-click="copyWebhook()">
|
||||
<pr-icon icon="'copy'" class-name="'mr-1'"></pr-icon>
|
||||
Copy link
|
||||
</button>
|
||||
<span>
|
||||
<pr-icon id="copyNotification" icon="'check'" mode="'success'" style="display: none"></pr-icon>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr authorization="DockerServiceLogs, DockerServiceUpdate, DockerServiceDelete">
|
||||
|
|
|
@ -236,6 +236,13 @@ angular.module('portainer.docker').controller('ServiceController', [
|
|||
updateServiceArray(service, 'ServiceMounts', service.ServiceMounts);
|
||||
};
|
||||
|
||||
$scope.toggleMountReadOnly = function toggleMountReadOnly(isReadOnly, index) {
|
||||
$scope.$evalAsync(function () {
|
||||
updateServiceArray($scope.service, 'ServiceMounts', $scope.service.ServiceMounts);
|
||||
$scope.service.ServiceMounts[index].ReadOnly = isReadOnly;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.addNetwork = function addNetwork(service) {
|
||||
if (!service.Networks) {
|
||||
service.Networks = [];
|
||||
|
@ -334,9 +341,11 @@ angular.module('portainer.docker').controller('ServiceController', [
|
|||
};
|
||||
|
||||
$scope.onWebhookChange = function (enabled) {
|
||||
enabled = enabled | '';
|
||||
$scope.$evalAsync(() => {
|
||||
$scope.updateWebhook($scope.service);
|
||||
$scope.WebhookExists = enabled;
|
||||
updateServiceAttribute($scope.service, 'Webhooks', enabled);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -724,6 +733,7 @@ angular.module('portainer.docker').controller('ServiceController', [
|
|||
$scope.isAdmin = Authentication.isAdmin();
|
||||
$scope.availableNetworks = data.availableNetworks;
|
||||
$scope.swarmNetworks = _.filter($scope.availableNetworks, (network) => network.Scope === 'swarm');
|
||||
$scope.WebhookExists = false;
|
||||
|
||||
const serviceNetworks = _.uniqBy(_.concat($scope.service.Model.Spec.Networks || [], $scope.service.Model.Spec.TaskTemplate.Networks || []), 'Target');
|
||||
const networks = _.filter(
|
||||
|
|
|
@ -6,6 +6,15 @@
|
|||
<pr-icon icon="'alert-circle'" mode="'primary'"></pr-icon>
|
||||
Switch to advanced mode to copy & paste multiple variables
|
||||
</div>
|
||||
<div class="col-sm-12 form-inline env-items-list">
|
||||
<environment-variables-simple-mode-item
|
||||
ng-repeat="variable in $ctrl.ngModel"
|
||||
variable="variable"
|
||||
index="$index"
|
||||
on-change="($ctrl.onChangeVariable)"
|
||||
on-remove="($ctrl.remove)"
|
||||
></environment-variables-simple-mode-item>
|
||||
</div>
|
||||
<div class="col-sm-12 environment-variables-simple-mode--actions">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="$ctrl.add()"> <pr-icon icon="'plus'"></pr-icon> Add an environment variable </button>
|
||||
<button
|
||||
|
@ -24,15 +33,6 @@
|
|||
File too large! Try uploading a file smaller than 1MB
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-sm-12 form-inline env-items-list">
|
||||
<environment-variables-simple-mode-item
|
||||
ng-repeat="variable in $ctrl.ngModel"
|
||||
variable="variable"
|
||||
index="$index"
|
||||
on-change="($ctrl.onChangeVariable)"
|
||||
on-remove="($ctrl.remove)"
|
||||
></environment-variables-simple-mode-item>
|
||||
</div>
|
||||
<div class="col-sm-12 small text-muted" ng-if="$ctrl.ngModel.length > 0 && $ctrl.showHelpMessage">
|
||||
<pr-icon icon="'alert-circle'" mode="'primary'"></pr-icon>
|
||||
Environment changes will not take effect until redeployment occurs manually or via webhook.
|
||||
|
|
|
@ -5,6 +5,7 @@ import { SwitchField } from '@@/form-components/SwitchField';
|
|||
export const switchField = r2a(SwitchField, [
|
||||
'tooltip',
|
||||
'checked',
|
||||
'index',
|
||||
'label',
|
||||
'name',
|
||||
'labelClass',
|
||||
|
|
|
@ -13,8 +13,9 @@ export interface Props {
|
|||
checked: boolean;
|
||||
id: string;
|
||||
name: string;
|
||||
onChange(checked: boolean): void;
|
||||
onChange(checked: boolean, index?: number): void;
|
||||
|
||||
index?: number;
|
||||
className?: string;
|
||||
dataCy?: string;
|
||||
disabled?: boolean;
|
||||
|
@ -28,6 +29,7 @@ export function Switch({
|
|||
disabled,
|
||||
dataCy,
|
||||
onChange,
|
||||
index,
|
||||
featureId,
|
||||
className,
|
||||
}: Props) {
|
||||
|
@ -47,7 +49,7 @@ export function Switch({
|
|||
id={id}
|
||||
checked={checked}
|
||||
disabled={disabled || limitedToBE}
|
||||
onChange={({ target: { checked } }) => onChange(checked)}
|
||||
onChange={({ target: { checked } }) => onChange(checked, index)}
|
||||
/>
|
||||
<span className="slider round before:content-['']" data-cy={dataCy} />
|
||||
</label>
|
||||
|
|
|
@ -7,6 +7,7 @@ function renderDefault({
|
|||
checked = false,
|
||||
label = 'label',
|
||||
onChange = jest.fn(),
|
||||
index,
|
||||
}: Partial<Props> = {}) {
|
||||
return render(
|
||||
<SwitchField
|
||||
|
@ -14,6 +15,7 @@ function renderDefault({
|
|||
name={name}
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
index={index}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -33,5 +35,17 @@ test('clicking should emit on-change with the opposite value', async () => {
|
|||
const switchElem = await findByRole('checkbox');
|
||||
fireEvent.click(switchElem);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(!checked);
|
||||
expect(onChange).toHaveBeenCalledWith(!checked, undefined);
|
||||
});
|
||||
|
||||
test('clicking should emit on-change with the opposite value and index', async () => {
|
||||
const onChange = jest.fn();
|
||||
const checked = true;
|
||||
const index = 3;
|
||||
const { findByRole } = renderDefault({ onChange, checked, index });
|
||||
|
||||
const switchElem = await findByRole('checkbox');
|
||||
fireEvent.click(switchElem);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(!checked, index);
|
||||
});
|
||||
|
|
|
@ -11,8 +11,9 @@ import { Switch } from './Switch';
|
|||
export interface Props {
|
||||
label: string;
|
||||
checked: boolean;
|
||||
onChange(value: boolean): void;
|
||||
onChange(value: boolean, index?: number): void;
|
||||
|
||||
index?: number;
|
||||
name?: string;
|
||||
tooltip?: ComponentProps<typeof Tooltip>['message'];
|
||||
setTooltipHtmlMessage?: ComponentProps<typeof Tooltip>['setHtmlMessage'];
|
||||
|
@ -28,6 +29,7 @@ export function SwitchField({
|
|||
tooltip,
|
||||
checked,
|
||||
label,
|
||||
index,
|
||||
name,
|
||||
labelClass,
|
||||
fieldClass,
|
||||
|
@ -57,6 +59,7 @@ export function SwitchField({
|
|||
checked={checked}
|
||||
disabled={disabled}
|
||||
onChange={onChange}
|
||||
index={index}
|
||||
featureId={featureId}
|
||||
dataCy={dataCy}
|
||||
/>
|
||||
|
|
|
@ -47,7 +47,7 @@ export function AccessControlPanelDetails({
|
|||
<table className="table">
|
||||
<tbody>
|
||||
<tr data-cy="access-ownership">
|
||||
<td>Ownership</td>
|
||||
<td className="w-1/5">Ownership</td>
|
||||
<td>
|
||||
<i
|
||||
className={clsx(ownershipIcon(ownership), 'space-right')}
|
||||
|
|
Loading…
Reference in New Issue