Add tags to GET /workflows

This commit is contained in:
Iván Ovejero 2021-04-13 12:00:49 +02:00
parent be7ec2d3e7
commit ffea0a01f6
3 changed files with 49 additions and 16 deletions

View file

@ -23,6 +23,7 @@ import { Repository } from 'typeorm';
import { ChildProcess } from 'child_process'; import { ChildProcess } from 'child_process';
import { Url } from 'url'; import { Url } from 'url';
import { Request } from 'express'; import { Request } from 'express';
import { TagEntity } from './databases/entities/TagEntity';
export interface IActivationError { export interface IActivationError {
time: number; time: number;
@ -80,13 +81,13 @@ export interface ITagBase {
} }
export interface ITagDb extends ITagBase { export interface ITagDb extends ITagBase {
id: number; id: string | number;
} }
// Almost identical to editor-ui.Interfaces.ts // Almost identical to editor-ui.Interfaces.ts
export interface IWorkflowDb extends IWorkflowBase { export interface IWorkflowDb extends IWorkflowBase {
id: number | string; id: number | string;
tags: Array<{ id: number; name: string }>; tags: TagEntity[] | Array<{ id: string; name: string }>; // TODO: Unify
} }
export interface IWorkflowResponse extends IWorkflowBase { export interface IWorkflowResponse extends IWorkflowBase {

View file

@ -502,7 +502,7 @@ class App {
const { tags } = req.body as { tags: string }; const { tags } = req.body as { tags: string };
if (tags) { if (tags) {
const tagIds = tags.split(',').map(Number); const tagIds = tags.split(',');
await TagHelpers.createTagWorkflowRelations(result.id as string, tagIds); await TagHelpers.createTagWorkflowRelations(result.id as string, tagIds);
result.tags = await TagHelpers.getTagsForResponseData(tagIds); result.tags = await TagHelpers.getTagsForResponseData(tagIds);
} }
@ -554,6 +554,19 @@ class App {
const results = await Db.collections.Workflow!.find(findQuery); 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) { for (const entry of results) {
(entry as unknown as IWorkflowShortResponse).id = entry.id.toString(); (entry as unknown as IWorkflowShortResponse).id = entry.id.toString();
} }
@ -654,7 +667,7 @@ class App {
if (tags) { if (tags) {
await TagHelpers.deleteAllTagsForWorkflow(id); await TagHelpers.deleteAllTagsForWorkflow(id);
const tagIds = tags.split(',').map(Number); const tagIds = tags.split(',');
for (const tagId of tagIds) { for (const tagId of tagIds) {
await TagHelpers.validateId(tagId); await TagHelpers.validateId(tagId);
@ -745,7 +758,7 @@ class App {
})); }));
// Creates a tag // 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); TagHelpers.validateRequestBody(req.body);
const { name } = req.body; const { name } = req.body;
@ -758,28 +771,28 @@ class App {
updatedAt: this.getCurrentDate(), 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 }; return { id, name };
})); }));
// Deletes a tag // Deletes a tag
this.app.delete(`/${this.restEndpoint}/tags/:id`, ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<boolean> => { this.app.delete(`/${this.restEndpoint}/tags/:id`, ResponseHelper.send(async (req: express.Request, res: express.Response): Promise<boolean> => {
const id = Number(req.params.id); const { id } = req.params;
await TagHelpers.validateId(id); await TagHelpers.validateId(id);
await Db.collections.Tag!.delete({ id }); await Db.collections.Tag!.delete({ id });
return true; return true;
})); }));
// Updates an existing tag // 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); TagHelpers.validateRequestBody(req.body);
const { name } = req.body; const { name } = req.body;
await TagHelpers.validateName(name); await TagHelpers.validateName(name);
TagHelpers.validateLength(name); TagHelpers.validateLength(name);
const id = Number(req.params.id); const { id } = req.params;
await TagHelpers.validateId(id); await TagHelpers.validateId(id);
const updatedTag: Partial<ITagDb> = { const updatedTag: Partial<ITagDb> = {

View file

@ -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. * 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<void> | never { export async function validateId(id: string): Promise<void> | never {
const findQuery = { where: { id } } as FindOneOptions; const findQuery = { where: { id } } as FindOneOptions;
const tag = await Db.collections.Tag!.findOne(findQuery); const tag = await Db.collections.Tag!.findOne(findQuery);
@ -116,15 +116,34 @@ export async function getAllTagsWithUsageCount(): Promise<Array<{
} }
/** /**
* Retrieve tag IDs and names, to be used in an API response. * Retrieve tag IDs and names, to be used in an API response
* for a workflow create/update operation.
*/
export async function getTagsByWorkflowIds(
workflowIds: string[]
): Promise<Array<{ workflowId: number; id: string; name: string }>> {
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( export async function getTagsForResponseData(
tagIds: number[] tagIds: string[]
): Promise<Array<{ id: number; name: string }>> { ): Promise<Array<{ id: string; name: string }>> {
return await Db.collections.Tag!.find({ return await Db.collections.Tag!.find({
select: ['id', 'name'], select: ['id', 'name'],
where: { id: In(tagIds) }, where: { id: In(tagIds) },
}); }) as Array<{ id: string; name: string }>;
} }
/** /**
@ -146,7 +165,7 @@ async function findRelations(
*/ */
export async function getWorkflowTags( export async function getWorkflowTags(
workflowId: string workflowId: string
): Promise<Array<{ id: number; name: string }>> { ): Promise<Array<{ id: string; name: string }>> {
return await getConnection().createQueryBuilder() return await getConnection().createQueryBuilder()
.select('tag_entity.id', 'id') .select('tag_entity.id', 'id')
.addSelect('tag_entity.name', 'name') .addSelect('tag_entity.name', 'name')
@ -170,7 +189,7 @@ export async function getWorkflowTags(
/** /**
* Link a workflow to one or more tags. * 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() await getConnection().createQueryBuilder()
.insert() .insert()
.into('workflows_tags') .into('workflows_tags')