From ffea0a01f62c13110964be0f5ed2dc7d98fec092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Tue, 13 Apr 2021 12:00:49 +0200 Subject: [PATCH] :zap: Add tags to GET /workflows --- packages/cli/src/Interfaces.ts | 5 +++-- packages/cli/src/Server.ts | 27 ++++++++++++++++++++------- packages/cli/src/TagHelpers.ts | 33 ++++++++++++++++++++++++++------- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index 2ad47fc41b..5d75ca71f4 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -23,6 +23,7 @@ import { Repository } from 'typeorm'; import { ChildProcess } from 'child_process'; import { Url } from 'url'; import { Request } from 'express'; +import { TagEntity } from './databases/entities/TagEntity'; export interface IActivationError { time: number; @@ -80,13 +81,13 @@ export interface ITagBase { } export interface ITagDb extends ITagBase { - id: number; + id: string | number; } // Almost identical to editor-ui.Interfaces.ts export interface IWorkflowDb extends IWorkflowBase { id: number | string; - tags: Array<{ id: number; name: string }>; + tags: TagEntity[] | Array<{ id: string; name: string }>; // TODO: Unify } export interface IWorkflowResponse extends IWorkflowBase { diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index fce81b7eb6..3169c76b2e 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -502,7 +502,7 @@ class App { const { tags } = req.body as { tags: string }; if (tags) { - const tagIds = tags.split(',').map(Number); + const tagIds = tags.split(','); await TagHelpers.createTagWorkflowRelations(result.id as string, tagIds); result.tags = await TagHelpers.getTagsForResponseData(tagIds); } @@ -554,6 +554,19 @@ class App { const results = await Db.collections.Workflow!.find(findQuery); + const tagsPerWorkflow = await TagHelpers.getTagsByWorkflowIds(results.map(({ id }) => id.toString())); + + // TODO: Improve + tagsPerWorkflow.forEach(({ workflowId, id, name }) => { + results.forEach(result => { + if (result.id !== workflowId) return; + // @ts-ignore + result.tags = result.tags + ? [...result.tags, { id, name }] + : [{ id, name }]; + }); + }); + for (const entry of results) { (entry as unknown as IWorkflowShortResponse).id = entry.id.toString(); } @@ -654,7 +667,7 @@ class App { if (tags) { await TagHelpers.deleteAllTagsForWorkflow(id); - const tagIds = tags.split(',').map(Number); + const tagIds = tags.split(','); for (const tagId of tagIds) { await TagHelpers.validateId(tagId); @@ -745,7 +758,7 @@ class App { })); // Creates a tag - this.app.post(`/${this.restEndpoint}/tags`, ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<{ id: number, name: string }> => { + this.app.post(`/${this.restEndpoint}/tags`, ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<{ id: string, name: string }> => { TagHelpers.validateRequestBody(req.body); const { name } = req.body; @@ -758,28 +771,28 @@ class App { updatedAt: this.getCurrentDate(), }; - const { id } = await Db.collections.Tag!.save(newTag); + const { id } = await Db.collections.Tag!.save(newTag) as { id: string }; return { id, name }; })); // Deletes a tag this.app.delete(`/${this.restEndpoint}/tags/:id`, ResponseHelper.send(async (req: express.Request, res: express.Response): Promise => { - const id = Number(req.params.id); + const { id } = req.params; await TagHelpers.validateId(id); await Db.collections.Tag!.delete({ id }); return true; })); // Updates an existing tag - this.app.patch(`/${this.restEndpoint}/tags/:id`, ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<{ id: number, name: string }> => { + this.app.patch(`/${this.restEndpoint}/tags/:id`, ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<{ id: string, name: string }> => { TagHelpers.validateRequestBody(req.body); const { name } = req.body; await TagHelpers.validateName(name); TagHelpers.validateLength(name); - const id = Number(req.params.id); + const { id } = req.params; await TagHelpers.validateId(id); const updatedTag: Partial = { diff --git a/packages/cli/src/TagHelpers.ts b/packages/cli/src/TagHelpers.ts index e66ad778d2..c9ff45fbf9 100644 --- a/packages/cli/src/TagHelpers.ts +++ b/packages/cli/src/TagHelpers.ts @@ -17,7 +17,7 @@ import { /** * Validate whether a tag ID exists so that it can be used for a workflow create or tag update operation. */ -export async function validateId(id: number): Promise | never { +export async function validateId(id: string): Promise | never { const findQuery = { where: { id } } as FindOneOptions; const tag = await Db.collections.Tag!.findOne(findQuery); @@ -116,15 +116,34 @@ export async function getAllTagsWithUsageCount(): Promise> { + return await getConnection().createQueryBuilder() + .select('workflows_tags.workflowId', 'workflowId') + .addSelect('tag_entity.id', 'id') + .addSelect('tag_entity.name', 'name') + .from('workflows_tags', 'workflows_tags') + .leftJoin('tag_entity', 'tag_entity', 'tag_entity.id = workflows_tags.tagId') + .where('workflows_tags.workflowId IN (:...workflowIds)', { workflowIds }) + .getRawMany(); +} + + +/** + * Retrieve tag IDs and names, to be used in an API response + * for a workflow create/update operation. */ export async function getTagsForResponseData( - tagIds: number[] -): Promise> { + tagIds: string[] +): Promise> { return await Db.collections.Tag!.find({ select: ['id', 'name'], where: { id: In(tagIds) }, - }); + }) as Array<{ id: string; name: string }>; } /** @@ -146,7 +165,7 @@ async function findRelations( */ export async function getWorkflowTags( workflowId: string -): Promise> { +): Promise> { return await getConnection().createQueryBuilder() .select('tag_entity.id', 'id') .addSelect('tag_entity.name', 'name') @@ -170,7 +189,7 @@ export async function getWorkflowTags( /** * Link a workflow to one or more tags. */ -export async function createTagWorkflowRelations(workflowId: string, tagIds: number[]) { +export async function createTagWorkflowRelations(workflowId: string, tagIds: string[]) { await getConnection().createQueryBuilder() .insert() .into('workflows_tags')