1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

switched for scaling replicas with Slider component instead of Buttons+Input

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2023-02-16 13:47:21 +02:00
parent 7f6a46b987
commit 33fee80af9
3 changed files with 41 additions and 80 deletions

View File

@ -29,7 +29,7 @@ export class ReplicationControllerApi extends KubeApi<ReplicationController> {
return this.request.get(this.getScaleApiUrl(params)); return this.request.get(this.getScaleApiUrl(params));
} }
scale(params: { namespace: string; name: string }, replicas: number) { scale(params: { namespace: string; name: string }, replicas: number): Promise<Scale> {
return this.request.patch(this.getScaleApiUrl(params), { return this.request.patch(this.getScaleApiUrl(params), {
data: { data: {
metadata: params, metadata: params,

View File

@ -4,10 +4,13 @@
*/ */
.ReplicationControllerDetails { .ReplicationControllerDetails {
.replicas {
.desiredReplicas {
display: flex; display: flex;
gap: calc(var(--margin) * 2); gap: calc(var(--margin) * 2);
align-items: center; align-items: center;
> * {
flex-shrink: 0;
}
} }
} }

View File

@ -5,112 +5,60 @@
import styles from "./replicationcontroller-details.module.scss"; import styles from "./replicationcontroller-details.module.scss";
import React from "react"; import React from "react";
import { makeObservable, observable } from "mobx"; import { action, makeObservable, observable } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import { DrawerItem, DrawerTitle } from "../drawer"; import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge"; import { Badge } from "../badge";
import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { KubeObjectDetailsProps } from "../kube-object-details";
import type { ReplicationControllerStore } from "./replicationcontroller-store";
import replicationControllerStoreInjectable from "./replicationcontroller-store.injectable";
import type { import type {
ReplicationController, ReplicationController,
ReplicationControllerApi, ReplicationControllerApi,
} from "../../../common/k8s-api/endpoints"; } from "../../../common/k8s-api/endpoints";
import replicationControllerApiInjectable import replicationControllerApiInjectable
from "../../../common/k8s-api/endpoints/replication-controller.api.injectable"; from "../../../common/k8s-api/endpoints/replication-controller.api.injectable";
import { Button } from "../button";
import { Input } from "../input";
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable"; import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
import type { ShowNotification } from "../notifications"; import type { ShowNotification } from "../notifications";
import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable"; import { Slider } from "../slider";
export interface ReplicationControllerDetailsProps extends KubeObjectDetailsProps<ReplicationController> { export interface ReplicationControllerDetailsProps extends KubeObjectDetailsProps<ReplicationController> {
} }
interface Dependencies { interface Dependencies {
store: ReplicationControllerStore;
api: ReplicationControllerApi; api: ReplicationControllerApi;
showNotificationError: ShowNotification; showNotificationError: ShowNotification;
hideDetails(): void;
} }
@observer @observer
class NonInjectedReplicationControllerDetails<Props extends ReplicationControllerDetailsProps & Dependencies> extends React.Component<Props> { class NonInjectedReplicationControllerDetails<Props extends ReplicationControllerDetailsProps & Dependencies> extends React.Component<Props> {
@observable showScaleDialog = false; @observable sliderReplicasValue = this.props.object.getDesiredReplicas();
@observable sliderReplicasDisabled = false;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
makeObservable(this); makeObservable(this);
} }
inputRef = React.createRef<Input>(); @action
async scale(replicas: number) {
const { object: resource, api, showNotificationError } = this.props;
scale(replicas: number) { try {
const { object: resource, api } = this.props; await api.scale({
name: resource.getName(),
return api.scale({ namespace: resource.getNs(),
name: resource.getName(), }, replicas);
namespace: resource.getNs(), } catch (error) {
}, replicas); this.sliderReplicasValue = resource.getDesiredReplicas(); // rollback to last valid value
showNotificationError(error as Error);
}
} }
renderReplicasAndScaleDialog() { @action
const { object: resource, showNotificationError, hideDetails } = this.props; async onScaleSliderChangeCommitted(evt: React.FormEvent<any>, replicas: number) {
this.sliderReplicasDisabled = true;
if (this.showScaleDialog) { await this.scale(replicas);
return ( this.sliderReplicasDisabled = false;
<div className={styles.desiredReplicas}>
<Input
type="number"
min={1}
max={100}
defaultValue={resource.getDesiredReplicas().toString()}
ref={this.inputRef}
/>
<Button
accent
label="Cancel"
onClick={() => this.showScaleDialog = false}
/>
<Button
primary
label="Scale"
onClick={async () => {
const inputComponent = this.inputRef.current;
const newScaleVal = Number(inputComponent?.getValue());
if (isNaN(newScaleVal)) return;
try {
await this.scale(newScaleVal);
this.showScaleDialog = false;
hideDetails();
} catch (err) {
showNotificationError(String(err));
}
}}
/>
</div>
);
}
return (
<div className={styles.desiredReplicas}>
<div>
{resource.getDesiredReplicas()}
</div>
<Button
primary
label="Scale"
onClick={() => {
this.showScaleDialog = true;
requestAnimationFrame(() => this.inputRef.current?.focus());
}}
/>
</div>
);
} }
render() { render() {
@ -121,8 +69,20 @@ class NonInjectedReplicationControllerDetails<Props extends ReplicationControlle
<DrawerTitle> <DrawerTitle>
Spec Spec
</DrawerTitle> </DrawerTitle>
<DrawerItem name="Desired Replicas"> <DrawerItem name="Replicas">
{this.renderReplicasAndScaleDialog()} <div className={styles.replicas}>
<div>{resource.getDesiredReplicas()}</div>
<div>Scale</div>
<Slider
min={0}
max={100}
valueLabelDisplay="auto"
disabled={this.sliderReplicasDisabled}
value={this.sliderReplicasValue}
onChange={(evt, value) => this.sliderReplicasValue = value}
onChangeCommitted={(event, value) => this.onScaleSliderChangeCommitted(event, value as number)}
/>
</div>
</DrawerItem> </DrawerItem>
<DrawerItem name="Selectors" labelsOnly> <DrawerItem name="Selectors" labelsOnly>
{ {
@ -156,9 +116,7 @@ class NonInjectedReplicationControllerDetails<Props extends ReplicationControlle
export const ReplicationControllerDetails = withInjectables<Dependencies, ReplicationControllerDetailsProps>(NonInjectedReplicationControllerDetails, { export const ReplicationControllerDetails = withInjectables<Dependencies, ReplicationControllerDetailsProps>(NonInjectedReplicationControllerDetails, {
getProps: (di, props) => ({ getProps: (di, props) => ({
...props, ...props,
store: di.inject(replicationControllerStoreInjectable),
api: di.inject(replicationControllerApiInjectable), api: di.inject(replicationControllerApiInjectable),
showNotificationError: di.inject(showErrorNotificationInjectable), showNotificationError: di.inject(showErrorNotificationInjectable),
hideDetails: di.inject(hideDetailsInjectable),
}), }),
}); });