Some checks failed
CI / style (push) Has been cancelled
CI / build-client (push) Has been cancelled
CI / build-amd64 (push) Has been cancelled
CI / build-tester (push) Has been cancelled
CI / test (cockroachdb) (push) Has been cancelled
CI / test (mariadb) (push) Has been cancelled
CI / test (postgres) (push) Has been cancelled
CI / test (sqlite) (push) Has been cancelled
CI / build-arm64 (push) Has been cancelled
CI / build-armv7 (push) Has been cancelled
CI / publish-images (push) Has been cancelled
CI / publish-release (push) Has been cancelled
- Backend: Added ExternalSource enum, Filament3DFP model, and transform function - Backend: Updated _sync() to fetch from both SpoolmanDB and 3dfilamentprofiles - Frontend: Added source tabs to FilamentImportModal (All/SpoolmanDB/3DFP) - Frontend: Updated ExternalFilament interface with source and temp range fields - Frontend: Updated filament import handler to use temp range fields Also includes: - Dev mode styling (teal theme, DEV badge and banner) - Translation keys for source filtering Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
125 lines
3.9 KiB
TypeScript
125 lines
3.9 KiB
TypeScript
import { useTranslate } from "@refinedev/core";
|
|
import { Form, Modal, Select, Tabs } from "antd";
|
|
import { useMemo, useState } from "react";
|
|
import { Trans } from "react-i18next";
|
|
import { formatFilamentLabel } from "../pages/spools/functions";
|
|
import { searchMatches } from "../utils/filtering";
|
|
import { ExternalFilament, ExternalSource, useGetExternalDBFilaments } from "../utils/queryExternalDB";
|
|
|
|
export function FilamentImportModal(props: {
|
|
isOpen: boolean;
|
|
onImport: (filament: ExternalFilament) => void;
|
|
onClose: () => void;
|
|
}) {
|
|
const [form] = Form.useForm();
|
|
const t = useTranslate();
|
|
const [selectedSource, setSelectedSource] = useState<ExternalSource | "all">("all");
|
|
|
|
const externalFilaments = useGetExternalDBFilaments();
|
|
|
|
// Filter and format filaments based on selected source
|
|
const filamentOptions = useMemo(() => {
|
|
const filtered = externalFilaments.data?.filter((item) => {
|
|
if (selectedSource === "all") return true;
|
|
return item.source === selectedSource;
|
|
}) ?? [];
|
|
|
|
const options = filtered.map((item) => {
|
|
// Add source indicator to label if showing all
|
|
const sourceIndicator = selectedSource === "all" && item.source === ExternalSource.FILAMENT_PROFILES_3D
|
|
? "[3DFP] "
|
|
: "";
|
|
|
|
return {
|
|
label: sourceIndicator + formatFilamentLabel(
|
|
item.name,
|
|
item.diameter,
|
|
item.manufacturer,
|
|
item.material,
|
|
item.weight,
|
|
item.spool_type
|
|
),
|
|
value: item.id,
|
|
item: item,
|
|
};
|
|
});
|
|
|
|
options.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: "base" }));
|
|
return options;
|
|
}, [externalFilaments.data, selectedSource]);
|
|
|
|
// Count filaments by source
|
|
const counts = useMemo(() => {
|
|
const spoolmandb = externalFilaments.data?.filter(f => f.source === ExternalSource.SPOOLMANDB || !f.source).length ?? 0;
|
|
const threeDFP = externalFilaments.data?.filter(f => f.source === ExternalSource.FILAMENT_PROFILES_3D).length ?? 0;
|
|
return { spoolmandb, threeDFP, total: spoolmandb + threeDFP };
|
|
}, [externalFilaments.data]);
|
|
|
|
const handleSourceChange = (key: string) => {
|
|
setSelectedSource(key as ExternalSource | "all");
|
|
form.resetFields(["filament"]);
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
title={t("filament.form.import_external")}
|
|
open={props.isOpen}
|
|
onOk={() => form.submit()}
|
|
onCancel={() => props.onClose()}
|
|
width={600}
|
|
>
|
|
<p>
|
|
<Trans
|
|
i18nKey={"filament.form.import_external_description"}
|
|
components={{
|
|
br: <br />,
|
|
}}
|
|
/>
|
|
</p>
|
|
|
|
<Tabs
|
|
activeKey={selectedSource}
|
|
onChange={handleSourceChange}
|
|
items={[
|
|
{
|
|
key: "all",
|
|
label: `${t("filament.form.all_sources")} (${counts.total})`,
|
|
},
|
|
{
|
|
key: ExternalSource.SPOOLMANDB,
|
|
label: `SpoolmanDB (${counts.spoolmandb})`,
|
|
},
|
|
{
|
|
key: ExternalSource.FILAMENT_PROFILES_3D,
|
|
label: `3D Filament Profiles (${counts.threeDFP})`,
|
|
},
|
|
]}
|
|
/>
|
|
|
|
<Form
|
|
layout="vertical"
|
|
form={form}
|
|
onFinish={(values) => {
|
|
const filament = filamentOptions.find((item) => item.value === values.filament)?.item;
|
|
if (!filament) {
|
|
throw new Error("Filament not found");
|
|
}
|
|
props.onImport(filament);
|
|
props.onClose();
|
|
form.resetFields();
|
|
setSelectedSource("all");
|
|
}}
|
|
>
|
|
<Form.Item name="filament" rules={[{ required: true }]}>
|
|
<Select
|
|
options={filamentOptions}
|
|
showSearch
|
|
filterOption={(input, option) => typeof option?.label === "string" && searchMatches(input, option?.label)}
|
|
placeholder={t("filament.form.select_filament")}
|
|
/>
|
|
</Form.Item>
|
|
</Form>
|
|
</Modal>
|
|
);
|
|
}
|