-
Notifications
You must be signed in to change notification settings - Fork 706
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add slider component for adding the disk size (#1206)
- Loading branch information
Andres Martinez Gotor
authored
Oct 8, 2019
1 parent
122f4aa
commit 32d70fd
Showing
12 changed files
with
757 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,7 @@ | |
color: #5f6369; | ||
font-size: 0.9em; | ||
} | ||
|
||
.disk_size_input { | ||
width: 75%; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
dashboard/src/components/DeploymentForm/BasicDeploymentForm/DiskSizeParam.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import { shallow } from "enzyme"; | ||
import * as React from "react"; | ||
import { IBasicFormParam } from "shared/types"; | ||
import Slider from "../../../components/Slider"; | ||
import DiskSizeParam from "./DiskSizeParam"; | ||
|
||
const defaultProps = { | ||
id: "disk", | ||
name: "diskSize", | ||
label: "Disk Size", | ||
param: { | ||
value: "10Gi", | ||
type: "string", | ||
path: "disk", | ||
} as IBasicFormParam, | ||
handleBasicFormParamChange: jest.fn(), | ||
}; | ||
|
||
it("renders a disk size param with a default value", () => { | ||
const wrapper = shallow(<DiskSizeParam {...defaultProps} />); | ||
expect(wrapper.state("Gi")).toBe(10); | ||
expect(wrapper).toMatchSnapshot(); | ||
}); | ||
|
||
it("changes the value of the param when the slider changes", () => { | ||
const param = { | ||
value: "10Gi", | ||
type: "string", | ||
path: "disk", | ||
} as IBasicFormParam; | ||
const handleBasicFormParamChange = jest.fn(() => { | ||
param.value = "20Gi"; | ||
return jest.fn(); | ||
}); | ||
|
||
const wrapper = shallow( | ||
<DiskSizeParam | ||
{...defaultProps} | ||
param={param} | ||
handleBasicFormParamChange={handleBasicFormParamChange} | ||
/>, | ||
); | ||
expect(wrapper.state("Gi")).toBe(10); | ||
|
||
const slider = wrapper.find(Slider); | ||
(slider.prop("onChange") as (values: number[]) => void)([20]); | ||
|
||
expect(param.value).toBe("20Gi"); | ||
expect(handleBasicFormParamChange.mock.calls[0]).toEqual([ | ||
"diskSize", | ||
{ value: "20Gi", type: "string", path: "disk" }, | ||
]); | ||
}); | ||
|
||
it("updates state but does not change param value during slider update (only when dropped in a point)", () => { | ||
const handleBasicFormParamChange = jest.fn(); | ||
const wrapper = shallow( | ||
<DiskSizeParam {...defaultProps} handleBasicFormParamChange={handleBasicFormParamChange} />, | ||
); | ||
expect(wrapper.state("Gi")).toBe(10); | ||
|
||
const slider = wrapper.find(Slider); | ||
(slider.prop("onUpdate") as (values: number[]) => void)([20]); | ||
|
||
expect(wrapper.state("Gi")).toBe(20); | ||
expect(handleBasicFormParamChange).not.toHaveBeenCalled(); | ||
}); | ||
|
||
describe("when changing the value in the input", () => { | ||
it("parses a number and forwards it", () => { | ||
const valueChange = jest.fn(); | ||
const handleBasicFormParamChange = jest.fn(() => valueChange); | ||
const wrapper = shallow( | ||
<DiskSizeParam {...defaultProps} handleBasicFormParamChange={handleBasicFormParamChange} />, | ||
); | ||
expect(wrapper.state("Gi")).toBe(10); | ||
|
||
const input = wrapper.find("input#disk"); | ||
const event = { currentTarget: { value: "20" } } as React.FormEvent<HTMLInputElement>; | ||
(input.prop("onChange") as ((e: React.FormEvent<HTMLInputElement>) => void))(event); | ||
|
||
expect(wrapper.state("Gi")).toBe(20); | ||
expect(valueChange.mock.calls[0]).toEqual([{ currentTarget: { value: "20Gi" } }]); | ||
}); | ||
|
||
it("ignores values in the input that are not digits", () => { | ||
const valueChange = jest.fn(); | ||
const handleBasicFormParamChange = jest.fn(() => valueChange); | ||
const wrapper = shallow( | ||
<DiskSizeParam {...defaultProps} handleBasicFormParamChange={handleBasicFormParamChange} />, | ||
); | ||
expect(wrapper.state("Gi")).toBe(10); | ||
|
||
const input = wrapper.find("input#disk"); | ||
const event = { currentTarget: { value: "foo20*#@$" } } as React.FormEvent<HTMLInputElement>; | ||
(input.prop("onChange") as ((e: React.FormEvent<HTMLInputElement>) => void))(event); | ||
|
||
expect(wrapper.state("Gi")).toBe(20); | ||
expect(valueChange.mock.calls[0]).toEqual([{ currentTarget: { value: "20Gi" } }]); | ||
}); | ||
|
||
it("accept decimal values", () => { | ||
const valueChange = jest.fn(); | ||
const handleBasicFormParamChange = jest.fn(() => valueChange); | ||
const wrapper = shallow( | ||
<DiskSizeParam {...defaultProps} handleBasicFormParamChange={handleBasicFormParamChange} />, | ||
); | ||
expect(wrapper.state("Gi")).toBe(10); | ||
|
||
const input = wrapper.find("input#disk"); | ||
const event = { currentTarget: { value: "20.5" } } as React.FormEvent<HTMLInputElement>; | ||
(input.prop("onChange") as ((e: React.FormEvent<HTMLInputElement>) => void))(event); | ||
|
||
expect(wrapper.state("Gi")).toBe(20.5); | ||
expect(valueChange.mock.calls[0]).toEqual([{ currentTarget: { value: "20.5Gi" } }]); | ||
}); | ||
|
||
it("modifies the max value of the slider if the input is bigger than 100", () => { | ||
const valueChange = jest.fn(); | ||
const handleBasicFormParamChange = jest.fn(() => valueChange); | ||
const wrapper = shallow( | ||
<DiskSizeParam {...defaultProps} handleBasicFormParamChange={handleBasicFormParamChange} />, | ||
); | ||
expect(wrapper.state("Gi")).toBe(10); | ||
|
||
const input = wrapper.find("input#disk"); | ||
const event = { currentTarget: { value: "200" } } as React.FormEvent<HTMLInputElement>; | ||
(input.prop("onChange") as ((e: React.FormEvent<HTMLInputElement>) => void))(event); | ||
|
||
expect(wrapper.state("Gi")).toBe(200); | ||
const slider = wrapper.find(Slider); | ||
expect(slider.prop("max")).toBe(200); | ||
}); | ||
}); |
93 changes: 93 additions & 0 deletions
93
dashboard/src/components/DeploymentForm/BasicDeploymentForm/DiskSizeParam.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import * as React from "react"; | ||
import { IBasicFormParam } from "shared/types"; | ||
import Slider from "../../../components/Slider"; | ||
|
||
export interface IDiskSizeParamProps { | ||
id: string; | ||
name: string; | ||
label: string; | ||
param: IBasicFormParam; | ||
handleBasicFormParamChange: ( | ||
name: string, | ||
p: IBasicFormParam, | ||
) => (e: React.FormEvent<HTMLInputElement>) => void; | ||
} | ||
|
||
export interface IDiskSizeParamState { | ||
Gi: number; | ||
} | ||
|
||
function toNumber(value: string) { | ||
// Force to return a Number from a string removing any character that is not a digit | ||
return Number(value.replace(/[^\d\.]/g, "")); | ||
} | ||
|
||
class DiskSizeParam extends React.Component<IDiskSizeParamProps, IDiskSizeParamState> { | ||
public state: IDiskSizeParamState = { | ||
Gi: toNumber(this.props.param.value) || 10, | ||
}; | ||
|
||
// onChangeSlider is executed when the slider is dropped at one point | ||
// at that point we update the parameter | ||
public onChangeSlider = (values: number[]) => { | ||
this.handleParamChange(values[0]); | ||
}; | ||
|
||
// onUpdateSlider is executed when dragging the slider | ||
// we just update the state here for a faster response | ||
public onUpdateSlider = (values: number[]) => { | ||
this.setState({ Gi: values[0] }); | ||
}; | ||
|
||
public onChangeInput = (e: React.FormEvent<HTMLInputElement>) => { | ||
const value = toNumber(e.currentTarget.value); | ||
this.setState({ Gi: value }); | ||
this.handleParamChange(value); | ||
}; | ||
|
||
public render() { | ||
const { param, label } = this.props; | ||
return ( | ||
<div> | ||
<label htmlFor={this.props.id}> | ||
{label} | ||
{param.description && ( | ||
<> | ||
<br /> | ||
<span className="description">{param.description}</span> | ||
</> | ||
)} | ||
<div className="row"> | ||
<div className="col-10"> | ||
<Slider | ||
min={1} | ||
max={Math.max(100, this.state.Gi)} | ||
default={this.state.Gi} | ||
onChange={this.onChangeSlider} | ||
onUpdate={this.onUpdateSlider} | ||
values={this.state.Gi} | ||
/> | ||
</div> | ||
<div className="col-2"> | ||
<input | ||
className="disk_size_input" | ||
id={this.props.id} | ||
onChange={this.onChangeInput} | ||
value={this.state.Gi} | ||
/> | ||
<span className="margin-l-normal">Gi</span> | ||
</div> | ||
</div> | ||
</label> | ||
</div> | ||
); | ||
} | ||
|
||
private handleParamChange = (value: number) => { | ||
this.props.handleBasicFormParamChange(this.props.name, this.props.param)({ | ||
currentTarget: { value: `${value}Gi` }, | ||
} as React.FormEvent<HTMLInputElement>); | ||
}; | ||
} | ||
|
||
export default DiskSizeParam; |
Oops, something went wrong.