Skip to content

Commit

Permalink
Fix the bloody number inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
Hornwitser committed Sep 7, 2024
1 parent 0aff731 commit 5e132f9
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 68 deletions.
37 changes: 7 additions & 30 deletions web/components/InputPosition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,26 @@ import { useState } from "react";

interface InputPositionProps {
id?: string;
value?: number[];
onChange?: (value: number[]) => void;
value?: string[];
onChange?: (value: string[]) => void;
}

/**
* Input position coordinates and get [x, y] as value, for use in antd Form
*/
export default function InputPosition(props: InputPositionProps) {
const { id, value = [], onChange } = props;
const [x, setX] = useState(0);
const [y, setY] = useState(0);

function triggerChange(changedValue: { x?: number; y?: number }) {
onChange?.([changedValue.x || x, changedValue.y || y]);
};

function onXChange(e: React.ChangeEvent<HTMLInputElement>) {
const newX = parseInt(e.target.value || "0", 10);
if (Number.isNaN(x)) {
return;
}
setX(newX);
triggerChange({ x: newX });
};
function onYChange(e: React.ChangeEvent<HTMLInputElement>) {
const newY = parseInt(e.target.value || "0", 10);
if (Number.isNaN(y)) {
return;
}
setY(newY);
triggerChange({ y: newY });
};
const { id, value = ["0", "0"], onChange } = props;

return (
<span id={id}>
<Input
value={value[0] || x}
onChange={onXChange}
value={value[0]}
onChange={e => onChange?.([e.target.value, value[1]])}
style={{ width: 100 }}
/>
<Input
value={value[1] || y}
onChange={onYChange}
value={value[1]}
onChange={e => onChange?.([value[0], e.target.value])}
style={{ width: 100 }}
/>
</span>
Expand Down
161 changes: 123 additions & 38 deletions web/pages/EdgeListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from "@clusterio/web_ui";

import * as messages from "../../messages";
import { EdgeTargetSpecification } from "../../src/types";
import { Edge, EdgeTargetSpecification } from "../../src/types";
import { WebPlugin } from "..";
import { InstanceSelector } from "../components/InstanceSelector";
import { direction_to_string } from "../../src/util/direction_to_string";
Expand All @@ -28,6 +28,72 @@ function EdgeTarget({ target }: { target: EdgeTargetSpecification }) {
</Card>;
}

function edgeToForm(edge?: Edge) {
if (!edge) {
return {
isDeleted: false,
length: 10,
active: false,
source: {
instanceId: undefined,
origin: ["0", "0"],
surface: "1",
direction: 0,
ready: false,
},
target: {
instanceId: undefined,
origin: ["0", "0"],
surface: "1",
direction: 0,
ready: false,
},
};
}

return {
...edge,
updatedAtMs: Date.now(),
length: String(edge.length),
source: {
...edge.source,
surface: String(edge.source.surface),
origin: edge.source.origin.map(String),
},
target: {
...edge.target,
surface: String(edge.target.surface),
origin: edge.target.origin.map(String),
},
};
}
type EdgeForm = NonNullable<ReturnType<typeof edgeToForm>>;

function formToEdge(form: EdgeForm, id: string, link_destinations: Edge["link_destinations"]): Edge {
return {
...form,
link_destinations,
id,
updatedAtMs: Date.now(),
length: Number(form.length),
active: false,
source: {
...form.source,
ready: false,
surface: Number.parseInt(form.source.surface, 10),
instanceId: form.source.instanceId!,
origin: form.source.origin.map(s => Number.parseInt(s, 10)),
},
target: {
...form.target,
ready: false,
surface: Number.parseInt(form.target.surface, 10),
instanceId: form.target.instanceId!,
origin: form.target.origin.map(s => Number.parseInt(s, 10)),
},
};
}

export default function EdgeListPage() {
const control = useContext(ControlContext);
const account = useAccount();
Expand Down Expand Up @@ -123,56 +189,61 @@ export default function EdgeListPage() {
destroyOnClose // Reset form when modal is closed
footer={null}
>
<Form
<Form<EdgeForm>
preserve={false} // Reset form when modal is closed
size="small"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
onFinish={(values) => {
values.id = editing;
values.updatedAtMs = Date.now();
values.source.ready = false;
values.target.ready = false;
values.active = false;
values.length = Number(values.length);
values.link_destinations = edgeConfigs.get(editing)?.link_destinations || {};
console.log(values);
control.send(new messages.SetEdgeConfig(values));
}}
initialValues={edgeConfigs.get(editing) || {
isDeleted: false,
length: 10,
active: false,
source: {
instanceId: undefined,
origin: [0, 0],
surface: 1,
direction: 0,
ready: false,
},
target: {
instanceId: undefined,
origin: [0, 0],
surface: 1,
direction: 0,
ready: false,
},
const original = edgeConfigs.get(editing);
const edge = formToEdge(values, editing, original?.link_destinations ?? {})
console.log(edge);
control.send(new messages.SetEdgeConfig(edge));
}}
initialValues={edgeToForm(edgeConfigs.get(editing))}
>
<Form.Item {...fIStyle} name="isDeleted" label="Delete" valuePropName="checked">
<Input type="checkbox" />
</Form.Item>
<Form.Item {...fIStyle} name="length" label="Length">
<Input type="number" />
<Form.Item
{...fIStyle}
name="length"
label="Length"
rules={[{ required: true, pattern: /^ *-?[0-9]+ *$/, message: "must be a number" }]}
>
<Input />
</Form.Item>
<Divider>Source</Divider>
<Form.Item {...fIStyle} name={["source", "instanceId"]} label="Source instance">
<Form.Item
{...fIStyle}
name={["source", "instanceId"]}
label="Source instance"
rules={[{ required: true }]}
>
<InstanceSelector />
</Form.Item>
<Form.Item {...fIStyle} name={["source", "origin"]} label="Position">
<Form.Item
{...fIStyle}
name={["source", "origin"]}
label="Position"
rules={[{
validator: async (_, value) => {
for (const pos of value) {
if (!/^ *-?[0-9]+ *$/.test(pos)) {
throw new Error("Position must be two numbers")
}
}
},
}]}
>
<InputPosition />
</Form.Item>
<Form.Item {...fIStyle} name={["source", "surface"]} label="Surface">
<Form.Item
{...fIStyle}
name={["source", "surface"]}
label="Surface"
rules={[{ required: true, pattern: /^ *-?[0-9]+ *$/, message: "must be a number" }]}
>
<Input />
</Form.Item>
<Form.Item {...fIStyle} name={["source", "direction"]} label="Direction">
Expand All @@ -183,13 +254,27 @@ export default function EdgeListPage() {
</Select>
</Form.Item>
<Divider>Target</Divider>
<Form.Item {...fIStyle} name={["target", "instanceId"]} label="Target instance">
<Form.Item
{...fIStyle}
name={["target", "instanceId"]}
label="Target instance"
rules={[{ required: true }]}
>
<InstanceSelector />
</Form.Item>
<Form.Item {...fIStyle} name={["target", "origin"]} label="Position">
<Form.Item
{...fIStyle}
name={["target", "origin"]}
label="Position"
>
<InputPosition />
</Form.Item>
<Form.Item {...fIStyle} name={["target", "surface"]} label="Surface">
<Form.Item
{...fIStyle}
name={["target", "surface"]}
label="Surface"
rules={[{ required: true, pattern: /^ *-?[0-9]+ *$/, message: "must be a number" }]}
>
<Input />
</Form.Item>
<Form.Item {...fIStyle} name={["target", "direction"]} label="Direction">
Expand Down

0 comments on commit 5e132f9

Please sign in to comment.