Added button to adjust filament

Resolves #428
Resolves #30
This commit is contained in:
Donkie
2024-08-06 11:34:47 +02:00
parent 00e35584f4
commit 701ed2fae6
3 changed files with 123 additions and 21 deletions

View File

@@ -177,9 +177,17 @@
"list": "Spools", "list": "Spools",
"show": "Show Spool", "show": "Show Spool",
"show_title": "[Spool #{{id}}] {{name}}", "show_title": "[Spool #{{id}}] {{name}}",
"archive": "Archive Spool" "archive": "Archive Spool",
"adjust": "Adjust Spool Filament"
}, },
"form": { "form": {
"measurement_type": {
"length": "Length",
"weight": "Weight"
},
"measurement_type_label": "Measurement Type",
"adjust_filament_help": "Here you can directly add or subtract filament from the spool. A positive value will consume filament, a negative value will add it.",
"adjust_filament_value": "Consume Amount",
"new_location_prompt": "Enter a new location", "new_location_prompt": "Enter a new location",
"spool_updated": "This spool has been updated by someone/something else since you opened this page. Saving will overwrite those changes!" "spool_updated": "This spool has been updated by someone/something else since you opened this page. Saving will overwrite those changes!"
}, },

View File

@@ -4,8 +4,10 @@ import { getAPIURL } from "../../utils/url";
import { ISpool } from "./model"; import { ISpool } from "./model";
import { IFilament } from "../filaments/model"; import { IFilament } from "../filaments/model";
import { SpoolType, useGetExternalDBFilaments } from "../../utils/queryExternalDB"; import { SpoolType, useGetExternalDBFilaments } from "../../utils/queryExternalDB";
import { useMemo } from "react"; import { useCallback, useMemo, useState } from "react";
import { useQueries } from "@tanstack/react-query"; import { useQueries } from "@tanstack/react-query";
import { Button, Form, InputNumber, Modal, Radio } from "antd";
import { useForm } from "antd/es/form/Form";
export async function setSpoolArchived(spool: ISpool, archived: boolean) { export async function setSpoolArchived(spool: ISpool, archived: boolean) {
const init: RequestInit = { const init: RequestInit = {
@@ -21,6 +23,27 @@ export async function setSpoolArchived(spool: ISpool, archived: boolean) {
await fetch(request, init); await fetch(request, init);
} }
/**
* Use some spool filament from this spool. Either specify length or weight.
* @param spool The spool
* @param length The length to add/subtract from the spool, in mm
* @param weight The weight to add/subtract from the spool, in g
*/
export async function useSpoolFilament(spool: ISpool, length?: number, weight?: number) {
const init: RequestInit = {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
use_length: length,
use_weight: weight,
}),
};
const request = new Request(`${getAPIURL()}/spool/${spool.id}/use`);
await fetch(request, init);
}
/** /**
* Returns an array of queries using the useQueries hook from @tanstack/react-query. * Returns an array of queries using the useQueries hook from @tanstack/react-query.
* Each query fetches a spool by its ID from the server. * Each query fetches a spool by its ID from the server.
@@ -149,3 +172,67 @@ export function useGetFilamentSelectOptions() {
allExternalFilaments: externalFilaments.data, allExternalFilaments: externalFilaments.data,
}; };
} }
type MeasurementType = "length" | "weight";
export function useSpoolAdjustModal() {
const t = useTranslate();
const [form] = useForm();
const [curSpool, setCurSpool] = useState<ISpool | null>(null);
const [measurementType, setMeasurementType] = useState<MeasurementType>("length");
const openSpoolAdjustModal = useCallback((spool: ISpool) => {
setCurSpool(spool);
}, []);
const spoolAdjustModal = useMemo(() => {
if (curSpool === null) {
return null;
}
const onSubmit = async () => {
if (curSpool === null) {
return;
}
const value = form.getFieldValue("filament_value");
if (value === undefined || value === null) {
return;
}
if (measurementType === "length") {
await useSpoolFilament(curSpool, value, undefined);
} else {
await useSpoolFilament(curSpool, undefined, value);
}
setCurSpool(null);
};
return (
<Modal title={t("spool.titles.adjust")} open onCancel={() => setCurSpool(null)} onOk={form.submit}>
<p>{t("spool.form.adjust_filament_help")}</p>
<Form form={form} initialValues={{ measurement_type: measurementType }} onFinish={onSubmit}>
<Form.Item label={t("spool.form.measurement_type_label")} name="measurement_type">
<Radio.Group
value={measurementType}
onChange={({ target: { value } }) => setMeasurementType(value as MeasurementType)}
>
<Radio.Button value="length">{t("spool.form.measurement_type.length")}</Radio.Button>
<Radio.Button value="weight">{t("spool.form.measurement_type.weight")}</Radio.Button>
</Radio.Group>
</Form.Item>
<Form.Item label={t("spool.form.adjust_filament_value")} name="filament_value">
<InputNumber precision={1} addonAfter={measurementType === "length" ? "mm" : "g"} />
</Form.Item>
</Form>
</Modal>
);
}, [curSpool, measurementType, t]);
return {
openSpoolAdjustModal,
spoolAdjustModal,
};
}

View File

@@ -1,4 +1,4 @@
import React from "react"; import React, { useCallback, useMemo } from "react";
import { IResourceComponentsProps, useInvalidate, useNavigation, useTranslate } from "@refinedev/core"; import { IResourceComponentsProps, useInvalidate, useNavigation, useTranslate } from "@refinedev/core";
import { useTable, List } from "@refinedev/antd"; import { useTable, List } from "@refinedev/antd";
import { Table, Button, Dropdown, Modal } from "antd"; import { Table, Button, Dropdown, Modal } from "antd";
@@ -13,6 +13,7 @@ import {
InboxOutlined, InboxOutlined,
PlusSquareOutlined, PlusSquareOutlined,
PrinterOutlined, PrinterOutlined,
ToolOutlined,
ToTopOutlined, ToTopOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { import {
@@ -26,7 +27,7 @@ import {
ActionsColumn, ActionsColumn,
CustomFieldColumn, CustomFieldColumn,
} from "../../components/column"; } from "../../components/column";
import { setSpoolArchived } from "./functions"; import { setSpoolArchived, useSpoolAdjustModal } from "./functions";
import { import {
useSpoolmanFilamentFilter, useSpoolmanFilamentFilter,
useSpoolmanLocations, useSpoolmanLocations,
@@ -102,6 +103,7 @@ export const SpoolList: React.FC<IResourceComponentsProps> = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const extraFields = useGetFields(EntityType.spool); const extraFields = useGetFields(EntityType.spool);
const currency = useCurrency(); const currency = useCurrency();
const { openSpoolAdjustModal, spoolAdjustModal } = useSpoolAdjustModal();
const allColumnsWithExtraFields = [...allColumns, ...(extraFields.data?.map((field) => "extra." + field.key) ?? [])]; const allColumnsWithExtraFields = [...allColumns, ...(extraFields.data?.map((field) => "extra." + field.key) ?? [])];
@@ -208,23 +210,27 @@ export const SpoolList: React.FC<IResourceComponentsProps> = () => {
} }
const { editUrl, showUrl, cloneUrl } = useNavigation(); const { editUrl, showUrl, cloneUrl } = useNavigation();
const actions = (record: ISpoolCollapsed) => { const actions = useCallback(
const actions: Action[] = [ (record: ISpoolCollapsed) => {
{ name: t("buttons.show"), icon: <EyeOutlined />, link: showUrl("spool", record.id) }, const actions: Action[] = [
{ name: t("buttons.edit"), icon: <EditOutlined />, link: editUrl("spool", record.id) }, { name: t("buttons.show"), icon: <EyeOutlined />, link: showUrl("spool", record.id) },
{ name: t("buttons.clone"), icon: <PlusSquareOutlined />, link: cloneUrl("spool", record.id) }, { name: t("buttons.edit"), icon: <EditOutlined />, link: editUrl("spool", record.id) },
]; { name: t("buttons.clone"), icon: <PlusSquareOutlined />, link: cloneUrl("spool", record.id) },
if (record.archived) { { name: t("spool.titles.adjust"), icon: <ToolOutlined />, onClick: () => openSpoolAdjustModal(record) },
actions.push({ ];
name: t("buttons.unArchive"), if (record.archived) {
icon: <ToTopOutlined />, actions.push({
onClick: () => archiveSpool(record, false), name: t("buttons.unArchive"),
}); icon: <ToTopOutlined />,
} else { onClick: () => archiveSpool(record, false),
actions.push({ name: t("buttons.archive"), icon: <InboxOutlined />, onClick: () => archiveSpoolPopup(record) }); });
} } else {
return actions; actions.push({ name: t("buttons.archive"), icon: <InboxOutlined />, onClick: () => archiveSpoolPopup(record) });
}; }
return actions;
},
[t, editUrl, showUrl, cloneUrl, openSpoolAdjustModal, archiveSpool, archiveSpoolPopup]
);
const originalOnChange = tableProps.onChange; const originalOnChange = tableProps.onChange;
tableProps.onChange = (pagination, filters, sorter, extra) => { tableProps.onChange = (pagination, filters, sorter, extra) => {
@@ -319,6 +325,7 @@ export const SpoolList: React.FC<IResourceComponentsProps> = () => {
</> </>
)} )}
> >
{spoolAdjustModal}
<Table <Table
{...tableProps} {...tableProps}
sticky sticky