diff --git a/packages/web_ui/src/components/ModsPage.tsx b/packages/web_ui/src/components/ModsPage.tsx
index e380bcb5..7b2e85ed 100644
--- a/packages/web_ui/src/components/ModsPage.tsx
+++ b/packages/web_ui/src/components/ModsPage.tsx
@@ -56,11 +56,13 @@ function ImportModPackButton() {
name="string"
rules={[
{ required: true },
- { async validator(rule, value) {
- if (value) {
- lib.ModPack.fromModPackString(value);
- }
- }},
+ {
+ async validator(rule, value) {
+ if (value) {
+ lib.ModPack.fromModPackString(value);
+ }
+ },
+ },
]}
>
@@ -236,54 +238,118 @@ export default function ModsPage() {
})}
/>
-
(
- strcmp(a.name, b.name) || a.integerVersion - b.integerVersion
- ),
- },
- {
- title: "Version",
- key: "version",
- align: "right",
- render: (_, mod) => <>
- {`${mod.version} `}
- {`/ ${mod.factorioVersion}`}
- >,
- },
- {
- title: "Filename",
- dataIndex: "filename",
- responsive: ["xl"],
- sorter: (a, b) => strcmp(a.filename, b.filename),
- },
- {
- title: "Size",
- key: "size",
- responsive: ["lg"],
- render: (_, mod) => lib.formatBytes(mod.size),
- align: "right",
- sorter: (a, b) => a.size - b.size,
- },
- {
- title: "Action",
- key: "action",
- responsive: ["lg"],
- render: (_, mod) => actions(mod),
- },
- ]}
- expandable={{
- expandedRowRender: (mod: lib.ModInfo) => ,
- expandedRowClassName: () => "no-expanded-padding",
+
+ mod.id}
- />
+ action={`${webRoot}api/upload-mod`}
+ showUploadList={false}
+ >
+ {
+ setIsDroppingFile(true);
+ }}
+ onDragLeave={e => {
+ if ((e.currentTarget as Node).contains(e.relatedTarget as Node)) {
+ return;
+ }
+ setIsDroppingFile(false);
+ }}
+ onDrop={e => setIsDroppingFile(false)}
+ >
+
+
(
+ strcmp(a.name, b.name) || a.integerVersion - b.integerVersion
+ ),
+ },
+ {
+ title: "Version",
+ key: "version",
+ align: "right",
+ render: (_, mod) => <>
+ {`${mod.version} `}
+ {`/ ${mod.factorioVersion}`}
+ >,
+ },
+ {
+ title: "Filename",
+ dataIndex: "filename",
+ responsive: ["xl"],
+ sorter: (a, b) => strcmp(a.filename, b.filename),
+ },
+ {
+ title: "Size",
+ key: "size",
+ responsive: ["lg"],
+ render: (_, mod) => lib.formatBytes(mod.size),
+ align: "right",
+ sorter: (a, b) => a.size - b.size,
+ },
+ {
+ title: "Action",
+ key: "action",
+ responsive: ["lg"],
+ render: (_, mod) => actions(mod),
+ },
+ ]}
+ expandable={{
+ expandedRowRender: (mod: lib.ModInfo) => ,
+ expandedRowClassName: () => "no-expanded-padding",
+ }}
+ dataSource={[...mods.values()]}
+ pagination={false}
+ rowKey={mod => mod.id}
+ />
+
+
;
}
diff --git a/packages/web_ui/src/components/SavesList.tsx b/packages/web_ui/src/components/SavesList.tsx
index 92ce287c..66f4f78d 100644
--- a/packages/web_ui/src/components/SavesList.tsx
+++ b/packages/web_ui/src/components/SavesList.tsx
@@ -15,6 +15,7 @@ import SectionHeader from "./SectionHeader";
import { useInstances } from "../model/instance";
import { useSavesOfInstance } from "../model/saves";
import { notifyErrorHandler } from "../util/notify";
+import { InboxOutlined } from "@ant-design/icons";
type ModalProps = {
@@ -150,7 +151,7 @@ function TransferModal(props: ModalProps) {
autoFocus
showSearch
filterOption={(input, option) => (
- (option?.title.toLowerCase().indexOf(input.toLowerCase())??-1) >= 0
+ (option?.title.toLowerCase().indexOf(input.toLowerCase()) ?? -1) >= 0
)}
>
{[...instances.values()].filter(
@@ -204,6 +205,7 @@ export default function SavesList(props: { instance: lib.InstanceDetails }) {
let [saves] = useSavesOfInstance(props.instance.id);
let [starting, setStarting] = useState(false);
let [uploadingFiles, setUploadingFiles] = useState([]);
+ const [isDroppingFile, setIsDroppingFile] = useState(false);
let hostOffline = ["unassigned", "unknown"].includes(props.instance.status!);
const saveTable = <>
{save.name}
- {save.loaded && }
- {save.loadByDefault && }
+ {save.loaded && }
+ {save.loadByDefault && }
>,
sorter: (a, b) => a.name.localeCompare(b.name),
},
@@ -240,7 +242,7 @@ export default function SavesList(props: { instance: lib.InstanceDetails }) {
expandable={{
columnWidth: 33,
expandRowByClick: true,
- expandedRowRender: save =>
+ expandedRowRender: save =>
{account.hasPermission("core.instance.start") &&