diff --git a/app/kubernetes/registries/kube-registry-access-view/kube-registry-access-view.controller.js b/app/kubernetes/registries/kube-registry-access-view/kube-registry-access-view.controller.js
index 11f7cd889..facae44f0 100644
--- a/app/kubernetes/registries/kube-registry-access-view/kube-registry-access-view.controller.js
+++ b/app/kubernetes/registries/kube-registry-access-view/kube-registry-access-view.controller.js
@@ -1,5 +1,5 @@
-import { confirmDelete } from '@@/modals/confirm';
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
+import { confirmDeleteAccess } from '@/react/kubernetes/cluster/RegistryAccessView/ConfirmDeleteAccess';
export default class KubernetesRegistryAccessController {
/* @ngInject */
@@ -32,9 +32,7 @@ export default class KubernetesRegistryAccessController {
const removeNamespaces = namespaces.map(({ value }) => value);
const nsToUpdate = this.savedResourcePools.map(({ value }) => value).filter((value) => !removeNamespaces.includes(value));
- const displayedMessage =
- 'This registry might be used by one or more applications inside this environment. Removing the registry access could lead to a service interruption for these applications.
Do you wish to continue?';
- confirmDelete(displayedMessage).then((confirmed) => {
+ confirmDeleteAccess().then((confirmed) => {
if (confirmed) {
return this.updateNamespaces(nsToUpdate);
}
@@ -48,6 +46,7 @@ export default class KubernetesRegistryAccessController {
namespaces,
});
this.$state.reload(this.$state.current);
+ this.Notifications.success('Success', 'Registry access updated');
} catch (err) {
this.Notifications.error('Failure', err, 'Failed saving registry access');
}
diff --git a/app/kubernetes/views/cluster/node/nodeController.js b/app/kubernetes/views/cluster/node/nodeController.js
index bfdeaddbc..c80e5a15e 100644
--- a/app/kubernetes/views/cluster/node/nodeController.js
+++ b/app/kubernetes/views/cluster/node/nodeController.js
@@ -8,7 +8,7 @@ import { KubernetesNodeLabelFormValues, KubernetesNodeTaintFormValues } from 'Ku
import { KubernetesNodeTaintEffects, KubernetesNodeAvailabilities } from 'Kubernetes/node/models';
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
import { KubernetesNodeHelper } from 'Kubernetes/node/helper';
-import { confirmUpdate } from '@@/modals/confirm';
+import { confirmUpdateNode } from '@/react/kubernetes/cluster/NodeView/ConfirmUpdateNode';
class KubernetesNodeController {
/* @ngInject */
@@ -264,44 +264,8 @@ class KubernetesNodeController {
const cordonWarning = this.computeCordonWarning();
const drainWarning = this.computeDrainWarning();
- if (taintsWarning && !labelsWarning) {
- confirmUpdate(
- 'Changes to taints will immediately deschedule applications running on this node without the corresponding tolerations. Do you wish to continue?',
- (confirmed) => {
- if (confirmed) {
- return this.$async(this.updateNodeAsync);
- }
- }
- );
- } else if (!taintsWarning && labelsWarning) {
- confirmUpdate(
- 'Removing or changing a label that is used might prevent applications from being scheduled on this node in the future. Do you wish to continue?',
- (confirmed) => {
- if (confirmed) {
- return this.$async(this.updateNodeAsync);
- }
- }
- );
- } else if (taintsWarning && labelsWarning) {
- confirmUpdate(
- 'Changes to taints will immediately deschedule applications running on this node without the corresponding tolerations.
Removing or changing a label that is used might prevent applications from scheduling on this node in the future.\n\nDo you wish to continue?',
- (confirmed) => {
- if (confirmed) {
- return this.$async(this.updateNodeAsync);
- }
- }
- );
- } else if (cordonWarning) {
- confirmUpdate(
- 'Marking this node as unschedulable will effectively cordon the node and prevent any new workload from being scheduled on that node. Are you sure?',
- (confirmed) => {
- if (confirmed) {
- return this.$async(this.updateNodeAsync);
- }
- }
- );
- } else if (drainWarning) {
- confirmUpdate('Draining this node will cause all workloads to be evicted from that node. This might lead to some service interruption. Are you sure?', (confirmed) => {
+ if (taintsWarning || labelsWarning || cordonWarning || drainWarning) {
+ confirmUpdateNode(taintsWarning, labelsWarning, cordonWarning, drainWarning).then((confirmed) => {
if (confirmed) {
return this.$async(this.updateNodeAsync);
}
diff --git a/app/kubernetes/views/configure/configureController.js b/app/kubernetes/views/configure/configureController.js
index a3354dec4..1a92afee0 100644
--- a/app/kubernetes/views/configure/configureController.js
+++ b/app/kubernetes/views/configure/configureController.js
@@ -10,6 +10,7 @@ import { getIngressControllerClassMap, updateIngressControllerClassMap } from '@
import { buildConfirmButton } from '@@/modals/utils';
import { confirm } from '@@/modals/confirm';
import { getIsRBACEnabled } from '@/react/kubernetes/cluster/getIsRBACEnabled';
+import { ModalType } from '@@/modals/Modal/types';
class KubernetesConfigureController {
/* #region CONSTRUCTOR */
@@ -392,6 +393,7 @@ class KubernetesConfigureController {
return confirm({
title: 'Are you sure?',
message: 'You currently have unsaved changes in the cluster setup view. Are you sure you want to leave?',
+ modalType: ModalType.Warn,
confirmButton: buildConfirmButton('Yes', 'danger'),
});
}
diff --git a/app/kubernetes/views/resource-pools/edit/resourcePoolController.js b/app/kubernetes/views/resource-pools/edit/resourcePoolController.js
index c353ea12e..7eb5c865c 100644
--- a/app/kubernetes/views/resource-pools/edit/resourcePoolController.js
+++ b/app/kubernetes/views/resource-pools/edit/resourcePoolController.js
@@ -15,6 +15,7 @@ import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
import { FeatureId } from '@/react/portainer/feature-flags/enums';
import { updateIngressControllerClassMap, getIngressControllerClassMap } from '@/react/kubernetes/cluster/ingressClass/utils';
import { confirmUpdate } from '@@/modals/confirm';
+import { confirmUpdateNamespace } from '@/react/kubernetes/namespaces/ItemView/ConfirmUpdateNamespace';
class KubernetesResourcePoolController {
/* #region CONSTRUCTOR */
@@ -178,19 +179,8 @@ class KubernetesResourcePoolController {
registries: registriesToDelete.length !== 0,
};
- if (warnings.quota || warnings.ingress || warnings.registries) {
- const messages = {
- quota:
- 'Reducing the quota assigned to an "in-use" namespace may have unintended consequences, including preventing running applications from functioning correctly and potentially even blocking them from running at all.',
- ingress: 'Deactivating ingresses may cause applications to be unaccessible. All ingress configurations from affected applications will be removed.',
- registries:
- 'Some registries you removed might be used by one or more applications inside this environment. Removing the registries access could lead to a service interruption for these applications.',
- };
- const displayedMessage = `${warnings.quota ? messages.quota + '
' : ''}
- ${warnings.ingress ? messages.ingress + '
' : ''}
- ${warnings.registries ? messages.registries + '
' : ''}
- Do you wish to continue?`;
- confirmUpdate(displayedMessage, (confirmed) => {
+ if (warnings.quota || warnings.registries) {
+ confirmUpdateNamespace(warnings.quota, warnings.ingress, warnings.registries).then((confirmed) => {
if (confirmed) {
return this.$async(this.updateResourcePoolAsync, this.savedFormValues, this.formValues);
}
diff --git a/app/react/components/Tip/SliderTooltip/SliderTooltip.module.css b/app/react/components/Tip/SliderTooltip/SliderTooltip.module.css
index fa0deccec..476decada 100644
--- a/app/react/components/Tip/SliderTooltip/SliderTooltip.module.css
+++ b/app/react/components/Tip/SliderTooltip/SliderTooltip.module.css
@@ -19,10 +19,12 @@
line-height: 18px;
padding: 8px 10px !important;
font-size: 12px !important;
+ user-select: none;
}
.tooltip-centered .tooltip-container {
text-align: center;
+ user-select: none;
}
.tooltip-message a {
diff --git a/app/react/kubernetes/cluster/NodeView/ConfirmUpdateNode.tsx b/app/react/kubernetes/cluster/NodeView/ConfirmUpdateNode.tsx
new file mode 100644
index 000000000..e4ae84750
--- /dev/null
+++ b/app/react/kubernetes/cluster/NodeView/ConfirmUpdateNode.tsx
@@ -0,0 +1,46 @@
+import { ModalType } from '@@/modals';
+import { confirm } from '@@/modals/confirm';
+import { buildConfirmButton } from '@@/modals/utils';
+
+export function confirmUpdateNode(
+ taintsWarning: boolean,
+ labelsWarning: boolean,
+ cordonWarning: boolean,
+ drainWarning: boolean
+) {
+ let message;
+ if (taintsWarning && !labelsWarning) {
+ message =
+ 'Changes to taints will immediately deschedule applications running on this node without the corresponding tolerations. Do you wish to continue?';
+ } else if (!taintsWarning && labelsWarning) {
+ message =
+ 'Removing or changing a label that is used might prevent applications from being scheduled on this node in the future. Do you wish to continue?';
+ } else if (taintsWarning && labelsWarning) {
+ message = (
+ <>
+
+ Changes to taints will immediately deschedule applications running on + this node without the corresponding tolerations. +
++ Removing or changing a label that is used might prevent applications + from scheduling on this node in the future. +
+Do you wish to continue?
+ > + ); + } else if (cordonWarning) { + message = + 'Marking this node as unschedulable will effectively cordon the node and prevent any new workload from being scheduled on that node. Are you sure?'; + } else if (drainWarning) { + message = + 'Draining this node will cause all workloads to be evicted from that node. This might lead to some service interruption. Are you sure?'; + } + + return confirm({ + title: 'Are you sure?', + modalType: ModalType.Warn, + message, + confirmButton: buildConfirmButton('Update', 'primary'), + }); +} diff --git a/app/react/kubernetes/cluster/RegistryAccessView/ConfirmDeleteAccess.tsx b/app/react/kubernetes/cluster/RegistryAccessView/ConfirmDeleteAccess.tsx new file mode 100644 index 000000000..5857dcfd2 --- /dev/null +++ b/app/react/kubernetes/cluster/RegistryAccessView/ConfirmDeleteAccess.tsx @@ -0,0 +1,19 @@ +import { confirmDestructive } from '@@/modals/confirm'; +import { buildConfirmButton } from '@@/modals/utils'; + +export function confirmDeleteAccess() { + return confirmDestructive({ + title: 'Are you sure?', + message: ( + <> ++ This registry might be used by one or more applications inside this + environment. Removing the registry access could lead to a service + interruption for these applications. +
+Do you wish to continue?
+ > + ), + confirmButton: buildConfirmButton('Remove', 'danger'), + }); +} diff --git a/app/react/kubernetes/namespaces/ItemView/ConfirmUpdateNamespace.tsx b/app/react/kubernetes/namespaces/ItemView/ConfirmUpdateNamespace.tsx new file mode 100644 index 000000000..4343fc58a --- /dev/null +++ b/app/react/kubernetes/namespaces/ItemView/ConfirmUpdateNamespace.tsx @@ -0,0 +1,42 @@ +import { ModalType } from '@@/modals'; +import { confirm } from '@@/modals/confirm'; +import { buildConfirmButton } from '@@/modals/utils'; + +export function confirmUpdateNamespace( + quotaWarning: boolean, + ingressWarning: boolean, + registriesWarning: boolean +) { + const message = ( + <> + {quotaWarning && ( ++ Reducing the quota assigned to an "in-use" namespace may + have unintended consequences, including preventing running + applications from functioning correctly and potentially even blocking + them from running at all. +
+ )} + {ingressWarning && ( ++ Deactivating ingresses may cause applications to be unaccessible. All + ingress configurations from affected applications will be removed. +
+ )} + {registriesWarning && ( ++ Some registries you removed might be used by one or more applications + inside this environment. Removing the registries access could lead to + a service interruption for these applications. +
+ )} + > + ); + + return confirm({ + title: 'Are you sure?', + modalType: ModalType.Warn, + message, + confirmButton: buildConfirmButton('Update', 'primary'), + }); +}