From a633c42904205eb38da413cb04aae5a6357514ea Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 25 Apr 2026 22:03:02 +0100 Subject: [PATCH 1/7] Fix default filter for online users table --- packages/web_ui/src/components/UsersTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web_ui/src/components/UsersTable.tsx b/packages/web_ui/src/components/UsersTable.tsx index 6f35f22f..15cecc01 100644 --- a/packages/web_ui/src/components/UsersTable.tsx +++ b/packages/web_ui/src/components/UsersTable.tsx @@ -199,7 +199,7 @@ export default function UsersTable({ instanceId, onlyOnline = false, pagination, title: "Last seen", key: "lastSeen", filterMultiple: false, - defaultFilteredValue: onlyOnline ? ["online"] : undefined, + defaultFilteredValue: onlyOnline ? "online" : undefined, filters: [ { text: "Online", value: "online" }, { text: "24h", value: "24h" }, From de51741835587878dc1cdcdb048189a68e033ba5 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 25 Apr 2026 22:06:36 +0100 Subject: [PATCH 2/7] Use `workspace:^` rather than `workspace:*` --- package.json | 10 +++++----- packages/controller/package.json | 4 ++-- packages/ctl/package.json | 2 +- packages/host/package.json | 2 +- packages/web_ui/package.json | 2 +- plugins/global_chat/package.json | 16 ++++++++-------- plugins/inventory_sync/package.json | 16 ++++++++-------- plugins/player_auth/package.json | 16 ++++++++-------- plugins/research_sync/package.json | 16 ++++++++-------- plugins/statistics_exporter/package.json | 12 ++++++------ plugins/subspace_storage/package.json | 16 ++++++++-------- 11 files changed, 56 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index f5b45dcc..051d0ab6 100644 --- a/package.json +++ b/package.json @@ -35,11 +35,11 @@ "external_plugins/*/*" ], "devDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/ctl": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", - "@clusterio/web_ui": "workspace:*", + "@clusterio/controller": "workspace:^", + "@clusterio/ctl": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.32.0", "@stylistic/eslint-plugin": "^5.2.2", diff --git a/packages/controller/package.json b/packages/controller/package.json index a2a2cde3..2bf103c7 100644 --- a/packages/controller/package.json +++ b/packages/controller/package.json @@ -20,7 +20,7 @@ "node": ">=20" }, "dependencies": { - "@clusterio/lib": "workspace:*", + "@clusterio/lib": "workspace:^", "@sinclair/typebox": "catalog:", "busboy": "^1.6.0", "compression": "^1.8.0", @@ -34,7 +34,7 @@ "yargs": "^17.7.2" }, "devDependencies": { - "@clusterio/web_ui": "workspace:*", + "@clusterio/web_ui": "workspace:^", "@swc/core": "catalog:", "@types/busboy": "^1.5.0", "@types/compression": "^1.7.2", diff --git a/packages/ctl/package.json b/packages/ctl/package.json index 3a116f6a..74ff843b 100644 --- a/packages/ctl/package.json +++ b/packages/ctl/package.json @@ -20,7 +20,7 @@ "node": ">=20" }, "dependencies": { - "@clusterio/lib": "workspace:*", + "@clusterio/lib": "workspace:^", "as-table": "^1.0.55", "winston": "catalog:", "yargs": "^17.7.2" diff --git a/packages/host/package.json b/packages/host/package.json index d13341bc..edce1aaf 100644 --- a/packages/host/package.json +++ b/packages/host/package.json @@ -21,7 +21,7 @@ "node": ">=20" }, "dependencies": { - "@clusterio/lib": "workspace:*", + "@clusterio/lib": "workspace:^", "@sinclair/typebox": "catalog:", "jimp": "^1.6.0", "jszip": "catalog:", diff --git a/packages/web_ui/package.json b/packages/web_ui/package.json index 07e5943e..514da6d6 100644 --- a/packages/web_ui/package.json +++ b/packages/web_ui/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@ant-design/icons": "^5.6.1", - "@clusterio/lib": "workspace:*", + "@clusterio/lib": "workspace:^", "@sinclair/typebox": "^0.30.4", "@swc/core": "^1.13.3", "antd": "^5.24.2", diff --git a/plugins/global_chat/package.json b/plugins/global_chat/package.json index fcc5dd61..8eb6babe 100644 --- a/plugins/global_chat/package.json +++ b/plugins/global_chat/package.json @@ -23,19 +23,19 @@ "node": ">=20" }, "peerDependencies": { - "@clusterio/web_ui": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/ctl": "workspace:*", - "@clusterio/lib": "workspace:*" + "@clusterio/web_ui": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/ctl": "workspace:^", + "@clusterio/lib": "workspace:^" }, "dependencies": { "@sinclair/typebox": "catalog:" }, "devDependencies": { - "@clusterio/web_ui": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/ctl": "workspace:*", - "@clusterio/lib": "workspace:*", + "@clusterio/web_ui": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/ctl": "workspace:^", + "@clusterio/lib": "workspace:^", "@types/node": "catalog:", "@types/react": "catalog:", "typescript": "catalog:", diff --git a/plugins/inventory_sync/package.json b/plugins/inventory_sync/package.json index 6784d56c..143e8301 100644 --- a/plugins/inventory_sync/package.json +++ b/plugins/inventory_sync/package.json @@ -23,19 +23,19 @@ "node": ">=20" }, "peerDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", - "@clusterio/web_ui": "workspace:*" + "@clusterio/controller": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^" }, "dependencies": { "@sinclair/typebox": "catalog:" }, "devDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", - "@clusterio/web_ui": "workspace:*", + "@clusterio/controller": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^", "@types/node": "catalog:", "@types/react": "catalog:", "antd": "catalog:", diff --git a/plugins/player_auth/package.json b/plugins/player_auth/package.json index 425b10c3..d9c387ae 100644 --- a/plugins/player_auth/package.json +++ b/plugins/player_auth/package.json @@ -23,10 +23,10 @@ "node": ">=20" }, "peerDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/web_ui": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*" + "@clusterio/controller": "workspace:^", + "@clusterio/web_ui": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^" }, "dependencies": { "@sinclair/typebox": "catalog:", @@ -34,10 +34,10 @@ "express": "catalog:" }, "devDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/web_ui": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", + "@clusterio/controller": "workspace:^", + "@clusterio/web_ui": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", "@types/express": "catalog:", "@types/jsonwebtoken": "catalog:", "@types/node": "catalog:", diff --git a/plugins/research_sync/package.json b/plugins/research_sync/package.json index 0be0222e..ee361afe 100644 --- a/plugins/research_sync/package.json +++ b/plugins/research_sync/package.json @@ -23,19 +23,19 @@ "node": ">=20" }, "peerDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", - "@clusterio/web_ui": "workspace:*" + "@clusterio/controller": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^" }, "dependencies": { "@sinclair/typebox": "catalog:" }, "devDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", - "@clusterio/web_ui": "workspace:*", + "@clusterio/controller": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^", "@types/node": "catalog:", "@types/react": "catalog:", "typescript": "catalog:", diff --git a/plugins/statistics_exporter/package.json b/plugins/statistics_exporter/package.json index 5c6679e9..20020025 100644 --- a/plugins/statistics_exporter/package.json +++ b/plugins/statistics_exporter/package.json @@ -23,14 +23,14 @@ "node": ">=20" }, "peerDependencies": { - "@clusterio/web_ui": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*" + "@clusterio/web_ui": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^" }, "devDependencies": { - "@clusterio/web_ui": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", + "@clusterio/web_ui": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", "@types/node": "catalog:", "@types/react": "catalog:", "typescript": "catalog:", diff --git a/plugins/subspace_storage/package.json b/plugins/subspace_storage/package.json index 5422ae96..148775c8 100644 --- a/plugins/subspace_storage/package.json +++ b/plugins/subspace_storage/package.json @@ -23,19 +23,19 @@ "node": ">=20" }, "peerDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", - "@clusterio/web_ui": "workspace:*" + "@clusterio/controller": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^" }, "dependencies": { "@sinclair/typebox": "catalog:" }, "devDependencies": { - "@clusterio/controller": "workspace:*", - "@clusterio/host": "workspace:*", - "@clusterio/lib": "workspace:*", - "@clusterio/web_ui": "workspace:*", + "@clusterio/controller": "workspace:^", + "@clusterio/host": "workspace:^", + "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^", "@types/express": "catalog:", "@types/node": "catalog:", "@types/react": "catalog:", From 746b11ff656b11613f6b784f38c27c8f98423ee5 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 25 Apr 2026 22:18:32 +0100 Subject: [PATCH 3/7] Add scrollable div to player auth server list --- plugins/player_auth/web/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/player_auth/web/index.tsx b/plugins/player_auth/web/index.tsx index 9dac7de1..12118708 100644 --- a/plugins/player_auth/web/index.tsx +++ b/plugins/player_auth/web/index.tsx @@ -89,9 +89,11 @@ function LoginForm(props: LoginFormProps) { Start Factorio, join one of the following multiplayer servers and type /web-login into the chat: - +
+ +
  • Enter the code displayed in the in-game dialog here: From a22186ca01934d8cfaa30c4835cbe51c0bafe042 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 25 Apr 2026 22:19:49 +0100 Subject: [PATCH 4/7] Add a newline after each section title in change log --- scripts/pr_to_changelog.mts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pr_to_changelog.mts b/scripts/pr_to_changelog.mts index 8886f44e..87562a62 100644 --- a/scripts/pr_to_changelog.mts +++ b/scripts/pr_to_changelog.mts @@ -191,7 +191,7 @@ function printMarkdown(changelog: Changelog, issues: Issue[], refText: (issue: I const sections = new Set([...changelogSections, ...Object.keys(changelog)]); for (const section of sections) { if (section in changelog) { - console.log(`### ${section}`); + console.log(`### ${section}\n`); const entries = changelog[section]; console.log(entries.map(text => ( `- ${text.replaceAll(/#(\d+)/g, (ref, idAsText) => { From 2c30fa4a943cba2abc171045cc9941883ad6dd2d Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 25 Apr 2026 22:38:23 +0100 Subject: [PATCH 5/7] Add user section to changelog script --- scripts/github_api.mts | 5 +++++ scripts/pr_to_changelog.mts | 27 ++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/scripts/github_api.mts b/scripts/github_api.mts index 3b4f16ea..1f03a51c 100644 --- a/scripts/github_api.mts +++ b/scripts/github_api.mts @@ -95,6 +95,11 @@ export interface Issue { html_url: string, state: string, body?: string | null, + user: { + login: string, + url: string, + html_url: string, + } pull_request?: { url: string, html_url: string, diff --git a/scripts/pr_to_changelog.mts b/scripts/pr_to_changelog.mts index 87562a62..a5bbb7bf 100644 --- a/scripts/pr_to_changelog.mts +++ b/scripts/pr_to_changelog.mts @@ -187,7 +187,13 @@ async function fetchIssuesUpdatedSince(since: string) { ); } -function printMarkdown(changelog: Changelog, issues: Issue[], refText: (issue: Issue) => string) { +function printMarkdown( + changelog: Changelog, + issues: Issue[], + users: Issue["user"][], + refText: (issue: Issue) => string, + userText: (user: Issue["user"]) => string, +) { const sections = new Set([...changelogSections, ...Object.keys(changelog)]); for (const section of sections) { if (section in changelog) { @@ -209,6 +215,9 @@ function printMarkdown(changelog: Changelog, issues: Issue[], refText: (issue: I console.log(); } } + + console.log(`Many thanks to the following for contributing to this release:`); + console.log(users.map(userText).join("\n")) } async function main() { @@ -222,13 +231,21 @@ async function main() { )); const changelog = changelogFromPullRequests(pullRequests, issues); + const users = [...new Map(pullRequests.map(issue => [issue.user.login, issue.user])).values()] console.log(); - console.log("=== Github markdown ==="); - printMarkdown(changelog, issues, issue => `${repository}#${issue.number}`); + console.log("=== Github Release Markdown ==="); + printMarkdown(changelog, issues, users, + issue => `${repository}#${issue.number}`, + user => `@${user.login}`, + ); + console.log(); - console.log("=== Discord markdown ==="); - printMarkdown(changelog, issues, issue => `[#${issue.number}](<${issue.html_url}>)`); + console.log("=== Discord / Changelog Markdown ==="); + printMarkdown(changelog, issues, users, + issue => `[#${issue.number}](<${issue.html_url}>)`, + user => `[@${user.login}](<${user.html_url}>)` + ); } if (import.meta.main) { From 1bb51988ac48aae57f1b932c56db3e2c7871a039 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 25 Apr 2026 23:32:30 +0100 Subject: [PATCH 6/7] Fix popconfirm on instance kill button --- .../src/components/InstanceControlButton.tsx | 61 +++++++++++-------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/packages/web_ui/src/components/InstanceControlButton.tsx b/packages/web_ui/src/components/InstanceControlButton.tsx index 2f1636e3..1090f2b3 100644 --- a/packages/web_ui/src/components/InstanceControlButton.tsx +++ b/packages/web_ui/src/components/InstanceControlButton.tsx @@ -21,6 +21,7 @@ export default function InstanceControlButton(props: InstanceControlButtonProps) const account = useAccount(); const control = useContext(ControlContext); const [switching, setSwitching] = useState(false); + const [popconfirm, setPopconfirm] = useState(null); const instanceId = props.instance.id; const instanceStatus = props.instance.status; @@ -88,35 +89,43 @@ export default function InstanceControlButton(props: InstanceControlButtonProps) if (account.hasPermission("core.instance.kill")) { actions.push({ key: "kill", + label: "Kill", danger: true, disabled: instanceStatus === "stopped", - label: ( - Killing this instance may leave you save and player data corrupted. - Are you sure you want to kill the instance? - } - placement="bottomRight" - okText="Kill" - okButtonProps={{ danger: true }} - onConfirm={() => { - control.sendTo( - { instanceId }, - new lib.InstanceKillRequest(), - ).catch( - notifyErrorHandler("Error killing instance") - ).finally(actionFinish); - }} - > - Kill - ), + onClick: () => setPopconfirm("kill"), }); } - return ; + return
    + + + Killing this instance may leave you save and player data corrupted. + Are you sure you want to kill the instance? + } + open={popconfirm === "kill"} + placement="bottomRight" + okText="Kill" + okButtonProps={{ danger: true }} + onCancel={() => setPopconfirm(null)} + onConfirm={() => { + control.sendTo( + { instanceId }, + new lib.InstanceKillRequest(), + ).catch( + notifyErrorHandler("Error killing instance") + ).finally(actionFinish); + setPopconfirm(null); + }} + > + {/* Used to position the popup under the button */} + + +
    ; } From 40e6961711db210bee8d6d7722c1b114331fd46b Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Thu, 14 May 2026 12:51:04 +0100 Subject: [PATCH 7/7] Fix conflict between defaultFilteredValue and responsive --- packages/web_ui/src/components/UsersTable.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/web_ui/src/components/UsersTable.tsx b/packages/web_ui/src/components/UsersTable.tsx index 15cecc01..ec39a5d3 100644 --- a/packages/web_ui/src/components/UsersTable.tsx +++ b/packages/web_ui/src/components/UsersTable.tsx @@ -199,7 +199,7 @@ export default function UsersTable({ instanceId, onlyOnline = false, pagination, title: "Last seen", key: "lastSeen", filterMultiple: false, - defaultFilteredValue: onlyOnline ? "online" : undefined, + defaultFilteredValue: onlyOnline ? ["online"] : undefined, filters: [ { text: "Online", value: "online" }, { text: "24h", value: "24h" }, @@ -231,7 +231,8 @@ export default function UsersTable({ instanceId, onlyOnline = false, pagination, }, sorter: (a: lib.UserDetails, b: lib.UserDetails) => sortLastSeen(a, b, instanceId, instanceId), render: (_: any, user: lib.UserDetails) => formatLastSeen(user, instanceId), - responsive: ["lg"], + // Responsive breaks defaultFilteredValue, see: https://github.com/ant-design/ant-design/issues/32847 + // responsive: ["lg"], }, );