From 47c0e0f1cc2dfa07d5ced1caf7a55ca1e642b93e Mon Sep 17 00:00:00 2001 From: Aidan Jones Date: Mon, 30 Sep 2024 13:20:46 -0400 Subject: [PATCH] Change Workflow construction methods - constructor is now private - create and restore are static functions that return a Workflow instance - getSnapshot is also static now - updated parameters of the modified functions --- .../common/workflow/index.ts | 49 +++++++++---------- .../workflows/[product_id]/+page.server.ts | 7 ++- .../tasks/[product_id]/+page.server.ts | 9 ++-- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/source/SIL.AppBuilder.Portal/common/workflow/index.ts b/source/SIL.AppBuilder.Portal/common/workflow/index.ts index f0bd51346..8c170dfb6 100644 --- a/source/SIL.AppBuilder.Portal/common/workflow/index.ts +++ b/source/SIL.AppBuilder.Portal/common/workflow/index.ts @@ -33,55 +33,54 @@ export class Workflow { private adminLevel: RequiredAdminLevel; private productType: ProductType; - constructor(productId: string) { + private constructor(productId: string, input: WorkflowInput) { this.productId = productId; - this.currentState = null; - this.flow = null; + this.adminLevel = input.adminLevel; + this.productType = input.productType; } /* PUBLIC METHODS */ /** Create a new workflow instance and populate the database tables. */ - public async create(input: WorkflowInput, productId?: string): Promise { - this.flow?.stop(); - this.currentState = null; - this.productId = productId ?? this.productId; - this.adminLevel = input.adminLevel; - this.productType = input.productType; - + public static async create(productId: string, input: WorkflowInput): Promise { DatabaseWrites.workflowInstances.upsert({ where: { - ProductId: this.productId + ProductId: productId }, update: {}, create: { Snapshot: '', - ProductId: this.productId + ProductId: productId } }); - this.flow = createActor(DefaultWorkflow, { + const flow = new Workflow(productId, input); + + flow.flow = createActor(DefaultWorkflow, { inspect: (e) => { - if (e.type === '@xstate.snapshot') this.inspect(e); + if (e.type === '@xstate.snapshot') flow.inspect(e); }, input: input }); - this.flow.start(); + flow.flow.start(); + + return flow; } /** Restore from a snapshot in the database. */ - public async restore(): Promise { - this.flow?.stop(); - this.currentState = null; - const snap = await this.getSnapshot(); - this.flow = createActor(DefaultWorkflow, { + public static async restore(productId: string): Promise { + const snap = await Workflow.getSnapshot(productId); + const flow = new Workflow(productId, snap.input); + flow.flow = createActor(DefaultWorkflow, { snapshot: snap ? DefaultWorkflow.resolveState(snap) : undefined, inspect: (e) => { - if (e.type === '@xstate.snapshot') this.inspect(e); + if (e.type === '@xstate.snapshot') flow.inspect(e); }, input: snap.input }); - this.flow.start(); + flow.flow.start(); + + return flow; } /** Send a transition event to the workflow. */ @@ -99,12 +98,12 @@ export class Workflow { } /** Retrieves the workflow's snapshot from the database and sets the `WorkflowAdminLevel` and `ProductType` */ - public async getSnapshot(): Promise { + public static async getSnapshot(productId: string): Promise { const snap = JSON.parse( ( await prisma.workflowInstances.findUnique({ where: { - ProductId: this.productId + ProductId: productId }, select: { Snapshot: true @@ -112,8 +111,6 @@ export class Workflow { }) )?.Snapshot || 'null' ) as Snapshot | null; - this.adminLevel = snap?.input.adminLevel; - this.productType = snap?.input.productType; return snap; } diff --git a/source/SIL.AppBuilder.Portal/src/routes/(authenticated)/admin/workflows/[product_id]/+page.server.ts b/source/SIL.AppBuilder.Portal/src/routes/(authenticated)/admin/workflows/[product_id]/+page.server.ts index 0a86e02bf..26e0172c6 100644 --- a/source/SIL.AppBuilder.Portal/src/routes/(authenticated)/admin/workflows/[product_id]/+page.server.ts +++ b/source/SIL.AppBuilder.Portal/src/routes/(authenticated)/admin/workflows/[product_id]/+page.server.ts @@ -51,9 +51,9 @@ export const load: PageServerLoad = async ({ params, url, locals }) => { } }); - const flow = new Workflow(params.product_id); + const flow = await Workflow.restore(params.product_id); - const snap = await flow.getSnapshot(); + const snap = await Workflow.getSnapshot(params.product_id); return { instance: instance, @@ -68,8 +68,7 @@ export const actions = { const form = await superValidate(request, valibot(jumpStateSchema)); if (!form.valid) return fail(400, { form, ok: false }); - const flow = new Workflow(params.product_id); - await flow.restore(); + const flow = await Workflow.restore(params.product_id); flow.send({ type: 'Jump', diff --git a/source/SIL.AppBuilder.Portal/src/routes/(authenticated)/tasks/[product_id]/+page.server.ts b/source/SIL.AppBuilder.Portal/src/routes/(authenticated)/tasks/[product_id]/+page.server.ts index 6b55b4b96..a0e749c10 100644 --- a/source/SIL.AppBuilder.Portal/src/routes/(authenticated)/tasks/[product_id]/+page.server.ts +++ b/source/SIL.AppBuilder.Portal/src/routes/(authenticated)/tasks/[product_id]/+page.server.ts @@ -29,10 +29,8 @@ type Fields = { export const load = (async ({ params, url, locals }) => { const session = await locals.auth(); // TODO: permission check - const flow = new Workflow(params.product_id); - await flow.restore(); - - const snap = await flow.getSnapshot(); + const flow = await Workflow.restore(params.product_id); + const snap = await Workflow.getSnapshot(params.product_id); const product = await prisma.products.findUnique({ where: { @@ -176,8 +174,7 @@ export const actions = { const form = await superValidate(request, valibot(sendActionSchema)); if (!form.valid) return fail(400, { form, ok: false }); - const flow = new Workflow(params.product_id); - await flow.restore(); + const flow = await Workflow.restore(params.product_id); //double check that state matches current snapshot if (form.data.state === flow.state()) {