Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

N21-1598 Change calculation of Tool usage #4689

Merged
merged 6 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 65 additions & 3 deletions apps/server/src/modules/board/repo/board-do.repo.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { createMock } from '@golevelup/ts-jest';
import { MongoMemoryDatabaseModule } from '@infra/database';
import { NotFoundError } from '@mikro-orm/core';
import { EntityManager } from '@mikro-orm/mongodb';
import { EntityManager, ObjectId } from '@mikro-orm/mongodb';
import { FilesStorageClientAdapterService } from '@modules/files-storage-client';
import { DrawingElementAdapterService } from '@modules/tldraw-client/service/drawing-element-adapter.service';
import { ContextExternalToolService } from '@modules/tool/context-external-tool/service';
import { NotFoundException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { AnyBoardDo, BoardExternalReferenceType, Card, Column, ColumnBoard } from '@shared/domain/domainobject';
import { CardNode, RichTextElementNode } from '@shared/domain/entity';
import { CardNode, ColumnBoardNode, ExternalToolElementNodeEntity, RichTextElementNode } from '@shared/domain/entity';
import { EntityId } from '@shared/domain/types';
import {
cardFactory,
cardNodeFactory,
Expand All @@ -16,12 +18,16 @@ import {
columnBoardNodeFactory,
columnFactory,
columnNodeFactory,
contextExternalToolEntityFactory,
contextExternalToolFactory,
courseFactory,
externalToolElementNodeFactory,
fileElementFactory,
richTextElementFactory,
richTextElementNodeFactory,
} from '@shared/testing';
import { DrawingElementAdapterService } from '@modules/tldraw-client/service/drawing-element-adapter.service';
import { ContextExternalToolEntity } from '../../tool';
import { ContextExternalTool } from '../../tool/context-external-tool/domain';
import { BoardDoRepo } from './board-do.repo';
import { BoardNodeRepo } from './board-node.repo';
import { RecursiveDeleteVisitor } from './recursive-delete.vistor';
Expand Down Expand Up @@ -267,6 +273,62 @@ describe(BoardDoRepo.name, () => {
});
});

describe('countBoardUsageForExternalTools', () => {
describe('when counting the amount of boards used by the selected tools', () => {
const setup = async () => {
const contextExternalToolId: EntityId = new ObjectId().toHexString();
const contextExternalTool: ContextExternalTool = contextExternalToolFactory.buildWithId(
undefined,
contextExternalToolId
);
const contextExternalToolEntity: ContextExternalToolEntity = contextExternalToolEntityFactory.buildWithId(
undefined,
contextExternalToolId
);
const otherContextExternalToolEntity: ContextExternalToolEntity =
contextExternalToolEntityFactory.buildWithId();

const board: ColumnBoardNode = columnBoardNodeFactory.buildWithId();
const otherBoard: ColumnBoardNode = columnBoardNodeFactory.buildWithId();
const card: CardNode = cardNodeFactory.buildWithId({ parent: board });
const otherCard: CardNode = cardNodeFactory.buildWithId({ parent: otherBoard });
const externalToolElements: ExternalToolElementNodeEntity[] = externalToolElementNodeFactory.buildListWithId(
2,
{
parent: card,
contextExternalTool: contextExternalToolEntity,
}
);
const otherExternalToolElement: ExternalToolElementNodeEntity = externalToolElementNodeFactory.buildWithId({
parent: otherCard,
contextExternalTool: otherContextExternalToolEntity,
});

await em.persistAndFlush([
board,
otherBoard,
card,
otherCard,
...externalToolElements,
otherExternalToolElement,
contextExternalToolEntity,
]);

return {
contextExternalTool,
};
};

it('should return the amount of boards used by the selected tools', async () => {
const { contextExternalTool } = await setup();

const result: number = await repo.countBoardUsageForExternalTools([contextExternalTool]);

expect(result).toEqual(1);
});
});
});

