From 782e93f4a195425160a01777c1a472e3dbee4fa6 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Tue, 15 Jun 2021 14:24:35 +0200 Subject: [PATCH 1/3] Add changelog entry for #380 Add entry in CHANGELOG.md for the save management feature. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eba715c2..2991fa6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Packaged and uploaded to npm again, greatly simplifying distribution and installation of both Clusterio and plugins. - Added centralized logging for the cluster. All logs from both Clusterio and Factorio is stored in a shared log which can be inspected and queried. +- Added remote save management with the ability to list, create, upload, download, delete and load saves for instances. ### Features From cc562a451e5e2c7b953f632a667101a51cd33219 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Tue, 15 Jun 2021 14:25:45 +0200 Subject: [PATCH 2/3] Fix create instance modal Fix copy and paste bug in the name check for the create instance moddal. --- packages/web_ui/src/components/InstancesPage.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/web_ui/src/components/InstancesPage.jsx b/packages/web_ui/src/components/InstancesPage.jsx index bab926ba..71fb90a4 100644 --- a/packages/web_ui/src/components/InstancesPage.jsx +++ b/packages/web_ui/src/components/InstancesPage.jsx @@ -21,7 +21,8 @@ function CreateInstanceButton(props) { async function createInstance() { let values = form.getFieldsValue(); if (!values.instanceName) { - form.setFields([{ name: "mapGenSettings", errors: ["Name is required"] }]); + form.setFields([{ name: "instanceName", errors: ["Name is required"] }]); + return; } let instanceConfig = new libConfig.InstanceConfig("control"); From fc08438164597b986c0df6b6ab18094d78dda56c Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Tue, 15 Jun 2021 14:35:24 +0200 Subject: [PATCH 3/3] Add generate slave token button Add a generate slave token button to the web interface and modify the generateSlaveToken message and corresponding ctl command to have the slave id be optional. The random id is the desired behavior when adding a slave with the installer, as it'll ask for the token for the new slave and deduce the id from the token. --- packages/ctl/ctl.js | 5 +- packages/lib/link/messages.js | 2 +- packages/master/src/ControlConnection.js | 6 +- packages/web_ui/src/components/SlavesPage.jsx | 72 ++++++++++++++++++- test/integration/clusterio.js | 3 + 5 files changed, 81 insertions(+), 7 deletions(-) diff --git a/packages/ctl/ctl.js b/packages/ctl/ctl.js index 6ddc1d09..7d15d6e5 100755 --- a/packages/ctl/ctl.js +++ b/packages/ctl/ctl.js @@ -137,10 +137,11 @@ slaveCommands.add(new libCommand.Command({ slaveCommands.add(new libCommand.Command({ definition: ["generate-token", "Generate token for a slave", (yargs) => { - yargs.option("id", { type: "number", nargs: 1, describe: "Slave id", demandOption: true }); + yargs.option("id", { type: "number", nargs: 1, describe: "Slave id" }); }], handler: async function(args, control) { - let response = await libLink.messages.generateSlaveToken.send(control, { slave_id: args.id }); + let slaveId = typeof args.id === "number" ? args.id : null; + let response = await libLink.messages.generateSlaveToken.send(control, { slave_id: slaveId }); print(response.token); }, })); diff --git a/packages/lib/link/messages.js b/packages/lib/link/messages.js index 6ba0a8a4..dbb84455 100644 --- a/packages/lib/link/messages.js +++ b/packages/lib/link/messages.js @@ -422,7 +422,7 @@ messages.generateSlaveToken = new Request({ links: ["control-master"], permission: "core.slave.generate_token", requestProperties: { - "slave_id": { type: "integer" }, + "slave_id": { type: ["integer", "null"] }, }, responseProperties: { "token": { type: "string" }, diff --git a/packages/master/src/ControlConnection.js b/packages/master/src/ControlConnection.js index ddf42e83..2792774b 100644 --- a/packages/master/src/ControlConnection.js +++ b/packages/master/src/ControlConnection.js @@ -130,7 +130,11 @@ class ControlConnection extends BaseConnection { } async generateSlaveTokenRequestHandler(message) { - return { token: this.generateSlaveToken(message.data.slave_id) }; + let slaveId = message.data.slave_id; + if (slaveId === null) { + slaveId = Math.random() * 2**31 | 0; + } + return { token: this.generateSlaveToken(slaveId) }; } async createSlaveConfigRequestHandler(message) { diff --git a/packages/web_ui/src/components/SlavesPage.jsx b/packages/web_ui/src/components/SlavesPage.jsx index 0283c8bb..74af789a 100644 --- a/packages/web_ui/src/components/SlavesPage.jsx +++ b/packages/web_ui/src/components/SlavesPage.jsx @@ -1,11 +1,73 @@ -import React, { useContext } from "react"; -import { Table } from "antd"; +import React, { useContext, useRef, useState } from "react"; +import { Button, Form, Input, Modal, PageHeader, Table } from "antd"; import libLink from "@clusterio/lib/link"; import ControlContext from "./ControlContext"; import PageLayout from "./PageLayout"; import { useSlaveList } from "../model/slave"; +import { notifyErrorHandler } from "../util/notify"; + + +function GenerateSlaveTokenButton(props) { + let control = useContext(ControlContext); + let [visible, setVisible] = useState(false); + let [token, setToken] = useState(null); + let [form] = Form.useForm(); + let tokenTextAreaRef = useRef(null); + + async function generateToken() { + let values = form.getFieldsValue(); + let slaveId = null; + if (values.slaveId) { + slaveId = Number.parseInt(values.slaveId, 10); + if (Number.isNaN(slaveId)) { + form.setFields([{ name: "slaveId", errors: ["Must be an integer"] }]); + return; + } + form.setFields([{ name: "slaveId", errors: [] }]); + } + + let result = await libLink.messages.generateSlaveToken.send(control, { slave_id: slaveId }); + setToken(result.token); + } + + return <> + + { + setVisible(false); + setToken(null); + form.resetFields(); + }} + > +
+ + + + + + + + + + +
+
+ ; +} export default function SlavesPage() { @@ -13,7 +75,11 @@ export default function SlavesPage() { let [slaveList] = useSlaveList(); return -

Slaves

+ + />