mirror of
https://github.com/portainer/portainer.git
synced 2025-08-07 23:05:26 +02:00
chore(deps): upgrade tailwind and prettier [EE-5218] (#10068)
This commit is contained in:
parent
cb7377ead6
commit
0e2eb17220
69 changed files with 444 additions and 316 deletions
|
@ -19,7 +19,7 @@ describe('mockT', () => {
|
|||
${'{{number}} of {{total}}'} | ${{ number: 0, total: 999 }} | ${'0 of 999'}
|
||||
${'There was an error:\n{{error}}'} | ${{ error: 'Failed' }} | ${'There was an error:\nFailed'}
|
||||
${'Click:{{li}}{{li2}}{{li_3}}'} | ${{ li: '', li2: 'https://', li_3: '!@#$%' }} | ${'Click:https://!@#$%'}
|
||||
${'{{happy}}😏y✔{{sad}}{{laugh}}'} | ${{ happy: '😃', sad: '😢', laugh: '🤣' }} | ${'😃😏y✔😢🤣'}
|
||||
${'{{happy}}😏y✔{{sad}}{{laugh}}'} | ${{ happy: '😃', sad: '😢', laugh: '🤣' }} | ${'😃😏y✔😢🤣'}
|
||||
`(
|
||||
'should return correctly while handling arguments in different scenarios',
|
||||
({ testText, args, expectedText }) => {
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
@font-face {
|
||||
font-family: 'nomad-icon';
|
||||
src: url('nomad-icon/nomad-icon.eot?6tre2n');
|
||||
src: url('nomad-icon/nomad-icon.eot?6tre2n#iefix') format('embedded-opentype'), url('nomad-icon/nomad-icon.ttf?6tre2n') format('truetype'),
|
||||
url('nomad-icon/nomad-icon.woff?6tre2n') format('woff'), url('nomad-icon/nomad-icon.svg?6tre2n#nomad-icon') format('svg');
|
||||
src:
|
||||
url('nomad-icon/nomad-icon.eot?6tre2n#iefix') format('embedded-opentype'),
|
||||
url('nomad-icon/nomad-icon.ttf?6tre2n') format('truetype'),
|
||||
url('nomad-icon/nomad-icon.woff?6tre2n') format('woff'),
|
||||
url('nomad-icon/nomad-icon.svg?6tre2n#nomad-icon') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</td>
|
||||
<td ng-if="!allowCheckbox"></td>
|
||||
<td>
|
||||
<a ui-sref="docker.networks.network({ id: item.Id, nodeName: item.NodeName })" title="{{ item.Name }}">{{ item.Name | truncate : 40 }}</a>
|
||||
<a ui-sref="docker.networks.network({ id: item.Id, nodeName: item.NodeName })" title="{{ item.Name }}">{{ item.Name | truncate: 40 }}</a>
|
||||
<span style="margin-left: 10px" class="label label-info image-tag space-left" ng-if="item.ResourceControl.System">System</span>
|
||||
</td>
|
||||
<td>{{ item.StackName ? item.StackName : '-' }}</td>
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
></container-quick-actions>
|
||||
</td>
|
||||
<td>{{ item.Slot ? item.Slot : '-' }}</td>
|
||||
<td>{{ item.NodeId | tasknodename : $ctrl.nodes }}</td>
|
||||
<td>{{ item.NodeId | tasknodename: $ctrl.nodes }}</td>
|
||||
<td>{{ item.Updated | getisodate }}</td>
|
||||
</tr>
|
||||
<tr ng-if="$ctrl.state.filteredDataSet.length === 0">
|
||||
|
|
|
@ -180,7 +180,7 @@
|
|||
<td ng-show="$ctrl.columnVisibility.columns.image.display">{{ item.Image | hideshasum }}</td>
|
||||
<td ng-controller="ServicesDatatableActionsController as actionCtrl">
|
||||
{{ item.Mode }}
|
||||
<code>{{ item.Tasks | runningtaskscount }}</code> / <code>{{ item.Mode === 'replicated' ? item.Replicas : ($ctrl.nodes | availablenodecount : item) }}</code>
|
||||
<code>{{ item.Tasks | runningtaskscount }}</code> / <code>{{ item.Mode === 'replicated' ? item.Replicas : ($ctrl.nodes | availablenodecount: item) }}</code>
|
||||
<span ng-if="item.Mode === 'replicated' && !item.Scale" authorization="DockerServiceUpdate">
|
||||
<a class="interactive vertical-center" ng-click="item.Scale = true; item.ReplicaCount = item.Replicas; $event.stopPropagation();">
|
||||
<pr-icon icon="'minimize-2'"></pr-icon>
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
></container-quick-actions>
|
||||
</td>
|
||||
<td ng-if="$ctrl.showSlotColumn">{{ item.Slot ? item.Slot : '-' }}</td>
|
||||
<td>{{ item.NodeId | tasknodename : $ctrl.nodes }}</td>
|
||||
<td>{{ item.NodeId | tasknodename: $ctrl.nodes }}</td>
|
||||
<td>{{ item.Updated | getisodate }}</td>
|
||||
</tr>
|
||||
<tr ng-if="!$ctrl.dataset">
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
<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="docker.volumes.volume({ id: item.Id, nodeName: item.NodeName })" class="monospaced" title="{{ item.Id }}">{{ item.Id | truncate : 40 }}</a>
|
||||
<a ui-sref="docker.volumes.volume({ id: item.Id, nodeName: item.NodeName })" class="monospaced" title="{{ item.Id }}">{{ item.Id | truncate: 40 }}</a>
|
||||
|
||||
<button
|
||||
ng-if="$ctrl.showBrowseAction"
|
||||
|
|
|
@ -25,15 +25,15 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>Volume Plugins</td>
|
||||
<td>{{ $ctrl.engine.volumePlugins | arraytostr : ', ' }}</td>
|
||||
<td>{{ $ctrl.engine.volumePlugins | arraytostr: ', ' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Network Plugins</td>
|
||||
<td>{{ $ctrl.engine.networkPlugins | arraytostr : ', ' }}</td>
|
||||
<td>{{ $ctrl.engine.networkPlugins | arraytostr: ', ' }}</td>
|
||||
</tr>
|
||||
<tr ng-if="$ctrl.engine.engineLabels.length">
|
||||
<td>Engine Labels</td>
|
||||
<td>{{ $ctrl.engine.engineLabels | labelsToStr : ', ' }}</td>
|
||||
<td>{{ $ctrl.engine.engineLabels | labelsToStr: ', ' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -401,7 +401,7 @@
|
|||
<span class="input-group-addon">volume</span>
|
||||
<select class="form-control" ng-model="volume.name">
|
||||
<option selected disabled hidden value="">Select a volume</option>
|
||||
<option ng-repeat="vol in availableVolumes" ng-value="vol.Name">{{ vol.Name | truncate : 30 }} - {{ vol.Driver | truncate : 30 }}</option>
|
||||
<option ng-repeat="vol in availableVolumes" ng-value="vol.Name">{{ vol.Name | truncate: 30 }} - {{ vol.Driver | truncate: 30 }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- !volume -->
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
</span>
|
||||
</rd-widget-header>
|
||||
<rd-widget-body>
|
||||
<pre ng-show="state.DisplayTextView">{{ containerInfo | json : 4 }}</pre>
|
||||
<pre ng-show="state.DisplayTextView">{{ containerInfo | json: 4 }}</pre>
|
||||
<json-tree ng-hide="state.DisplayTextView" object="containerInfo" root-name="containerInfo.Id" start-expanded="true"></json-tree>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="pull-left" ng-repeat="tag in image.RepoTags" style="display: table">
|
||||
<div class="input-group col-md-1 !pr-3.5 !pl-3.5">
|
||||
<div class="input-group col-md-1 !pl-3.5 !pr-3.5">
|
||||
<span class="input-group-addon" style="border-right: 1px solid var(--border-input-group-addon-color); border-radius: 4px" data-cy="image-tag-{{ tag }}">{{
|
||||
tag
|
||||
}}</span>
|
||||
|
@ -20,13 +20,13 @@
|
|||
</a>
|
||||
</span>
|
||||
|
||||
<span class="my-0 mx-1" authorization="DockerImageCreate">
|
||||
<span class="mx-1 my-0" authorization="DockerImageCreate">
|
||||
<a data-toggle="tooltip" class="btn btn-primary interactive" title="Pull from registry" ng-click="pullTag(tag)">
|
||||
<pr-icon icon="'download'" class="text-white"></pr-icon>
|
||||
</a>
|
||||
</span>
|
||||
|
||||
<span class="my-0 mx-1" authorization="DockerImageDelete">
|
||||
<span class="mx-1 my-0" authorization="DockerImageDelete">
|
||||
<a data-toggle="tooltip" class="btn btn-primary interactive" title="Remove tag" ng-click="removeTag(tag)">
|
||||
<pr-icon icon="'trash-2'" class="text-white"></pr-icon>
|
||||
</a>
|
||||
|
@ -213,7 +213,7 @@
|
|||
{{ layer.CreatedBy | imagelayercommand }}
|
||||
</span>
|
||||
<span id="layer-command-{{ $index }}-short">
|
||||
{{ layer.CreatedBy | imagelayercommand | truncate : 130 }}
|
||||
{{ layer.CreatedBy | imagelayercommand | truncate: 130 }}
|
||||
<span ng-if="layer.CreatedBy.length > 130" class="ml-1">
|
||||
<a id="layer-command-expander{{ $index }}" class="btn" ng-click="toggleLayerCommand($index)">
|
||||
<pr-icon icon="'plus'" mode="'alt'"></pr-icon>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<option value="bind">Bind</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="!pt-6 !pb-0 !align-top">
|
||||
<td class="!pb-0 !pt-6 !align-top">
|
||||
<div class="mb-6">
|
||||
<select
|
||||
class="form-control !h-[30px] !text-[13px]"
|
||||
|
@ -61,7 +61,7 @@
|
|||
<div class="vertical-center"><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Source is required. </div></div
|
||||
>
|
||||
</td>
|
||||
<td class="!pt-6 !pb-0 !align-top">
|
||||
<td class="!pb-0 !pt-6 !align-top">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control mb-6 !h-[30px] !text-[13px]"
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>Total memory</td>
|
||||
<td>{{ totalMemory | humansize : 2 }}</td>
|
||||
<td>{{ totalMemory | humansize: 2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
</div>
|
||||
<div>{{ node.Role }}</div>
|
||||
<div>CPU: {{ node.CPUs / 1000000000 }}</div>
|
||||
<div>Memory: {{ node.Memory | humansize : 2 }}</div>
|
||||
<div>Memory: {{ node.Memory | humansize: 2 }}</div>
|
||||
<div
|
||||
><span class="label label-{{ node.Status | nodestatusbadge }}">{{ node.Status }}</span></div
|
||||
>
|
||||
|
@ -114,7 +114,7 @@
|
|||
<div>Image: {{ task.Spec.ContainerSpec.Image | hideshasum }}</div>
|
||||
<div>Status: {{ task.Status.State }}</div>
|
||||
<div>Update: {{ task.Updated | getisodate }}</div>
|
||||
<div ng-if="task.Spec.Resources.Limits.MemoryBytes">Memory limit: {{ task.Spec.Resources.Limits.MemoryBytes | humansize : 2 : 2 }}</div>
|
||||
<div ng-if="task.Spec.Resources.Limits.MemoryBytes">Memory limit: {{ task.Spec.Resources.Limits.MemoryBytes | humansize: 2 : 2 }}</div>
|
||||
<div ng-if="task.Spec.Resources.Limits.NanoCPUs">CPU limit: {{ task.Spec.Resources.Limits.NanoCPUs / 1000000000 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en" ng-app="<%= name %>" ng-strict-di data-edition="<%= process.env.PORTAINER_EDITION %>">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
|
|
@ -289,7 +289,7 @@
|
|||
<a ui-sref="kubernetes.resourcePools.resourcePool({ id: item.ResourcePool })" ng-click="$event.stopPropagation()">{{ item.ResourcePool }}</a>
|
||||
</td>
|
||||
<td title="{{ item.Image }}"
|
||||
>{{ item.Image | truncate : 64 }} <span ng-if="item.Containers.length > 1">+ {{ item.Containers.length - 1 }}</span></td
|
||||
>{{ item.Image | truncate: 64 }} <span ng-if="item.Containers.length > 1">+ {{ item.Containers.length - 1 }}</span></td
|
||||
>
|
||||
<td>{{ item.ApplicationType | kubernetesApplicationTypeText }}</td>
|
||||
<td ng-if="item.ApplicationType !== $ctrl.KubernetesApplicationTypes.POD">
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
><a ui-sref="kubernetes.applications.application({ name: item.Name, namespace: item.ResourcePool })">{{ item.Name }}</a></td
|
||||
>
|
||||
<td>{{ item.StackName || '-' }}</td>
|
||||
<td title="{{ item.Image }}">{{ item.Image | truncate : 64 }}</td>
|
||||
<td title="{{ item.Image }}">{{ item.Image | truncate: 64 }}</td>
|
||||
</tr>
|
||||
<tr ng-if="!$ctrl.dataset">
|
||||
<td colspan="3" class="text-muted text-center">Loading...</td>
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
<a ui-sref="kubernetes.resourcePools.resourcePool({ id: item.ResourcePool })">{{ item.ResourcePool }}</a>
|
||||
</td>
|
||||
<td title="{{ item.Image }}"
|
||||
>{{ item.Image | truncate : 64 }} <span ng-if="item.Containers.length > 1">+ {{ item.Containers.length - 1 }}</span></td
|
||||
>{{ item.Image | truncate: 64 }} <span ng-if="item.Containers.length > 1">+ {{ item.Containers.length - 1 }}</span></td
|
||||
>
|
||||
<td>{{ item.CPU | kubernetesApplicationCPUValue }}</td>
|
||||
<td>{{ item.Memory | humansize }}</td>
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
</td>
|
||||
<td>{{ item.StackName || '-' }}</td>
|
||||
<td title="{{ item.Image }}"
|
||||
>{{ item.Image | truncate : 64 }} <span ng-if="item.Containers.length > 1">+ {{ item.Containers.length - 1 }}</span></td
|
||||
>{{ item.Image | truncate: 64 }} <span ng-if="item.Containers.length > 1">+ {{ item.Containers.length - 1 }}</span></td
|
||||
>
|
||||
<td>{{ item.CPU | kubernetesApplicationCPUValue }}</td>
|
||||
<td>{{ item.Memory | humansize }}</td>
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
<div class="col-sm-12">
|
||||
<button
|
||||
ng-if="!$ctrl.state.showCustomValues && !$ctrl.state.loadingValues"
|
||||
class="btn btn-xs btn-default vertical-center mr-2 !ml-0"
|
||||
class="btn btn-xs btn-default vertical-center !ml-0 mr-2"
|
||||
ng-click="$ctrl.state.showCustomValues = true;"
|
||||
>
|
||||
<pr-icon icon="'plus'" class="vertical-center"></pr-icon>
|
||||
|
@ -102,7 +102,7 @@
|
|||
<pr-icon icon="'refresh-cw'" class="mr-1"></pr-icon>
|
||||
Loading values.yaml...
|
||||
</span>
|
||||
<button ng-if="$ctrl.state.showCustomValues" class="btn btn-xs btn-default vertical-center mr-2 !ml-0" ng-click="$ctrl.state.showCustomValues = false;">
|
||||
<button ng-if="$ctrl.state.showCustomValues" class="btn btn-xs btn-default vertical-center !ml-0 mr-2" ng-click="$ctrl.state.showCustomValues = false;">
|
||||
<pr-icon icon="'minus'" class="vertical-center"></pr-icon>
|
||||
Hide custom values
|
||||
</button>
|
||||
|
|
|
@ -1218,85 +1218,86 @@
|
|||
|
||||
<div class="col-sm-12 form-inline">
|
||||
<div ng-repeat-start="placement in ctrl.formValues.Placements" class="!mb-2">
|
||||
<div class="col-sm-5 input-group mr-2 ng-class=" { striked: placement.NeedsDeletion }">
|
||||
<select
|
||||
class="form-control !rounded"
|
||||
ng-model="placement.Label"
|
||||
ng-options="label as (label.Key | kubernetesNodeLabelHumanReadbleText) for label in ctrl.nodesLabels"
|
||||
ng-change="ctrl.onChangePlacementLabel($index)"
|
||||
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
|
||||
data-cy="k8sAppCreate-placementLabel_{{ $index }}"
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-5 input-group mr-2" ng-class="{ striked: placement.NeedsDeletion }">
|
||||
<select
|
||||
class="form-control !rounded"
|
||||
ng-model="placement.Value"
|
||||
ng-options="value for value in placement.Label.Values"
|
||||
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
|
||||
data-cy="k8sAppCreate-placementName_{{ $index }}"
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-5 input-group mr-2" ng-class="{ striked: placement.NeedsDeletion }">
|
||||
<select
|
||||
class="form-control !rounded"
|
||||
ng-model="placement.Label"
|
||||
ng-options="label as (label.Key | kubernetesNodeLabelHumanReadbleText) for label in ctrl.nodesLabels"
|
||||
ng-change="ctrl.onChangePlacementLabel($index)"
|
||||
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
|
||||
data-cy="k8sAppCreate-placementLabel_{{ $index }}"
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-5 input-group mr-2" ng-class="{ striked: placement.NeedsDeletion }">
|
||||
<select
|
||||
class="form-control !rounded"
|
||||
ng-model="placement.Value"
|
||||
ng-options="value for value in placement.Label.Values"
|
||||
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
|
||||
data-cy="k8sAppCreate-placementName_{{ $index }}"
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-1 input-group">
|
||||
<button
|
||||
ng-if="!placement.NeedsDeletion"
|
||||
class="btn btn-md btn-dangerlight btn-only-icon !ml-0"
|
||||
type="button"
|
||||
ng-click="ctrl.removePlacement($index)"
|
||||
data-cy="k8sAppCreate-deletePlacementButton"
|
||||
>
|
||||
<pr-icon icon="'trash-2'" size="'md'"></pr-icon>
|
||||
</button>
|
||||
<button
|
||||
ng-if="placement.NeedsDeletion"
|
||||
class="btn btn-sm btn-light btn-only-icon !ml-0"
|
||||
type="button"
|
||||
ng-click="ctrl.restorePlacement($index)"
|
||||
data-cy="k8sAppCreate-restorePlacementButton"
|
||||
>
|
||||
<pr-icon icon="'rotate-cw'" size="'md'"></pr-icon>
|
||||
</button>
|
||||
<div class="col-sm-1 input-group">
|
||||
<button
|
||||
ng-if="!placement.NeedsDeletion"
|
||||
class="btn btn-md btn-dangerlight btn-only-icon !ml-0"
|
||||
type="button"
|
||||
ng-click="ctrl.removePlacement($index)"
|
||||
data-cy="k8sAppCreate-deletePlacementButton"
|
||||
>
|
||||
<pr-icon icon="'trash-2'" size="'md'"></pr-icon>
|
||||
</button>
|
||||
<button
|
||||
ng-if="placement.NeedsDeletion"
|
||||
class="btn btn-sm btn-light btn-only-icon !ml-0"
|
||||
type="button"
|
||||
ng-click="ctrl.restorePlacement($index)"
|
||||
data-cy="k8sAppCreate-restorePlacementButton"
|
||||
>
|
||||
<pr-icon icon="'rotate-cw'" size="'md'"></pr-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-repeat-end ng-show="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<div class="col-sm-5 input-group">
|
||||
<div class="small text-warning" ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<p class="vertical-center" ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> This label is already defined.
|
||||
</p>
|
||||
<div ng-repeat-end ng-show="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<div class="col-sm-5 input-group">
|
||||
<div class="small text-warning" ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<p class="vertical-center" ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> This label is already defined.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<span class="btn btn-primary btn-sm btn btn-sm btn-light mb-2 !ml-0 mt-2" ng-click="ctrl.addPlacement()">
|
||||
<pr-icon icon="'plus'" size="'sm'"></pr-icon> Add rule
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="ctrl.showPlacementPolicySection()">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">Placement policy</label>
|
||||
<span class="btn btn-primary btn-sm btn btn-sm btn-light mb-2 !ml-0 mt-2" ng-click="ctrl.addPlacement()">
|
||||
<pr-icon icon="'plus'" size="'sm'"></pr-icon> Add rule
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="ctrl.showPlacementPolicySection()">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">Placement policy</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12 small text-muted"> Specify the policy associated to the placement rules. </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12 small text-muted"> Specify the policy associated to the placement rules. </div>
|
||||
</div>
|
||||
|
||||
<box-selector
|
||||
ng-if="ctrl.formValues.Placements.length"
|
||||
options="ctrl.placementOptions"
|
||||
slim="true"
|
||||
value="ctrl.formValues.PlacementType"
|
||||
on-change="(ctrl.onChangePlacementType)"
|
||||
radio-name="'placementType'"
|
||||
></box-selector>
|
||||
</div>
|
||||
|
||||
<box-selector
|
||||
ng-if="ctrl.formValues.Placements.length"
|
||||
options="ctrl.placementOptions"
|
||||
slim="true"
|
||||
value="ctrl.formValues.PlacementType"
|
||||
on-change="(ctrl.onChangePlacementType)"
|
||||
radio-name="'placementType'"
|
||||
></box-selector>
|
||||
</div>
|
||||
<!-- #endregion -->
|
||||
</div>
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
|
||||
<div
|
||||
ng-if="!ctrl.isRBACEnabled"
|
||||
class="small mt-1 mb-6 flex w-full gap-1 rounded-lg border border-solid border-warning-5 bg-warning-2 p-4 text-warning-8 th-highcontrast:bg-yellow-11 th-highcontrast:text-white th-dark:bg-yellow-11 th-dark:text-white"
|
||||
class="small mb-6 mt-1 flex w-full gap-1 rounded-lg border border-solid border-warning-5 bg-warning-2 p-4 text-warning-8 th-highcontrast:bg-yellow-11 th-highcontrast:text-white th-dark:bg-yellow-11 th-dark:text-white"
|
||||
>
|
||||
<div class="mt-0.5">
|
||||
<pr-icon icon="'alert-triangle'" feather="true" class-name="'text-warning-7 th-dark:text-white th-highcontrast:text-white'"></pr-icon>
|
||||
|
@ -281,7 +281,7 @@
|
|||
<tr ng-repeat="class in ctrl.StorageClasses">
|
||||
<td>
|
||||
<div class="flex h-full flex-row items-center">
|
||||
<label class="switch mr-2 mb-0">
|
||||
<label class="switch mb-0 mr-2">
|
||||
<input type="checkbox" ng-model="class.selected" /><span class="slider round" data-cy="kubeSetup-storageToggle{{ class.Name }}"></span>
|
||||
</label>
|
||||
<span>{{ class.Name }}</span>
|
||||
|
@ -297,7 +297,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<div class="flex h-full flex-row items-center">
|
||||
<label class="switch mr-2 mb-0"
|
||||
<label class="switch mb-0 mr-2"
|
||||
><input type="checkbox" ng-model="class.AllowVolumeExpansion" /><span
|
||||
class="slider round"
|
||||
data-cy="kubeSetup-storageExpansionToggle{{ class.Name }}"
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<tr
|
||||
ng-if="
|
||||
$ctrl.dataset.length === 0 ||
|
||||
($ctrl.dataset | filter : $ctrl.state.textFilter | orderBy : $ctrl.state.orderBy : $ctrl.state.reverseOrder | itemsPerPage : $ctrl.state.paginatedItemLimit).length === 0
|
||||
($ctrl.dataset | filter: $ctrl.state.textFilter | orderBy: $ctrl.state.orderBy : $ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit).length === 0
|
||||
"
|
||||
>
|
||||
<td colspan="2" class="text-muted text-center">{{ $ctrl.emptyDatasetMessage }}</td>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
</template-item-actions>
|
||||
</template-item>
|
||||
<div ng-if="!$ctrl.templates" class="text-muted text-center"> Loading... </div>
|
||||
<div ng-if="($ctrl.templates | filter : $ctrl.state.textFilter).length === 0" class="text-muted text-center"> No templates available. </div>
|
||||
<div ng-if="($ctrl.templates | filter: $ctrl.state.textFilter).length === 0" class="text-muted text-center"> No templates available. </div>
|
||||
</div>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
|
|
|
@ -12,9 +12,12 @@ angular.module('portainer.app').directive('focusIf', function ($timeout) {
|
|||
}
|
||||
function focus(condition) {
|
||||
if (condition) {
|
||||
$timeout(function () {
|
||||
dom.focus();
|
||||
}, $scope.$eval($attrs.focusDelay) || 0);
|
||||
$timeout(
|
||||
function () {
|
||||
dom.focus();
|
||||
},
|
||||
$scope.$eval($attrs.focusDelay) || 0
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
</template-item>
|
||||
<div ng-if="!$ctrl.templates" class="text-muted text-center"> Loading... </div>
|
||||
<div
|
||||
ng-if="($ctrl.templates | filter : $ctrl.filterByTemplateType | filter : $ctrl.filterByCategory | filter : $ctrl.state.textFilter).length === 0"
|
||||
ng-if="($ctrl.templates | filter: $ctrl.filterByTemplateType | filter: $ctrl.filterByCategory | filter: $ctrl.state.textFilter).length === 0"
|
||||
class="text-muted text-center"
|
||||
>
|
||||
No templates available.
|
||||
|
|
|
@ -85,7 +85,7 @@ export function defaultErrorParser(axiosError: AxiosError) {
|
|||
}
|
||||
|
||||
export function isAxiosError<
|
||||
ResponseType = { message: string; details: string }
|
||||
ResponseType = { message: string; details: string },
|
||||
>(error: unknown): error is AxiosError<ResponseType> {
|
||||
return axiosOrigin.isAxiosError(error);
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
data-cy="auth-passwordInputToggle"
|
||||
type="button"
|
||||
ng-click="ctrl.toggleShowPassword()"
|
||||
class="absolute top-0 right-0 flex h-[34px] w-[50px] items-center justify-center border-none bg-transparent"
|
||||
class="absolute right-0 top-0 flex h-[34px] w-[50px] items-center justify-center border-none bg-transparent"
|
||||
tooltip-append-to-body="true"
|
||||
tooltip-placement="top"
|
||||
tooltip-class="portainer-tooltip"
|
||||
|
|
|
@ -44,7 +44,7 @@ export function mutationOptions<
|
|||
TData = unknown,
|
||||
TError = unknown,
|
||||
TVariables = void,
|
||||
TContext = unknown
|
||||
TContext = unknown,
|
||||
>(...options: MutationOptions<TData, TError, TVariables, TContext>[]) {
|
||||
return mergeOptions(options);
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ export function queryOptions<
|
|||
TQueryFnData = unknown,
|
||||
TError = unknown,
|
||||
TData = TQueryFnData,
|
||||
TQueryKey extends QueryKey = QueryKey
|
||||
TQueryKey extends QueryKey = QueryKey,
|
||||
>(...options: QueryOptions<TQueryFnData, TError, TData, TQueryKey>[]) {
|
||||
return mergeOptions(options);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ export function withControlledInput<T>(
|
|||
// extract keys of values that will be updated outside of React lifecycle and their handler functions
|
||||
const keysToControl = Object.entries(controlledValueOnChangePairs) as [
|
||||
keyof T,
|
||||
keyof T
|
||||
keyof T,
|
||||
][];
|
||||
|
||||
function WrapperComponent(props: T) {
|
||||
|
@ -99,7 +99,7 @@ export function withControlledInput<T>(
|
|||
(value: T[keyof T]) => {
|
||||
// update the state with the value coming from WrappedComponent
|
||||
setControlledValues(
|
||||
(c) => ({ ...c, [valueKey]: value } as KeyRecord<T>)
|
||||
(c) => ({ ...c, [valueKey]: value }) as KeyRecord<T>
|
||||
);
|
||||
|
||||
// call the bound handler func to update the value outside of React
|
||||
|
|
|
@ -70,9 +70,9 @@ export function createFormValidationComponent<TFormModel, TData = never>(
|
|||
return {
|
||||
template: `<ng-form name="$ctrl.form">
|
||||
<${kebabName} ${propsWithErrors
|
||||
.filter((p) => p !== 'onChange')
|
||||
.map((p) => `${_.kebabCase(p)}="$ctrl.${p}"`)
|
||||
.join(' ')}
|
||||
.filter((p) => p !== 'onChange')
|
||||
.map((p) => `${_.kebabCase(p)}="$ctrl.${p}"`)
|
||||
.join(' ')}
|
||||
on-change="($ctrl.handleChange)"
|
||||
></${kebabName}>
|
||||
</ng-form>`,
|
||||
|
|
|
@ -51,7 +51,7 @@ export function BoxOption<T extends Value>({
|
|||
{!disabled && (
|
||||
<div
|
||||
className={clsx(
|
||||
'absolute top-4 right-4 flex h-4 w-4 items-center justify-center border border-solid font-bold text-white',
|
||||
'absolute right-4 top-4 flex h-4 w-4 items-center justify-center border border-solid font-bold text-white',
|
||||
{
|
||||
'border-gray-6 bg-white': !selected,
|
||||
'border-blue-8 bg-blue-8': selected,
|
||||
|
|
|
@ -11,7 +11,7 @@ interface Props {
|
|||
export function LimitedToBeIndicator({ tooltipId, url }: Props) {
|
||||
return (
|
||||
<div className="absolute left-0 top-0 w-full">
|
||||
<div className="mx-auto flex max-w-fit items-center gap-1 rounded-b-lg bg-warning-4 py-1 px-3 text-sm th-dark:bg-[color:var(--bg-BE-only)]">
|
||||
<div className="mx-auto flex max-w-fit items-center gap-1 rounded-b-lg bg-warning-4 px-3 py-1 text-sm th-dark:bg-[color:var(--bg-BE-only)]">
|
||||
<a
|
||||
className="text-warning-9 th-dark:text-blue-8"
|
||||
href={url}
|
||||
|
|
|
@ -43,7 +43,7 @@ export function DashboardItem({
|
|||
>
|
||||
<div
|
||||
className={clsx(
|
||||
'text-muted absolute top-2 right-2 flex items-center text-xs transition-opacity',
|
||||
'text-muted absolute right-2 top-2 flex items-center text-xs transition-opacity',
|
||||
isRefetching ? 'opacity-100' : 'opacity-0'
|
||||
)}
|
||||
>
|
||||
|
@ -52,7 +52,7 @@ export function DashboardItem({
|
|||
</div>
|
||||
<div
|
||||
className={clsx(
|
||||
'text-muted absolute top-2 right-2 flex items-center text-xs transition-opacity',
|
||||
'text-muted absolute right-2 top-2 flex items-center text-xs transition-opacity',
|
||||
isLoading ? 'opacity-100' : 'opacity-0'
|
||||
)}
|
||||
>
|
||||
|
|
|
@ -21,7 +21,7 @@ export function EnvironmentStatusBadgeItem({
|
|||
className={clsx(
|
||||
'flex items-center gap-1',
|
||||
'rounded border-2 border-solid',
|
||||
'w-fit py-px px-1',
|
||||
'w-fit px-1 py-px',
|
||||
'text-xs font-semibold text-gray-7',
|
||||
{
|
||||
'border-green-3 bg-green-2': color === 'success',
|
||||
|
|
|
@ -64,7 +64,7 @@ export function InsightsBox({
|
|||
<Button
|
||||
icon={X}
|
||||
className={clsx(
|
||||
'absolute top-3 right-2 flex !text-gray-7 hover:!text-gray-8 th-highcontrast:!text-gray-6 th-highcontrast:hover:!text-gray-5 th-dark:!text-gray-6 th-dark:hover:!text-gray-5',
|
||||
'absolute right-2 top-3 flex !text-gray-7 hover:!text-gray-8 th-highcontrast:!text-gray-6 th-highcontrast:hover:!text-gray-5 th-dark:!text-gray-6 th-dark:hover:!text-gray-5',
|
||||
type === 'slim' && insightCloseId && 'top-1'
|
||||
)}
|
||||
color="link"
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
background-color: var(--bg-tooltip-color) !important;
|
||||
color: var(--text-tooltip-color) !important;
|
||||
border-radius: 10px !important;
|
||||
box-shadow: 0 2px 4px 0 rgba(34, 36, 38, 0.12), 0 2px 10px 0 rgba(34, 36, 38, 0.15) !important;
|
||||
box-shadow:
|
||||
0 2px 4px 0 rgba(34, 36, 38, 0.12),
|
||||
0 2px 10px 0 rgba(34, 36, 38, 0.15) !important;
|
||||
max-width: 400px;
|
||||
min-width: 50px;
|
||||
font-size: 1rem !important;
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
background-color: var(--bg-tooltip-color) !important;
|
||||
color: var(--text-tooltip-color) !important;
|
||||
border-radius: 10px !important;
|
||||
box-shadow: 0 2px 4px 0 rgba(34, 36, 38, 0.12), 0 2px 10px 0 rgba(34, 36, 38, 0.15) !important;
|
||||
box-shadow:
|
||||
0 2px 4px 0 rgba(34, 36, 38, 0.12),
|
||||
0 2px 10px 0 rgba(34, 36, 38, 0.15) !important;
|
||||
min-width: 50px;
|
||||
font-size: 1rem !important;
|
||||
text-align: left;
|
||||
|
|
|
@ -84,7 +84,7 @@ export function createPersistedStore<T extends BasicTableSettings>(
|
|||
storageKey: string,
|
||||
initialSortBy?: string | { id: string; desc: boolean },
|
||||
create: (set: ZustandSetFunc<T>) => Omit<T, keyof BasicTableSettings> = () =>
|
||||
({} as T)
|
||||
({}) as T
|
||||
) {
|
||||
return createStore<T>()(
|
||||
persist(
|
||||
|
@ -93,7 +93,7 @@ export function createPersistedStore<T extends BasicTableSettings>(
|
|||
...sortableSettings<T>(set, initialSortBy),
|
||||
...paginationSettings<T>(set),
|
||||
...create(set),
|
||||
} as T),
|
||||
}) as T,
|
||||
{
|
||||
name: `datatable_settings_${keyBuilder(storageKey)}`,
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ export type TableState<TSettings extends BasicTableSettings> = TSettings & {
|
|||
};
|
||||
|
||||
export function useTableState<
|
||||
TSettings extends BasicTableSettings = BasicTableSettings
|
||||
TSettings extends BasicTableSettings = BasicTableSettings,
|
||||
>(
|
||||
store: ReturnType<typeof createPersistedStore<TSettings>>,
|
||||
storageKey: string
|
||||
|
|
|
@ -22,7 +22,7 @@ export function FormSectionTitle({
|
|||
<label
|
||||
htmlFor={htmlFor}
|
||||
className={clsx(
|
||||
'col-sm-12 mt-1 mb-2 flex cursor-pointer items-center pl-0 font-medium',
|
||||
'col-sm-12 mb-2 mt-1 flex cursor-pointer items-center pl-0 font-medium',
|
||||
tailwindTitleSize[titleSize]
|
||||
)}
|
||||
>
|
||||
|
@ -33,7 +33,7 @@ export function FormSectionTitle({
|
|||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'col-sm-12 mt-1 mb-2 pl-0 font-medium',
|
||||
'col-sm-12 mb-2 mt-1 pl-0 font-medium',
|
||||
tailwindTitleSize[titleSize]
|
||||
)}
|
||||
>
|
||||
|
|
|
@ -14,7 +14,7 @@ export function InputGroupButtonWrapper({
|
|||
'input-group-btn [&>button]:!ml-0',
|
||||
// the button should be rounded at the end (right) if it's the last child and start (left) if it's the first child
|
||||
// if the button is in the middle of the group, it shouldn't be rounded
|
||||
'[&>button]:!rounded-none [&:last-child>button]:!rounded-r-[5px] [&:first-child>button]:!rounded-l-[5px]'
|
||||
'[&:first-child>button]:!rounded-l-[5px] [&:last-child>button]:!rounded-r-[5px] [&>button]:!rounded-none'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -57,16 +57,28 @@
|
|||
/* Match the same box shadow styles as the other portainer inputs, which are inherited from the bootstrap form-control class */
|
||||
.portainer-selector-root .portainer-selector__control--is-focused {
|
||||
border-color: #66afe9;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s;
|
||||
-webkit-box-shadow:
|
||||
inset 0 1px 1px rgba(0, 0, 0, 0.075),
|
||||
0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow:
|
||||
inset 0 1px 1px rgba(0, 0, 0, 0.075),
|
||||
0 0 8px rgba(102, 175, 233, 0.6);
|
||||
transition:
|
||||
border-color ease-in-out 0.15s,
|
||||
-webkit-box-shadow ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.portainer-selector-root .portainer-selector__control--is-focused:hover {
|
||||
border-color: #66afe9;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s;
|
||||
-webkit-box-shadow:
|
||||
inset 0 1px 1px rgba(0, 0, 0, 0.075),
|
||||
0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow:
|
||||
inset 0 1px 1px rgba(0, 0, 0, 0.075),
|
||||
0 0 8px rgba(102, 175, 233, 0.6);
|
||||
transition:
|
||||
border-color ease-in-out 0.15s,
|
||||
-webkit-box-shadow ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.portainer-selector-root.sm .portainer-selector__control {
|
||||
|
|
|
@ -19,7 +19,7 @@ interface DefaultOption {
|
|||
type RegularProps<
|
||||
Option = DefaultOption,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
Group extends GroupBase<Option> = GroupBase<Option>,
|
||||
> = { isCreatable?: false; size?: 'sm' | 'md' } & ReactSelectProps<
|
||||
Option,
|
||||
IsMulti,
|
||||
|
@ -30,7 +30,7 @@ type RegularProps<
|
|||
type CreatableProps<
|
||||
Option = DefaultOption,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
Group extends GroupBase<Option> = GroupBase<Option>,
|
||||
> = { isCreatable: true; size?: 'sm' | 'md' } & ReactSelectCreatableProps<
|
||||
Option,
|
||||
IsMulti,
|
||||
|
@ -40,7 +40,7 @@ type CreatableProps<
|
|||
type Props<
|
||||
Option = DefaultOption,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
Group extends GroupBase<Option> = GroupBase<Option>,
|
||||
> =
|
||||
| CreatableProps<Option, IsMulti, Group>
|
||||
| RegularProps<Option, IsMulti, Group>;
|
||||
|
@ -48,7 +48,7 @@ type Props<
|
|||
export function Select<
|
||||
Option = DefaultOption,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
Group extends GroupBase<Option> = GroupBase<Option>,
|
||||
>({
|
||||
className,
|
||||
isCreatable = false,
|
||||
|
@ -70,7 +70,7 @@ export function Select<
|
|||
export function Creatable<
|
||||
Option = DefaultOption,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
Group extends GroupBase<Option> = GroupBase<Option>,
|
||||
>({ className, ...props }: ReactSelectCreatableProps<Option, IsMulti, Group>) {
|
||||
return (
|
||||
<ReactSelectCreatable
|
||||
|
|
|
@ -38,9 +38,15 @@
|
|||
.switch :checked + i {
|
||||
padding-right: 0;
|
||||
padding-left: var(--switch-size);
|
||||
-webkit-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5), inset 0 0 40px #337ab7;
|
||||
-moz-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5), inset 0 0 40px #337ab7;
|
||||
box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5), inset 0 0 40px #337ab7;
|
||||
-webkit-box-shadow:
|
||||
inset 0 0 1px rgba(0, 0, 0, 0.5),
|
||||
inset 0 0 40px #337ab7;
|
||||
-moz-box-shadow:
|
||||
inset 0 0 1px rgba(0, 0, 0, 0.5),
|
||||
inset 0 0 40px #337ab7;
|
||||
box-shadow:
|
||||
inset 0 0 1px rgba(0, 0, 0, 0.5),
|
||||
inset 0 0 40px #337ab7;
|
||||
}
|
||||
|
||||
.switch :disabled + i {
|
||||
|
@ -60,7 +66,9 @@
|
|||
|
||||
.switch.business i {
|
||||
background-color: var(--BE-only);
|
||||
box-shadow: inset 0 0 1px rgb(0 0 0 / 50%), inset 0 0 40px var(--BE-only);
|
||||
box-shadow:
|
||||
inset 0 0 1px rgb(0 0 0 / 50%),
|
||||
inset 0 0 40px var(--BE-only);
|
||||
}
|
||||
|
||||
.switch input[type='checkbox']:disabled + .slider {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useRef, useState, useCallback, useEffect } from 'react';
|
||||
|
||||
export function useCaretPosition<
|
||||
T extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement
|
||||
T extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement,
|
||||
>() {
|
||||
const node = useRef<T>(null);
|
||||
const [start, setStart] = useState(0);
|
||||
|
|
|
@ -15,7 +15,7 @@ export function CloseButton({
|
|||
className={clsx(
|
||||
styles.close,
|
||||
className,
|
||||
'close-button absolute top-4 right-5'
|
||||
'close-button absolute right-5 top-4'
|
||||
)}
|
||||
onClick={() => onClose()}
|
||||
>
|
||||
|
|
|
@ -67,7 +67,7 @@ export function EnvironmentsDatatable() {
|
|||
env.Id,
|
||||
edgeStackQuery.data?.Status[env.Id]
|
||||
),
|
||||
} satisfies EdgeStackEnvironment)
|
||||
}) satisfies EdgeStackEnvironment
|
||||
),
|
||||
[
|
||||
currentFileVersion,
|
||||
|
|
|
@ -125,7 +125,7 @@ function ErrorCell({ getValue }: CellContext<EdgeStackEnvironment, string>) {
|
|||
className="flex cursor-pointer"
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
>
|
||||
<div className="pt-0.5 pr-1">
|
||||
<div className="pr-1 pt-0.5">
|
||||
<Icon icon={isExpanded ? ChevronDown : ChevronRight} />
|
||||
</div>
|
||||
<div
|
||||
|
|
|
@ -196,14 +196,17 @@ function getUniqNames(appName: string, services: ServiceFormValues[]) {
|
|||
function getServiceTypeCounts(
|
||||
services: ServiceFormValues[]
|
||||
): Record<ServiceTypeValue, number> {
|
||||
return services.reduce((acc, service) => {
|
||||
const type = serviceTypeEnumsToValues[service.Type];
|
||||
const count = acc[type];
|
||||
return {
|
||||
...acc,
|
||||
[type]: count ? count + 1 : 1,
|
||||
};
|
||||
}, {} as Record<ServiceTypeValue, number>);
|
||||
return services.reduce(
|
||||
(acc, service) => {
|
||||
const type = serviceTypeEnumsToValues[service.Type];
|
||||
const count = acc[type];
|
||||
return {
|
||||
...acc,
|
||||
[type]: count ? count + 1 : 1,
|
||||
};
|
||||
},
|
||||
{} as Record<ServiceTypeValue, number>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,15 +216,18 @@ function getServiceTypeHasErrors(
|
|||
services: ServiceFormValues[],
|
||||
errors: FormikErrors<ServiceFormValues[] | undefined>
|
||||
): Record<ServiceTypeValue, boolean> {
|
||||
return services.reduce((acc, service, index) => {
|
||||
const type = serviceTypeEnumsToValues[service.Type];
|
||||
const serviceHasErrors = !!errors?.[index];
|
||||
// if the service type already has an error, don't overwrite it
|
||||
if (acc[type] === true) return acc;
|
||||
// otherwise, set the error to the value of serviceHasErrors
|
||||
return {
|
||||
...acc,
|
||||
[type]: serviceHasErrors,
|
||||
};
|
||||
}, {} as Record<ServiceTypeValue, boolean>);
|
||||
return services.reduce(
|
||||
(acc, service, index) => {
|
||||
const type = serviceTypeEnumsToValues[service.Type];
|
||||
const serviceHasErrors = !!errors?.[index];
|
||||
// if the service type already has an error, don't overwrite it
|
||||
if (acc[type] === true) return acc;
|
||||
// otherwise, set the error to the value of serviceHasErrors
|
||||
return {
|
||||
...acc,
|
||||
[type]: serviceHasErrors,
|
||||
};
|
||||
},
|
||||
{} as Record<ServiceTypeValue, boolean>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ export function PublishingExplaination() {
|
|||
ingresses
|
||||
</a>
|
||||
:
|
||||
<ul className="mt-3 ml-5 [&>li]:mb-3 [&>li>ul>li]:ml-5">
|
||||
<ul className="ml-5 mt-3 [&>li>ul>li]:ml-5 [&>li]:mb-3">
|
||||
<li>
|
||||
<b>Inside</b> the cluster{' '}
|
||||
<b>
|
||||
|
|
|
@ -97,15 +97,16 @@ function getIngressPathsForAppServices(
|
|||
if (!ingress.Paths) {
|
||||
return [];
|
||||
}
|
||||
const matchingIngressPaths = ingress.Paths?.filter((path) =>
|
||||
services?.some((service) => {
|
||||
const servicePorts = service.spec?.ports?.map((port) => port.port);
|
||||
// include the ingress if the ingress path has a matching service name and port
|
||||
return (
|
||||
path.ServiceName === service.metadata?.name &&
|
||||
servicePorts?.includes(path.Port)
|
||||
);
|
||||
})
|
||||
const matchingIngressPaths = ingress.Paths?.filter(
|
||||
(path) =>
|
||||
services?.some((service) => {
|
||||
const servicePorts = service.spec?.ports?.map((port) => port.port);
|
||||
// include the ingress if the ingress path has a matching service name and port
|
||||
return (
|
||||
path.ServiceName === service.metadata?.name &&
|
||||
servicePorts?.includes(path.Port)
|
||||
);
|
||||
})
|
||||
).map((path) => {
|
||||
const secure =
|
||||
(ingress.TLS &&
|
||||
|
|
|
@ -84,7 +84,7 @@ async function getApplicationsForNamespace(
|
|||
|
||||
// if not known, get the type of an application (Deployment, DaemonSet, StatefulSet or naked pod) by name
|
||||
export async function getApplication<
|
||||
T extends Application | string = Application
|
||||
T extends Application | string = Application,
|
||||
>(
|
||||
environmentId: EnvironmentId,
|
||||
namespace: string,
|
||||
|
@ -233,7 +233,7 @@ async function patchApplicationByKind<T extends Application>(
|
|||
}
|
||||
|
||||
async function getApplicationByKind<
|
||||
T extends Application | string = Application
|
||||
T extends Application | string = Application,
|
||||
>(
|
||||
environmentId: EnvironmentId,
|
||||
namespace: string,
|
||||
|
|
|
@ -12,7 +12,7 @@ import { parseKubernetesAxiosError } from '../axiosError';
|
|||
|
||||
// when yaml is set to true, the expected return type is a string
|
||||
export function useHorizontalAutoScalarQuery<
|
||||
T extends HorizontalPodAutoscaler | string = HorizontalPodAutoscaler
|
||||
T extends HorizontalPodAutoscaler | string = HorizontalPodAutoscaler,
|
||||
>(
|
||||
environmentId: EnvironmentId,
|
||||
namespace: string,
|
||||
|
@ -62,7 +62,7 @@ export async function getNamespaceHorizontalPodAutoscalers(
|
|||
}
|
||||
|
||||
export async function getNamespaceHorizontalPodAutoscaler<
|
||||
T extends HorizontalPodAutoscaler | string = HorizontalPodAutoscaler
|
||||
T extends HorizontalPodAutoscaler | string = HorizontalPodAutoscaler,
|
||||
>(
|
||||
environmentId: EnvironmentId,
|
||||
namespace: string,
|
||||
|
|
|
@ -233,23 +233,31 @@ export function getRollbackPatchPayload(
|
|||
// keep the annotations to skip from the deployment, in the patch
|
||||
const applicationAnnotations = application.metadata?.annotations || {};
|
||||
const applicationAnnotationsInPatch =
|
||||
unchangedAnnotationKeysForRollbackPatch.reduce((acc, annotationKey) => {
|
||||
if (applicationAnnotations[annotationKey]) {
|
||||
acc[annotationKey] = applicationAnnotations[annotationKey];
|
||||
}
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
unchangedAnnotationKeysForRollbackPatch.reduce(
|
||||
(acc, annotationKey) => {
|
||||
if (applicationAnnotations[annotationKey]) {
|
||||
acc[annotationKey] = applicationAnnotations[annotationKey];
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>
|
||||
);
|
||||
|
||||
// add any annotations from the target revision that shouldn't be skipped
|
||||
const revisionAnnotations = previousRevision.metadata?.annotations || {};
|
||||
const revisionAnnotationsInPatch = Object.entries(
|
||||
revisionAnnotations
|
||||
).reduce((acc, [annotationKey, annotationValue]) => {
|
||||
if (!unchangedAnnotationKeysForRollbackPatch.includes(annotationKey)) {
|
||||
acc[annotationKey] = annotationValue;
|
||||
}
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
).reduce(
|
||||
(acc, [annotationKey, annotationValue]) => {
|
||||
if (
|
||||
!unchangedAnnotationKeysForRollbackPatch.includes(annotationKey)
|
||||
) {
|
||||
acc[annotationKey] = annotationValue;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>
|
||||
);
|
||||
|
||||
const patchAnnotations = {
|
||||
...applicationAnnotationsInPatch,
|
||||
|
|
|
@ -14,11 +14,12 @@ export function getIsConfigMapInUse(
|
|||
? app?.spec
|
||||
: app?.spec?.template?.spec;
|
||||
|
||||
const hasEnvVarReference = appSpec?.containers.some((container) =>
|
||||
container.env?.some(
|
||||
(envVar) =>
|
||||
envVar.valueFrom?.configMapKeyRef?.name === configMap.metadata?.name
|
||||
)
|
||||
const hasEnvVarReference = appSpec?.containers.some(
|
||||
(container) =>
|
||||
container.env?.some(
|
||||
(envVar) =>
|
||||
envVar.valueFrom?.configMapKeyRef?.name === configMap.metadata?.name
|
||||
)
|
||||
);
|
||||
const hasVolumeReference = appSpec?.volumes?.some(
|
||||
(volume) => volume.configMap?.name === configMap.metadata?.name
|
||||
|
|
|
@ -11,11 +11,12 @@ export function getIsSecretInUse(secret: Secret, applications: Application[]) {
|
|||
? app?.spec
|
||||
: app?.spec?.template?.spec;
|
||||
|
||||
const hasEnvVarReference = appSpec?.containers.some((container) =>
|
||||
container.env?.some(
|
||||
(envVar) =>
|
||||
envVar.valueFrom?.secretKeyRef?.name === secret.metadata?.name
|
||||
)
|
||||
const hasEnvVarReference = appSpec?.containers.some(
|
||||
(container) =>
|
||||
container.env?.some(
|
||||
(envVar) =>
|
||||
envVar.valueFrom?.secretKeyRef?.name === secret.metadata?.name
|
||||
)
|
||||
);
|
||||
const hasVolumeReference = appSpec?.volumes?.some(
|
||||
(volume) => volume.secret?.secretName === secret.metadata?.name
|
||||
|
|
|
@ -44,7 +44,7 @@ export function Annotations({
|
|||
/>
|
||||
</div>
|
||||
{errors[`annotations.key[${i}]`] && (
|
||||
<FormError className="mt-1 !mb-0">
|
||||
<FormError className="!mb-0 mt-1">
|
||||
{errors[`annotations.key[${i}]`]}
|
||||
</FormError>
|
||||
)}
|
||||
|
@ -64,7 +64,7 @@ export function Annotations({
|
|||
/>
|
||||
</div>
|
||||
{errors[`annotations.value[${i}]`] && (
|
||||
<FormError className="mt-1 !mb-0">
|
||||
<FormError className="!mb-0 mt-1">
|
||||
{errors[`annotations.value[${i}]`]}
|
||||
</FormError>
|
||||
)}
|
||||
|
|
|
@ -79,7 +79,7 @@ export function CreateIngressView() {
|
|||
string[],
|
||||
Ingress[],
|
||||
Record<string, number>,
|
||||
Record<string, string>
|
||||
Record<string, string>,
|
||||
] => {
|
||||
const ruleCounterByNamespace: Record<string, number> = {};
|
||||
const hostWithTLS: Record<string, string> = {};
|
||||
|
|
|
@ -311,7 +311,7 @@ export function IngressForm({
|
|||
<TooltipWithChildren message="Use annotations to configure options for an ingress. Review Nginx or Traefik documentation to find the annotations supported by your choice of ingress type.">
|
||||
<span>
|
||||
<Button
|
||||
className="btn btn-sm btn-light mb-2 !ml-0"
|
||||
className="btn btn-sm btn-light !ml-0 mb-2"
|
||||
onClick={() => addNewAnnotation()}
|
||||
icon={Plus}
|
||||
>
|
||||
|
@ -406,13 +406,13 @@ export function IngressForm({
|
|||
/>
|
||||
</InputGroup>
|
||||
{errors[`hosts[${hostIndex}].host`] && (
|
||||
<FormError className="mt-1 !mb-0">
|
||||
<FormError className="!mb-0 mt-1">
|
||||
{errors[`hosts[${hostIndex}].host`]}
|
||||
</FormError>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="form-group col-sm-6 col-lg-4 !pr-0 !pl-2">
|
||||
<div className="form-group col-sm-6 col-lg-4 !pl-2 !pr-0">
|
||||
<InputGroup size="small">
|
||||
<InputGroup.Addon>TLS secret</InputGroup.Addon>
|
||||
<Select
|
||||
|
@ -490,7 +490,7 @@ export function IngressForm({
|
|||
|
||||
{host.Paths.map((path, pathIndex) => (
|
||||
<div
|
||||
className="row path mt-5 !mb-5"
|
||||
className="row path !mb-5 mt-5"
|
||||
key={`path_${path.Key}}`}
|
||||
>
|
||||
<div className="form-group col-sm-3 col-xl-2 !m-0 !pl-0">
|
||||
|
@ -531,7 +531,7 @@ export function IngressForm({
|
|||
{errors[
|
||||
`hosts[${hostIndex}].paths[${pathIndex}].servicename`
|
||||
] && (
|
||||
<FormError className="error-inline mt-1 !mb-0">
|
||||
<FormError className="error-inline !mb-0 mt-1">
|
||||
{
|
||||
errors[
|
||||
`hosts[${hostIndex}].paths[${pathIndex}].servicename`
|
||||
|
@ -587,7 +587,7 @@ export function IngressForm({
|
|||
{errors[
|
||||
`hosts[${hostIndex}].paths[${pathIndex}].serviceport`
|
||||
] && (
|
||||
<FormError className="mt-1 !mb-0">
|
||||
<FormError className="!mb-0 mt-1">
|
||||
{
|
||||
errors[
|
||||
`hosts[${hostIndex}].paths[${pathIndex}].serviceport`
|
||||
|
@ -639,7 +639,7 @@ export function IngressForm({
|
|||
{errors[
|
||||
`hosts[${hostIndex}].paths[${pathIndex}].pathType`
|
||||
] && (
|
||||
<FormError className="mt-1 !mb-0">
|
||||
<FormError className="!mb-0 mt-1">
|
||||
{
|
||||
errors[
|
||||
`hosts[${hostIndex}].paths[${pathIndex}].pathType`
|
||||
|
@ -672,7 +672,7 @@ export function IngressForm({
|
|||
{errors[
|
||||
`hosts[${hostIndex}].paths[${pathIndex}].path`
|
||||
] && (
|
||||
<FormError className="mt-1 !mb-0">
|
||||
<FormError className="!mb-0 mt-1">
|
||||
{
|
||||
errors[
|
||||
`hosts[${hostIndex}].paths[${pathIndex}].path`
|
||||
|
|
|
@ -63,7 +63,7 @@ export function AssociateAMTDialog({
|
|||
{environments.map((env) => (
|
||||
<div
|
||||
key={env.Id}
|
||||
className={clsx('flex h-8 items-center pt-1 pl-2')}
|
||||
className={clsx('flex h-8 items-center pl-2 pt-1')}
|
||||
>
|
||||
<Checkbox
|
||||
id={`${env.Id}`}
|
||||
|
|
|
@ -57,7 +57,7 @@ function CreateView() {
|
|||
/>
|
||||
|
||||
<BetaAlert
|
||||
className="ml-[15px] mb-2"
|
||||
className="mb-2 ml-[15px]"
|
||||
message="Beta feature - currently limited to standalone Linux and Nomad edge devices."
|
||||
/>
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ function ItemView() {
|
|||
/>
|
||||
|
||||
<BetaAlert
|
||||
className="ml-[15px] mb-2"
|
||||
className="mb-2 ml-[15px]"
|
||||
message="Beta feature - currently limited to standalone Linux and Nomad edge devices."
|
||||
/>
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ export function ListView() {
|
|||
/>
|
||||
|
||||
<BetaAlert
|
||||
className="ml-[15px] mb-2"
|
||||
className="mb-2 ml-[15px]"
|
||||
message="Beta feature - currently limited to standalone Linux and Nomad edge devices."
|
||||
/>
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ export function Sidebar() {
|
|||
>
|
||||
<Header logo={LogoURL} />
|
||||
{/* negative margin + padding -> scrollbar won't hide the content */}
|
||||
<div className="mt-6 -mr-4 flex-1 overflow-y-auto pr-4">
|
||||
<div className="-mr-4 mt-6 flex-1 overflow-y-auto pr-4">
|
||||
<ul className="space-y-9">
|
||||
<SidebarItem
|
||||
to="portainer.home"
|
||||
|
|
|
@ -66,7 +66,7 @@ export function Head({
|
|||
|
||||
return (
|
||||
<Tippy
|
||||
className="!rounded-md bg-blue-9 !py-2 !px-3 !opacity-100 be:bg-gray-9 th-dark:bg-gray-true-9"
|
||||
className="!rounded-md bg-blue-9 !px-3 !py-2 !opacity-100 be:bg-gray-9 th-dark:bg-gray-true-9"
|
||||
content={label}
|
||||
delay={[0, 0]}
|
||||
duration={[0, 0]}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue