diff --git a/client/public/locales/en/common.json b/client/public/locales/en/common.json
index e30c352..d0ff6d4 100644
--- a/client/public/locales/en/common.json
+++ b/client/public/locales/en/common.json
@@ -224,7 +224,9 @@
"show_title": "[Filament #{{id}}] {{name}}"
},
"form": {
- "filament_updated": "This filament has been updated by someone/something else since you opened this page. Saving will overwrite those changes!"
+ "filament_updated": "This filament has been updated by someone/something else since you opened this page. Saving will overwrite those changes!",
+ "import_external": "Import from External",
+ "import_external_description": "Select a filament in the list to automatically populate its details in the filament creation form. This will overwrite any data you have entered in the form.
A Manufacturer object will be created automatically when you click Ok, if necessary."
},
"buttons": {
"add_spool": "Add Spool"
diff --git a/client/src/components/filamentImportModal.tsx b/client/src/components/filamentImportModal.tsx
new file mode 100644
index 0000000..97ac725
--- /dev/null
+++ b/client/src/components/filamentImportModal.tsx
@@ -0,0 +1,66 @@
+import { Form, InputNumber, Modal, Select } from "antd";
+import { useState } from "react";
+import { ExternalFilament, useGetExternalDBFilaments } from "../utils/queryExternalDB";
+import { formatFilamentLabel } from "../pages/spools/functions";
+import { searchMatches } from "../utils/filtering";
+import { useTranslate } from "@refinedev/core";
+import { Trans } from "react-i18next";
+
+export function FilamentImportModal(props: {
+ isOpen: boolean;
+ onImport: (filament: ExternalFilament) => void;
+ onClose: () => void;
+}) {
+ const [form] = Form.useForm();
+ const t = useTranslate();
+
+ const externalFilaments = useGetExternalDBFilaments();
+ const filamentOptions =
+ externalFilaments.data?.map((item) => {
+ return {
+ label: formatFilamentLabel(item.name, item.diameter, item.manufacturer, item.material, item.weight),
+ value: item.id,
+ item: item,
+ };
+ }) ?? [];
+ filamentOptions.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: "base" }));
+
+ return (
+ form.submit()}
+ onCancel={() => props.onClose()}
+ >
+
+
+
+
+ );
+}
diff --git a/client/src/pages/filaments/create.tsx b/client/src/pages/filaments/create.tsx
index 6de8a79..3880527 100644
--- a/client/src/pages/filaments/create.tsx
+++ b/client/src/pages/filaments/create.tsx
@@ -1,7 +1,7 @@
import React from "react";
-import { HttpError, IResourceComponentsProps, useTranslate } from "@refinedev/core";
+import { HttpError, IResourceComponentsProps, useInvalidate, useTranslate } from "@refinedev/core";
import { Create, useForm, useSelect } from "@refinedev/antd";
-import { Form, Input, Select, InputNumber, ColorPicker, Button, Typography } from "antd";
+import { Form, Input, Select, InputNumber, ColorPicker, Button, Typography, Modal } from "antd";
import TextArea from "antd/es/input/TextArea";
import { numberFormatter, numberParser } from "../../utils/parsing";
import { IVendor } from "../vendors/model";
@@ -11,6 +11,11 @@ import { ExtraFieldFormItem, StringifiedExtras } from "../../components/extraFie
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
+import { searchMatches } from "../../utils/filtering";
+import { ExternalFilament, useGetExternalDBFilaments } from "../../utils/queryExternalDB";
+import { formatFilamentLabel } from "../spools/functions";
+import { FilamentImportModal } from "../../components/filamentImportModal";
+import { getOrCreateVendorFromExternal } from "../vendors/functions";
dayjs.extend(utc);
@@ -22,6 +27,8 @@ export const FilamentCreate: React.FC({
+ const { selectProps: vendorSelect } = useSelect({
resource: "vendor",
optionLabel: "name",
});
+ const importFilament = async (filament: ExternalFilament) => {
+ const vendor = await getOrCreateVendorFromExternal(filament.manufacturer);
+ await invalidate({
+ resource: "vendor",
+ invalidates: ["list", "detail"],
+ });
+
+ form.setFieldsValue({
+ name: filament.name,
+ vendor_id: vendor.id,
+ material: filament.material,
+ density: filament.density,
+ diameter: filament.diameter,
+ weight: filament.weight,
+ spool_weight: filament.spool_weight || undefined,
+ color_hex: filament.color_hex,
+ settings_extruder_temp: filament.extruder_temp || undefined,
+ settings_bed_temp: filament.bed_temp || undefined,
+ });
+ };
+
// Use useEffect to update the form's initialValues when the extra fields are loaded
// This is necessary because the form is rendered before the extra fields are loaded
React.useEffect(() => {
@@ -67,6 +95,13 @@ export const FilamentCreate: React.FC (
+ <>
+
+ >
+ )}
footerButtons={() => (
<>