diff --git a/backend/events.go b/backend/events.go index 45e8775..8e6a3ef 100644 --- a/backend/events.go +++ b/backend/events.go @@ -237,6 +237,11 @@ func ListenNewStackEvents(db *sql.DB) { return } + if err := stackModel.EndProcessing(ctx, stackID); err != nil { + newStacksLogger.Error("failed to finish processing", "error", err) + return + } + newStacksLogger.Debug("Finished processing stack", "StackID", stackID) }() } diff --git a/backend/models/lists.go b/backend/models/lists.go index 7519cb0..1d5cbd5 100644 --- a/backend/models/lists.go +++ b/backend/models/lists.go @@ -121,6 +121,16 @@ func (m ListModel) StartProcessing(ctx context.Context, processingListID uuid.UU return err } +func (m ListModel) EndProcessing(ctx context.Context, processingListID uuid.UUID) error { + startProcessingStmt := ProcessingLists. + UPDATE(ProcessingLists.Status). + SET(model.Progress_Complete). + WHERE(ProcessingLists.ID.EQ(UUID(processingListID))) + + _, err := startProcessingStmt.ExecContext(ctx, m.dbPool) + return err +} + // ======================================== // INSERT methods // ======================================== diff --git a/frontend/src/components/notifications/ProcessingImage.tsx b/frontend/src/components/notifications/ProcessingImage.tsx index e59ecc5..b3eb0ed 100644 --- a/frontend/src/components/notifications/ProcessingImage.tsx +++ b/frontend/src/components/notifications/ProcessingImage.tsx @@ -8,7 +8,8 @@ export const ProcessingImages: Component = () => { const notifications = useNotifications(); const processingNumber = () => - Object.keys(notifications.state.ProcessingImages).length; + Object.keys(notifications.state.ProcessingImages).length + + Object.keys(notifications.state.ProcessingLists).length; return ( @@ -16,7 +17,7 @@ export const ProcessingImages: Component = () => { 0}>

Processing {processingNumber()}{" "} - {processingNumber() === 1 ? "image" : "images"} + {processingNumber() === 1 ? "item" : "items"} ...

@@ -30,10 +31,8 @@ export const ProcessingImages: Component = () => { 0 - } - fallback={

No images to process

} + when={processingNumber() > 0} + fallback={

No items to process

} > {([id, _image]) => ( @@ -57,6 +56,24 @@ export const ProcessingImages: Component = () => {
)} + + + {([, _list]) => ( + + {(list) => ( +
+
+

New Stack: {list().Name}

+
+ +
+ )} +
+ )} +
diff --git a/frontend/src/contexts/Notifications.tsx b/frontend/src/contexts/Notifications.tsx index cf49e47..abe0160 100644 --- a/frontend/src/contexts/Notifications.tsx +++ b/frontend/src/contexts/Notifications.tsx @@ -10,18 +10,27 @@ import { useContext, } from "solid-js"; import { base } from "@network/index"; -import { processingImagesValidator } from "@network/notifications"; +import { + notificationValidator, + processingImagesValidator, + processingListValidator, +} from "@network/notifications"; type NotificationState = { ProcessingImages: Record< string, InferOutput | undefined >; + ProcessingLists: Record< + string, + InferOutput | undefined + >; }; export const Notifications = (onCompleteImage: () => void) => { const [state, setState] = createStore({ ProcessingImages: {}, + ProcessingLists: {}, }); const { processingImages } = useSearchImageContext(); @@ -45,21 +54,32 @@ export const Notifications = (onCompleteImage: () => void) => { return; } - const processingImage = safeParse(processingImagesValidator, jsonData); - if (!processingImage.success) { + const notification = safeParse(notificationValidator, jsonData); + if (!notification.success) { console.error("Processing image could not be parsed.", e.data); return; } - console.log("SSE: ", processingImage); + console.log("SSE: ", notification); - const { ImageID, Status } = processingImage.output; + if (notification.output.Type === "image") { + const { ImageID, Status } = notification.output; - if (Status === "complete") { - setState("ProcessingImages", ImageID, undefined); - onCompleteImage(); - } else { - setState("ProcessingImages", ImageID, processingImage.output); + if (Status === "complete") { + setState("ProcessingImages", ImageID, undefined); + onCompleteImage(); + } else { + setState("ProcessingImages", ImageID, notification.output); + } + } else if (notification.output.Type === "list") { + const { ListID, Status } = notification.output; + + if (Status === "complete") { + setState("ProcessingLists", ListID, undefined); + onCompleteImage(); + } else { + setState("ProcessingLists", ListID, notification.output); + } } }; @@ -83,6 +103,7 @@ export const Notifications = (onCompleteImage: () => void) => { images.map((i) => [ i.ImageID, { + Type: "image", ImageID: i.ImageID, ImageName: i.Image.ImageName, Status: i.Status, diff --git a/frontend/src/network/notifications.ts b/frontend/src/network/notifications.ts index 4f90128..b4505b0 100644 --- a/frontend/src/network/notifications.ts +++ b/frontend/src/network/notifications.ts @@ -1,6 +1,21 @@ import { literal, pipe, strictObject, string, union, uuid } from "valibot"; +export const processingListValidator = strictObject({ + Type: literal("list"), + + Name: string(), + ListID: pipe(string(), uuid()), + + Status: union([ + literal("not-started"), + literal("in-progress"), + literal("complete"), + ]), +}); + export const processingImagesValidator = strictObject({ + Type: literal("image"), + ImageID: pipe(string(), uuid()), ImageName: string(), Status: union([ @@ -9,3 +24,8 @@ export const processingImagesValidator = strictObject({ literal("complete"), ]), }); + +export const notificationValidator = union([ + processingListValidator, + processingImagesValidator, +]);