+
@@ -117,14 +121,16 @@
diff --git a/app/kubernetes/views/resource-pools/edit/resourcePoolController.js b/app/kubernetes/views/resource-pools/edit/resourcePoolController.js
index 331082811..39d85d287 100644
--- a/app/kubernetes/views/resource-pools/edit/resourcePoolController.js
+++ b/app/kubernetes/views/resource-pools/edit/resourcePoolController.js
@@ -69,6 +69,8 @@ class KubernetesResourcePoolController {
this.onToggleStorageQuota = this.onToggleStorageQuota.bind(this);
this.onChangeIngressControllerAvailability = this.onChangeIngressControllerAvailability.bind(this);
this.onRegistriesChange = this.onRegistriesChange.bind(this);
+ this.handleMemoryLimitChange = this.handleMemoryLimitChange.bind(this);
+ this.handleCpuLimitChange = this.handleCpuLimitChange.bind(this);
}
/* #endregion */
@@ -122,6 +124,18 @@ class KubernetesResourcePoolController {
}
}
+ handleMemoryLimitChange(memoryLimit) {
+ return this.$async(async () => {
+ this.formValues.MemoryLimit = memoryLimit;
+ });
+ }
+
+ handleCpuLimitChange(cpuLimit) {
+ return this.$async(async () => {
+ this.formValues.CpuLimit = cpuLimit;
+ });
+ }
+
showEditor() {
this.state.showEditorTab = true;
this.selectTab(2);
diff --git a/app/portainer/react/components/index.ts b/app/portainer/react/components/index.ts
index 14eeff6f0..2a2ee45dc 100644
--- a/app/portainer/react/components/index.ts
+++ b/app/portainer/react/components/index.ts
@@ -33,6 +33,7 @@ import { FallbackImage } from '@@/FallbackImage';
import { BadgeIcon } from '@@/BadgeIcon';
import { TeamsSelector } from '@@/TeamsSelector';
import { PortainerSelect } from '@@/form-components/PortainerSelect';
+import { Slider } from '@@/form-components/Slider';
import { fileUploadField } from './file-upload-field';
import { switchField } from './switch-field';
@@ -184,6 +185,18 @@ export const componentsModule = angular
'isClearable',
])
)
+ .component(
+ 'porSlider',
+ r2a(Slider, [
+ 'min',
+ 'max',
+ 'step',
+ 'value',
+ 'onChange',
+ 'visibleTooltip',
+ 'dataCy',
+ ])
+ )
.component(
'porAccessManagementUsersSelector',
r2a(PorAccessManagementUsersSelector, ['onChange', 'options', 'value'])
diff --git a/app/react/components/form-components/Slider/Slider.module.css b/app/react/components/form-components/Slider/Slider.module.css
index db5aa38e5..6cd2af8d5 100644
--- a/app/react/components/form-components/Slider/Slider.module.css
+++ b/app/react/components/form-components/Slider/Slider.module.css
@@ -7,26 +7,50 @@
}
.slider :global .rc-slider-handle {
- width: 32px;
- height: 32px;
- margin-top: -14px;
+ @apply border-blue-8 border-2;
+ width: 24px;
+ height: 24px;
+ margin-top: -8px;
border-radius: 16px;
cursor: pointer;
- background-color: #0db9f0;
+ background-color: #ffffff;
+}
+
+.slider :global .rc-slider-track {
+ @apply bg-blue-8;
}
.slider :global .rc-slider-handle:after {
position: absolute;
- top: 10px;
- left: 10px;
- width: 8px;
- height: 8px;
+ top: 8px;
+ left: 8px;
+ width: 9px;
+ height: 9px;
background: #ffffff;
- border-radius: 4px;
+ border-radius: 5px;
content: '';
}
-.slider :global .rc-slider-mark-text,
-.slider :global .rc-slider-tooltip-inner {
- font-family: Inter, serif;
+.slider :global .rc-slider-mark-text {
+ font-size: 14px;
+ color: var(--text-body-color);
+}
+
+.slider :global .rc-slider-tooltip-arrow {
+ bottom: 2px;
+ border-top-color: var(--bg-tooltip-color);
+}
+
+.slider :global .rc-slider-tooltip-placement-top {
+ padding: 6px 0px;
+}
+
+.slider :global .rc-slider-tooltip-inner {
+ font-size: 14px;
+ color: var(--text-tooltip-color);
+ height: fit-content;
+ background-color: var(--bg-tooltip-color);
+ box-shadow: 0 2px 4px 0 rgb(34 36 38 / 12%), 0 2px 10px 0 rgb(34 36 38 / 15%);
+ padding: 8px 12px;
+ text-align: center;
}
diff --git a/app/react/components/form-components/Slider/Slider.stories.tsx b/app/react/components/form-components/Slider/Slider.stories.tsx
index 76f14457a..1cd7da5bc 100644
--- a/app/react/components/form-components/Slider/Slider.stories.tsx
+++ b/app/react/components/form-components/Slider/Slider.stories.tsx
@@ -8,7 +8,14 @@ export default {
title: 'Components/Form/Slider',
} as Meta;
-function Template({ value, min, max, step }: JSX.IntrinsicAttributes & Props) {
+function Template({
+ value,
+ min,
+ max,
+ step,
+ dataCy,
+ visibleTooltip,
+}: JSX.IntrinsicAttributes & Props) {
const [sliderValue, setSliderValue] = useState(min);
useEffect(() => {
@@ -22,6 +29,8 @@ function Template({ value, min, max, step }: JSX.IntrinsicAttributes & Props) {
step={step}
value={sliderValue}
onChange={setSliderValue}
+ dataCy={dataCy}
+ visibleTooltip={visibleTooltip}
/>
);
}
@@ -32,4 +41,6 @@ Primary.args = {
max: 100,
step: 1,
value: 5,
+ visibleTooltip: true,
+ dataCy: 'someView-coolSlider',
};
diff --git a/app/react/components/form-components/Slider/Slider.test.tsx b/app/react/components/form-components/Slider/Slider.test.tsx
index 403881753..cd5d375a6 100644
--- a/app/react/components/form-components/Slider/Slider.test.tsx
+++ b/app/react/components/form-components/Slider/Slider.test.tsx
@@ -8,9 +8,19 @@ function renderDefault({
step = 1,
value = min,
onChange = () => {},
+ dataCy = 'someView-coolSlider',
+ visibleTooltip = true,
}: Partial
= {}) {
return render(
-
+
);
}
diff --git a/app/react/components/form-components/Slider/Slider.tsx b/app/react/components/form-components/Slider/Slider.tsx
index e60c1fb57..a07d55409 100644
--- a/app/react/components/form-components/Slider/Slider.tsx
+++ b/app/react/components/form-components/Slider/Slider.tsx
@@ -9,13 +9,25 @@ export interface Props {
step: number;
value: number;
onChange: (value: number) => void;
+ // true if you want to always show the tooltip
+ dataCy: string;
+ visibleTooltip?: boolean;
}
-export function Slider({ min, max, step, value, onChange }: Props) {
+export function Slider({
+ min,
+ max,
+ step,
+ value,
+ onChange,
+ dataCy,
+ visibleTooltip: visible,
+}: Props) {
const SliderWithTooltip = RcSlider.createSliderWithTooltip(RcSlider);
+ // if the tooltip is always visible, hide the marks when tooltip value gets close to the edges
const marks = {
- [min]: translateMinValue(min),
- [max]: max.toString(),
+ [min]: visible && value / max < 0.1 ? '' : translateMinValue(min),
+ [max]: visible && value / max > 0.9 ? '' : max.toString(),
};
return (
@@ -29,6 +41,11 @@ export function Slider({ min, max, step, value, onChange }: Props) {
defaultValue={value}
onAfterChange={onChange}
className={styles.slider}
+ tipProps={{ visible }}
+ railStyle={{ height: 8 }}
+ trackStyle={{ height: 8 }}
+ dotStyle={{ visibility: 'hidden' }}
+ data-cy={dataCy}
/>
);
diff --git a/app/react/components/form-components/Slider/index.ts b/app/react/components/form-components/Slider/index.ts
new file mode 100644
index 000000000..f84acd84c
--- /dev/null
+++ b/app/react/components/form-components/Slider/index.ts
@@ -0,0 +1 @@
+export { Slider } from './Slider';