describe('getAncestorIds', () => {
describe('when having only a root boardnode', () => {
const setup = async () => {
Expand Down
18 changes: 17 additions & 1 deletion apps/server/src/modules/board/repo/board-do.repo.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Utils } from '@mikro-orm/core';
import { EntityManager, ObjectId } from '@mikro-orm/mongodb';
import type { ContextExternalTool } from '@modules/tool/context-external-tool/domain';
import { Injectable, NotFoundException } from '@nestjs/common';
import { AnyBoardDo, BoardExternalReference } from '@shared/domain/domainobject';
import { BoardNode, ColumnBoardNode } from '@shared/domain/entity';
import { BoardNode, ColumnBoardNode, ExternalToolElementNodeEntity } from '@shared/domain/entity';
import { EntityId } from '@shared/domain/types';
import { BoardDoBuilderImpl } from './board-do.builder-impl';
import { BoardNodeRepo } from './board-node.repo';
Expand Down Expand Up @@ -81,6 +82,21 @@ export class BoardDoRepo {
return domainObject;
}

async countBoardUsageForExternalTools(contextExternalTools: ContextExternalTool[]) {
const toolIds: EntityId[] = contextExternalTools
.map((tool: ContextExternalTool): EntityId | undefined => tool.id)
.filter((id: EntityId | undefined): id is EntityId => !!id);

const boardNodes: ExternalToolElementNodeEntity[] = await this.em.find(ExternalToolElementNodeEntity, {
contextExternalTool: { $in: toolIds },
});

const boardIds: EntityId[] = boardNodes.map((node: ExternalToolElementNodeEntity): EntityId => node.ancestorIds[0]);
const boardCount: number = new Set(boardIds).size;

return boardCount;
}

async getAncestorIds(boardDo: AnyBoardDo): Promise<EntityId[]> {
const boardNode = await this.boardNodeRepo.findById(boardDo.id);
return boardNode.ancestorIds;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { ContextExternalTool } from '@modules/tool/context-external-tool/domain';
import { BadRequestException, NotFoundException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import {
Expand All @@ -9,14 +10,16 @@ import {
SubmissionContainerElement,
} from '@shared/domain/domainobject';
import { InputFormat } from '@shared/domain/types';
import { drawingElementFactory, setupEntities } from '@shared/testing';
import {
cardFactory,
contextExternalToolFactory,
drawingElementFactory,
fileElementFactory,
linkElementFactory,
richTextElementFactory,
setupEntities,
submissionContainerElementFactory,
} from '@shared/testing/factory/domainobject';
} from '@shared/testing';
import {
DrawingContentBody,
FileContentBody,
Expand Down Expand Up @@ -118,7 +121,7 @@ describe(ContentElementService.name, () => {
});

describe('findParentOfId', () => {
describe('when parent is a vaid node', () => {
describe('when parent is a valid node', () => {
const setup = () => {
const card = cardFactory.build();
const element = richTextElementFactory.build();
Expand Down Expand Up @@ -154,6 +157,36 @@ describe(ContentElementService.name, () => {
});
});

describe('countBoardUsageForExternalTools', () => {
describe('when counting the amount of boards used by tools', () => {
const setup = () => {
const contextExternalTools: ContextExternalTool[] = contextExternalToolFactory.buildListWithId(3);

boardDoRepo.countBoardUsageForExternalTools.mockResolvedValueOnce(3);

return {
contextExternalTools,
};
};

it('should count the usages', async () => {
const { contextExternalTools } = setup();

await service.countBoardUsageForExternalTools(contextExternalTools);

expect(boardDoRepo.countBoardUsageForExternalTools).toHaveBeenCalledWith(contextExternalTools);
});

it('should return the amount of boards', async () => {
const { contextExternalTools } = setup();

const result: number = await service.countBoardUsageForExternalTools(contextExternalTools);

expect(result).toEqual(3);
});
});
});

describe('create', () => {
describe('when creating a content element of type', () => {
const setup = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ContextExternalTool } from '@modules/tool/context-external-tool/domain';
import { Injectable, NotFoundException } from '@nestjs/common';
import {
AnyBoardDo,
Expand Down Expand Up @@ -40,10 +41,18 @@ export class ContentElementService {
return parent;
}

async countBoardUsageForExternalTools(contextExternalTools: ContextExternalTool[]): Promise<number> {
const count: number = await this.boardDoRepo.countBoardUsageForExternalTools(contextExternalTools);

return count;
}

async create(parent: Card | SubmissionItem, type: ContentElementType): Promise<AnyContentElementDo> {
const element = this.contentElementFactory.build(type);
parent.addChild(element);

await this.boardDoRepo.save(parent.children, parent);

return element;
}

Expand Down
22 changes: 18 additions & 4 deletions apps/server/src/modules/tool/common/common-tool.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import { BoardModule } from '@modules/board';
import { LegacySchoolModule } from '@modules/legacy-school';
import { Module } from '@nestjs/common';
import { forwardRef, Module } from '@nestjs/common';
import { ContextExternalToolRepo, SchoolExternalToolRepo } from '@shared/repo';
import { LoggerModule } from '@src/core/logger';
import { CommonToolService, CommonToolValidationService } from './service';
import { CommonToolMetadataService } from './service/common-tool-metadata.service';

@Module({
imports: [LoggerModule, LegacySchoolModule],
imports: [LoggerModule, LegacySchoolModule, forwardRef(() => BoardModule)],
// TODO: make deletion of entities cascading, adjust ExternalToolService.deleteExternalTool and remove the repos from here
providers: [CommonToolService, CommonToolValidationService, SchoolExternalToolRepo, ContextExternalToolRepo],
exports: [CommonToolService, CommonToolValidationService, SchoolExternalToolRepo, ContextExternalToolRepo],
providers: [
CommonToolService,
CommonToolValidationService,
SchoolExternalToolRepo,
ContextExternalToolRepo,
CommonToolMetadataService,
],
exports: [
CommonToolService,
CommonToolValidationService,
SchoolExternalToolRepo,
ContextExternalToolRepo,
CommonToolMetadataService,
],
})
export class CommonToolModule {}
Loading
Loading