feat: Add color column with filter to spool list
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

Add optional color column to spool list showing filament color swatches
with multi-select filtering capability.

Backend:
- GET /api/v1/color endpoint to list distinct filament colors
- filament.color_hex query param on spool list for filtering

Frontend:
- ColorFilterColumn component renders color swatches
- useSpoolmanColors() hook fetches available colors
- Filter dropdown shows swatches with hex codes
- Column hidden by default (enable via column selector)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 21:11:18 -06:00
parent 8fc06cdb18
commit 9bfc322f32
9 changed files with 193 additions and 11 deletions

View File

@@ -18,6 +18,7 @@ import { useNavigate } from "react-router";
import {
Action,
ActionsColumn,
ColorFilterColumn,
CustomFieldColumn,
DateColumn,
FilteredQueryColumn,
@@ -28,6 +29,7 @@ import {
} from "../../components/column";
import { useLiveify } from "../../components/liveify";
import {
useSpoolmanColors,
useSpoolmanFilamentFilter,
useSpoolmanLocations,
useSpoolmanLotNumbers,
@@ -48,6 +50,7 @@ interface ISpoolCollapsed extends ISpool {
"filament.combined_name": string; // Eg. "Prusa - PLA Red"
"filament.id": number;
"filament.material"?: string;
"filament.color_hex"?: string;
}
function collapseSpool(element: ISpool): ISpoolCollapsed {
@@ -65,6 +68,7 @@ function collapseSpool(element: ISpool): ISpoolCollapsed {
"filament.combined_name": filament_name,
"filament.id": element.filament.id,
"filament.material": element.filament.material,
"filament.color_hex": element.filament.color_hex,
};
}
@@ -72,6 +76,7 @@ function translateColumnI18nKey(columnName: string): string {
columnName = columnName.replace(".", "_");
if (columnName === "filament_combined_name") columnName = "filament_name";
else if (columnName === "filament_material") columnName = "material";
else if (columnName === "filament_color_hex") columnName = "color";
return `spool.fields.${columnName}`;
}
@@ -80,6 +85,7 @@ const namespace = "spoolList-v2";
const allColumns: (keyof ISpoolCollapsed & string)[] = [
"id",
"filament.combined_name",
"filament.color_hex",
"filament.material",
"price",
"used_weight",
@@ -94,7 +100,7 @@ const allColumns: (keyof ISpoolCollapsed & string)[] = [
"comment",
];
const defaultColumns = allColumns.filter(
(column_id) => ["registered", "used_length", "remaining_length", "lot_nr"].indexOf(column_id) === -1
(column_id) => ["registered", "used_length", "remaining_length", "lot_nr", "filament.color_hex"].indexOf(column_id) === -1
);
export const SpoolList: React.FC<IResourceComponentsProps> = () => {
@@ -367,6 +373,14 @@ export const SpoolList: React.FC<IResourceComponentsProps> = () => {
dataId: "filament.combined_name",
filterValueQuery: useSpoolmanFilamentFilter(),
}),
ColorFilterColumn({
...commonProps,
id: "filament.color_hex",
i18nkey: "spool.fields.color",
filterValueQuery: useSpoolmanColors(),
colorGetter: (record: ISpoolCollapsed) => record.filament.color_hex,
width: 60,
}),
FilteredQueryColumn({
...commonProps,
id: "filament.material",