Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Changelog

## Unreleased
- Add filament label printing with separate presets, QR codes, and AML export (labels and pages), plus AML size control and filament QR scanning support.
90 changes: 88 additions & 2 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"i18next": "^25.7.3",
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"jszip": "3.10.1",
"react": "^19.2.3",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
Expand All @@ -39,19 +40,19 @@
"@refinedev/cli": "^2.16.50",
"@types/loadable__component": "^5.13.10",
"@types/node": "^25.0.3",
"@types/react-dom": "^19.2.3",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^5.1.2",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.26",
"eslint-plugin-react": "^7.37.5",
"eslint": "^9.39.2",
"globals": "^17.0.0",
"prettier": "3.7.4",
"typescript-eslint": "^8.52.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.52.0",
"vite": "^7.3.0",
"vite-plugin-mkcert": "^1.17.9",
"vite-plugin-pwa": "^1.2.0"
Expand Down
36 changes: 34 additions & 2 deletions client/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,21 @@
"helpMargin": "Margins should be configured to match your label paper and printer, changing these will affect the size of the entire grid.",
"helpPrinterMargin": "Safe-Zone should be set to how close to the paper edge your printer can print, changing these will not affect the entire grid.",
"print": "Print",
"exportLabels": "Export Labels",
"columns": "Columns",
"rows": "Rows",
"paperSize": "Paper Size",
"customSize": "Custom",
"dimensions": "Dimensions",
"amlLabelSize": "AML Label Size",
"exportFormat": "Export Format",
"exportFormatOptions": {
"png": "PNG",
"aml": "AML"
},
"exportAsZip": "Export as .zip",
"exportDpi": "Export DPI",
"exportDpiHelp": "Higher DPI makes sharper PNG/AML exports but increases file size and export time.",
"showBorder": "Show Border",
"previewScale": "Preview Scale",
"skipItems": "Skip Items",
Expand All @@ -92,6 +102,10 @@
"grid": "Grid"
},
"settings": "Presets",
"spoolPrintPresets": "Spool Print Presets",
"filamentPrintPresets": "Filament Print Presets",
"spoolImagePresets": "Spool Image Presets",
"filamentImagePresets": "Filament Image Presets",
"defaultSettings": "Default",
"addSettings": "Add New Preset",
"newSetting": "New",
Expand All @@ -100,13 +114,21 @@
"deleteSettingsConfirm": "Are you sure you want to delete this preset?",
"settingsName": "Preset Name",
"saveSetting": "Save Presets",
"saveAsImage": "Save as Image"
"saveAsImage": "Save as Image",
"saveAsAmlLabels": "Save as AML (Labels)"
},
"qrcode": {
"button": "Print Labels",
"exportButton": "Export Labels",
"selectButton": "Export/Print",
"selectTitle": "Export / Print Labels",
"title": "Label Printing",
"template": "Label Template",
"filenameTemplate": "Filename Template",
"filenameTemplateTooltipSpool": "Use {} to insert values of the spool object as text. Refer to the label template rules and available tags for more details.",
"filenameTemplateTooltipFilament": "Use {} to insert values of the filament object as text. Refer to the label template rules and available tags for more details.",
"templateHelp": "Use {} to insert values of the spool object as text. For example, {id} will be replaced with the spool id, or {filament.material} will be replaced with the material of the spool. if a value is missing it will be replaced with \"?\". A second set of {} can be used to remove this. In addition, any text between the sets of {} will be removed if the value is missing. For example, {Lot Nr: {lot_nr}} will only show the label if the spool has a lot number. Enclose text with double asterix ** to make it bold. Click the button to view a list of all available tags.",
"templateHelpFilament": "Use {} to insert values of the filament object as text. For example, {id} will be replaced with the filament id, or {vendor.name} will be replaced with the vendor name. If a value is missing it will be replaced with \"?\". A second set of {} can be used to remove this. In addition, any text between the sets of {} will be removed if the value is missing. For example, {Article: {article_number}} will only show the label if a filament has an article number. Enclose text with double asterix ** to make it bold. Click the button to view a list of all available tags.",
"textSize": "Label Text Size",
"showContent": "Print Label",
"useHTTPUrl": {
Expand All @@ -127,12 +149,22 @@
},
"spoolSelect": {
"title": "Select Spools",
"description": "Select spools to print labels for.",
"description": "Select spools to export or print labels for.",
"searchPlaceholder": "Search vendor, filament, material, location, lot #",
"showArchived": "Show Archived",
"noSpoolsSelected": "You have not selected any spools.",
"selectAll": "Select/Unselect All",
"selectedTotal_one": "{{count}} spool selected",
"selectedTotal_other": "{{count}} spools selected"
},
"filamentSelect": {
"title": "Select Filaments",
"description": "Select filaments to export or print labels for.",
"searchPlaceholder": "Search vendor, name, material, article #",
"noFilamentsSelected": "You have not selected any filaments.",
"selectAll": "Select/Unselect All",
"selectedTotal_one": "{{count}} filament selected",
"selectedTotal_other": "{{count}} filaments selected"
}
},
"scanner": {
Expand Down
5 changes: 5 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ function App() {
/>
<Route path="edit/:id" element={<LoadableResourcePage resource="spools" page="edit" />} />
<Route path="show/:id" element={<LoadableResourcePage resource="spools" page="show" />} />
<Route path="labels" element={<LoadablePage name="spoolLabels" />} />
<Route path="print" element={<LoadablePage name="printing" />} />
<Route path="export" element={<LoadablePage name="printingExport" />} />
</Route>
<Route path="/filament">
<Route index element={<LoadableResourcePage resource="filaments" page="list" />} />
Expand All @@ -208,6 +210,9 @@ function App() {
/>
<Route path="edit/:id" element={<LoadableResourcePage resource="filaments" page="edit" />} />
<Route path="show/:id" element={<LoadableResourcePage resource="filaments" page="show" />} />
<Route path="labels" element={<LoadablePage name="filamentLabels" />} />
<Route path="print" element={<LoadablePage name="filamentPrinting" />} />
<Route path="export" element={<LoadablePage name="filamentExport" />} />
</Route>
<Route path="/vendor">
<Route index element={<LoadableResourcePage resource="vendors" page="list" />} />
Expand Down
8 changes: 7 additions & 1 deletion client/src/components/column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ interface BaseColumnProps<Obj extends Entity> {
title?: string;
align?: AlignType;
sorter?: boolean;
ellipsis?: boolean;
t: (key: string) => string;
navigate: (link: string) => void;
dataSource: Obj[];
Expand All @@ -62,6 +63,7 @@ interface FilteredColumnProps {
allowMultipleFilters?: boolean;
onFilterDropdownOpen?: () => void;
loadingFilters?: boolean;
filterSearch?: boolean | ((input: string, record: ColumnFilterItem) => boolean);
}

interface CustomColumnProps<Obj> {
Expand Down Expand Up @@ -90,6 +92,7 @@ function Column<Obj extends Entity>(
dataIndex: props.id,
align: props.align,
title: props.title ?? t(props.i18nkey ?? `${props.i18ncat}.fields.${props.id}`),
ellipsis: props.ellipsis,
filterMultiple: props.allowMultipleFilters ?? true,
width: props.width ?? undefined,
onCell: props.onCell ?? undefined,
Expand All @@ -108,6 +111,7 @@ function Column<Obj extends Entity>(
if (props.filters && props.filteredValue) {
columnProps.filters = props.filters;
columnProps.filteredValue = props.filteredValue;
columnProps.filterSearch = props.filterSearch ?? true;
if (props.loadingFilters) {
columnProps.filterDropdown = <FilterDropdownLoading />;
}
Expand Down Expand Up @@ -356,7 +360,9 @@ export function SpoolIconColumn<Obj extends Entity>(props: SpoolIconColumnProps<
<SpoolIcon color={colorObj} />
</Col>
)}
<Col flex="auto">{value}</Col>
<Col flex="auto" style={{ minWidth: 0 }}>
{value}
</Col>
</Row>
);
},
Expand Down
19 changes: 4 additions & 15 deletions client/src/components/otherModels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,29 +86,18 @@ export function useSpoolmanFilamentFilter(enabled: boolean = false) {
}

export function useSpoolmanFilamentNames(enabled: boolean = false) {
return useQuery<IFilament[], unknown, string[]>({
return useQuery<string[]>({
enabled: enabled,
queryKey: ["filaments"],
queryKey: ["filamentNames"],
queryFn: async () => {
const response = await fetch(getAPIURL() + "/filament");
const response = await fetch(getAPIURL() + "/filament-name");
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
},
select: (data) => {
// Concatenate vendor name and filament name
let names = data
.filter((filament) => {
return filament.name !== null && filament.name !== undefined && filament.name !== "";
})
.map((filament) => {
return filament.name ?? "<unknown>";
})
.sort();
// Remove duplicates
names = [...new Set(names)];
return names;
return data.sort();
},
});
}
Expand Down
Loading