Files
factorio-scenario-ExpCluster/exp_roles/web/components/RoleProperties.tsx
T
2026-08-06 07:19:36 +00:00

179 lines
5.0 KiB
TypeScript

import React, { useContext, useEffect, useState } from "react";
import { Button, Col, ColorPicker, Form, Input, InputNumber, Row, Switch, Tooltip } from "antd";
import * as lib from "@clusterio/lib";
import { ControlContext, SectionHeader, useAccount, notifyErrorHandler } from "@clusterio/web_ui";
import { RoleColor, RoleMetaRecord, RoleMetaUpdateRequest } from "../../messages";
import type { WebPlugin } from "..";
const MS_PER_HOUR = 3600000;
type RoleFormValues = {
order: number;
priority: number;
shortHand: string;
tag: string;
color: string | { toRgb(): { r: number, g: number, b: number } } | null;
autoAssignHours: number | null;
blockAutoAssign: boolean;
};
/**
* In game properties of a role, shown at the end of the core role page.
*
* The name, description and permissions of a role are owned by clusterio, this
* only covers the properties which only mean something in game.
*/
export default function RoleProperties(props: { plugin: WebPlugin, role?: lib.Role }) {
const control = useContext(ControlContext);
const account = useAccount();
const [form] = Form.useForm<RoleFormValues>();
const [applying, setApplying] = useState(false);
const [roles] = props.plugin.useRoles();
const record = props.role ? roles.get(props.role.id) : undefined;
const meta = record?.meta;
const canUpdate = account.hasPermission("core.role.update");
useEffect(() => {
if (!meta) {
return;
}
form.setFieldsValue({
order: meta.order,
priority: meta.priority,
shortHand: meta.shortHand,
tag: meta.tag,
color: meta.color ? `rgb(${meta.color.r}, ${meta.color.g}, ${meta.color.b})` : null,
autoAssignHours: meta.autoAssignOnlineTimeMs === null
? null
: meta.autoAssignOnlineTimeMs / MS_PER_HOUR,
blockAutoAssign: meta.blockAutoAssign,
});
}, [meta, form]);
if (!props.role || !meta) {
return null;
}
async function apply() {
const values = form.getFieldsValue();
let color: RoleColor | null = null;
if (values.color && typeof values.color !== "string") {
const rgb = values.color.toRgb();
color = new RoleColor(Math.round(rgb.r), Math.round(rgb.g), Math.round(rgb.b));
} else if (typeof values.color === "string") {
const match = values.color.match(/(\d+)\D+(\d+)\D+(\d+)/);
if (match) {
color = new RoleColor(Number(match[1]), Number(match[2]), Number(match[3]));
}
}
await control.send(new RoleMetaUpdateRequest(new RoleMetaRecord(
props.role!.id,
values.order,
values.priority,
values.shortHand ?? "",
values.tag ?? "",
color,
values.autoAssignHours === null || values.autoAssignHours === undefined
? null
: values.autoAssignHours * MS_PER_HOUR,
values.blockAutoAssign ?? false,
)));
}
const labelled = (text: string, tip: string) => <Tooltip title={tip}>{text}</Tooltip>;
return <>
<SectionHeader
title="In Game Properties"
extra={canUpdate ? <Button
type="primary"
loading={applying}
onClick={() => {
setApplying(true);
apply()
.catch(notifyErrorHandler("Error updating role properties"))
.finally(() => setApplying(false));
}}
>Apply in game properties</Button> : undefined}
/>
<Form
form={form}
disabled={!canUpdate}
labelAlign="left"
labelCol={{ span: 12 }}
wrapperCol={{ span: 12 }}
labelWrap
>
<Row gutter={[16, 0]}>
<Col xs={24} md={12} xl={8}>
<Form.Item
name="order"
label={labelled("Order", "A lower value is a more privileged role")}
>
<InputNumber style={{ width: "100%" }} />
</Form.Item>
<Form.Item
name="priority"
label={labelled(
"Priority",
"Only the roles with the highest priority a player holds apply, "
+ "which is how Jail suppresses every other role"
)}
>
<InputNumber style={{ width: "100%" }} />
</Form.Item>
</Col>
<Col xs={24} md={12} xl={8}>
<Form.Item
name="shortHand"
label={labelled("Short hand", "Short form of the name, used where space is limited")}
>
<Input />
</Form.Item>
<Form.Item
name="tag"
label={labelled("Tag", "Shown next to the names of players with this role")}
>
<Input />
</Form.Item>
<Form.Item
name="color"
label={labelled("Colour", "Used for the role name and tag in game")}
>
<ColorPicker allowClear format="rgb" disabledAlpha />
</Form.Item>
</Col>
<Col xs={24} md={12} xl={8}>
<Form.Item
name="autoAssignHours"
label={labelled(
"Auto assign after (hours)",
"Granted once a player reaches this much online time across the cluster. "
+ "Leave empty to never grant it automatically"
)}
>
<InputNumber min={0} placeholder="Never" style={{ width: "100%" }} />
</Form.Item>
<Form.Item
name="blockAutoAssign"
label={labelled(
"Block auto assign",
"Players holding this role are never granted any other role automatically"
)}
valuePropName="checked"
>
<Switch />
</Form.Item>
</Col>
</Row>
</Form>
</>;
}