Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#76 spool list, no reload on page change #172

Merged
merged 10 commits into from
Oct 29, 2023
4 changes: 3 additions & 1 deletion client/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"buttons": {
"create": "Create",
"save": "Save",
"saveAndAdd": "Save and Add",
"logout": "Log out",
"delete": "Delete",
"edit": "Edit",
Expand Down Expand Up @@ -190,7 +191,8 @@
"comment": "Comment",
"settings_extruder_temp": "Extruder Temp",
"settings_bed_temp": "Bed Temp",
"color_hex": "Color"
"color_hex": "Color",
"spools": "Show Spools"
},
"fields_help": {
"name": "Filament name, to distinguish this filament type among others from the same vendor. Should contain the color for example.",
Expand Down
17 changes: 14 additions & 3 deletions client/src/pages/filaments/create.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { IResourceComponentsProps, useTranslate } from "@refinedev/core";
import { Create, useForm, useSelect } from "@refinedev/antd";
import { Form, Input, Select, InputNumber, ColorPicker } from "antd";
import { Form, Input, Select, InputNumber, ColorPicker, Button } from "antd";
import TextArea from "antd/es/input/TextArea";
import { numberFormatter, numberParser } from "../../utils/parsing";
import { IVendor } from "../vendors/model";
Expand All @@ -14,7 +14,7 @@ interface CreateOrCloneProps {
export const FilamentCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps> = (props) => {
const t = useTranslate();

const { formProps, saveButtonProps, formLoading } = useForm<IFilament>();
const { form, formProps, saveButtonProps, formLoading, onFinish, redirect } = useForm<IFilament>();

if (props.mode === "clone" && formProps.initialValues) {
// Fix the vendor_id
Expand All @@ -23,6 +23,12 @@ export const FilamentCreate: React.FC<IResourceComponentsProps & CreateOrClonePr
}
}

const handleSubmit = async (redirectTo: "list" | "edit" | "create") => {
let values = await form.validateFields();
await onFinish(values);
redirect(redirectTo, (values as IFilament).id);
}

const { selectProps } = useSelect<IVendor>({
resource: "vendor",
optionLabel: "name",
Expand All @@ -32,7 +38,12 @@ export const FilamentCreate: React.FC<IResourceComponentsProps & CreateOrClonePr
<Create
title={props.mode === "create" ? t("filament.titles.create") : t("filament.titles.clone")}
isLoading={formLoading}
saveButtonProps={saveButtonProps}
footerButtons={() => (
<>
<Button type="primary" onClick={() => handleSubmit("list")}>{t("buttons.save")}</Button>
<Button type="primary" onClick={() => handleSubmit("create")}>{t("buttons.saveAndAdd")}</Button>
</>
)}
>
<Form {...formProps} layout="vertical">
<Form.Item
Expand Down
27 changes: 19 additions & 8 deletions client/src/pages/filaments/show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import utc from "dayjs/plugin/utc";
import { IFilament } from "./model";
import { enrichText } from "../../utils/parsing";
import { IVendor } from "../vendors/model";

import { useNavigate } from "react-router-dom";
dayjs.extend(utc);

const { Title } = Typography;

export const FilamentShow: React.FC<IResourceComponentsProps> = () => {
const t = useTranslate();

const navigate = useNavigate();
const { queryResult } = useShow<IFilament>({
liveMode: "auto",
});
Expand All @@ -31,17 +31,24 @@ export const FilamentShow: React.FC<IResourceComponentsProps> = () => {
return t("filament.titles.show_title", { id: item.id, name: vendorPrefix + item.name });
};

const formatVendor = (item: IVendor) => {
const URL = `/vendor/show/${item.id}`;
return <a href={URL}>{item.name}</a>;
};
const gotoVendor = (): undefined => {
const URL = `/vendor/show/${record?.vendor?.id}`;
navigate(URL);
}

const gotoSpools = (): undefined => {
const URL = `/spool#filters=[{"field":"filament.id","operator":"in","value":[${record?.id}]}]`
navigate(URL);
}

return (
<Show isLoading={isLoading} title={record ? formatTitle(record) : ""}>
<Title level={5}>{t("filament.fields.id")}</Title>
<NumberField value={record?.id ?? ""} />
<Title level={5}>{t("filament.fields.vendor")}</Title>
<TextField value={record?.vendor ? formatVendor(record?.vendor) : ""} />
<button onClick={gotoVendor} style={{ background: 'none', border: 'none', color: 'blue', cursor: 'pointer', paddingLeft: 0 }}>
{record ? record.vendor?.name : ""}
</button>
<Title level={5}>{t("filament.fields.registered")}</Title>
<DateField
value={dayjs.utc(record?.registered).local()}
Expand Down Expand Up @@ -110,7 +117,11 @@ export const FilamentShow: React.FC<IResourceComponentsProps> = () => {
<TextField value={record?.article_number} />
<Title level={5}>{t("filament.fields.comment")}</Title>
<TextField value={enrichText(record?.comment)} />
</Show>
<Title level={5}>{t("filament.fields.spools")}</Title>
<button onClick={gotoSpools} style={{ background: 'none', border: 'none', color: 'blue', cursor: 'pointer', paddingLeft: 0 }}>
{record ? formatTitle(record) : ""}
</button>
</Show >
);
};

Expand Down
58 changes: 53 additions & 5 deletions client/src/pages/spools/create.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { IResourceComponentsProps, useTranslate } from "@refinedev/core";
import { Create, useForm, useSelect } from "@refinedev/antd";
import { Form, Input, DatePicker, Select, InputNumber, Radio, Divider } from "antd";
import { Form, Input, DatePicker, Select, InputNumber, Radio, Divider, Button } from "antd";
import dayjs from "dayjs";
import TextArea from "antd/es/input/TextArea";
import { IFilament } from "../filaments/model";
import { ISpool } from "./model";
import { numberFormatter, numberParser } from "../../utils/parsing";
import { useSpoolmanLocations } from "../../components/otherModels";
import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
import '../../utils/overrides.css'

interface CreateOrCloneProps {
mode: "create" | "clone";
Expand All @@ -16,7 +18,10 @@ interface CreateOrCloneProps {
export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps> = (props) => {
const t = useTranslate();

const { form, formProps, saveButtonProps, formLoading } = useForm<ISpool>();
const { form, formProps, formLoading, onFinish, redirect } = useForm<ISpool>({
redirect: false,
warnWhenUnsavedChanges: false
});

if (props.mode === "clone" && formProps.initialValues) {
// Clear out the values that we don't want to clone
Expand All @@ -28,6 +33,18 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
formProps.initialValues.filament_id = formProps.initialValues.filament.id;
}

const handleSubmit = async (redirectTo: "list" | "edit" | "create") => {
let values = await form.validateFields();
if (quantity > 1) {
let submit = Array(quantity).fill(values);
// queue multiple creates this way for now Refine doesn't seem to map Arrays to createMany or multiple creates like it says it does
submit.forEach(async r => await onFinish(r));
} else {
await onFinish(values);
}
redirect(redirectTo, (values as ISpool).id);
}

const { queryResult } = useSelect<IFilament>({
resource: "filament",
});
Expand Down Expand Up @@ -100,11 +117,42 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
allLocations.push(newLocation.trim());
}

const [quantity, setQuantity] = useState(1);
const incrementQty = () => {
setQuantity(quantity + 1);
}

const decrementQty = () => {
setQuantity(quantity - 1);
}

return (
<Create
title={props.mode === "create" ? t("spool.titles.create") : t("spool.titles.clone")}
saveButtonProps={saveButtonProps}
isLoading={formLoading}
footerButtons={() => (
<>
<div style={{ display: 'flex', backgroundColor: '#141414', border: '1px solid #424242', borderRadius: '6px' }}>
<Button type="text" style={{ padding: 0, width: 32, height: 32 }} onClick={decrementQty}>
<MinusOutlined />
</Button>
<InputNumber
name="Quantity"
min={1}
id="qty-input"
controls={false}
value={quantity}
>
</InputNumber>
<Button type="text" style={{ padding: 0, width: 32, height: 32 }} onClick={incrementQty}>
<PlusOutlined />
</Button>
</div>
<Button type="primary" onClick={() => handleSubmit("list")}>{t("buttons.save")}</Button>
<Button type="primary" onClick={() => handleSubmit("create")}>{t("buttons.saveAndAdd")}</Button>
</>
)
}
>
<Form {...formProps} layout="vertical">
<Form.Item
Expand Down Expand Up @@ -278,7 +326,7 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
<TextArea maxLength={1024} />
</Form.Item>
</Form>
</Create>
</Create >
);
};

Expand Down
17 changes: 14 additions & 3 deletions client/src/pages/vendors/create.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { IResourceComponentsProps, useTranslate } from "@refinedev/core";
import { Create, useForm } from "@refinedev/antd";
import { Form, Input } from "antd";
import { Button, Form, Input } from "antd";
import TextArea from "antd/es/input/TextArea";
import { IVendor } from "./model";

Expand All @@ -12,13 +12,24 @@ interface CreateOrCloneProps {
export const VendorCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps> = (props) => {
const t = useTranslate();

const { formProps, saveButtonProps, formLoading } = useForm<IVendor>();
const { form, formProps, saveButtonProps, formLoading, onFinish, redirect } = useForm<IVendor>();

const handleSubmit = async (redirectTo: "list" | "edit" | "create") => {
let values = await form.validateFields();
await onFinish(values);
redirect(redirectTo, (values as IVendor).id);
}

return (
<Create
title={props.mode === "create" ? t("vendor.titles.create") : t("vendor.titles.clone")}
isLoading={formLoading}
saveButtonProps={saveButtonProps}
footerButtons={() => (
<>
<Button type="primary" onClick={() => handleSubmit("list")}>{t("buttons.save")}</Button>
<Button type="primary" onClick={() => handleSubmit("create")}>{t("buttons.saveAndAdd")}</Button>
</>
)}
>
<Form {...formProps} layout="vertical">
<Form.Item
Expand Down
3 changes: 3 additions & 0 deletions client/src/utils/overrides.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#qty-input {
text-align: center !important;
}
clevelandcs marked this conversation as resolved.
Show resolved Hide resolved
14 changes: 7 additions & 7 deletions client/src/utils/saveload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ export function useInitialTableState(tableId: string): TableState {
const savedSorters = hasHashProperty("sorters")
? getHashProperty("sorters")
: isLocalStorageAvailable
? localStorage.getItem(`${tableId}-sorters`)
: null;
? localStorage.getItem(`${tableId}-sorters`)
: null;
const savedFilters = hasHashProperty("filters")
? getHashProperty("filters")
: isLocalStorageAvailable
? localStorage.getItem(`${tableId}-filters`)
: null;
? localStorage.getItem(`${tableId}-filters`)
: null;
const savedPagination = hasHashProperty("pagination")
? getHashProperty("pagination")
: isLocalStorageAvailable
? localStorage.getItem(`${tableId}-pagination`)
: null;
? localStorage.getItem(`${tableId}-pagination`)
: null;
const savedShowColumns = isLocalStorageAvailable ? localStorage.getItem(`${tableId}-showColumns`) : null;

const sorters = savedSorters ? JSON.parse(savedSorters) : [{ field: "id", order: "asc" }];
Expand Down Expand Up @@ -59,7 +59,7 @@ export function useStoreInitialState(tableId: string, state: TableState) {
if (filters.length > 0) {
if (isLocalStorageAvailable) {
localStorage.setItem(`${tableId}-filters`, JSON.stringify(filters));
setURLHash("filters", JSON.stringify(state.filters));
setURLHash("filters", JSON.stringify(filters));
}
} else {
localStorage.removeItem(`${tableId}-filters`);
Expand Down