Skip to content

Commit 7188a5c

Browse files
committed
Number inputs (:trollface:)
1 parent 2ebdf30 commit 7188a5c

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

components/dashboard/src/components/forms/TextInputField.tsx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ type Props = TextInputProps & {
1818
topMargin?: boolean;
1919
containerClassName?: string;
2020
};
21-
2221
export const TextInputField: FunctionComponent<Props> = memo(
2322
({ label, id, hint, error, topMargin, containerClassName, ...props }) => {
2423
const maybeId = useId();
@@ -71,3 +70,36 @@ export const TextInput: FunctionComponent<TextInputProps> = memo(({ className, o
7170
/>
7271
);
7372
});
73+
74+
type NumberInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "type"> & {
75+
onChange?: (newValue: number) => void;
76+
onBlur?: () => void;
77+
};
78+
export const NumberInput: FunctionComponent<NumberInputProps> = memo(({ className, onChange, onBlur, ...props }) => {
79+
const handleChange = useCallback(
80+
(e) => {
81+
onChange && onChange(e.target.valueAsNumber);
82+
},
83+
[onChange],
84+
);
85+
86+
const handleBlur = useCallback(() => onBlur && onBlur(), [onBlur]);
87+
88+
return (
89+
<input
90+
// 7px top/bottom padding ensures height matches buttons (36px)
91+
className={cn(
92+
"py-[7px] w-full max-w-lg rounded-lg",
93+
"text-pk-content-primary",
94+
"bg-pk-surface-primary",
95+
"border-pk-border-base",
96+
"text-sm",
97+
className,
98+
)}
99+
onChange={handleChange}
100+
onBlur={handleBlur}
101+
type="number"
102+
{...props}
103+
/>
104+
);
105+
});

components/dashboard/src/teams/policies/MaxParallelWorkspaces.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import { FormEvent, useEffect, useState } from "react";
99
import { ConfigurationSettingsField } from "../../repositories/detail/ConfigurationSettingsField";
1010
import { Heading3, Subheading } from "@podkit/typography/Headings";
1111
import { InputField } from "../../components/forms/InputField";
12-
import { TextInput } from "../../components/forms/TextInputField";
12+
import { NumberInput } from "../../components/forms/TextInputField";
1313
import { LoadingButton } from "@podkit/buttons/LoadingButton";
1414
import { MAX_PARALLEL_WORKSPACES_FREE, MAX_PARALLEL_WORKSPACES_PAID } from "@gitpod/gitpod-protocol";
1515
import { PlainMessage } from "@bufbuild/protobuf";
16+
import { useInstallationConfiguration } from "../../data/installation/default-workspace-image-query";
1617

1718
type Props = {
1819
isOwner: boolean;
@@ -40,6 +41,8 @@ export const MaxParallelWorkspaces = ({
4041
);
4142

4243
const organizationDefault = isPaidPlan ? MAX_PARALLEL_WORKSPACES_PAID : MAX_PARALLEL_WORKSPACES_FREE;
44+
const { data: installationConfig } = useInstallationConfiguration();
45+
const isDedicatedInstallation = !!installationConfig?.isDedicatedInstallation;
4346

4447
const handleSubmit = async (e: FormEvent) => {
4548
e.preventDefault();
@@ -66,13 +69,15 @@ export const MaxParallelWorkspaces = ({
6669
</Subheading>
6770
<form onSubmit={handleSubmit}>
6871
<InputField label="Maximum parallel running workspaces" error={error} className="mb-4">
69-
<TextInput
72+
<NumberInput
7073
value={maxParallelWorkspaces ?? ""}
7174
onChange={(newValue) => {
72-
setMaxParallelWorkspaces(parseInt(newValue));
75+
setMaxParallelWorkspaces(newValue);
7376
setError(undefined);
7477
}}
7578
disabled={isLoading || !isOwner}
79+
min={0}
80+
max={isDedicatedInstallation ? undefined : organizationDefault}
7681
/>
7782
</InputField>
7883
<LoadingButton type="submit" loading={isLoading} disabled={!isOwner}>

0 commit comments

Comments
 (0)