From cfaae4fc50c2d15ef3f47fbf12ca99d3ec6d4009 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 11 Sep 2023 19:30:30 +0200 Subject: [PATCH 001/186] Created empty version_control resource --- backend/src/version_control/version_control.module.ts | 0 backend/src/version_control/version_control.service.spec.ts | 0 backend/src/version_control/version_control.service.ts | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 backend/src/version_control/version_control.module.ts create mode 100644 backend/src/version_control/version_control.service.spec.ts create mode 100644 backend/src/version_control/version_control.service.ts diff --git a/backend/src/version_control/version_control.module.ts b/backend/src/version_control/version_control.module.ts new file mode 100644 index 00000000..e69de29b diff --git a/backend/src/version_control/version_control.service.spec.ts b/backend/src/version_control/version_control.service.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts new file mode 100644 index 00000000..e69de29b From 6df880a57bdb395921200c44e971e2afffca792b Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 12 Sep 2023 13:15:16 +0200 Subject: [PATCH 002/186] Updated file with boilerplate code --- .../version_control.service.spec.ts | 22 +++++++++++++++++++ .../version_control.service.ts | 7 ++++++ 2 files changed, 29 insertions(+) diff --git a/backend/src/version_control/version_control.service.spec.ts b/backend/src/version_control/version_control.service.spec.ts index e69de29b..1eac65a3 100644 --- a/backend/src/version_control/version_control.service.spec.ts +++ b/backend/src/version_control/version_control.service.spec.ts @@ -0,0 +1,22 @@ +import { + Test, + TestingModule, +} from '@nestjs/testing'; +import { VersionControlService } from './version_control.service'; + + +describe('ConversionService', () => { + let service: VersionControlService; + + beforeEach(async () => { + const module: TestingModule = + await Test.createTestingModule({ + providers: [VersionControlService], + }).compile(); + + service = module.get( + VersionControlService, + ); + }); + +}); \ No newline at end of file diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index e69de29b..c39f3998 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -0,0 +1,7 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class VersionControlService { + + +} From 8d9ee9e13373cd11d7841d8601e608c7a9ca5ff8 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 12 Sep 2023 13:15:39 +0200 Subject: [PATCH 003/186] Deleted module file for version_control service --- backend/src/version_control/version_control.module.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/src/version_control/version_control.module.ts diff --git a/backend/src/version_control/version_control.module.ts b/backend/src/version_control/version_control.module.ts deleted file mode 100644 index e69de29b..00000000 From afab34930e7edda8305b5e55d62c7cf366a13cb4 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 12 Sep 2023 16:26:42 +0200 Subject: [PATCH 004/186] Added snapshot array creation --- backend/src/s3/s3.service.ts | 69 ++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index 69d69e4d..8edf8a9c 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -22,6 +22,9 @@ export class S3Service { awsS3SecretAccessKey = process.env.AWS_S3_SECRET_ACCESS_KEY; + MAX_DIFFS = 10; + MAX_SNAPSHOTS = 5; + private readonly s3Client = new S3Client({ credentials: { accessKeyId: this.awsS3AccessKeyId, @@ -57,7 +60,6 @@ export class S3Service { console.log('Delete Error: ' + err); return undefined; } - return markdownFileDTO; } @@ -103,7 +105,8 @@ export class S3Service { return undefined; } - for (let i = 0; i < 10; i++) { + // Create diff objects + for (let i = 0; i < this.MAX_DIFFS; i++) { try { await this.s3Client.send( new PutObjectCommand({ @@ -114,12 +117,30 @@ export class S3Service { ); } catch (err) { console.log( - `S3 diff ${i} file creation error: ` + + `S3 diff ${i} object creation error: ` + err, ); return undefined; } } + + // Create snapshot objects + for (let j = 0; j < this.MAX_SNAPSHOTS; j++) { + try { + await this.s3Client.send( + new PutObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/snapshot/${j}`, + Body: new Uint8Array(Buffer.from('')), + }), + ); + } catch (err) { + console.log( + `S3 snapshot ${j} object creation error`, + ); + return undefined; + } + } markdownFileDTO.Content = ''; markdownFileDTO.Size = 0; return markdownFileDTO; @@ -222,6 +243,48 @@ export class S3Service { return markdownFileDTO; } + async deleteAllDiffs( + markdownFileDTO: MarkdownFileDTO, + ) { + const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; + for (let i = 0; i < this.MAX_DIFFS; i++) { + try { + // await fs.unlink(`./storage/${filePath}`); + /*const response = */ await this.s3Client.send( + new DeleteObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/diff/${i}`, + }), + ); + } catch (err) { + console.log('Delete all diffs error: ' + err); + return undefined; + } + } + } + + async deleteAllSnapshots( + markdownFileDTO: MarkdownFileDTO, + ) { + const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; + for (let i = 0; i < this.MAX_SNAPSHOTS; i++) { + try { + // await fs.unlink(`./storage/${filePath}`); + /*const response = */ await this.s3Client.send( + new DeleteObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/snapshot/${i}`, + }), + ); + } catch (err) { + console.log( + 'Delete all diffs error: ' + err, + ); + return undefined; + } + } + } + async createAsset(assetDTO: AssetDTO) { // Generate new AssetID const newAssetDTO = new AssetDTO(); From e0c7c21d58e857a180bdc055e442a1befa65dc0b Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 12 Sep 2023 16:28:38 +0200 Subject: [PATCH 005/186] Added calls to delete all diffs and snapshots --- .../src/file_manager/__mocks__/file_manager.service.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/file_manager/__mocks__/file_manager.service.ts b/backend/src/file_manager/__mocks__/file_manager.service.ts index bfdf62a9..abd1329c 100644 --- a/backend/src/file_manager/__mocks__/file_manager.service.ts +++ b/backend/src/file_manager/__mocks__/file_manager.service.ts @@ -233,6 +233,14 @@ export class FileManagerServiceMock { markdownFileDTO, ); + await this.s3service.deleteAllDiffs( + markdownFileDTO, + ); + + await this.s3service.deleteAllSnapshots( + markdownFileDTO, + ); + return this.markdownFilesService.remove( markdownFileDTO, ); From 1b3917eb623396538af784ef25cd2ed29356b763 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 12 Sep 2023 16:29:01 +0200 Subject: [PATCH 006/186] Laid out plan for getters and setters --- .../version_control/version_control.service.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index c39f3998..9b22cbf5 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -2,6 +2,19 @@ import { Injectable } from '@nestjs/common'; @Injectable() export class VersionControlService { + saveDiff() {} - + getDiff() {} + + getAllDiffs() {} + + //==----------------------------------------------------- + + createSnapshot() {} + + saveSnapshot() {} + + getSnapshot() {} + + getAllSnapshots() {} } From 772d3edb89ba43ad41ec116740668fc3dbe4fb80 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 12 Sep 2023 16:39:12 +0200 Subject: [PATCH 007/186] Updated error message --- backend/src/s3/s3.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index 8edf8a9c..301b8cbd 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -278,7 +278,7 @@ export class S3Service { ); } catch (err) { console.log( - 'Delete all diffs error: ' + err, + 'Delete all snapshots error: ' + err, ); return undefined; } From df79785f3d87c9605dec157e26ca3aaa7dbc88c8 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 12 Sep 2023 17:10:58 +0200 Subject: [PATCH 008/186] Added calls to delete all diffs and snapshots --- backend/src/file_manager/file_manager.service.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/src/file_manager/file_manager.service.ts b/backend/src/file_manager/file_manager.service.ts index 5d1699e3..f62457ee 100644 --- a/backend/src/file_manager/file_manager.service.ts +++ b/backend/src/file_manager/file_manager.service.ts @@ -257,10 +257,21 @@ export class FileManagerService { await this.s3ServiceMock.deleteFile( markdownFileDTO, ); + + // TODO: decide on a return value here, otherwise two calls to remove md file are made + // OR remove the mdservice.remove call from s3serviceMock.deleteFile } else { await this.s3service.deleteFile( markdownFileDTO, ); + + await this.s3service.deleteAllDiffs( + markdownFileDTO, + ); + + await this.s3service.deleteAllSnapshots( + markdownFileDTO, + ); } return this.markdownFilesService.remove( From fdd0b147e813c9492031418815dbc70958e17b37 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 12 Sep 2023 17:11:27 +0200 Subject: [PATCH 009/186] Removed debugging statements --- backend/src/s3/s3.service.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index 301b8cbd..c2501d8f 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -249,15 +249,16 @@ export class S3Service { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; for (let i = 0; i < this.MAX_DIFFS; i++) { try { - // await fs.unlink(`./storage/${filePath}`); - /*const response = */ await this.s3Client.send( + await this.s3Client.send( new DeleteObjectCommand({ Bucket: this.awsS3BucketName, Key: `${filePath}/diff/${i}`, }), ); } catch (err) { - console.log('Delete all diffs error: ' + err); + console.log( + 'Delete all diffs error: ' + err, + ); return undefined; } } @@ -269,8 +270,7 @@ export class S3Service { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; for (let i = 0; i < this.MAX_SNAPSHOTS; i++) { try { - // await fs.unlink(`./storage/${filePath}`); - /*const response = */ await this.s3Client.send( + await this.s3Client.send( new DeleteObjectCommand({ Bucket: this.awsS3BucketName, Key: `${filePath}/snapshot/${i}`, From 3a4e2b31f17337b216c0cd9b079b73581fe23ef2 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Fri, 15 Sep 2023 16:21:17 +0200 Subject: [PATCH 010/186] Added functions for finding logical order of circular array --- .../version_control.service.ts | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index 9b22cbf5..b832be5e 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -1,20 +1,48 @@ import { Injectable } from '@nestjs/common'; +import { DiffDTO } from './dto/diff.dto'; @Injectable() export class VersionControlService { - saveDiff() {} + saveDiff(diffDTO: DiffDTO) {} - getDiff() {} + getDiff(diffDTO: DiffDTO) {} getAllDiffs() {} //==----------------------------------------------------- - createSnapshot() {} - saveSnapshot() {} getSnapshot() {} getAllSnapshots() {} + + ///===---------------------------------------------------- + // Helpers + + getLogicalIndex( + idx: number, + head: number, + arr_len: number, + ): number { + return (idx - head + arr_len) % arr_len; + } + + reorderArray( + arr: number[], + head: number, + ): number[] { + const logicalOrder: number[] = new Array( + arr.length, + ).fill(0); + for (let idx = 0; idx < arr.length; idx++) { + const logicalIndex = this.getLogicalIndex( + idx, + head, + arr.length, + ); + logicalOrder[logicalIndex] = arr[idx]; + } + return logicalOrder; + } } From b1b9f328d08507bcd45d40f82f2565f7bccae65f Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Fri, 15 Sep 2023 16:26:43 +0200 Subject: [PATCH 011/186] Updated function name to be more descriptive --- backend/src/version_control/version_control.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index b832be5e..18874d9f 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -28,7 +28,7 @@ export class VersionControlService { return (idx - head + arr_len) % arr_len; } - reorderArray( + getLogicalOrder( arr: number[], head: number, ): number[] { From 8e6d3662fc6d2d59cd7af923a18f8011b1838d85 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Fri, 15 Sep 2023 16:54:26 +0200 Subject: [PATCH 012/186] Updated function calls to match new s3service names --- backend/src/file_manager/file_manager.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/file_manager/file_manager.service.ts b/backend/src/file_manager/file_manager.service.ts index f62457ee..37eab51e 100644 --- a/backend/src/file_manager/file_manager.service.ts +++ b/backend/src/file_manager/file_manager.service.ts @@ -265,11 +265,11 @@ export class FileManagerService { markdownFileDTO, ); - await this.s3service.deleteAllDiffs( + await this.s3service.deleteAllDiffsForFile( markdownFileDTO, ); - await this.s3service.deleteAllSnapshots( + await this.s3service.deleteAllSnapshotsForFile( markdownFileDTO, ); } From a71e61a17d9844af7e216b4d9fb10048eb7fb345 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Fri, 15 Sep 2023 16:55:06 +0200 Subject: [PATCH 013/186] Separated one function into two --- backend/src/s3/s3.service.ts | 90 +++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index c2501d8f..d43f6fbc 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -22,7 +22,7 @@ export class S3Service { awsS3SecretAccessKey = process.env.AWS_S3_SECRET_ACCESS_KEY; - MAX_DIFFS = 10; + MAX_DIFFS = 50; MAX_SNAPSHOTS = 5; private readonly s3Client = new S3Client({ @@ -105,42 +105,9 @@ export class S3Service { return undefined; } - // Create diff objects - for (let i = 0; i < this.MAX_DIFFS; i++) { - try { - await this.s3Client.send( - new PutObjectCommand({ - Bucket: this.awsS3BucketName, - Key: `${filePath}/diff/${i}`, - Body: new Uint8Array(Buffer.from('')), - }), - ); - } catch (err) { - console.log( - `S3 diff ${i} object creation error: ` + - err, - ); - return undefined; - } - } + this.createDiffsForFile(markdownFileDTO); + this.createSnapshotsForFile(markdownFileDTO); - // Create snapshot objects - for (let j = 0; j < this.MAX_SNAPSHOTS; j++) { - try { - await this.s3Client.send( - new PutObjectCommand({ - Bucket: this.awsS3BucketName, - Key: `${filePath}/snapshot/${j}`, - Body: new Uint8Array(Buffer.from('')), - }), - ); - } catch (err) { - console.log( - `S3 snapshot ${j} object creation error`, - ); - return undefined; - } - } markdownFileDTO.Content = ''; markdownFileDTO.Size = 0; return markdownFileDTO; @@ -243,7 +210,30 @@ export class S3Service { return markdownFileDTO; } - async deleteAllDiffs( + async createDiffsForFile( + markdownFileDTO: MarkdownFileDTO, + ) { + const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; + for (let i = 0; i < this.MAX_DIFFS; i++) { + try { + await this.s3Client.send( + new PutObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/diff/${i}`, + Body: new Uint8Array(Buffer.from('')), + }), + ); + } catch (err) { + console.log( + `S3 diff ${i} object creation error: ` + + err, + ); + return undefined; + } + } + } + + async deleteAllDiffsForFile( markdownFileDTO: MarkdownFileDTO, ) { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; @@ -264,7 +254,31 @@ export class S3Service { } } - async deleteAllSnapshots( + async createSnapshotsForFile( + markdownFileDTO: MarkdownFileDTO, + ) { + const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; + + // Create snapshot objects + for (let j = 0; j < this.MAX_SNAPSHOTS; j++) { + try { + await this.s3Client.send( + new PutObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/snapshot/${j}`, + Body: new Uint8Array(Buffer.from('')), + }), + ); + } catch (err) { + console.log( + `S3 snapshot ${j} object creation error`, + ); + return undefined; + } + } + } + + async deleteAllSnapshotsForFile( markdownFileDTO: MarkdownFileDTO, ) { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; From 924451a0b15ac31d621f45c60e2c431350fcf016 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Fri, 15 Sep 2023 16:55:33 +0200 Subject: [PATCH 014/186] Added conceptual skeletion of what controller will offer --- .../version_control.controller.ts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 backend/src/version_control/version_control.controller.ts diff --git a/backend/src/version_control/version_control.controller.ts b/backend/src/version_control/version_control.controller.ts new file mode 100644 index 00000000..5b1ba03a --- /dev/null +++ b/backend/src/version_control/version_control.controller.ts @@ -0,0 +1,36 @@ +import { + Body, + Controller, + Post, +} from '@nestjs/common'; +import { VersionControlService } from './version_control.service'; +import { DiffDTO } from './dto/diff.dto'; + +@Controller('version_control') +export class VersionControlController { + constructor( + private readonly versionControlService: VersionControlService, + ) {} + + @Post('save_diff') + saveDiff(@Body() diffDTO: DiffDTO) { + this.versionControlService.saveDiff(diffDTO); + } + + @Post('get_diff') + getDiff(@Body() diffDTO: DiffDTO) { + return this.versionControlService.getDiff( + diffDTO, + ); + } + + @Post('get_all_diffs') + getAllDiffs() { + return this.versionControlService.getAllDiffs(); + } + + @Post('save_snapshot') + saveSnapshot() { + this.versionControlService.saveSnapshot(); + } +} From 9411ed2cc07cf02c05909b350d629baa5b19572c Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Fri, 15 Sep 2023 16:55:57 +0200 Subject: [PATCH 015/186] Added docs for getAllSnapshots --- .../src/version_control/version_control.service.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index 18874d9f..131bfe3b 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -15,7 +15,19 @@ export class VersionControlService { getSnapshot() {} - getAllSnapshots() {} + /** + * @dev frontend calls retrieveOne for file opened by user + * @dev frontend needs to render all snapshots for the file + * as dropdown options + * + * @returns all snapshots for this file, in logical order + */ + getAllSnapshots() { + + // calls s3Service.getAllSnapshots() + // reorders snapshots in logical order + // return logically ordered snapshots + } ///===---------------------------------------------------- // Helpers From ad84e19741e12f5fc0bf8f8a85ee537e88fd88d0 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 06:18:35 +0200 Subject: [PATCH 016/186] Diff and Snapshot array getters --- frontend/src/app/services/version.control.service.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 6cf7787e..0fdb1618 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -42,6 +42,14 @@ export class VersionControlService { this.diffArr[0] = new DiffDTO(); } + getDiffArr(): DiffDTO[] { + return this.diffArr; + } + + getSnapshotArr(): SnapshotDTO[] { + return this.snapshotArr; + } + createDiff(fileDTO: FileDTO): DiffDTO { const latestSnapshot = this.getLatestSnapshot(); let snapshotContent = latestSnapshot.content; From d459414e90c6a5d47204b2d38b044ca32afb8021 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 06:19:43 +0200 Subject: [PATCH 017/186] Diff and Snapshot array setters --- frontend/src/app/services/version.control.service.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 0fdb1618..672aa93b 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -50,6 +50,16 @@ export class VersionControlService { return this.snapshotArr; } + setDiffArr(inArr: DiffDTO[]): DiffDTO[] { + this.diffArr = inArr; + return this.diffArr; + } + + setSnapshotArr(inArr: SnapshotDTO[]): SnapshotDTO[] { + this.snapshotArr = inArr; + return this.snapshotArr; + } + createDiff(fileDTO: FileDTO): DiffDTO { const latestSnapshot = this.getLatestSnapshot(); let snapshotContent = latestSnapshot.content; From 2e39213163c4febb706f63bc79f8265dc466611e Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 06:21:16 +0200 Subject: [PATCH 018/186] Push to Diff and Snapshot arrays --- .../app/services/version.control.service.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 672aa93b..f47faee5 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -46,20 +46,30 @@ export class VersionControlService { return this.diffArr; } - getSnapshotArr(): SnapshotDTO[] { - return this.snapshotArr; - } - setDiffArr(inArr: DiffDTO[]): DiffDTO[] { this.diffArr = inArr; return this.diffArr; } + pushToDiffArr(element: DiffDTO): DiffDTO[] { + this.diffArr.push(element); + return this.diffArr; + } + + getSnapshotArr(): SnapshotDTO[] { + return this.snapshotArr; + } + setSnapshotArr(inArr: SnapshotDTO[]): SnapshotDTO[] { this.snapshotArr = inArr; return this.snapshotArr; } + pushToSnapshotArr(element: SnapshotDTO): SnapshotDTO[] { + this.snapshotArr.push(element); + return this.snapshotArr; + } + createDiff(fileDTO: FileDTO): DiffDTO { const latestSnapshot = this.getLatestSnapshot(); let snapshotContent = latestSnapshot.content; From 6be1492e6fdd35e3e021380b699b07df38ac6818 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 06:29:09 +0200 Subject: [PATCH 019/186] MockData for testing created --- frontend/src/assets/MockData/VersionControl/abc123_d1 | 2 ++ frontend/src/assets/MockData/VersionControl/abc123_d2 | 3 +++ frontend/src/assets/MockData/VersionControl/abc123_d3 | 3 +++ frontend/src/assets/MockData/VersionControl/abc123_d4 | 3 +++ frontend/src/assets/MockData/VersionControl/abc123_s0 | 0 5 files changed, 11 insertions(+) create mode 100644 frontend/src/assets/MockData/VersionControl/abc123_d1 create mode 100644 frontend/src/assets/MockData/VersionControl/abc123_d2 create mode 100644 frontend/src/assets/MockData/VersionControl/abc123_d3 create mode 100644 frontend/src/assets/MockData/VersionControl/abc123_d4 create mode 100644 frontend/src/assets/MockData/VersionControl/abc123_s0 diff --git a/frontend/src/assets/MockData/VersionControl/abc123_d1 b/frontend/src/assets/MockData/VersionControl/abc123_d1 new file mode 100644 index 00000000..0ec105d5 --- /dev/null +++ b/frontend/src/assets/MockData/VersionControl/abc123_d1 @@ -0,0 +1,2 @@ +@@ -0,0 +1,67 @@ ++Hamlet: Do you see yonder cloud that's almost in shape of a camel?%0A \ No newline at end of file diff --git a/frontend/src/assets/MockData/VersionControl/abc123_d2 b/frontend/src/assets/MockData/VersionControl/abc123_d2 new file mode 100644 index 00000000..6d36f9af --- /dev/null +++ b/frontend/src/assets/MockData/VersionControl/abc123_d2 @@ -0,0 +1,3 @@ +@@ -59,8 +59,63 @@ + a camel? ++%0APolonius: By the mass, and 'tis like a camel, indeed.%0A \ No newline at end of file diff --git a/frontend/src/assets/MockData/VersionControl/abc123_d3 b/frontend/src/assets/MockData/VersionControl/abc123_d3 new file mode 100644 index 00000000..70f86249 --- /dev/null +++ b/frontend/src/assets/MockData/VersionControl/abc123_d3 @@ -0,0 +1,3 @@ +@@ -113,8 +113,47 @@ + indeed. ++%0AHamlet: Methinks it is like a weasel.%0A \ No newline at end of file diff --git a/frontend/src/assets/MockData/VersionControl/abc123_d4 b/frontend/src/assets/MockData/VersionControl/abc123_d4 new file mode 100644 index 00000000..a90a5003 --- /dev/null +++ b/frontend/src/assets/MockData/VersionControl/abc123_d4 @@ -0,0 +1,3 @@ +@@ -151,8 +151,115 @@ + weasel. ++%0APolonius: It is backed like a weasel.%0AHamlet: Or like a whale?%0APolonius: Very like a whale.%0A-- Shakespeare \ No newline at end of file diff --git a/frontend/src/assets/MockData/VersionControl/abc123_s0 b/frontend/src/assets/MockData/VersionControl/abc123_s0 new file mode 100644 index 00000000..e69de29b From 3e5034030f270430595e6856506da54b1ad18207 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 06:32:06 +0200 Subject: [PATCH 020/186] Hijacked login button for testing --- frontend/src/app/login/login.component.ts | 40 ++++++++++--------- .../app/services/version.control.service.ts | 1 + 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/frontend/src/app/login/login.component.ts b/frontend/src/app/login/login.component.ts index 68927572..26da70b5 100644 --- a/frontend/src/app/login/login.component.ts +++ b/frontend/src/app/login/login.component.ts @@ -6,6 +6,7 @@ import { MessageService } from 'primeng/api'; import { environment } from 'src/environments/environment'; import { CredentialResponse, PromptMomentNotification } from 'google-one-tap'; +import { VersionControlService } from '../services/version.control.service'; // import { HttpClient, HttpHeaders } from '@angular/common/http'; @@ -33,7 +34,8 @@ export class LoginComponent { private elementRef: ElementRef, private userService: UserService, @Inject(ActivatedRoute) private route: ActivatedRoute, - private messageService: MessageService + private messageService: MessageService, + private versionControlService: VersionControlService ) {} ngOnInit(): void { const data = history.state; @@ -93,23 +95,25 @@ export class LoginComponent { } async login(): Promise { - if (!this.email || this.email === '') { - this.messageService.add({ - severity: 'error', - summary: 'Error', - detail: `Email field empty`, - }); - } else if (!this.password || this.password === '') { - this.messageService.add({ - severity: 'error', - summary: 'Error', - detail: `Password field empty`, - }); - } else { - if (await this.userService.login(this.email, this.password)) { - this.navigateToPage('home'); - } - } + // if (!this.email || this.email === '') { + // this.messageService.add({ + // severity: 'error', + // summary: 'Error', + // detail: `Email field empty`, + // }); + // } else if (!this.password || this.password === '') { + // this.messageService.add({ + // severity: 'error', + // summary: 'Error', + // detail: `Password field empty`, + // }); + // } else { + // if (await this.userService.login(this.email, this.password)) { + // this.navigateToPage('home'); + // } + // } + + this.versionControlService.init(); } async autoLogin(): Promise { diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index f47faee5..acca0ed9 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -38,6 +38,7 @@ export class VersionControlService { // } init(): void { + // TODO: Un-hijack login this.snapshotArr[0] = new SnapshotDTO(); this.diffArr[0] = new DiffDTO(); } From 11f199c6b9e8c2524a42eab167c9abad78603c09 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 06:46:16 +0200 Subject: [PATCH 021/186] Initialising of MockData --- frontend/src/app/login/login.component.ts | 2 +- .../app/services/version.control.service.ts | 43 +++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/login/login.component.ts b/frontend/src/app/login/login.component.ts index 26da70b5..439f6b30 100644 --- a/frontend/src/app/login/login.component.ts +++ b/frontend/src/app/login/login.component.ts @@ -113,7 +113,7 @@ export class LoginComponent { // } // } - this.versionControlService.init(); + await this.versionControlService.init(); } async autoLogin(): Promise { diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index acca0ed9..456bec61 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -37,10 +37,47 @@ export class VersionControlService { // }); // } - init(): void { + async init(): Promise { // TODO: Un-hijack login - this.snapshotArr[0] = new SnapshotDTO(); - this.diffArr[0] = new DiffDTO(); + this.snapshotArr = []; + this.diffArr = []; + + let text1: string = ''; + let text2: string = ''; + const diffPathArr: string[] = []; + diffPathArr.push('../assets/MockData/VersionControl/abc123_d1'); + diffPathArr.push('../assets/MockData/VersionControl/abc123_d2'); + diffPathArr.push('../assets/MockData/VersionControl/abc123_d3'); + diffPathArr.push('../assets/MockData/VersionControl/abc123_d4'); + + const snapshotPathArr: string[] = []; + snapshotPathArr.push('../assets/MockData/VersionControl/abc123_s0'); + + for (let element of snapshotPathArr) { + this.http.get(element, { responseType: 'text' }).subscribe((data) => { + var tempDTO = new SnapshotDTO(); + tempDTO.fileID = 'abc123'; + tempDTO.snapshotNumber = +element.charAt(element.length - 1); + tempDTO.content = data; + this.snapshotArr.push(tempDTO); + }); + } + + for (let element of diffPathArr) { + this.http.get(element, { responseType: 'text' }).subscribe((data) => { + var tempDTO = new DiffDTO(); + tempDTO.fileID = 'abc123'; + tempDTO.snapshotNumber = +element.charAt(element.length - 1); + tempDTO.content = data; + this.diffArr.push(tempDTO); + }); + } + + await new Promise((f) => setTimeout(f, 10)); + + for (let element of this.diffArr) { + console.log(element); + } } getDiffArr(): DiffDTO[] { From 81d6f6c94876caf01faec045ac5f766e8d512f08 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 06:47:17 +0200 Subject: [PATCH 022/186] mini refactor to use setter --- frontend/src/app/services/version.control.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 456bec61..1b7fb990 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -59,7 +59,7 @@ export class VersionControlService { tempDTO.fileID = 'abc123'; tempDTO.snapshotNumber = +element.charAt(element.length - 1); tempDTO.content = data; - this.snapshotArr.push(tempDTO); + this.pushToSnapshotArr(tempDTO); }); } @@ -69,7 +69,7 @@ export class VersionControlService { tempDTO.fileID = 'abc123'; tempDTO.snapshotNumber = +element.charAt(element.length - 1); tempDTO.content = data; - this.diffArr.push(tempDTO); + this.pushToDiffArr(tempDTO); }); } From fe45386d741422db65410a6978399da8f313858d Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 06:54:58 +0200 Subject: [PATCH 023/186] Building version from snapshot --- frontend/src/app/services/dto/version.dto.ts | 13 +++++++++++++ .../src/app/services/version.control.service.ts | 12 ++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 frontend/src/app/services/dto/version.dto.ts diff --git a/frontend/src/app/services/dto/version.dto.ts b/frontend/src/app/services/dto/version.dto.ts new file mode 100644 index 00000000..7b2ba5aa --- /dev/null +++ b/frontend/src/app/services/dto/version.dto.ts @@ -0,0 +1,13 @@ +export class VersionDTO { + fileID: string; + diff: boolean; + content: string; + prevContent: string; + + constructor() { + this.fileID = ''; + this.diff = true; + this.content = ''; + this.prevContent = ''; + } +} diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 1b7fb990..6ddcace9 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -8,6 +8,7 @@ import { SnapshotDTO } from './dto/snapshot.dto'; import { FileDTO } from './dto/file.dto'; import { FileService } from './file.service'; +import { VersionDTO } from './dto/version.dto'; @Injectable({ providedIn: 'root', @@ -108,6 +109,17 @@ export class VersionControlService { return this.snapshotArr; } + buildSnapshotVersion(snapshot: SnapshotDTO): VersionDTO { + const tempDTO = new VersionDTO(); + + tempDTO.content = snapshot.content; + tempDTO.diff = false; + tempDTO.fileID = snapshot.fileID; + tempDTO.prevContent = ''; + + return tempDTO; + } + createDiff(fileDTO: FileDTO): DiffDTO { const latestSnapshot = this.getLatestSnapshot(); let snapshotContent = latestSnapshot.content; From d7f8082514429a36397c36b49a092f78fd8b160b Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 07:31:25 +0200 Subject: [PATCH 024/186] Building of diff version and context --- frontend/src/app/services/dto/version.dto.ts | 4 +- .../app/services/version.control.service.ts | 52 +++++++++++++++++-- .../assets/MockData/VersionControl/abc123_d1 | 4 +- .../assets/MockData/VersionControl/abc123_d2 | 4 +- .../assets/MockData/VersionControl/abc123_d3 | 4 +- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/frontend/src/app/services/dto/version.dto.ts b/frontend/src/app/services/dto/version.dto.ts index 7b2ba5aa..b6deb105 100644 --- a/frontend/src/app/services/dto/version.dto.ts +++ b/frontend/src/app/services/dto/version.dto.ts @@ -1,12 +1,12 @@ export class VersionDTO { fileID: string; - diff: boolean; + isDiff: boolean; content: string; prevContent: string; constructor() { this.fileID = ''; - this.diff = true; + this.isDiff = true; this.content = ''; this.prevContent = ''; } diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 6ddcace9..98d40ba4 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -18,6 +18,7 @@ export class VersionControlService { public snapshotArr: SnapshotDTO[] = []; public diffArr: DiffDTO[] = []; + public versionArr: VersionDTO[] = []; private DiffPatchService = new DiffMatchPatch(); // async test(): Promise { @@ -42,6 +43,7 @@ export class VersionControlService { // TODO: Un-hijack login this.snapshotArr = []; this.diffArr = []; + this.versionArr = []; let text1: string = ''; let text2: string = ''; @@ -68,7 +70,8 @@ export class VersionControlService { this.http.get(element, { responseType: 'text' }).subscribe((data) => { var tempDTO = new DiffDTO(); tempDTO.fileID = 'abc123'; - tempDTO.snapshotNumber = +element.charAt(element.length - 1); + tempDTO.diffNumber = +element.charAt(element.length - 1); + tempDTO.snapshotNumber = this.snapshotArr[0].snapshotNumber; tempDTO.content = data; this.pushToDiffArr(tempDTO); }); @@ -76,7 +79,15 @@ export class VersionControlService { await new Promise((f) => setTimeout(f, 10)); + for (let element of this.snapshotArr) { + this.versionArr.push(this.buildSnapshotVersion(element)); + } + for (let element of this.diffArr) { + this.versionArr.push(this.buildDiffVersion(element, this.snapshotArr[0])); + } + + for (let element of this.versionArr) { console.log(element); } } @@ -113,13 +124,44 @@ export class VersionControlService { const tempDTO = new VersionDTO(); tempDTO.content = snapshot.content; - tempDTO.diff = false; + tempDTO.isDiff = false; tempDTO.fileID = snapshot.fileID; tempDTO.prevContent = ''; return tempDTO; } + buildDiffVersion(diff: DiffDTO, snapshot: SnapshotDTO): VersionDTO { + const tempDTO = new VersionDTO(); + + tempDTO.content = diff.content; + tempDTO.isDiff = true; + tempDTO.fileID = diff.fileID; + tempDTO.prevContent = this.buildDiffContext(diff, snapshot); + + return tempDTO; + } + + buildDiffContext(diff: DiffDTO, snapshot: SnapshotDTO): string { + let retString = snapshot.content; + + const tempArr = this.diffArr.filter((ele) => { + return ele.diffNumber < diff.diffNumber; + }); + + tempArr.sort( + (a, b) => + a.diffNumber > b.diffNumber ? 1 : a.diffNumber < b.diffNumber ? -1 : 0 // Ascending sort on diffNumber + ); + + for (let element of tempArr) { + let patches = this.DiffPatchService.patch_fromText(element.content); + retString = this.DiffPatchService.patch_apply(patches, retString)[0]; + } + + return retString; + } + createDiff(fileDTO: FileDTO): DiffDTO { const latestSnapshot = this.getLatestSnapshot(); let snapshotContent = latestSnapshot.content; @@ -128,9 +170,9 @@ export class VersionControlService { const latestDiffNumber = latestDiff.diffNumber; // Get all relevant diffs - const relevantDiffs = this.diffArr.filter( - (a) => a.snapshotNumber === latestSnapshot.snapshotNumber - ); + const relevantDiffs = this.diffArr.filter((ele) => { + return ele.snapshotNumber === latestSnapshot.snapshotNumber; + }); // Patch all relevant diffs for (let diff of relevantDiffs) { diff --git a/frontend/src/assets/MockData/VersionControl/abc123_d1 b/frontend/src/assets/MockData/VersionControl/abc123_d1 index 0ec105d5..508c7604 100644 --- a/frontend/src/assets/MockData/VersionControl/abc123_d1 +++ b/frontend/src/assets/MockData/VersionControl/abc123_d1 @@ -1,2 +1,2 @@ -@@ -0,0 +1,67 @@ -+Hamlet: Do you see yonder cloud that's almost in shape of a camel?%0A \ No newline at end of file +@@ -0,0 +1,66 @@ ++Hamlet: Do you see yonder cloud that's almost in shape of a camel? \ No newline at end of file diff --git a/frontend/src/assets/MockData/VersionControl/abc123_d2 b/frontend/src/assets/MockData/VersionControl/abc123_d2 index 6d36f9af..7ba84a89 100644 --- a/frontend/src/assets/MockData/VersionControl/abc123_d2 +++ b/frontend/src/assets/MockData/VersionControl/abc123_d2 @@ -1,3 +1,3 @@ -@@ -59,8 +59,63 @@ +@@ -59,8 +59,62 @@ a camel? -+%0APolonius: By the mass, and 'tis like a camel, indeed.%0A \ No newline at end of file ++%0APolonius: By the mass, and 'tis like a camel, indeed. \ No newline at end of file diff --git a/frontend/src/assets/MockData/VersionControl/abc123_d3 b/frontend/src/assets/MockData/VersionControl/abc123_d3 index 70f86249..55f51240 100644 --- a/frontend/src/assets/MockData/VersionControl/abc123_d3 +++ b/frontend/src/assets/MockData/VersionControl/abc123_d3 @@ -1,3 +1,3 @@ -@@ -113,8 +113,47 @@ +@@ -113,8 +113,46 @@ indeed. -+%0AHamlet: Methinks it is like a weasel.%0A \ No newline at end of file ++%0AHamlet: Methinks it is like a weasel. \ No newline at end of file From 2288601a57ef5703549cb06ac70c3468aeb6c8e4 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 07:51:36 +0200 Subject: [PATCH 025/186] Visualise complete? --- .../app/services/version.control.service.ts | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 98d40ba4..1498aa7f 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -79,17 +79,7 @@ export class VersionControlService { await new Promise((f) => setTimeout(f, 10)); - for (let element of this.snapshotArr) { - this.versionArr.push(this.buildSnapshotVersion(element)); - } - - for (let element of this.diffArr) { - this.versionArr.push(this.buildDiffVersion(element, this.snapshotArr[0])); - } - - for (let element of this.versionArr) { - console.log(element); - } + this.visualise(); } getDiffArr(): DiffDTO[] { @@ -120,6 +110,37 @@ export class VersionControlService { return this.snapshotArr; } + visualise(): void { + // Build snapshot version + for (let element of this.snapshotArr) { + this.versionArr.push(this.buildSnapshotVersion(element)); + } + + // Build diff version + for (let element of this.diffArr) { + this.versionArr.push(this.buildDiffVersion(element, this.snapshotArr[0])); + } + + // Visualise snapshot + const snapshotVersions = this.versionArr.filter((ele) => { + return !ele.isDiff; + }); + console.log(snapshotVersions); + + //Visualise diff + const diffVersions = this.versionArr.filter((ele) => { + return ele.isDiff; + }); + + for (let element of diffVersions) { + let dpsDiff = this.DiffPatchService.diff_main( + element.prevContent, + element.content + ); + console.log(this.DiffPatchService.diff_prettyHtml(dpsDiff)); + } + } + buildSnapshotVersion(snapshot: SnapshotDTO): VersionDTO { const tempDTO = new VersionDTO(); @@ -134,11 +155,16 @@ export class VersionControlService { buildDiffVersion(diff: DiffDTO, snapshot: SnapshotDTO): VersionDTO { const tempDTO = new VersionDTO(); - tempDTO.content = diff.content; tempDTO.isDiff = true; tempDTO.fileID = diff.fileID; tempDTO.prevContent = this.buildDiffContext(diff, snapshot); + const patches = this.DiffPatchService.patch_fromText(diff.content); + tempDTO.content = this.DiffPatchService.patch_apply( + patches, + tempDTO.prevContent + )[0]; + return tempDTO; } From fc40ddccd6c9477047de7dca34ee042ec9dd3c78 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 07:54:22 +0200 Subject: [PATCH 026/186] Removed old functionality --- .../app/services/version.control.service.ts | 88 +------------------ 1 file changed, 1 insertion(+), 87 deletions(-) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 1498aa7f..0532a384 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -132,6 +132,7 @@ export class VersionControlService { return ele.isDiff; }); + // Could optimise by saving pretty html somewhere on save for (let element of diffVersions) { let dpsDiff = this.DiffPatchService.diff_main( element.prevContent, @@ -187,91 +188,4 @@ export class VersionControlService { return retString; } - - createDiff(fileDTO: FileDTO): DiffDTO { - const latestSnapshot = this.getLatestSnapshot(); - let snapshotContent = latestSnapshot.content; - - const latestDiff = this.getLatestDiff(); // TODO: Check what we need when there are no diffs - const latestDiffNumber = latestDiff.diffNumber; - - // Get all relevant diffs - const relevantDiffs = this.diffArr.filter((ele) => { - return ele.snapshotNumber === latestSnapshot.snapshotNumber; - }); - - // Patch all relevant diffs - for (let diff of relevantDiffs) { - snapshotContent = this.patchDiff(snapshotContent, diff); - } - - // Create newest diff and readable patch - const diff = this.DiffPatchService.diff_main( - snapshotContent, - fileDTO.content - ); - const patches = this.DiffPatchService.patch_make(diff); - - // Create and set new DTO - const readableDiff = new DiffDTO(); - readableDiff.diffNumber = latestDiffNumber + 1; - readableDiff.fileID = fileDTO.fileID; - readableDiff.snapshotNumber = latestSnapshot.snapshotNumber; // TODO: Doesn't take into account squashing of diffs - readableDiff.content = this.DiffPatchService.patch_toText(patches); - return readableDiff; - } - - getLatestSnapshot(): SnapshotDTO { - // TODO: No need to sort - // Get latest snapshot - this.snapshotArr.sort((a, b) => - a.snapshotNumber > b.snapshotNumber - ? 1 - : a.snapshotNumber < b.snapshotNumber - ? -1 - : 0 - ); - - return this.snapshotArr[0]; - } - - getLatestDiff(): DiffDTO { - // Get latest diff number - this.diffArr.sort((a, b) => - a.diffNumber > b.diffNumber ? 1 : a.diffNumber < b.diffNumber ? -1 : 0 - ); - - return this.diffArr[0]; - } - - patchDiff(content: string, diffDTO: DiffDTO): string { - const patches = this.DiffPatchService.patch_fromText(diffDTO.content); - const patchResult = this.DiffPatchService.patch_apply(patches, content); - return patchResult[0]; - } - - patchVersion(fileDTO: FileDTO, diffDTO: DiffDTO[]): string { - return ''; - } - - patchSnapshot(fileDTO: FileDTO, snapshotDTO: SnapshotDTO): string { - return ''; - } - - squashDiffs(diffDTOs: DiffDTO[]): SnapshotDTO { - const latestSnapshot = this.getLatestSnapshot(); - let snapshotContent = latestSnapshot.content; - - // Patch all diffs - for (let diff of diffDTOs) { - snapshotContent = this.patchDiff(snapshotContent, diff); - } - - const newSnapshot = new SnapshotDTO(); - newSnapshot.content = snapshotContent; - newSnapshot.fileID = latestSnapshot.fileID; - newSnapshot.snapshotNumber = latestSnapshot.snapshotNumber + 1; - - return newSnapshot; - } } From 58e40b90db7774ba306e0e9e8313d00d2ff33617 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 08:02:34 +0200 Subject: [PATCH 027/186] Modularised getting of a readable patch --- frontend/src/app/services/dto/file.dto.ts | 9 --------- frontend/src/app/services/version.control.service.ts | 10 ++++++++-- 2 files changed, 8 insertions(+), 11 deletions(-) delete mode 100644 frontend/src/app/services/dto/file.dto.ts diff --git a/frontend/src/app/services/dto/file.dto.ts b/frontend/src/app/services/dto/file.dto.ts deleted file mode 100644 index 2dbbdef9..00000000 --- a/frontend/src/app/services/dto/file.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class FileDTO { - fileID: string; - content: string; - - constructor() { - this.fileID = ''; - this.content = ''; - } -} diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 0532a384..c256bf10 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@angular/core'; import { UserService } from './user.service'; // import DiffMatchPatch from 'diff-match-patch'; -import { Diff, diff_match_patch as DiffMatchPatch } from 'diff-match-patch'; +import { diff_match_patch as DiffMatchPatch } from 'diff-match-patch'; import { HttpClient } from '@angular/common/http'; import { DiffDTO } from './dto/diff.dto'; import { SnapshotDTO } from './dto/snapshot.dto'; -import { FileDTO } from './dto/file.dto'; +import { MarkdownFileDTO } from './dto/markdown_file.dto'; import { FileService } from './file.service'; import { VersionDTO } from './dto/version.dto'; @@ -188,4 +188,10 @@ export class VersionControlService { return retString; } + + getReadablePatch(text1: string, text2: string): string { + const dpsDiff = this.DiffPatchService.diff_main(text1, text2); + const patches = this.DiffPatchService.patch_make(dpsDiff); + return this.DiffPatchService.patch_toText(patches); + } } From 3c4be2f3af7a64c76a632b7f710447d64898ce82 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 08:13:54 +0200 Subject: [PATCH 028/186] Modularised sorting --- .../app/services/version.control.service.ts | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index c256bf10..d457fece 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -176,10 +176,7 @@ export class VersionControlService { return ele.diffNumber < diff.diffNumber; }); - tempArr.sort( - (a, b) => - a.diffNumber > b.diffNumber ? 1 : a.diffNumber < b.diffNumber ? -1 : 0 // Ascending sort on diffNumber - ); + this.sortDiffArr(tempArr); for (let element of tempArr) { let patches = this.DiffPatchService.patch_fromText(element.content); @@ -194,4 +191,22 @@ export class VersionControlService { const patches = this.DiffPatchService.patch_make(dpsDiff); return this.DiffPatchService.patch_toText(patches); } + + sortSnapshotArr(inArr: SnapshotDTO[]): void { + // Ascending sort on snapshotNumber + inArr.sort((a, b) => + a.snapshotNumber > b.snapshotNumber + ? 1 + : a.snapshotNumber < b.snapshotNumber + ? -1 + : 0 + ); + } + + sortDiffArr(inArr: DiffDTO[]): void { + // Ascending sort on diffNumber + inArr.sort((a, b) => + a.diffNumber > b.diffNumber ? 1 : a.diffNumber < b.diffNumber ? -1 : 0 + ); + } } From 68de4fb764c2b894ef79881836e12a375665ecc8 Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 08:17:38 +0200 Subject: [PATCH 029/186] Theoretical restore functionality --- .../app/services/version.control.service.ts | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index d457fece..749d5138 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -86,11 +86,6 @@ export class VersionControlService { return this.diffArr; } - setDiffArr(inArr: DiffDTO[]): DiffDTO[] { - this.diffArr = inArr; - return this.diffArr; - } - pushToDiffArr(element: DiffDTO): DiffDTO[] { this.diffArr.push(element); return this.diffArr; @@ -100,16 +95,29 @@ export class VersionControlService { return this.snapshotArr; } - setSnapshotArr(inArr: SnapshotDTO[]): SnapshotDTO[] { - this.snapshotArr = inArr; - return this.snapshotArr; - } - pushToSnapshotArr(element: SnapshotDTO): SnapshotDTO[] { this.snapshotArr.push(element); return this.snapshotArr; } + sortSnapshotArr(inArr: SnapshotDTO[]): void { + // Ascending sort on snapshotNumber + inArr.sort((a, b) => + a.snapshotNumber > b.snapshotNumber + ? 1 + : a.snapshotNumber < b.snapshotNumber + ? -1 + : 0 + ); + } + + sortDiffArr(inArr: DiffDTO[]): void { + // Ascending sort on diffNumber + inArr.sort((a, b) => + a.diffNumber > b.diffNumber ? 1 : a.diffNumber < b.diffNumber ? -1 : 0 + ); + } + visualise(): void { // Build snapshot version for (let element of this.snapshotArr) { @@ -192,21 +200,29 @@ export class VersionControlService { return this.DiffPatchService.patch_toText(patches); } - sortSnapshotArr(inArr: SnapshotDTO[]): void { - // Ascending sort on snapshotNumber - inArr.sort((a, b) => - a.snapshotNumber > b.snapshotNumber - ? 1 - : a.snapshotNumber < b.snapshotNumber - ? -1 - : 0 - ); + snapshotRestore(snapshot: SnapshotDTO): void { + this.snapshotArr = this.snapshotArr.filter((ele) => { + return ele.snapshotNumber <= snapshot.snapshotNumber; + }); + + this.diffArr = this.diffArr.filter((ele) => { + return ele.snapshotNumber <= snapshot.snapshotNumber; + }); + + this.sortSnapshotArr(this.snapshotArr); + this.sortDiffArr(this.diffArr); } - sortDiffArr(inArr: DiffDTO[]): void { - // Ascending sort on diffNumber - inArr.sort((a, b) => - a.diffNumber > b.diffNumber ? 1 : a.diffNumber < b.diffNumber ? -1 : 0 - ); + diffRestore(diff: DiffDTO): void { + this.snapshotArr = this.snapshotArr.filter((ele) => { + return ele.snapshotNumber <= diff.snapshotNumber; + }); + + this.diffArr = this.diffArr.filter((ele) => { + return ele.snapshotNumber <= diff.snapshotNumber; + }); + + this.sortSnapshotArr(this.snapshotArr); + this.sortDiffArr(this.diffArr); } } From f6c84abbe1c5033bac0dfaf42c818db010829635 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 16:15:01 +0200 Subject: [PATCH 030/186] Created new diff dto --- backend/src/diffs/dto/diffs.dto.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 backend/src/diffs/dto/diffs.dto.ts diff --git a/backend/src/diffs/dto/diffs.dto.ts b/backend/src/diffs/dto/diffs.dto.ts new file mode 100644 index 00000000..b2d9edbb --- /dev/null +++ b/backend/src/diffs/dto/diffs.dto.ts @@ -0,0 +1,19 @@ +export class DiffDTO { + DiffID: string; + MarkdownID: string; + UserID: string; + DisplayID: number; + S3DiffID: number; + LastModified: Date; + Content: string; + + constructor() { + this.DiffID = undefined; + this.MarkdownID = undefined; + this.UserID = undefined; + this.DisplayID = undefined; + this.S3DiffID = undefined; + this.LastModified = undefined; + this.Content = undefined; + } +} \ No newline at end of file From f929a0e0ba92d8d6ecae17bd63166d0a7161e2a6 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 16:21:00 +0200 Subject: [PATCH 031/186] Updated names to new s3service naming scheme --- backend/src/file_manager/__mocks__/file_manager.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/file_manager/__mocks__/file_manager.service.ts b/backend/src/file_manager/__mocks__/file_manager.service.ts index abd1329c..6c5ae77d 100644 --- a/backend/src/file_manager/__mocks__/file_manager.service.ts +++ b/backend/src/file_manager/__mocks__/file_manager.service.ts @@ -233,11 +233,11 @@ export class FileManagerServiceMock { markdownFileDTO, ); - await this.s3service.deleteAllDiffs( + await this.s3service.deleteAllDiffsForFile( markdownFileDTO, ); - await this.s3service.deleteAllSnapshots( + await this.s3service.deleteAllSnapshotsForFile( markdownFileDTO, ); From 84c6d2b5df80ced2140a528d82f9146dea9402cf Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 16:21:31 +0200 Subject: [PATCH 032/186] Imported new diff dto --- backend/src/version_control/version_control.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index 131bfe3b..ee333719 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { DiffDTO } from './dto/diff.dto'; +import { DiffDTO } from 'src/diffs/dto/diffs.dto'; @Injectable() export class VersionControlService { From eb75bccfc3def209d8a1331a69fcf095b041c8ec Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 16:21:54 +0200 Subject: [PATCH 033/186] Imported new diff dto --- backend/src/version_control/version_control.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/version_control/version_control.controller.ts b/backend/src/version_control/version_control.controller.ts index 5b1ba03a..6e4ee679 100644 --- a/backend/src/version_control/version_control.controller.ts +++ b/backend/src/version_control/version_control.controller.ts @@ -4,7 +4,7 @@ import { Post, } from '@nestjs/common'; import { VersionControlService } from './version_control.service'; -import { DiffDTO } from './dto/diff.dto'; +import { DiffDTO } from 'src/diffs/dto/diffs.dto'; @Controller('version_control') export class VersionControlController { From c2aae464f122f10752c4a6ae5abe132d6df879fa Mon Sep 17 00:00:00 2001 From: Dylan Kapnias Date: Sat, 16 Sep 2023 16:26:16 +0200 Subject: [PATCH 034/186] Un-hijacked the login button --- frontend/src/app/login/login.component.ts | 38 +++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/frontend/src/app/login/login.component.ts b/frontend/src/app/login/login.component.ts index 439f6b30..f970d7b8 100644 --- a/frontend/src/app/login/login.component.ts +++ b/frontend/src/app/login/login.component.ts @@ -95,25 +95,25 @@ export class LoginComponent { } async login(): Promise { - // if (!this.email || this.email === '') { - // this.messageService.add({ - // severity: 'error', - // summary: 'Error', - // detail: `Email field empty`, - // }); - // } else if (!this.password || this.password === '') { - // this.messageService.add({ - // severity: 'error', - // summary: 'Error', - // detail: `Password field empty`, - // }); - // } else { - // if (await this.userService.login(this.email, this.password)) { - // this.navigateToPage('home'); - // } - // } - - await this.versionControlService.init(); + if (!this.email || this.email === '') { + this.messageService.add({ + severity: 'error', + summary: 'Error', + detail: `Email field empty`, + }); + } else if (!this.password || this.password === '') { + this.messageService.add({ + severity: 'error', + summary: 'Error', + detail: `Password field empty`, + }); + } else { + if (await this.userService.login(this.email, this.password)) { + this.navigateToPage('home'); + } + } + + // await this.versionControlService.init(); } async autoLogin(): Promise { From 5521d367f6c5ee6d6d317d510fb6c12d7632d211 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 18:09:31 +0200 Subject: [PATCH 035/186] Added functions for logical to s3 array conversion --- .../version_control.service.ts | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index ee333719..0ea481c1 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -1,20 +1,44 @@ import { Injectable } from '@nestjs/common'; +import { DiffsService } from 'src/diffs/diffs.service'; import { DiffDTO } from 'src/diffs/dto/diffs.dto'; +import { S3ServiceMock } from 'src/s3/__mocks__/s3.service'; +import { S3Service } from 'src/s3/s3.service'; @Injectable() export class VersionControlService { - saveDiff(diffDTO: DiffDTO) {} + constructor( + private diffService: DiffsService, + private s3service: S3Service, + private s3ServiceMock: S3ServiceMock, + ) {} + + ///===----------------------------------------------------- + + saveDiff(diffDTO: DiffDTO) { + // get nextDiffID + // calls s3Service.saveDiff() + // check if snapshot needs to be created + // update diff metadata in table + } + + ///===----------------------------------------------------- getDiff(diffDTO: DiffDTO) {} + ///===----------------------------------------------------- + getAllDiffs() {} - //==----------------------------------------------------- + ///===----------------------------------------------------- saveSnapshot() {} + ///===----------------------------------------------------- + getSnapshot() {} + ///===----------------------------------------------------- + /** * @dev frontend calls retrieveOne for file opened by user * @dev frontend needs to render all snapshots for the file @@ -23,7 +47,6 @@ export class VersionControlService { * @returns all snapshots for this file, in logical order */ getAllSnapshots() { - // calls s3Service.getAllSnapshots() // reorders snapshots in logical order // return logically ordered snapshots @@ -33,13 +56,27 @@ export class VersionControlService { // Helpers getLogicalIndex( - idx: number, + s3Index: number, head: number, arr_len: number, ): number { - return (idx - head + arr_len) % arr_len; + return (s3Index - head + arr_len) % arr_len; } + ///===----------------------------------------------------- + + getIndexInS3( + logicalIndex: number, + arr_len: number, + head: number, + ) { + return ( + (logicalIndex + head - arr_len) % arr_len + ); + } + + ///===----------------------------------------------------- + getLogicalOrder( arr: number[], head: number, From febabc0538da0a412b611012f86b05daa7e56f7a Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 19:22:00 +0200 Subject: [PATCH 036/186] Updated data type of UserID to number --- backend/src/diffs/dto/diffs.dto.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/diffs/dto/diffs.dto.ts b/backend/src/diffs/dto/diffs.dto.ts index b2d9edbb..10f2bd1e 100644 --- a/backend/src/diffs/dto/diffs.dto.ts +++ b/backend/src/diffs/dto/diffs.dto.ts @@ -1,7 +1,7 @@ export class DiffDTO { DiffID: string; MarkdownID: string; - UserID: string; + UserID: number; DisplayID: number; S3DiffID: number; LastModified: Date; @@ -16,4 +16,4 @@ export class DiffDTO { this.LastModified = undefined; this.Content = undefined; } -} \ No newline at end of file +} From fa0869d838ec0196387b2b75313977a073876c98 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 19:22:28 +0200 Subject: [PATCH 037/186] Updated UserID data type to number --- backend/src/diffs/entities/diffs.entity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/diffs/entities/diffs.entity.ts b/backend/src/diffs/entities/diffs.entity.ts index 274f9562..28f7e745 100644 --- a/backend/src/diffs/entities/diffs.entity.ts +++ b/backend/src/diffs/entities/diffs.entity.ts @@ -13,7 +13,7 @@ export class Diff { MarkdownID: string; @Column() - UserID: string; + UserID: number; @Column() DisplayID: string; From b734bf8fe2f18e6998dbd5e13a0ff4f247636d20 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 19:22:55 +0200 Subject: [PATCH 038/186] Updated names of function calls --- backend/src/file_manager/file_manager.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/file_manager/file_manager.service.ts b/backend/src/file_manager/file_manager.service.ts index 37eab51e..c49cf1e1 100644 --- a/backend/src/file_manager/file_manager.service.ts +++ b/backend/src/file_manager/file_manager.service.ts @@ -265,11 +265,11 @@ export class FileManagerService { markdownFileDTO, ); - await this.s3service.deleteAllDiffsForFile( + await this.s3service.deleteDiffObjectsForFile( markdownFileDTO, ); - await this.s3service.deleteAllSnapshotsForFile( + await this.s3service.deleteSnapshotObjectsForFile( markdownFileDTO, ); } From 9eb669b564d9d33f45c7aafbb36612dccb2b034a Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 19:24:27 +0200 Subject: [PATCH 039/186] Updated the names of function calls --- backend/src/file_manager/__mocks__/file_manager.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/file_manager/__mocks__/file_manager.service.ts b/backend/src/file_manager/__mocks__/file_manager.service.ts index 6c5ae77d..1a52d088 100644 --- a/backend/src/file_manager/__mocks__/file_manager.service.ts +++ b/backend/src/file_manager/__mocks__/file_manager.service.ts @@ -233,11 +233,11 @@ export class FileManagerServiceMock { markdownFileDTO, ); - await this.s3service.deleteAllDiffsForFile( + await this.s3service.deleteDiffObjectsForFile( markdownFileDTO, ); - await this.s3service.deleteAllSnapshotsForFile( + await this.s3service.deleteSnapshotObjectsForFile( markdownFileDTO, ); From add3ab1970872dec27fb198a3c750277d24a4ab9 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 19:24:47 +0200 Subject: [PATCH 040/186] Changed UserID data type to number --- backend/src/s3/s3.service.ts | 99 +++++++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 12 deletions(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index d43f6fbc..617273f6 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -10,6 +10,7 @@ import { import * as fs from 'fs/promises'; // for local storage import * as CryptoJS from 'crypto-js'; import { AssetDTO } from '../assets/dto/asset.dto'; +import { DiffDTO } from 'src/diffs/dto/diffs.dto'; @Injectable() export class S3Service { @@ -22,8 +23,7 @@ export class S3Service { awsS3SecretAccessKey = process.env.AWS_S3_SECRET_ACCESS_KEY; - MAX_DIFFS = 50; - MAX_SNAPSHOTS = 5; + ///===---------------------------------------------------- private readonly s3Client = new S3Client({ credentials: { @@ -33,6 +33,8 @@ export class S3Service { region: this.awsS3BucketRegion, }); + ///===---------------------------------------------------- + async deleteFile( markdownFileDTO: MarkdownFileDTO, ) { @@ -63,6 +65,8 @@ export class S3Service { return markdownFileDTO; } + ///===---------------------------------------------------- + async createFile( markdownFileDTO: MarkdownFileDTO, ) { @@ -105,14 +109,20 @@ export class S3Service { return undefined; } - this.createDiffsForFile(markdownFileDTO); - this.createSnapshotsForFile(markdownFileDTO); + this.createDiffObjectsForFile( + markdownFileDTO, + ); + this.createSnapshotObjectsForFile( + markdownFileDTO, + ); markdownFileDTO.Content = ''; markdownFileDTO.Size = 0; return markdownFileDTO; } + ///===---------------------------------------------------- + async saveFile( markdownFileDTO: MarkdownFileDTO, ) { @@ -168,6 +178,8 @@ export class S3Service { return markdownFileDTO; } + ///===---------------------------------------------------- + async retrieveFile( markdownFileDTO: MarkdownFileDTO, ) { @@ -210,11 +222,17 @@ export class S3Service { return markdownFileDTO; } - async createDiffsForFile( + ///===---------------------------------------------------- + + async createDiffObjectsForFile( markdownFileDTO: MarkdownFileDTO, ) { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; - for (let i = 0; i < this.MAX_DIFFS; i++) { + for ( + let i = 0; + i < parseInt(process.env.MAX_DIFFS); + i++ + ) { try { await this.s3Client.send( new PutObjectCommand({ @@ -233,11 +251,42 @@ export class S3Service { } } - async deleteAllDiffsForFile( + ///===---------------------------------------------------- + + async saveDiff(diffDTO: DiffDTO) { + const filePath = `${diffDTO.UserID}/${diffDTO.MarkdownID}`; + + try { + // await fs.writeFile( + // `./storage/${filePath}/diff/${diffDTO.S3DiffID}`, + // diffDTO.Content, + // 'utf-8', + // ); + /*const response = */ await this.s3Client.send( + new PutObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/diff/${diffDTO.S3DiffID}`, + Body: diffDTO.Content, + }), + ); + } catch (err) { + console.log('Write File Error: ' + err); + return undefined; + } + return diffDTO; + } + + ///===---------------------------------------------------- + + async deleteDiffObjectsForFile( markdownFileDTO: MarkdownFileDTO, ) { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; - for (let i = 0; i < this.MAX_DIFFS; i++) { + for ( + let i = 0; + i < parseInt(process.env.MAX_DIFFS); + i++ + ) { try { await this.s3Client.send( new DeleteObjectCommand({ @@ -254,13 +303,19 @@ export class S3Service { } } - async createSnapshotsForFile( + ///===---------------------------------------------------- + + async createSnapshotObjectsForFile( markdownFileDTO: MarkdownFileDTO, ) { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; // Create snapshot objects - for (let j = 0; j < this.MAX_SNAPSHOTS; j++) { + for ( + let j = 0; + j < parseInt(process.env.MAX_SNAPSHOTS); + j++ + ) { try { await this.s3Client.send( new PutObjectCommand({ @@ -278,11 +333,17 @@ export class S3Service { } } - async deleteAllSnapshotsForFile( + ///===---------------------------------------------------- + + async deleteSnapshotObjectsForFile( markdownFileDTO: MarkdownFileDTO, ) { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; - for (let i = 0; i < this.MAX_SNAPSHOTS; i++) { + for ( + let i = 0; + i < parseInt(process.env.SNAPSHOTS); + i++ + ) { try { await this.s3Client.send( new DeleteObjectCommand({ @@ -299,6 +360,8 @@ export class S3Service { } } + ///===---------------------------------------------------- + async createAsset(assetDTO: AssetDTO) { // Generate new AssetID const newAssetDTO = new AssetDTO(); @@ -328,6 +391,8 @@ export class S3Service { return newAssetDTO; } + ///===---------------------------------------------------- + async saveTextractResponse( saveAssetDTO: AssetDTO, textractResponse: any, @@ -376,6 +441,8 @@ export class S3Service { return saveAssetDTO; } + ///===---------------------------------------------------- + async saveImageAsset(saveAssetDTO: AssetDTO) { let filePath = `${saveAssetDTO.UserID}`; @@ -422,6 +489,8 @@ export class S3Service { return saveAssetDTO; } + ///===---------------------------------------------------- + async saveTextAssetImage( saveAssetDTO: AssetDTO, ) { @@ -470,6 +539,8 @@ export class S3Service { return saveAssetDTO; } + ///===---------------------------------------------------- + async retrieveAssetByID( assetID: string, userID: number, @@ -523,6 +594,8 @@ export class S3Service { } } + ///===---------------------------------------------------- + async retrieveAsset( retrieveAssetDTO: AssetDTO, ) { @@ -570,6 +643,8 @@ export class S3Service { return retrieveAssetDTO; } + ///===---------------------------------------------------- + async deleteAsset(assetDTO: AssetDTO) { console.log('Delete Asset (s3)'); let filePath = `${assetDTO.UserID}`; From fbc2029d0d0b0c340a26f12ff39723c1943a1d9e Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 19:25:20 +0200 Subject: [PATCH 041/186] Changed UserID data type to number --- backend/src/snapshots/entities/snapshots.entity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/snapshots/entities/snapshots.entity.ts b/backend/src/snapshots/entities/snapshots.entity.ts index 0b128556..ba45d58d 100644 --- a/backend/src/snapshots/entities/snapshots.entity.ts +++ b/backend/src/snapshots/entities/snapshots.entity.ts @@ -13,7 +13,7 @@ export class Snapshot { MarkdownID: string; @Column() - UserID: string; + UserID: number; @Column() DisplayID: string; From a89e52597e76c5a89d24907002865309866273b8 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sat, 16 Sep 2023 19:41:50 +0200 Subject: [PATCH 042/186] Added functions to get head diff/snapshot in array --- .../markdown_files/markdown_files.service.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/backend/src/markdown_files/markdown_files.service.ts b/backend/src/markdown_files/markdown_files.service.ts index 4de622da..b5075cd7 100644 --- a/backend/src/markdown_files/markdown_files.service.ts +++ b/backend/src/markdown_files/markdown_files.service.ts @@ -120,4 +120,24 @@ export class MarkdownFilesService { markdownToUpdate, ); } + + async getNextDiffID(markdownID: string) { + const markdownFile = + await this.markdownFileRepository.findOneBy( + { + MarkdownID: markdownID, + }, + ); + return markdownFile.NextDiffID; + } + + async getNextSnapshotID(markdownID: string) { + const markdownFile = + await this.markdownFileRepository.findOneBy( + { + MarkdownID: markdownID, + }, + ); + return markdownFile.NextSnapshotID; + } } From 3cced63ee6b64fa938eb493569bed06033796e39 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:01:15 +0200 Subject: [PATCH 043/186] Increased timeout for jest tests --- backend/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index 5ab21ba4..8707c867 100644 --- a/backend/package.json +++ b/backend/package.json @@ -103,6 +103,7 @@ "**/*.(t|j)s" ], "coverageDirectory": "../coverage", - "testEnvironment": "node" + "testEnvironment": "node", + "testTimeout": 30000 } } From 441f76530bf67b7be48c21acd713fb22a6cc78e3 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:10:34 +0200 Subject: [PATCH 044/186] Added function: updateDiff to update diff metadata --- backend/src/diffs/diffs.service.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backend/src/diffs/diffs.service.ts b/backend/src/diffs/diffs.service.ts index b6ccc3a5..e5ab6b88 100644 --- a/backend/src/diffs/diffs.service.ts +++ b/backend/src/diffs/diffs.service.ts @@ -9,4 +9,13 @@ export class DiffsService { @InjectRepository(Diff) private diffRepository: Repository, ) {} + + async updateDiff(nextDiffID: number) { + const diff = await this.diffRepository.findOne({ + where: { S3DiffID: nextDiffID }, + }); + + diff.LastModified = new Date(); + await this.diffRepository.save(diff); + } } From d897bec7accb98dc300439e0d44d83175cebbaf5 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:11:10 +0200 Subject: [PATCH 045/186] Removed redundant column from diff entity --- backend/src/diffs/entities/diffs.entity.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/diffs/entities/diffs.entity.ts b/backend/src/diffs/entities/diffs.entity.ts index 28f7e745..3d69ad46 100644 --- a/backend/src/diffs/entities/diffs.entity.ts +++ b/backend/src/diffs/entities/diffs.entity.ts @@ -15,9 +15,6 @@ export class Diff { @Column() UserID: number; - @Column() - DisplayID: string; - @Column() S3DiffID: number; From e71642fff74567f4ffb176ebd552bb51d8875ecd Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:11:34 +0200 Subject: [PATCH 046/186] Added function to increment head of circular array --- .../markdown_files/markdown_files.service.ts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/backend/src/markdown_files/markdown_files.service.ts b/backend/src/markdown_files/markdown_files.service.ts index b5075cd7..a69f0b3a 100644 --- a/backend/src/markdown_files/markdown_files.service.ts +++ b/backend/src/markdown_files/markdown_files.service.ts @@ -3,6 +3,7 @@ import { HttpStatus, Injectable, } from '@nestjs/common'; +import 'dotenv/config'; import { MarkdownFileDTO } from './dto/markdown_file.dto'; import { MarkdownFile } from './entities/markdown_file.entity'; import { InjectRepository } from '@nestjs/typeorm'; @@ -121,6 +122,8 @@ export class MarkdownFilesService { ); } + ///===---------------------------------------------------- + async getNextDiffID(markdownID: string) { const markdownFile = await this.markdownFileRepository.findOneBy( @@ -131,6 +134,8 @@ export class MarkdownFilesService { return markdownFile.NextDiffID; } + ///===---------------------------------------------------- + async getNextSnapshotID(markdownID: string) { const markdownFile = await this.markdownFileRepository.findOneBy( @@ -140,4 +145,40 @@ export class MarkdownFilesService { ); return markdownFile.NextSnapshotID; } + + ///===---------------------------------------------------- + + async incrementNextDiffID(markdownID: string) { + const markdownFile = + await this.markdownFileRepository.findOneBy( + { + MarkdownID: markdownID, + }, + ); + markdownFile.NextDiffID = + (markdownFile.NextDiffID + 1) % + parseInt(process.env.MAX_DIFFS); + return this.markdownFileRepository.save( + markdownFile, + ); + } + + ///===---------------------------------------------------- + + async incrementNextSnapshotID( + markdownID: string, + ) { + const markdownFile = + await this.markdownFileRepository.findOneBy( + { + MarkdownID: markdownID, + }, + ); + markdownFile.NextSnapshotID = + (markdownFile.NextSnapshotID + 1) % + parseInt(process.env.MAX_SNAPSHOTS); + return this.markdownFileRepository.save( + markdownFile, + ); + } } From 44dd81c75baf3860ed533d2ea525b629bfa94bce Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:12:04 +0200 Subject: [PATCH 047/186] Added function: getAllDiffsForSnapshot --- backend/src/s3/s3.service.ts | 88 ++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index 617273f6..1fa219ed 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -10,7 +10,8 @@ import { import * as fs from 'fs/promises'; // for local storage import * as CryptoJS from 'crypto-js'; import { AssetDTO } from '../assets/dto/asset.dto'; -import { DiffDTO } from 'src/diffs/dto/diffs.dto'; +import { DiffDTO } from '../diffs/dto/diffs.dto'; +import { SnapshotDTO } from '../snapshots/dto/snapshot.dto'; @Injectable() export class S3Service { @@ -253,19 +254,17 @@ export class S3Service { ///===---------------------------------------------------- - async saveDiff(diffDTO: DiffDTO) { + async saveDiff( + diffDTO: DiffDTO, + nextDiffID: number, + ) { const filePath = `${diffDTO.UserID}/${diffDTO.MarkdownID}`; try { - // await fs.writeFile( - // `./storage/${filePath}/diff/${diffDTO.S3DiffID}`, - // diffDTO.Content, - // 'utf-8', - // ); - /*const response = */ await this.s3Client.send( + await this.s3Client.send( new PutObjectCommand({ Bucket: this.awsS3BucketName, - Key: `${filePath}/diff/${diffDTO.S3DiffID}`, + Key: `${filePath}/diff/${nextDiffID}`, Body: diffDTO.Content, }), ); @@ -278,6 +277,54 @@ export class S3Service { ///===---------------------------------------------------- + /** + * @notes every snapshot is associated with n previous diffs. + * The IDs of the associated diffs do not change unless + * a change is made to the relevant versioning env variables. + */ + + async getAllDiffsForSnapshot( + snapshotDTO: SnapshotDTO, + ) { + const filePath = `${snapshotDTO.UserID}/${snapshotDTO.MarkdownID}`; + + let diffDTOs: DiffDTO[] = []; + + const firstDiffID = + snapshotDTO.S3SnapshotID * + parseInt(process.env.DIFFS_PER_SNAPSHOT); + + for ( + let j = firstDiffID; + j < + firstDiffID + + parseInt(process.env.DIFFS_PER_SNAPSHOT); + j++ + ) { + try { + const response = await this.s3Client.send( + new GetObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/diff/${j}`, + }), + ); + + const diffDTO = new DiffDTO(); + diffDTO.Content = + await response.Body.transformToString(); + diffDTOs.push(diffDTO); + } catch (err) { + console.log( + `S3 diff ${j} read error: ` + err, + ); + return undefined; + } + } + return diffDTOs; + } + + ///===---------------------------------------------------- + async deleteDiffObjectsForFile( markdownFileDTO: MarkdownFileDTO, ) { @@ -362,6 +409,29 @@ export class S3Service { ///===---------------------------------------------------- + async saveSnapshot( + snapshotDTO: SnapshotDTO, + nextSnapshotID: number, + ) { + const filePath = `${snapshotDTO.UserID}/${snapshotDTO.MarkdownID}`; + + try { + await this.s3Client.send( + new PutObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/snapshot/${nextSnapshotID}`, + Body: snapshotDTO.Content, + }), + ); + } catch (err) { + console.log('Write File Error: ' + err); + return undefined; + } + return snapshotDTO; + } + + ///===---------------------------------------------------- + async createAsset(assetDTO: AssetDTO) { // Generate new AssetID const newAssetDTO = new AssetDTO(); From 0e367ede5b9399a5e1b4b770cd6ca3f6b54d6956 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:12:17 +0200 Subject: [PATCH 048/186] Created dto for single snapshot --- backend/src/snapshots/dto/snapshot.dto.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 backend/src/snapshots/dto/snapshot.dto.ts diff --git a/backend/src/snapshots/dto/snapshot.dto.ts b/backend/src/snapshots/dto/snapshot.dto.ts new file mode 100644 index 00000000..1cb34e81 --- /dev/null +++ b/backend/src/snapshots/dto/snapshot.dto.ts @@ -0,0 +1,19 @@ +export class SnapshotDTO { + SnapshotID: string; + MarkdownID: string; + UserID: number; + DisplayID: number; + S3SnapshotID: number; + LastModified: Date; + Content: string; + + constructor() { + this.SnapshotID = undefined; + this.MarkdownID = undefined; + this.UserID = undefined; + this.DisplayID = undefined; + this.S3SnapshotID = undefined; + this.LastModified = undefined; + this.Content = undefined; + } +} \ No newline at end of file From e366dd4b5a606b5db3cce31ff6df9a05712aa6eb Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:12:32 +0200 Subject: [PATCH 049/186] Updated parameters of various functions --- .../version_control.controller.ts | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/backend/src/version_control/version_control.controller.ts b/backend/src/version_control/version_control.controller.ts index 6e4ee679..b4fda562 100644 --- a/backend/src/version_control/version_control.controller.ts +++ b/backend/src/version_control/version_control.controller.ts @@ -4,7 +4,8 @@ import { Post, } from '@nestjs/common'; import { VersionControlService } from './version_control.service'; -import { DiffDTO } from 'src/diffs/dto/diffs.dto'; +import { DiffDTO } from '../diffs/dto/diffs.dto'; +import { SnapshotDTO } from '../snapshots/dto/snapshot.dto'; @Controller('version_control') export class VersionControlController { @@ -12,11 +13,15 @@ export class VersionControlController { private readonly versionControlService: VersionControlService, ) {} + ///===---------------------------------------------------- + @Post('save_diff') saveDiff(@Body() diffDTO: DiffDTO) { this.versionControlService.saveDiff(diffDTO); } + ///===---------------------------------------------------- + @Post('get_diff') getDiff(@Body() diffDTO: DiffDTO) { return this.versionControlService.getDiff( @@ -24,13 +29,21 @@ export class VersionControlController { ); } + ///===---------------------------------------------------- + @Post('get_all_diffs') - getAllDiffs() { - return this.versionControlService.getAllDiffs(); + getAllDiffs(@Body() snapshotDTO: SnapshotDTO) { + return this.versionControlService.getAllDiffsForSnapshot( + snapshotDTO, + ); } + ///===---------------------------------------------------- + @Post('save_snapshot') - saveSnapshot() { - this.versionControlService.saveSnapshot(); + saveSnapshot(@Body() snapshotDTO: SnapshotDTO) { + this.versionControlService.saveSnapshot( + snapshotDTO, + ); } } From df54ba7b69bcb1a25f00fd5628d16d6766007c3d Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:13:01 +0200 Subject: [PATCH 050/186] Fixed repository dependency issues --- .../version_control.service.spec.ts | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/backend/src/version_control/version_control.service.spec.ts b/backend/src/version_control/version_control.service.spec.ts index 1eac65a3..119f6f42 100644 --- a/backend/src/version_control/version_control.service.spec.ts +++ b/backend/src/version_control/version_control.service.spec.ts @@ -3,20 +3,63 @@ import { TestingModule, } from '@nestjs/testing'; import { VersionControlService } from './version_control.service'; +import { DiffsService } from '../diffs/diffs.service'; +import { MarkdownFilesService } from '../markdown_files/markdown_files.service'; +import { S3Service } from '../s3/s3.service'; +import { S3ServiceMock } from '../s3/__mocks__/s3.service'; +import { getRepositoryToken } from '@nestjs/typeorm'; +import { Diff } from '../diffs/entities/diffs.entity'; +import { Repository } from 'typeorm'; +import { MarkdownFile } from '../markdown_files/entities/markdown_file.entity'; - -describe('ConversionService', () => { +describe('VersionControlService', () => { let service: VersionControlService; + let diffsService: DiffsService; + let markdownFilesService: MarkdownFilesService; + let s3Service: S3Service; + let s3ServiceMock: S3ServiceMock; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [VersionControlService], + providers: [ + VersionControlService, + DiffsService, + MarkdownFilesService, + S3Service, + S3ServiceMock, + { + provide: getRepositoryToken(Diff), + useClass: Repository, + }, + { + provide: + getRepositoryToken(MarkdownFile), + useClass: Repository, + }, + ], }).compile(); service = module.get( VersionControlService, ); + + diffsService = + module.get(DiffsService); + + markdownFilesService = + module.get( + MarkdownFilesService, + ); + + s3Service = module.get(S3Service); + + s3ServiceMock = module.get( + S3ServiceMock, + ); }); -}); \ No newline at end of file + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); From 591c28deb9f711a8d216ecddba29ac70ba510463 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Sun, 17 Sep 2023 21:13:21 +0200 Subject: [PATCH 051/186] Added logic to saveDiff/Snapshot functions --- .../version_control.service.ts | 64 +++++++++++++++---- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index 0ea481c1..66d13ccb 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -1,24 +1,45 @@ import { Injectable } from '@nestjs/common'; -import { DiffsService } from 'src/diffs/diffs.service'; -import { DiffDTO } from 'src/diffs/dto/diffs.dto'; -import { S3ServiceMock } from 'src/s3/__mocks__/s3.service'; -import { S3Service } from 'src/s3/s3.service'; +import { DiffsService } from '../diffs/diffs.service'; +import { DiffDTO } from '../diffs/dto/diffs.dto'; +import { MarkdownFilesService } from '../markdown_files/markdown_files.service'; +import { S3ServiceMock } from '../s3/__mocks__/s3.service'; +import { S3Service } from '../s3/s3.service'; +import { SnapshotDTO } from '../snapshots/dto/snapshot.dto'; @Injectable() export class VersionControlService { constructor( private diffService: DiffsService, - private s3service: S3Service, + private markdownFileService: MarkdownFilesService, + private s3Service: S3Service, private s3ServiceMock: S3ServiceMock, ) {} ///===----------------------------------------------------- - saveDiff(diffDTO: DiffDTO) { - // get nextDiffID - // calls s3Service.saveDiff() - // check if snapshot needs to be created - // update diff metadata in table + async saveDiff(diffDTO: DiffDTO) { + const nextDiffID = + await this.markdownFileService.getNextDiffID( + diffDTO.MarkdownID, + ); + + this.s3Service.saveDiff(diffDTO, nextDiffID); + + if ( + nextDiffID % + parseInt( + process.env.DIFFS_PER_SNAPSHOT, + ) === + 0 && + nextDiffID !== 0 + ) { + // create snapshot + } + + await this.diffService.updateDiff(nextDiffID); + await this.markdownFileService.incrementNextDiffID( + diffDTO.MarkdownID, + ); } ///===----------------------------------------------------- @@ -27,11 +48,30 @@ export class VersionControlService { ///===----------------------------------------------------- - getAllDiffs() {} + getAllDiffsForSnapshot( + snapshotDTO: SnapshotDTO, + ) {} ///===----------------------------------------------------- - saveSnapshot() {} + async saveSnapshot(snapshotDTO: SnapshotDTO) { + const nextSnapshotID = + await this.markdownFileService.getNextSnapshotID( + snapshotDTO.MarkdownID, + ); + + this.s3Service.saveSnapshot( + snapshotDTO, + nextSnapshotID, + ); + + await this.diffService.updateDiff( + nextSnapshotID, + ); + await this.markdownFileService.incrementNextDiffID( + snapshotDTO.MarkdownID, + ); + } ///===----------------------------------------------------- From a48964f64bef68ab39431946ca3da7a7097ff584 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:14:32 +0200 Subject: [PATCH 052/186] Solved dependency issues --- backend/src/app.module.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 9669ee9e..68a2691c 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -28,6 +28,10 @@ import { TextractService } from './textract/textract.service'; import { ResetPasswordModule } from './reset_password/reset_password.module'; import { ResetPasswordRequest } from './reset_password/entities/reset_password_request.entity'; import { MailService } from './mail/mail.service'; +import { DiffsService } from './diffs/diffs.service'; +import { SnapshotService } from './snapshots/snapshots.service'; +import { Diff } from './diffs/entities/diffs.entity'; +import { Snapshot } from './snapshots/entities/snapshots.entity'; @Module({ imports: [ @@ -41,6 +45,8 @@ import { MailService } from './mail/mail.service'; TypeOrmModule.forFeature([ ResetPasswordRequest, ]), + TypeOrmModule.forFeature([Diff]), + TypeOrmModule.forFeature([Snapshot]), MarkdownFilesModule, FoldersModule, S3Module, @@ -62,6 +68,8 @@ import { MailService } from './mail/mail.service'; ConversionService, TextractService, MailService, + DiffsService, + SnapshotService, ], }) export class AppModule {} From 0902137324465090e6195907c3b650b88c37ec8f Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:14:52 +0200 Subject: [PATCH 053/186] Added function: createDiffs in database --- backend/src/diffs/diffs.service.ts | 49 +++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/backend/src/diffs/diffs.service.ts b/backend/src/diffs/diffs.service.ts index e5ab6b88..1d6002d3 100644 --- a/backend/src/diffs/diffs.service.ts +++ b/backend/src/diffs/diffs.service.ts @@ -1,7 +1,10 @@ -import { Injectable } from "@nestjs/common"; -import { InjectRepository } from "@nestjs/typeorm"; -import { Repository } from "typeorm"; -import { Diff } from "./entities/diffs.entity"; +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Diff } from './entities/diffs.entity'; +import 'dotenv/config'; +import * as CryptoJS from 'crypto-js'; +import { MarkdownFileDTO } from '../markdown_files/dto/markdown_file.dto'; @Injectable() export class DiffsService { @@ -11,11 +14,43 @@ export class DiffsService { ) {} async updateDiff(nextDiffID: number) { - const diff = await this.diffRepository.findOne({ - where: { S3DiffID: nextDiffID }, - }); + const diff = + await this.diffRepository.findOne({ + where: { S3DiffID: nextDiffID }, + }); diff.LastModified = new Date(); await this.diffRepository.save(diff); } + + async createDiffs( + markdownFileDTO: MarkdownFileDTO, + ) { + const diffRecords = []; + for ( + let i = 0; + i < parseInt(process.env.MAX_DIFFS); + i++ + ) { + const diffID = CryptoJS.SHA256( + markdownFileDTO.UserID.toString() + + new Date().getTime().toString() + + i.toString(), + ).toString(); + + diffRecords.push({ + DiffID: diffID, + MarkdownID: markdownFileDTO.MarkdownID, + UserID: markdownFileDTO.UserID, + S3DiffID: i, + }); + } + await this.diffRepository.insert(diffRecords); + } + + async deleteDiffs(markdownFileDTO: MarkdownFileDTO) { + await this.diffRepository.delete({ + MarkdownID: markdownFileDTO.MarkdownID, + }); + } } From 9bb209361d30520740df88723786d59cd5e8ea60 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 14:15:06 +0200 Subject: [PATCH 054/186] Basic test for saving diffs --- frontend/src/app/edit/edit.component.ts | 14 +++- frontend/src/app/services/dto/diff.dto.ts | 18 +++--- .../app/services/version.control.service.ts | 64 ++++++++++++++----- 3 files changed, 70 insertions(+), 26 deletions(-) diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index 90966930..25e87331 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -15,6 +15,7 @@ import { DialogService } from 'primeng/dynamicdialog'; import { FileService } from '../services/file.service'; import { EditService } from '../services/edit.service'; import { AssetService } from '../services/asset.service'; +import { VersionControlService } from '../services/version.control.service'; import { Inject } from '@angular/core'; import { MessageService } from 'primeng/api'; import { set } from 'cypress/types/lodash'; @@ -44,6 +45,7 @@ export class EditComponent implements AfterViewInit, OnInit { noAssetsAvailable: boolean = false; isTouchScreen: boolean = false; sideBarTab: boolean = false; + prevVersion: string = ''; public editor: DecoupledEditor = {} as DecoupledEditor; public globalAreaReference!: HTMLElement; @@ -55,7 +57,8 @@ export class EditComponent implements AfterViewInit, OnInit { private editService: EditService, private assetService: AssetService, private clipboard: Clipboard, - private messageService: MessageService + private messageService: MessageService, + private versionControlService: VersionControlService ) {} @HostListener('window:beforeunload', ['$event']) @@ -84,7 +87,7 @@ export class EditComponent implements AfterViewInit, OnInit { } async ngOnInit(): Promise { - + this.prevVersion = this.editService.getContent() as string; this.speedDialItems = [ { icon: 'pi pi-pencil', @@ -249,6 +252,13 @@ export class EditComponent implements AfterViewInit, OnInit { saveDocumentContents() { // Save the document quill content to localStorage when changes occur // const editableArea: HTMLElement = this.elementRef.nativeElement.querySelector('.document-editor__editable'); + + console.log(this.prevVersion) + console.log(this.editor.getData()); + const diff = this.versionControlService.getReadablePatch(this.prevVersion as string, this.editor.getData()); + console.log(diff); + this.versionControlService.saveDiff(this.editService.getMarkdownID() as string,diff); + this.prevVersion = this.editor.getData(); let contents = this.editor.getData(); let pass = this.editService.getDocumentPassword(); if(pass != '' && pass != undefined) { diff --git a/frontend/src/app/services/dto/diff.dto.ts b/frontend/src/app/services/dto/diff.dto.ts index 416a110c..de2bd12c 100644 --- a/frontend/src/app/services/dto/diff.dto.ts +++ b/frontend/src/app/services/dto/diff.dto.ts @@ -1,13 +1,15 @@ export class DiffDTO { - fileID: string; - diffNumber: number; - snapshotNumber: number; - content: string; + UserID: string; + FileID: string; + DiffNumber: number; + SnapshotNumber: number; + Content: string; constructor() { - this.fileID = ''; - this.diffNumber = 0; - this.snapshotNumber = 0; - this.content = ''; + this.UserID = ''; + this.FileID = ''; + this.DiffNumber = 0; + this.SnapshotNumber = 0; + this.Content = ''; } } diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 749d5138..e907d7c7 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -2,19 +2,22 @@ import { Injectable } from '@angular/core'; import { UserService } from './user.service'; // import DiffMatchPatch from 'diff-match-patch'; import { diff_match_patch as DiffMatchPatch } from 'diff-match-patch'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; import { DiffDTO } from './dto/diff.dto'; import { SnapshotDTO } from './dto/snapshot.dto'; import { MarkdownFileDTO } from './dto/markdown_file.dto'; import { FileService } from './file.service'; import { VersionDTO } from './dto/version.dto'; +import { environment } from 'src/environments/environment'; @Injectable({ providedIn: 'root', }) export class VersionControlService { - constructor(private http: HttpClient, private fileService: FileService) {} + userService: any; + constructor(private http: HttpClient, private fileService: FileService) { } public snapshotArr: SnapshotDTO[] = []; public diffArr: DiffDTO[] = []; @@ -69,10 +72,10 @@ export class VersionControlService { for (let element of diffPathArr) { this.http.get(element, { responseType: 'text' }).subscribe((data) => { var tempDTO = new DiffDTO(); - tempDTO.fileID = 'abc123'; - tempDTO.diffNumber = +element.charAt(element.length - 1); - tempDTO.snapshotNumber = this.snapshotArr[0].snapshotNumber; - tempDTO.content = data; + tempDTO.FileID = 'abc123'; + tempDTO.DiffNumber = +element.charAt(element.length - 1); + tempDTO.SnapshotNumber = this.snapshotArr[0].snapshotNumber; + tempDTO.Content = data; this.pushToDiffArr(tempDTO); }); } @@ -106,15 +109,15 @@ export class VersionControlService { a.snapshotNumber > b.snapshotNumber ? 1 : a.snapshotNumber < b.snapshotNumber - ? -1 - : 0 + ? -1 + : 0 ); } sortDiffArr(inArr: DiffDTO[]): void { // Ascending sort on diffNumber inArr.sort((a, b) => - a.diffNumber > b.diffNumber ? 1 : a.diffNumber < b.diffNumber ? -1 : 0 + a.DiffNumber > b.DiffNumber ? 1 : a.DiffNumber < b.DiffNumber ? -1 : 0 ); } @@ -165,10 +168,10 @@ export class VersionControlService { const tempDTO = new VersionDTO(); tempDTO.isDiff = true; - tempDTO.fileID = diff.fileID; + tempDTO.fileID = diff.FileID; tempDTO.prevContent = this.buildDiffContext(diff, snapshot); - const patches = this.DiffPatchService.patch_fromText(diff.content); + const patches = this.DiffPatchService.patch_fromText(diff.Content); tempDTO.content = this.DiffPatchService.patch_apply( patches, tempDTO.prevContent @@ -181,13 +184,13 @@ export class VersionControlService { let retString = snapshot.content; const tempArr = this.diffArr.filter((ele) => { - return ele.diffNumber < diff.diffNumber; + return ele.DiffNumber < diff.DiffNumber; }); this.sortDiffArr(tempArr); for (let element of tempArr) { - let patches = this.DiffPatchService.patch_fromText(element.content); + let patches = this.DiffPatchService.patch_fromText(element.Content); retString = this.DiffPatchService.patch_apply(patches, retString)[0]; } @@ -206,7 +209,7 @@ export class VersionControlService { }); this.diffArr = this.diffArr.filter((ele) => { - return ele.snapshotNumber <= snapshot.snapshotNumber; + return ele.SnapshotNumber <= snapshot.snapshotNumber; }); this.sortSnapshotArr(this.snapshotArr); @@ -215,14 +218,43 @@ export class VersionControlService { diffRestore(diff: DiffDTO): void { this.snapshotArr = this.snapshotArr.filter((ele) => { - return ele.snapshotNumber <= diff.snapshotNumber; + return ele.snapshotNumber <= diff.SnapshotNumber; }); this.diffArr = this.diffArr.filter((ele) => { - return ele.snapshotNumber <= diff.snapshotNumber; + return ele.SnapshotNumber <= diff.SnapshotNumber; }); this.sortSnapshotArr(this.snapshotArr); this.sortDiffArr(this.diffArr); } + + saveDiff(fileID: string, content: string): Promise { + return new Promise((resolve, reject) => { + this.sendSaveDiff(fileID, content).subscribe({ + next: (response: HttpResponse) => { + if (response.status === 200) { + resolve(true); + } else { + resolve(false); + } + }, + }); + }); + } + + sendSaveDiff(fileId: string, content: string): Observable> { + const environmentURL = environment.apiURL; + const url = `${environmentURL}version_control/save_diff`; + const body = new DiffDTO(); + + body.UserID = this.userService.getUserID(); + body.Content = content; + body.FileID = fileId; + const headers = new HttpHeaders().set( + 'Authorization', + 'Bearer ' + this.userService.getAuthToken() + ); + return this.http.post(url, body, { headers, observe: 'response' }); + } } From bc0eff39569671ee3715a24ec658568fe316e8ee Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:15:06 +0200 Subject: [PATCH 055/186] Solved dependency issues --- backend/src/file_manager/file_manager.module.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/file_manager/file_manager.module.ts b/backend/src/file_manager/file_manager.module.ts index bca97939..eef6af36 100644 --- a/backend/src/file_manager/file_manager.module.ts +++ b/backend/src/file_manager/file_manager.module.ts @@ -15,6 +15,10 @@ import { S3ServiceMock } from '../s3/__mocks__/s3.service'; import { ResetPasswordService } from '../reset_password/reset_password.service'; import { ResetPasswordRequest } from '../reset_password/entities/reset_password_request.entity'; import { MailService } from '../mail/mail.service'; +import { DiffsService } from '../diffs/diffs.service'; +import { SnapshotService } from '../snapshots/snapshots.service'; +import { Diff } from '../diffs/entities/diffs.entity'; +import { Snapshot } from '../snapshots/entities/snapshots.entity'; @Module({ imports: [ @@ -24,6 +28,8 @@ import { MailService } from '../mail/mail.service'; TypeOrmModule.forFeature([ ResetPasswordRequest, ]), + TypeOrmModule.forFeature([Diff]), + TypeOrmModule.forFeature([Snapshot]), ], controllers: [FileManagerController], providers: [ @@ -37,6 +43,8 @@ import { MailService } from '../mail/mail.service'; S3ServiceMock, ResetPasswordService, MailService, + DiffsService, + SnapshotService, ], }) export class FileManagerModule {} From 8c6e52902cfb6b0eb47c4089a8987b35828f9702 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:15:27 +0200 Subject: [PATCH 056/186] Added calls to versioning functions --- .../src/file_manager/file_manager.service.ts | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/backend/src/file_manager/file_manager.service.ts b/backend/src/file_manager/file_manager.service.ts index c49cf1e1..44ca08d3 100644 --- a/backend/src/file_manager/file_manager.service.ts +++ b/backend/src/file_manager/file_manager.service.ts @@ -18,6 +18,8 @@ import { ExportDTO } from './dto/export.dto'; import * as CryptoJS from 'crypto-js'; import { ConversionService } from '../conversion/conversion.service'; import { ImportDTO } from './dto/import.dto'; +import { DiffsService } from '../diffs/diffs.service'; +import { SnapshotService } from '../snapshots/snapshots.service'; @Injectable() export class FileManagerService { @@ -28,14 +30,11 @@ export class FileManagerService { private conversionService: ConversionService, private userService: UsersService, private s3ServiceMock: S3ServiceMock, + private diffsService: DiffsService, + private snapshotService: SnapshotService, ) {} // File operations: ########################################################### - - // DB Requires the following fields to be initialised in the DTO: - // Path: string; .. TO PLACE THE FILE IN S3 - // Name: string; .. THE NEW NAME OF THE FILE - // Size: number; .. THE SIZE OF THE FILE IN MEGABYTES async createFile( markdownFileDTO: MarkdownFileDTO, isTest = false, @@ -78,13 +77,27 @@ export class FileManagerService { ); } + await this.s3service.createDiffObjectsForFile( + markdownFileDTO, + ); + + await this.s3service.createSnapshotObjectsForFile( + markdownFileDTO, + ); + + await this.diffsService.createDiffs( + markdownFileDTO, + ); + + await this.snapshotService.createSnapshots( + markdownFileDTO, + ); + return await this.markdownFilesService.create( markdownFileDTO, - ); // return the file to know ID; + ); } - // This function will need to return the latest diffs for - // the specified file (at most, 10 diffs) async retrieveFile( markdownFileDTO: MarkdownFileDTO, isTest = false, @@ -272,6 +285,14 @@ export class FileManagerService { await this.s3service.deleteSnapshotObjectsForFile( markdownFileDTO, ); + + await this.diffsService.deleteDiffs( + markdownFileDTO, + ); + + await this.snapshotService.deleteSnapshots( + markdownFileDTO, + ); } return this.markdownFilesService.remove( From 23bca5528b3b73ed2b592e82aad83fbbc25ed393 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:16:03 +0200 Subject: [PATCH 057/186] Added calls to versioning functions --- .../file_manager/__mocks__/file_manager.service.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/backend/src/file_manager/__mocks__/file_manager.service.ts b/backend/src/file_manager/__mocks__/file_manager.service.ts index 1a52d088..23268ab4 100644 --- a/backend/src/file_manager/__mocks__/file_manager.service.ts +++ b/backend/src/file_manager/__mocks__/file_manager.service.ts @@ -17,6 +17,8 @@ import { ExportDTO } from '../dto/export.dto'; import * as CryptoJS from 'crypto-js'; import { ConversionService } from '../../conversion/conversion.service'; import { ImportDTO } from '../dto/import.dto'; +import { DiffsService } from '../../diffs/diffs.service'; +import { SnapshotService } from '../../snapshots/snapshots.service'; @Injectable() export class FileManagerServiceMock { @@ -26,6 +28,8 @@ export class FileManagerServiceMock { private s3service: S3Service, private conversionService: ConversionService, private userService: UsersService, + private diffsService: DiffsService, + private snapshotService: SnapshotService, ) {} // File operations: ########################################################### @@ -241,6 +245,14 @@ export class FileManagerServiceMock { markdownFileDTO, ); + await this.diffsService.deleteDiffs( + markdownFileDTO, + ); + + await this.snapshotService.deleteSnapshots( + markdownFileDTO, + ); + return this.markdownFilesService.remove( markdownFileDTO, ); From 9c4c7c9435b59810439963ddf77b9e154d769437 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:16:32 +0200 Subject: [PATCH 058/186] Removed functions from createFile function --- backend/src/s3/s3.service.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index 1fa219ed..566d9faa 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -108,14 +108,7 @@ export class S3Service { 'S3 content file creation error: ' + err, ); return undefined; - } - - this.createDiffObjectsForFile( - markdownFileDTO, - ); - this.createSnapshotObjectsForFile( - markdownFileDTO, - ); + }; markdownFileDTO.Content = ''; markdownFileDTO.Size = 0; From a4a64081ad275677e2ed6c262c4f4f30e1af5f63 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:16:57 +0200 Subject: [PATCH 059/186] Added function createSnapshots to create refs in db --- backend/src/snapshots/snapshots.service.ts | 45 ++++++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/backend/src/snapshots/snapshots.service.ts b/backend/src/snapshots/snapshots.service.ts index f5841b30..64406dd6 100644 --- a/backend/src/snapshots/snapshots.service.ts +++ b/backend/src/snapshots/snapshots.service.ts @@ -1,7 +1,9 @@ -import { Injectable } from "@nestjs/common"; -import { InjectRepository } from "@nestjs/typeorm"; -import { Repository } from "typeorm"; -import { Snapshot } from "./entities/snapshots.entity"; +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Snapshot } from './entities/snapshots.entity'; +import { MarkdownFileDTO } from '../markdown_files/dto/markdown_file.dto'; +import * as CryptoJS from 'crypto-js'; @Injectable() export class SnapshotService { @@ -9,4 +11,39 @@ export class SnapshotService { @InjectRepository(Snapshot) private snapshotRepository: Repository, ) {} + + async createSnapshots( + markdownFileDTO: MarkdownFileDTO, + ) { + const snapshotRecords = []; + for ( + let i = 0; + i < parseInt(process.env.MAX_SNAPSHOTS); + i++ + ) { + const snapshotID = CryptoJS.SHA256( + markdownFileDTO.UserID.toString() + + new Date().getTime().toString() + + i.toString(), + ).toString(); + + snapshotRecords.push({ + SnapshotID: snapshotID, + MarkdownID: markdownFileDTO.MarkdownID, + UserID: markdownFileDTO.UserID, + S3SnapshotID: i, + }); + } + await this.snapshotRepository.insert( + snapshotRecords, + ); + } + + async deleteSnapshots( + markdownFileDTO: MarkdownFileDTO, + ) { + await this.snapshotRepository.delete({ + MarkdownID: markdownFileDTO.MarkdownID, + }); + } } From 48501eb6f1877d4f939565991d0b1ea502de558d Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:17:09 +0200 Subject: [PATCH 060/186] Removed redundant DisplayID field --- backend/src/snapshots/entities/snapshots.entity.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/snapshots/entities/snapshots.entity.ts b/backend/src/snapshots/entities/snapshots.entity.ts index ba45d58d..11f80275 100644 --- a/backend/src/snapshots/entities/snapshots.entity.ts +++ b/backend/src/snapshots/entities/snapshots.entity.ts @@ -15,9 +15,6 @@ export class Snapshot { @Column() UserID: number; - @Column() - DisplayID: string; - @Column() S3SnapshotID: number; From 9190d9a1a112af04da0291053d1b890049c85eac Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 14:25:06 +0200 Subject: [PATCH 061/186] Fixes to saving diff --- frontend/src/app/services/dto/diff.dto.ts | 4 ++-- frontend/src/app/services/version.control.service.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/services/dto/diff.dto.ts b/frontend/src/app/services/dto/diff.dto.ts index de2bd12c..3d584e22 100644 --- a/frontend/src/app/services/dto/diff.dto.ts +++ b/frontend/src/app/services/dto/diff.dto.ts @@ -1,12 +1,12 @@ export class DiffDTO { - UserID: string; + UserID: number; FileID: string; DiffNumber: number; SnapshotNumber: number; Content: string; constructor() { - this.UserID = ''; + this.UserID = 0; this.FileID = ''; this.DiffNumber = 0; this.SnapshotNumber = 0; diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index e907d7c7..c8614e01 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -16,8 +16,7 @@ import { environment } from 'src/environments/environment'; providedIn: 'root', }) export class VersionControlService { - userService: any; - constructor(private http: HttpClient, private fileService: FileService) { } + constructor(private http: HttpClient, private fileService: FileService, private userService: UserService) { } public snapshotArr: SnapshotDTO[] = []; public diffArr: DiffDTO[] = []; @@ -246,9 +245,10 @@ export class VersionControlService { sendSaveDiff(fileId: string, content: string): Observable> { const environmentURL = environment.apiURL; const url = `${environmentURL}version_control/save_diff`; + console.log(url); const body = new DiffDTO(); - body.UserID = this.userService.getUserID(); + body.UserID = this.userService.getUserID() as number; body.Content = content; body.FileID = fileId; const headers = new HttpHeaders().set( From a6bbcbd1815d304b572a65bca005a0b16db4b46f Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:39:18 +0200 Subject: [PATCH 062/186] Created module file for VersionControl --- .../version_control/version_control.module.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 backend/src/version_control/version_control.module.ts diff --git a/backend/src/version_control/version_control.module.ts b/backend/src/version_control/version_control.module.ts new file mode 100644 index 00000000..b66a72c2 --- /dev/null +++ b/backend/src/version_control/version_control.module.ts @@ -0,0 +1,30 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { DiffsService } from '../diffs/diffs.service'; +import { SnapshotService } from '../snapshots/snapshots.service'; +import { Diff } from '../diffs/entities/diffs.entity'; +import { Snapshot } from '../snapshots/entities/snapshots.entity'; +import { VersionControlController } from './version_control.controller'; +import { VersionControlService } from './version_control.service'; +import { MarkdownFilesService } from '../markdown_files/markdown_files.service'; +import { S3Service } from '../s3/s3.service'; +import { S3ServiceMock } from '../s3/__mocks__/s3.service'; +import { MarkdownFile } from '../markdown_files/entities/markdown_file.entity'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Diff]), + TypeOrmModule.forFeature([Snapshot]), + TypeOrmModule.forFeature([MarkdownFile]), + ], + controllers: [VersionControlController], + providers: [ + DiffsService, + SnapshotService, + VersionControlService, + MarkdownFilesService, + S3Service, + S3ServiceMock, + ], +}) +export class VersionControlModule {} From 7e660d75dd0a142ce01d9263ed7429a2e2d13ffa Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:39:40 +0200 Subject: [PATCH 063/186] Linked VersionControl endpoints --- backend/src/app.module.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 68a2691c..358b9e0f 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -32,6 +32,9 @@ import { DiffsService } from './diffs/diffs.service'; import { SnapshotService } from './snapshots/snapshots.service'; import { Diff } from './diffs/entities/diffs.entity'; import { Snapshot } from './snapshots/entities/snapshots.entity'; +import { VersionControlModule } from './version_control/version_control.module'; +import { VersionControlService } from './version_control/version_control.service'; +import { VersionControlController } from './version_control/version_control.controller'; @Module({ imports: [ @@ -52,12 +55,14 @@ import { Snapshot } from './snapshots/entities/snapshots.entity'; S3Module, FileManagerModule, AssetManagerModule, + VersionControlModule, ResetPasswordModule, ], controllers: [ AuthController, S3Controller, FileManagerController, + VersionControlController ], providers: [ FileManagerService, @@ -70,6 +75,7 @@ import { Snapshot } from './snapshots/entities/snapshots.entity'; MailService, DiffsService, SnapshotService, + VersionControlService, ], }) export class AppModule {} From 0677f4d39af12a7e525a0a034a79510cf1471223 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:59:09 +0200 Subject: [PATCH 064/186] Added debugging statements --- .../src/version_control/version_control.service.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index 66d13ccb..bda22efc 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -25,6 +25,10 @@ export class VersionControlService { this.s3Service.saveDiff(diffDTO, nextDiffID); + console.log( + '[versionControlService.saveDiff] Saved diff in s3', + ); + if ( nextDiffID % parseInt( @@ -37,9 +41,18 @@ export class VersionControlService { } await this.diffService.updateDiff(nextDiffID); + + console.log( + '[versionControlService.saveDiff] Updated diff in db', + ); + await this.markdownFileService.incrementNextDiffID( diffDTO.MarkdownID, ); + + console.log( + '[versionControlService.saveDiff] Incremented nextDiffID in db', + ); } ///===----------------------------------------------------- From 9dae74e9c11d9953126749f95b3b3475bcc3ae0e Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 14:59:19 +0200 Subject: [PATCH 065/186] Removed stale comment --- backend/src/file_manager/file_manager.service.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/file_manager/file_manager.service.ts b/backend/src/file_manager/file_manager.service.ts index 44ca08d3..216dc3a4 100644 --- a/backend/src/file_manager/file_manager.service.ts +++ b/backend/src/file_manager/file_manager.service.ts @@ -249,8 +249,6 @@ export class FileManagerService { ); } - // Assuming frontend will send the NextDiffID - return await this.markdownFilesService.updateAfterModification( markdownFileDTO, ); From ec2b3741b328229a22d0f8f309e2ea8df7c85ebc Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 15:31:40 +0200 Subject: [PATCH 066/186] Retrieve all snapshots --- frontend/src/app/edit/edit.component.ts | 5 +++- .../app/services/version.control.service.ts | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index 25e87331..1cb362e8 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -230,6 +230,7 @@ export class EditComponent implements AfterViewInit, OnInit { this.elementRef.nativeElement.ownerDocument.body.style.backgroundColor = '#E3E3E3'; this.elementRef.nativeElement.ownerDocument.body.style.overflow = 'hidden'; + this.refreshSidebarHistory(); this.refreshSidebar(); } @@ -495,7 +496,9 @@ export class EditComponent implements AfterViewInit, OnInit { } async refreshSidebarHistory() { - console.log('refreshing history'); + this.history = []; + this.history=await this.versionControlService.retrieveAllSnapshots(this.editService.getMarkdownID() as string); + } pageBreak() { diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index c8614e01..18652708 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -257,4 +257,32 @@ export class VersionControlService { ); return this.http.post(url, body, { headers, observe: 'response' }); } + + retrieveAllSnapshots(fileID: string): Promise { + return new Promise((resolve, reject) => { + this.sendRetrieveAllSnapshots(fileID).subscribe({ + next: (response: HttpResponse) => { + if (response.status === 200) { + resolve(response.body); + } else { + resolve(null); + } + }, + }); + }); + } + + sendRetrieveAllSnapshots(fileID: string): Observable> { + const environmentURL = environment.apiURL; + const url = `${environmentURL}version_control/get_all_snapshots`; + console.log(url); + const body = new SnapshotDTO(); + + body.fileID = fileID; + const headers = new HttpHeaders().set( + 'Authorization', + 'Bearer ' + this.userService.getAuthToken() + ); + return this.http.post(url, body, { headers, observe: 'response' }); + } } From 81a0493f5a7dad8c7c1336c95466aafdf8599796 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 15:41:05 +0200 Subject: [PATCH 067/186] Fixed snapshot dto --- frontend/src/app/services/dto/snapshot.dto.ts | 14 +++++----- .../app/services/version.control.service.ts | 27 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/frontend/src/app/services/dto/snapshot.dto.ts b/frontend/src/app/services/dto/snapshot.dto.ts index bd10d116..421d3b4c 100644 --- a/frontend/src/app/services/dto/snapshot.dto.ts +++ b/frontend/src/app/services/dto/snapshot.dto.ts @@ -1,11 +1,13 @@ export class SnapshotDTO { - fileID: string; - snapshotNumber: number; - content: string; + UserID: number; + FileID: string; + SnapshotNumber: number; + Content: string; constructor() { - this.fileID = ''; - this.snapshotNumber = 0; - this.content = ''; + this.UserID = 0; + this.FileID = ''; + this.SnapshotNumber = 0; + this.Content = ''; } } diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 18652708..ff761936 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -61,9 +61,9 @@ export class VersionControlService { for (let element of snapshotPathArr) { this.http.get(element, { responseType: 'text' }).subscribe((data) => { var tempDTO = new SnapshotDTO(); - tempDTO.fileID = 'abc123'; - tempDTO.snapshotNumber = +element.charAt(element.length - 1); - tempDTO.content = data; + tempDTO.FileID = 'abc123'; + tempDTO.SnapshotNumber = +element.charAt(element.length - 1); + tempDTO.Content = data; this.pushToSnapshotArr(tempDTO); }); } @@ -73,7 +73,7 @@ export class VersionControlService { var tempDTO = new DiffDTO(); tempDTO.FileID = 'abc123'; tempDTO.DiffNumber = +element.charAt(element.length - 1); - tempDTO.SnapshotNumber = this.snapshotArr[0].snapshotNumber; + tempDTO.SnapshotNumber = this.snapshotArr[0].SnapshotNumber; tempDTO.Content = data; this.pushToDiffArr(tempDTO); }); @@ -105,9 +105,9 @@ export class VersionControlService { sortSnapshotArr(inArr: SnapshotDTO[]): void { // Ascending sort on snapshotNumber inArr.sort((a, b) => - a.snapshotNumber > b.snapshotNumber + a.SnapshotNumber > b.SnapshotNumber ? 1 - : a.snapshotNumber < b.snapshotNumber + : a.SnapshotNumber < b.SnapshotNumber ? -1 : 0 ); @@ -155,9 +155,9 @@ export class VersionControlService { buildSnapshotVersion(snapshot: SnapshotDTO): VersionDTO { const tempDTO = new VersionDTO(); - tempDTO.content = snapshot.content; + tempDTO.content = snapshot.Content; tempDTO.isDiff = false; - tempDTO.fileID = snapshot.fileID; + tempDTO.fileID = snapshot.FileID; tempDTO.prevContent = ''; return tempDTO; @@ -180,7 +180,7 @@ export class VersionControlService { } buildDiffContext(diff: DiffDTO, snapshot: SnapshotDTO): string { - let retString = snapshot.content; + let retString = snapshot.Content; const tempArr = this.diffArr.filter((ele) => { return ele.DiffNumber < diff.DiffNumber; @@ -204,11 +204,11 @@ export class VersionControlService { snapshotRestore(snapshot: SnapshotDTO): void { this.snapshotArr = this.snapshotArr.filter((ele) => { - return ele.snapshotNumber <= snapshot.snapshotNumber; + return ele.SnapshotNumber <= snapshot.SnapshotNumber; }); this.diffArr = this.diffArr.filter((ele) => { - return ele.SnapshotNumber <= snapshot.snapshotNumber; + return ele.SnapshotNumber <= snapshot.SnapshotNumber; }); this.sortSnapshotArr(this.snapshotArr); @@ -217,7 +217,7 @@ export class VersionControlService { diffRestore(diff: DiffDTO): void { this.snapshotArr = this.snapshotArr.filter((ele) => { - return ele.snapshotNumber <= diff.SnapshotNumber; + return ele.SnapshotNumber <= diff.SnapshotNumber; }); this.diffArr = this.diffArr.filter((ele) => { @@ -278,7 +278,8 @@ export class VersionControlService { console.log(url); const body = new SnapshotDTO(); - body.fileID = fileID; + body.UserID = this.userService.getUserID() as number; + body.FileID = fileID; const headers = new HttpHeaders().set( 'Authorization', 'Bearer ' + this.userService.getAuthToken() From 871a5c6e9751ec216e947cf9cd76ffaa75473e6a Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 16:51:33 +0200 Subject: [PATCH 068/186] FileID refactored to markdownID --- frontend/src/app/services/dto/diff.dto.ts | 4 ++-- frontend/src/app/services/dto/snapshot.dto.ts | 4 ++-- .../app/services/version.control.service.ts | 20 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/services/dto/diff.dto.ts b/frontend/src/app/services/dto/diff.dto.ts index 3d584e22..f2ab2948 100644 --- a/frontend/src/app/services/dto/diff.dto.ts +++ b/frontend/src/app/services/dto/diff.dto.ts @@ -1,13 +1,13 @@ export class DiffDTO { UserID: number; - FileID: string; + MarkdownID: string; DiffNumber: number; SnapshotNumber: number; Content: string; constructor() { this.UserID = 0; - this.FileID = ''; + this.MarkdownID = ''; this.DiffNumber = 0; this.SnapshotNumber = 0; this.Content = ''; diff --git a/frontend/src/app/services/dto/snapshot.dto.ts b/frontend/src/app/services/dto/snapshot.dto.ts index 421d3b4c..49eca70b 100644 --- a/frontend/src/app/services/dto/snapshot.dto.ts +++ b/frontend/src/app/services/dto/snapshot.dto.ts @@ -1,12 +1,12 @@ export class SnapshotDTO { UserID: number; - FileID: string; + MarkdownID: string; SnapshotNumber: number; Content: string; constructor() { this.UserID = 0; - this.FileID = ''; + this.MarkdownID = ''; this.SnapshotNumber = 0; this.Content = ''; } diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index ff761936..70558e04 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -61,7 +61,7 @@ export class VersionControlService { for (let element of snapshotPathArr) { this.http.get(element, { responseType: 'text' }).subscribe((data) => { var tempDTO = new SnapshotDTO(); - tempDTO.FileID = 'abc123'; + tempDTO.MarkdownID = 'abc123'; tempDTO.SnapshotNumber = +element.charAt(element.length - 1); tempDTO.Content = data; this.pushToSnapshotArr(tempDTO); @@ -71,7 +71,7 @@ export class VersionControlService { for (let element of diffPathArr) { this.http.get(element, { responseType: 'text' }).subscribe((data) => { var tempDTO = new DiffDTO(); - tempDTO.FileID = 'abc123'; + tempDTO.MarkdownID = 'abc123'; tempDTO.DiffNumber = +element.charAt(element.length - 1); tempDTO.SnapshotNumber = this.snapshotArr[0].SnapshotNumber; tempDTO.Content = data; @@ -157,7 +157,7 @@ export class VersionControlService { tempDTO.content = snapshot.Content; tempDTO.isDiff = false; - tempDTO.fileID = snapshot.FileID; + tempDTO.fileID = snapshot.MarkdownID; tempDTO.prevContent = ''; return tempDTO; @@ -167,7 +167,7 @@ export class VersionControlService { const tempDTO = new VersionDTO(); tempDTO.isDiff = true; - tempDTO.fileID = diff.FileID; + tempDTO.fileID = diff.MarkdownID; tempDTO.prevContent = this.buildDiffContext(diff, snapshot); const patches = this.DiffPatchService.patch_fromText(diff.Content); @@ -242,7 +242,7 @@ export class VersionControlService { }); } - sendSaveDiff(fileId: string, content: string): Observable> { + sendSaveDiff(markdownID: string, content: string): Observable> { const environmentURL = environment.apiURL; const url = `${environmentURL}version_control/save_diff`; console.log(url); @@ -250,7 +250,7 @@ export class VersionControlService { body.UserID = this.userService.getUserID() as number; body.Content = content; - body.FileID = fileId; + body.MarkdownID = markdownID; const headers = new HttpHeaders().set( 'Authorization', 'Bearer ' + this.userService.getAuthToken() @@ -258,9 +258,9 @@ export class VersionControlService { return this.http.post(url, body, { headers, observe: 'response' }); } - retrieveAllSnapshots(fileID: string): Promise { + retrieveAllSnapshots(markdownID: string): Promise { return new Promise((resolve, reject) => { - this.sendRetrieveAllSnapshots(fileID).subscribe({ + this.sendRetrieveAllSnapshots(markdownID).subscribe({ next: (response: HttpResponse) => { if (response.status === 200) { resolve(response.body); @@ -272,14 +272,14 @@ export class VersionControlService { }); } - sendRetrieveAllSnapshots(fileID: string): Observable> { + sendRetrieveAllSnapshots(markdownID: string): Observable> { const environmentURL = environment.apiURL; const url = `${environmentURL}version_control/get_all_snapshots`; console.log(url); const body = new SnapshotDTO(); body.UserID = this.userService.getUserID() as number; - body.FileID = fileID; + body.MarkdownID = markdownID; const headers = new HttpHeaders().set( 'Authorization', 'Bearer ' + this.userService.getAuthToken() From 445c3e1acdf48a4d7e6b6eb219f69442607fe956 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 16:56:55 +0200 Subject: [PATCH 069/186] Updated nomenclature --- frontend/src/app/services/dto/version.dto.ts | 16 ++++++------ .../app/services/version.control.service.ts | 26 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/frontend/src/app/services/dto/version.dto.ts b/frontend/src/app/services/dto/version.dto.ts index b6deb105..4cb051cf 100644 --- a/frontend/src/app/services/dto/version.dto.ts +++ b/frontend/src/app/services/dto/version.dto.ts @@ -1,13 +1,13 @@ export class VersionDTO { - fileID: string; - isDiff: boolean; - content: string; - prevContent: string; + MarkdownID: string; + IsDiff: boolean; + Content: string; + PrevContent: string; constructor() { - this.fileID = ''; - this.isDiff = true; - this.content = ''; - this.prevContent = ''; + this.MarkdownID = ''; + this.IsDiff = true; + this.Content = ''; + this.PrevContent = ''; } } diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index 70558e04..cdf28c60 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -133,20 +133,20 @@ export class VersionControlService { // Visualise snapshot const snapshotVersions = this.versionArr.filter((ele) => { - return !ele.isDiff; + return !ele.IsDiff; }); console.log(snapshotVersions); //Visualise diff const diffVersions = this.versionArr.filter((ele) => { - return ele.isDiff; + return ele.IsDiff; }); // Could optimise by saving pretty html somewhere on save for (let element of diffVersions) { let dpsDiff = this.DiffPatchService.diff_main( - element.prevContent, - element.content + element.PrevContent, + element.Content ); console.log(this.DiffPatchService.diff_prettyHtml(dpsDiff)); } @@ -155,10 +155,10 @@ export class VersionControlService { buildSnapshotVersion(snapshot: SnapshotDTO): VersionDTO { const tempDTO = new VersionDTO(); - tempDTO.content = snapshot.Content; - tempDTO.isDiff = false; - tempDTO.fileID = snapshot.MarkdownID; - tempDTO.prevContent = ''; + tempDTO.Content = snapshot.Content; + tempDTO.IsDiff = false; + tempDTO.MarkdownID = snapshot.MarkdownID; + tempDTO.PrevContent = ''; return tempDTO; } @@ -166,14 +166,14 @@ export class VersionControlService { buildDiffVersion(diff: DiffDTO, snapshot: SnapshotDTO): VersionDTO { const tempDTO = new VersionDTO(); - tempDTO.isDiff = true; - tempDTO.fileID = diff.MarkdownID; - tempDTO.prevContent = this.buildDiffContext(diff, snapshot); + tempDTO.IsDiff = true; + tempDTO.MarkdownID = diff.MarkdownID; + tempDTO.PrevContent = this.buildDiffContext(diff, snapshot); const patches = this.DiffPatchService.patch_fromText(diff.Content); - tempDTO.content = this.DiffPatchService.patch_apply( + tempDTO.Content = this.DiffPatchService.patch_apply( patches, - tempDTO.prevContent + tempDTO.PrevContent )[0]; return tempDTO; From a04062bb57ca23dc7c620da48aeaafbdafd3fc9b Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 17:00:36 +0200 Subject: [PATCH 070/186] Logging response from retrieve all snapshots --- frontend/src/app/services/version.control.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index cdf28c60..a5961393 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -262,6 +262,7 @@ export class VersionControlService { return new Promise((resolve, reject) => { this.sendRetrieveAllSnapshots(markdownID).subscribe({ next: (response: HttpResponse) => { + console.log(response); if (response.status === 200) { resolve(response.body); } else { From 95d9c1fa8034c22cc6254d083e84a94640fd56ce Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 17:35:53 +0200 Subject: [PATCH 071/186] Created version_history dto --- .../src/version_control/dto/version_history.dto.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 backend/src/version_control/dto/version_history.dto.ts diff --git a/backend/src/version_control/dto/version_history.dto.ts b/backend/src/version_control/dto/version_history.dto.ts new file mode 100644 index 00000000..70d728d8 --- /dev/null +++ b/backend/src/version_control/dto/version_history.dto.ts @@ -0,0 +1,12 @@ +import { DiffDTO } from '../../diffs/dto/diffs.dto'; +import { SnapshotDTO } from '../../snapshots/dto/snapshot.dto'; + +export class VersionHistoryDTO { + DiffHistory: DiffDTO[]; + SnapshotHistory: SnapshotDTO[]; + + constructor() { + this.DiffHistory = undefined; + this.SnapshotHistory = undefined; + } +} From c3c5d9a966db9ac880aa7ad391fdecb7636a4e1d Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 17:41:52 +0200 Subject: [PATCH 072/186] Refactored obj naming --- frontend/src/app/edit/edit.component.html | 4 ++-- frontend/src/app/edit/edit.component.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/edit/edit.component.html b/frontend/src/app/edit/edit.component.html index ea3901c6..921fea19 100644 --- a/frontend/src/app/edit/edit.component.html +++ b/frontend/src/app/edit/edit.component.html @@ -248,8 +248,8 @@

History

-

{{obj.name}}

-

{{obj.date}}

+

{{obj.Name}}

+

{{obj.DateCreated}}

diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index 1cb362e8..8236017a 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -498,7 +498,7 @@ export class EditComponent implements AfterViewInit, OnInit { async refreshSidebarHistory() { this.history = []; this.history=await this.versionControlService.retrieveAllSnapshots(this.editService.getMarkdownID() as string); - + } pageBreak() { @@ -606,13 +606,13 @@ export class EditComponent implements AfterViewInit, OnInit { insertContent(obj: any) { this.deselectAllHistory(); obj.isCurrent = true; - if(obj.id === 'LATEST') { + if(obj.SnapshotID === 'LATEST') { this.disableReadOnly(); - this.editor.setData(obj.html); + this.editor.setData(obj.Content); return; } this.enableReadOnly(); - this.editor.setData(obj.html); + this.editor.setData(obj.Content); } deselectAllHistory() { From aa48b652e04e13a9fbc2e914334da09324cdb8bd Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 17:42:08 +0200 Subject: [PATCH 073/186] Added retrieve all history endpoint --- .../app/services/version.control.service.ts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index a5961393..bc649112 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -287,4 +287,33 @@ export class VersionControlService { ); return this.http.post(url, body, { headers, observe: 'response' }); } + + retrieveAllHistory(markdownID: string): Promise { + return new Promise((resolve, reject) => { + this.sendRetrieveAllHistory(markdownID).subscribe({ + next: (response: HttpResponse) => { + console.log(response); + if (response.status === 200) { + resolve(response.body); + } else { + resolve(null); + } + }, + }); + }); + } + + sendRetrieveAllHistory(markdownID: string): Observable> { + const environmentURL = environment.apiURL; + const url = `${environmentURL}version_control/load_history`; + console.log(url); + const body = new MarkdownFileDTO(); + + body.MarkdownID = markdownID; + const headers = new HttpHeaders().set( + 'Authorization', + 'Bearer ' + this.userService.getAuthToken() + ); + return this.http.post(url, body, { headers, observe: 'response' }); + } } From 4dcc3b92efb7567715b69fa01c1fe5c57b835c30 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 18:06:08 +0200 Subject: [PATCH 074/186] Calling retrieve all history --- frontend/src/app/edit/edit.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index 8236017a..76c2f47e 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -497,7 +497,7 @@ export class EditComponent implements AfterViewInit, OnInit { async refreshSidebarHistory() { this.history = []; - this.history=await this.versionControlService.retrieveAllSnapshots(this.editService.getMarkdownID() as string); + this.history=await this.versionControlService.retrieveAllHistory(this.editService.getMarkdownID() as string); } From f0687d2e1a073f3927e010fb42d80419dae58f9b Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 18:20:35 +0200 Subject: [PATCH 075/186] Added userid field to retrieve all history --- frontend/src/app/services/version.control.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index bc649112..c4259069 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -309,6 +309,7 @@ export class VersionControlService { console.log(url); const body = new MarkdownFileDTO(); + body.UserID = this.userService.getUserID() as number; body.MarkdownID = markdownID; const headers = new HttpHeaders().set( 'Authorization', From 52233dde02f99a68cecf80f0d9ab2bce6f7dd177 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 18:22:27 +0200 Subject: [PATCH 076/186] Changed parameter for updateDiff --- backend/src/diffs/diffs.service.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/src/diffs/diffs.service.ts b/backend/src/diffs/diffs.service.ts index 1d6002d3..eb1a6ad1 100644 --- a/backend/src/diffs/diffs.service.ts +++ b/backend/src/diffs/diffs.service.ts @@ -13,10 +13,10 @@ export class DiffsService { private diffRepository: Repository, ) {} - async updateDiff(nextDiffID: number) { + async updateDiff(diffID: string) { const diff = await this.diffRepository.findOne({ - where: { S3DiffID: nextDiffID }, + where: { DiffID: diffID }, }); diff.LastModified = new Date(); @@ -48,9 +48,21 @@ export class DiffsService { await this.diffRepository.insert(diffRecords); } - async deleteDiffs(markdownFileDTO: MarkdownFileDTO) { + async deleteDiffs( + markdownFileDTO: MarkdownFileDTO, + ) { await this.diffRepository.delete({ MarkdownID: markdownFileDTO.MarkdownID, }); } + + async getAllDiffs( + markdownFileDTO: MarkdownFileDTO, + ) { + return await this.diffRepository.find({ + where: { + MarkdownID: markdownFileDTO.MarkdownID, + }, + }); + } } From 417ef525b0cbbf47f22bcc64f1640f8326dd0ac7 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 18:23:10 +0200 Subject: [PATCH 077/186] Added function: retrieveAllSnapshots --- backend/src/s3/s3.service.ts | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index 566d9faa..a9092c12 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -108,7 +108,7 @@ export class S3Service { 'S3 content file creation error: ' + err, ); return undefined; - }; + } markdownFileDTO.Content = ''; markdownFileDTO.Size = 0; @@ -425,6 +425,47 @@ export class S3Service { ///===---------------------------------------------------- + async retrieveAllSnapshots( + logicalOrder: number[], + snapshotDTO: SnapshotDTO, + ) { + const filePath = `${snapshotDTO.UserID}/${snapshotDTO.MarkdownID}`; + + let snapshotDTOs: SnapshotDTO[] = []; + + for ( + let i = 0; + i < logicalOrder.length; + i++ + ) { + console.log( + 'Trying to retrieve snapshot on path ', + `${filePath}/snapshot/${logicalOrder[i]}`, + ); + try { + const response = await this.s3Client.send( + new GetObjectCommand({ + Bucket: this.awsS3BucketName, + Key: `${filePath}/snapshot/${logicalOrder[i]}`, + }), + ); + + const snapshotDTO = new SnapshotDTO(); + snapshotDTO.Content = + await response.Body.transformToString(); + snapshotDTOs.push(snapshotDTO); + } catch (err) { + console.log( + `S3 snapshot ${i} read error: ` + err, + ); + return undefined; + } + } + return snapshotDTOs; + } + + ///===---------------------------------------------------- + async createAsset(assetDTO: AssetDTO) { // Generate new AssetID const newAssetDTO = new AssetDTO(); From 516d8c8a2cf314e927c355aa3b94ed09d257d806 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 18:24:21 +0200 Subject: [PATCH 078/186] Implemented load_history endpoint --- .../version_control.controller.ts | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/backend/src/version_control/version_control.controller.ts b/backend/src/version_control/version_control.controller.ts index b4fda562..40ef745b 100644 --- a/backend/src/version_control/version_control.controller.ts +++ b/backend/src/version_control/version_control.controller.ts @@ -1,16 +1,25 @@ import { Body, Controller, + HttpCode, + HttpStatus, Post, } from '@nestjs/common'; import { VersionControlService } from './version_control.service'; import { DiffDTO } from '../diffs/dto/diffs.dto'; import { SnapshotDTO } from '../snapshots/dto/snapshot.dto'; +import { MarkdownFileDTO } from 'src/markdown_files/dto/markdown_file.dto'; +import { VersionHistoryDTO } from './dto/version_history.dto'; +import { version } from 'os'; +import { SnapshotService } from '../snapshots/snapshots.service'; +import { DiffsService } from '../diffs/diffs.service'; @Controller('version_control') export class VersionControlController { constructor( private readonly versionControlService: VersionControlService, + private readonly snapshotService: SnapshotService, + private readonly diffService: DiffsService, ) {} ///===---------------------------------------------------- @@ -46,4 +55,53 @@ export class VersionControlController { snapshotDTO, ); } + + ///===---------------------------------------------------- + + @Post('get_all_snapshots') + @HttpCode(HttpStatus.OK) + getAllSnapshots( + @Body() snapshotDTO: SnapshotDTO, + ) { + return this.versionControlService.getAllSnapshots( + snapshotDTO, + ); + } + + ///===---------------------------------------------------- + + @Post('load_history') + @HttpCode(HttpStatus.OK) + async loadHistory( + @Body() markdownFileDTO: MarkdownFileDTO, + ) { + const versionHistoryDTO = + new VersionHistoryDTO(); + + const snapshots = + await this.snapshotService.getAllSnapshots( + markdownFileDTO, + ); + + const snapshotDTOs = + await this.versionControlService.convertSnapshotsToSnapshotDTOs( + snapshots, + ); + + versionHistoryDTO.SnapshotHistory = + snapshotDTOs; + + const diffs = + await this.diffService.getAllDiffs( + markdownFileDTO, + ); + + const diffDTOs = + await this.versionControlService.convertDiffsToDiffDTOs( + diffs, + ); + + versionHistoryDTO.DiffHistory = diffDTOs; + return versionHistoryDTO; + } } From de6a8a40f79304e9f9f265df2b63cf12813dc149 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 18:24:39 +0200 Subject: [PATCH 079/186] Added function: getAllSnapshots --- .../version_control.service.ts | 107 ++++++++++++++---- 1 file changed, 88 insertions(+), 19 deletions(-) diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index bda22efc..b6f89a6d 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -5,11 +5,15 @@ import { MarkdownFilesService } from '../markdown_files/markdown_files.service'; import { S3ServiceMock } from '../s3/__mocks__/s3.service'; import { S3Service } from '../s3/s3.service'; import { SnapshotDTO } from '../snapshots/dto/snapshot.dto'; +import { SnapshotService } from '../snapshots/snapshots.service'; +import { Snapshot } from '../snapshots/entities/snapshots.entity'; +import { Diff } from '../diffs/entities/diffs.entity'; @Injectable() export class VersionControlService { constructor( private diffService: DiffsService, + private snapshotService: SnapshotService, private markdownFileService: MarkdownFilesService, private s3Service: S3Service, private s3ServiceMock: S3ServiceMock, @@ -25,10 +29,6 @@ export class VersionControlService { this.s3Service.saveDiff(diffDTO, nextDiffID); - console.log( - '[versionControlService.saveDiff] Saved diff in s3', - ); - if ( nextDiffID % parseInt( @@ -37,22 +37,16 @@ export class VersionControlService { 0 && nextDiffID !== 0 ) { - // create snapshot + // TODO @Dylan create snapshot } - await this.diffService.updateDiff(nextDiffID); - - console.log( - '[versionControlService.saveDiff] Updated diff in db', + await this.diffService.updateDiff( + diffDTO.DiffID, ); await this.markdownFileService.incrementNextDiffID( diffDTO.MarkdownID, ); - - console.log( - '[versionControlService.saveDiff] Incremented nextDiffID in db', - ); } ///===----------------------------------------------------- @@ -78,9 +72,10 @@ export class VersionControlService { nextSnapshotID, ); - await this.diffService.updateDiff( - nextSnapshotID, + await this.snapshotService.updateSnapshot( + snapshotDTO.SnapshotID, ); + await this.markdownFileService.incrementNextDiffID( snapshotDTO.MarkdownID, ); @@ -99,10 +94,38 @@ export class VersionControlService { * * @returns all snapshots for this file, in logical order */ - getAllSnapshots() { - // calls s3Service.getAllSnapshots() - // reorders snapshots in logical order - // return logically ordered snapshots + async getAllSnapshots( + snapshotDTO: SnapshotDTO, + ) { + const snapshotRange = Array.from( + { + length: parseInt( + process.env.MAX_SNAPSHOTS, + ), + }, + (_, index) => index, + ); + + const nextSnapshotID = + await this.markdownFileService.getNextSnapshotID( + snapshotDTO.MarkdownID, + ); + + const logicalOrder = this.getLogicalOrder( + snapshotRange, + nextSnapshotID, + ); + + let snapshots = + await this.s3Service.retrieveAllSnapshots( + logicalOrder, + snapshotDTO, + ); + + snapshots = + this.pruneEmptySnapshots(snapshots); + + return snapshots; } ///===---------------------------------------------------- @@ -147,4 +170,50 @@ export class VersionControlService { } return logicalOrder; } + + ///===----------------------------------------------------- + + pruneEmptySnapshots(snapshots: SnapshotDTO[]) { + return snapshots.filter((snapshot) => { + return ( + snapshot.Content !== undefined && + snapshot.Content !== null && + snapshot.Content !== '' + ); + }); + } + + ///===---------------------------------------------------- + + async convertSnapshotsToSnapshotDTOs(snapshots: Snapshot[]) { + const snapshotDTOs = []; + for (let i = 0; i < snapshots.length; i++) { + const snapshot = snapshots[i]; + const snapshotDTO = new SnapshotDTO(); + snapshotDTO.SnapshotID = snapshot.SnapshotID; + snapshotDTO.MarkdownID = snapshot.MarkdownID; + snapshotDTO.UserID = snapshot.UserID; + snapshotDTO.S3SnapshotID = snapshot.S3SnapshotID; + snapshotDTO.LastModified = snapshot.LastModified; + snapshotDTOs.push(snapshotDTO); + } + return snapshotDTOs; + } + + ///===---------------------------------------------------- + + async convertDiffsToDiffDTOs(diffs: Diff[]) { + const diffDTOs = []; + for (let i = 0; i < diffs.length; i++) { + const diff = diffs[i]; + const diffDTO = new DiffDTO(); + diffDTO.DiffID = diff.DiffID; + diffDTO.MarkdownID = diff.MarkdownID; + diffDTO.UserID = diff.UserID; + diffDTO.S3DiffID = diff.S3DiffID; + diffDTO.LastModified = diff.LastModified; + diffDTOs.push(diffDTO); + } + return diffDTOs; + } } From b3e806270601f18fcd146afc28408d0bd8398ebd Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Mon, 18 Sep 2023 18:24:57 +0200 Subject: [PATCH 080/186] Added function: getAllSnapshots --- backend/src/snapshots/snapshots.service.ts | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/backend/src/snapshots/snapshots.service.ts b/backend/src/snapshots/snapshots.service.ts index 64406dd6..c1f113f7 100644 --- a/backend/src/snapshots/snapshots.service.ts +++ b/backend/src/snapshots/snapshots.service.ts @@ -12,6 +12,8 @@ export class SnapshotService { private snapshotRepository: Repository, ) {} + ///===----------------------------------------------------- + async createSnapshots( markdownFileDTO: MarkdownFileDTO, ) { @@ -39,6 +41,28 @@ export class SnapshotService { ); } + ///===----------------------------------------------------- + + async updateSnapshot( + snapshotID: string, + ) { + + } + + ///===----------------------------------------------------- + + async getAllSnapshots( + markdownFileDTO: MarkdownFileDTO, + ) { + return await this.snapshotRepository.find({ + where: { + MarkdownID: markdownFileDTO.MarkdownID, + }, + }); + } + + ///===----------------------------------------------------- + async deleteSnapshots( markdownFileDTO: MarkdownFileDTO, ) { From 5939bd976cde971a2fcbb20b5d4211ea9ae614ea Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Mon, 18 Sep 2023 18:36:20 +0200 Subject: [PATCH 081/186] Outputting all history in one array --- frontend/src/app/edit/edit.component.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index 76c2f47e..3f4723c4 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -497,8 +497,9 @@ export class EditComponent implements AfterViewInit, OnInit { async refreshSidebarHistory() { this.history = []; - this.history=await this.versionControlService.retrieveAllHistory(this.editService.getMarkdownID() as string); - + const data=await this.versionControlService.retrieveAllHistory(this.editService.getMarkdownID() as string); + this.history=data.SnapshotHistory.concat(data.DiffHistory); + } pageBreak() { From bc50ed187d08787b1e368252ebc348874891bec3 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 08:04:35 +0200 Subject: [PATCH 082/186] Added HasBeenUsed attribute --- backend/src/diffs/entities/diffs.entity.ts | 5 ++++- backend/src/snapshots/entities/snapshots.entity.ts | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/src/diffs/entities/diffs.entity.ts b/backend/src/diffs/entities/diffs.entity.ts index 3d69ad46..bef3518c 100644 --- a/backend/src/diffs/entities/diffs.entity.ts +++ b/backend/src/diffs/entities/diffs.entity.ts @@ -23,5 +23,8 @@ export class Diff { default: () => 'CURRENT_TIMESTAMP(3)', onUpdate: 'CURRENT_TIMESTAMP(3)', }) - LastModified: Date; + LastModified: Date; + + @Column() + HasBeenUsed: boolean; } diff --git a/backend/src/snapshots/entities/snapshots.entity.ts b/backend/src/snapshots/entities/snapshots.entity.ts index 11f80275..47892d59 100644 --- a/backend/src/snapshots/entities/snapshots.entity.ts +++ b/backend/src/snapshots/entities/snapshots.entity.ts @@ -24,4 +24,7 @@ export class Snapshot { onUpdate: 'CURRENT_TIMESTAMP(3)', }) LastModified: Date; + + @Column() + HasBeenUsed: boolean; } From 4edd44791bf7d678e869f602de28acdafce34a54 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 08:08:33 +0200 Subject: [PATCH 083/186] Retrieve only initialised diffs --- backend/src/diffs/diffs.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/diffs/diffs.service.ts b/backend/src/diffs/diffs.service.ts index eb1a6ad1..586f333d 100644 --- a/backend/src/diffs/diffs.service.ts +++ b/backend/src/diffs/diffs.service.ts @@ -62,6 +62,7 @@ export class DiffsService { return await this.diffRepository.find({ where: { MarkdownID: markdownFileDTO.MarkdownID, + HasBeenUsed: true, }, }); } From 74e2f4c540293444f120eb8ce2bf879f707e1a48 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 08:08:45 +0200 Subject: [PATCH 084/186] Retrieve only initialised snapshots --- backend/src/snapshots/snapshots.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/snapshots/snapshots.service.ts b/backend/src/snapshots/snapshots.service.ts index c1f113f7..32e43d21 100644 --- a/backend/src/snapshots/snapshots.service.ts +++ b/backend/src/snapshots/snapshots.service.ts @@ -68,6 +68,7 @@ export class SnapshotService { ) { await this.snapshotRepository.delete({ MarkdownID: markdownFileDTO.MarkdownID, + HasBeenUsed: true, }); } } From ca84fd7a20061042a78bf953acf303e43ab5c99a Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 12:16:27 +0200 Subject: [PATCH 085/186] Fixed .env reference to MAX_SNAPSHOTS --- backend/src/s3/s3.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index a9092c12..de153f08 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -381,7 +381,7 @@ export class S3Service { const filePath = `${markdownFileDTO.UserID}/${markdownFileDTO.MarkdownID}`; for ( let i = 0; - i < parseInt(process.env.SNAPSHOTS); + i < parseInt(process.env.MAX_SNAPSHOTS); i++ ) { try { From 30c0db2e7b6b64fb5f9417ba93e2ad9de53a690b Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 12:38:31 +0200 Subject: [PATCH 086/186] Provided default value for new attribute: HasBeenUsed --- backend/src/diffs/diffs.service.ts | 1 + backend/src/snapshots/snapshots.service.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/backend/src/diffs/diffs.service.ts b/backend/src/diffs/diffs.service.ts index 586f333d..41d0eb19 100644 --- a/backend/src/diffs/diffs.service.ts +++ b/backend/src/diffs/diffs.service.ts @@ -43,6 +43,7 @@ export class DiffsService { MarkdownID: markdownFileDTO.MarkdownID, UserID: markdownFileDTO.UserID, S3DiffID: i, + HasBeenUsed: false, }); } await this.diffRepository.insert(diffRecords); diff --git a/backend/src/snapshots/snapshots.service.ts b/backend/src/snapshots/snapshots.service.ts index 32e43d21..6bd466df 100644 --- a/backend/src/snapshots/snapshots.service.ts +++ b/backend/src/snapshots/snapshots.service.ts @@ -34,6 +34,7 @@ export class SnapshotService { MarkdownID: markdownFileDTO.MarkdownID, UserID: markdownFileDTO.UserID, S3SnapshotID: i, + HasBeenUsed: false, }); } await this.snapshotRepository.insert( From 6ea96755abda7ad5906d71647a18f76a8957fa6b Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 12:45:12 +0200 Subject: [PATCH 087/186] On first update, set HasBeenUsed to true --- backend/src/diffs/diffs.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/diffs/diffs.service.ts b/backend/src/diffs/diffs.service.ts index 41d0eb19..faba8741 100644 --- a/backend/src/diffs/diffs.service.ts +++ b/backend/src/diffs/diffs.service.ts @@ -20,6 +20,7 @@ export class DiffsService { }); diff.LastModified = new Date(); + diff.HasBeenUsed = true; await this.diffRepository.save(diff); } From ff1968b384cb9329242e89ef5f7478618efe7e53 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 12:48:26 +0200 Subject: [PATCH 088/186] Added support for new attribute HasBeenUsed --- backend/src/snapshots/snapshots.service.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/backend/src/snapshots/snapshots.service.ts b/backend/src/snapshots/snapshots.service.ts index 6bd466df..a9bcd2c1 100644 --- a/backend/src/snapshots/snapshots.service.ts +++ b/backend/src/snapshots/snapshots.service.ts @@ -44,10 +44,15 @@ export class SnapshotService { ///===----------------------------------------------------- - async updateSnapshot( - snapshotID: string, - ) { - + async updateSnapshot(snapshotID: string) { + const snapshot = + await this.snapshotRepository.findOne({ + where: { SnapshotID: snapshotID }, + }); + + snapshot.LastModified = new Date(); + snapshot.HasBeenUsed = true; + await this.snapshotRepository.save(snapshot); } ///===----------------------------------------------------- @@ -58,6 +63,7 @@ export class SnapshotService { return await this.snapshotRepository.find({ where: { MarkdownID: markdownFileDTO.MarkdownID, + HasBeenUsed: true, }, }); } From 44dc482ce441b4451376037145cf6b8f3af6c66d Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 12:53:37 +0200 Subject: [PATCH 089/186] Now using last modified field --- frontend/src/app/edit/edit.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/edit/edit.component.html b/frontend/src/app/edit/edit.component.html index 921fea19..14131593 100644 --- a/frontend/src/app/edit/edit.component.html +++ b/frontend/src/app/edit/edit.component.html @@ -249,7 +249,7 @@

History

{{obj.Name}}

-

{{obj.DateCreated}}

+

{{obj.LastModified}}

From e5e160c1a1ec59b9a05dbac74f3655edb24e46a4 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 13:03:25 +0200 Subject: [PATCH 090/186] Testing data sent on save_diff --- frontend/src/app/services/version.control.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index c4259069..f1356af2 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -255,6 +255,7 @@ export class VersionControlService { 'Authorization', 'Bearer ' + this.userService.getAuthToken() ); + console.log(body); return this.http.post(url, body, { headers, observe: 'response' }); } From e6eeae5067db05a3800ac7c4721331ea9101aafd Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 13:04:21 +0200 Subject: [PATCH 091/186] Reformatted the way in which history gets stored --- frontend/src/app/edit/edit.component.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index 3f4723c4..bc07509f 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -498,7 +498,21 @@ export class EditComponent implements AfterViewInit, OnInit { async refreshSidebarHistory() { this.history = []; const data=await this.versionControlService.retrieveAllHistory(this.editService.getMarkdownID() as string); - this.history=data.SnapshotHistory.concat(data.DiffHistory); + const snapshot=data.SnapshotHistory; + const diff=data.DiffHistory; + + for(let i = 0; i < snapshot.length; i++) { + snapshot[i].LastModified = this.formatDate(snapshot[i].LastModified); + snapshot[i].Name = "Snapshot " + i; + for(let j = 0; j < diff.length; j++) { + if(snapshot[i].SnapshotID === diff[j].SnapshotID) { + snapshot[i].ChildDiff = diff[j]; + diff[j].LastModified = this.formatDate(diff[j].LastModified); + diff[j].Name = "Diff " + j; + } + } + } + this.history=snapshot; } From dc71036776752c40ed4b2222d5cea13375d84054 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 13:44:00 +0200 Subject: [PATCH 092/186] Update to dto --- frontend/src/app/services/dto/diff.dto.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/app/services/dto/diff.dto.ts b/frontend/src/app/services/dto/diff.dto.ts index f2ab2948..b4cd40c3 100644 --- a/frontend/src/app/services/dto/diff.dto.ts +++ b/frontend/src/app/services/dto/diff.dto.ts @@ -4,6 +4,7 @@ export class DiffDTO { DiffNumber: number; SnapshotNumber: number; Content: string; + SnapshotPayload: string; constructor() { this.UserID = 0; @@ -11,5 +12,6 @@ export class DiffDTO { this.DiffNumber = 0; this.SnapshotNumber = 0; this.Content = ''; + this.SnapshotPayload = ''; } } From 8d45e005cd2e29f42ef50fecb5ce68ebe0908914 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 13:47:44 +0200 Subject: [PATCH 093/186] Now sending snapshotpayload on save diff --- frontend/src/app/edit/edit.component.ts | 2 +- frontend/src/app/services/version.control.service.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index bc07509f..db452195 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -258,7 +258,7 @@ export class EditComponent implements AfterViewInit, OnInit { console.log(this.editor.getData()); const diff = this.versionControlService.getReadablePatch(this.prevVersion as string, this.editor.getData()); console.log(diff); - this.versionControlService.saveDiff(this.editService.getMarkdownID() as string,diff); + this.versionControlService.saveDiff(this.editService.getMarkdownID() as string,diff, this.editor.getData()); this.prevVersion = this.editor.getData(); let contents = this.editor.getData(); let pass = this.editService.getDocumentPassword(); diff --git a/frontend/src/app/services/version.control.service.ts b/frontend/src/app/services/version.control.service.ts index f1356af2..d27e1d06 100644 --- a/frontend/src/app/services/version.control.service.ts +++ b/frontend/src/app/services/version.control.service.ts @@ -228,9 +228,9 @@ export class VersionControlService { this.sortDiffArr(this.diffArr); } - saveDiff(fileID: string, content: string): Promise { + saveDiff(fileID: string, content: string, snapshotPayload:string): Promise { return new Promise((resolve, reject) => { - this.sendSaveDiff(fileID, content).subscribe({ + this.sendSaveDiff(fileID, content, snapshotPayload).subscribe({ next: (response: HttpResponse) => { if (response.status === 200) { resolve(true); @@ -242,7 +242,7 @@ export class VersionControlService { }); } - sendSaveDiff(markdownID: string, content: string): Observable> { + sendSaveDiff(markdownID: string, content: string, snapshotPayload:string): Observable> { const environmentURL = environment.apiURL; const url = `${environmentURL}version_control/save_diff`; console.log(url); @@ -251,6 +251,7 @@ export class VersionControlService { body.UserID = this.userService.getUserID() as number; body.Content = content; body.MarkdownID = markdownID; + body.SnapshotPayload = snapshotPayload; const headers = new HttpHeaders().set( 'Authorization', 'Bearer ' + this.userService.getAuthToken() From 2283f8ceee9965c5298939f1e5b6b4a29c15bc1a Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 14:04:46 +0200 Subject: [PATCH 094/186] Added SnapshotID field in dto --- backend/src/diffs/dto/diffs.dto.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/diffs/dto/diffs.dto.ts b/backend/src/diffs/dto/diffs.dto.ts index 10f2bd1e..4cdad6c3 100644 --- a/backend/src/diffs/dto/diffs.dto.ts +++ b/backend/src/diffs/dto/diffs.dto.ts @@ -6,6 +6,8 @@ export class DiffDTO { S3DiffID: number; LastModified: Date; Content: string; + SnapshotPayload: string; + SnapshotID: string; constructor() { this.DiffID = undefined; @@ -15,5 +17,7 @@ export class DiffDTO { this.S3DiffID = undefined; this.LastModified = undefined; this.Content = undefined; + this.SnapshotPayload = undefined; + this.SnapshotID = undefined; } } From 3d8db8f81d6cd0a419597eeba77b0e5f49887cb4 Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 14:14:23 +0200 Subject: [PATCH 095/186] Added logic for returning snapshots to the frontend --- backend/src/diffs/diffs.service.ts | 11 +++- backend/src/s3/s3.service.ts | 8 +-- backend/src/snapshots/snapshots.service.ts | 10 +++- .../version_control.controller.ts | 39 ++++++++------ .../version_control.service.ts | 51 ++++++++++++++----- 5 files changed, 82 insertions(+), 37 deletions(-) diff --git a/backend/src/diffs/diffs.service.ts b/backend/src/diffs/diffs.service.ts index faba8741..82334c75 100644 --- a/backend/src/diffs/diffs.service.ts +++ b/backend/src/diffs/diffs.service.ts @@ -5,6 +5,7 @@ import { Diff } from './entities/diffs.entity'; import 'dotenv/config'; import * as CryptoJS from 'crypto-js'; import { MarkdownFileDTO } from '../markdown_files/dto/markdown_file.dto'; +import { DiffDTO } from './dto/diffs.dto'; @Injectable() export class DiffsService { @@ -13,10 +14,16 @@ export class DiffsService { private diffRepository: Repository, ) {} - async updateDiff(diffID: string) { + async updateDiff( + diffDTO: DiffDTO, + nextDiffID: number, + ) { const diff = await this.diffRepository.findOne({ - where: { DiffID: diffID }, + where: { + MarkdownID: diffDTO.MarkdownID, + S3DiffID: nextDiffID, + }, }); diff.LastModified = new Date(); diff --git a/backend/src/s3/s3.service.ts b/backend/src/s3/s3.service.ts index de153f08..5d490b8e 100644 --- a/backend/src/s3/s3.service.ts +++ b/backend/src/s3/s3.service.ts @@ -403,24 +403,24 @@ export class S3Service { ///===---------------------------------------------------- async saveSnapshot( - snapshotDTO: SnapshotDTO, + diffDTO: DiffDTO, nextSnapshotID: number, ) { - const filePath = `${snapshotDTO.UserID}/${snapshotDTO.MarkdownID}`; + const filePath = `${diffDTO.UserID}/${diffDTO.MarkdownID}`; try { await this.s3Client.send( new PutObjectCommand({ Bucket: this.awsS3BucketName, Key: `${filePath}/snapshot/${nextSnapshotID}`, - Body: snapshotDTO.Content, + Body: diffDTO.SnapshotPayload, }), ); } catch (err) { console.log('Write File Error: ' + err); return undefined; } - return snapshotDTO; + return diffDTO; } ///===---------------------------------------------------- diff --git a/backend/src/snapshots/snapshots.service.ts b/backend/src/snapshots/snapshots.service.ts index a9bcd2c1..599a2419 100644 --- a/backend/src/snapshots/snapshots.service.ts +++ b/backend/src/snapshots/snapshots.service.ts @@ -44,10 +44,16 @@ export class SnapshotService { ///===----------------------------------------------------- - async updateSnapshot(snapshotID: string) { + async updateSnapshot( + markdownID: string, + nextSnapshotID: number, + ) { const snapshot = await this.snapshotRepository.findOne({ - where: { SnapshotID: snapshotID }, + where: { + MarkdownID: markdownID, + S3SnapshotID: nextSnapshotID, + }, }); snapshot.LastModified = new Date(); diff --git a/backend/src/version_control/version_control.controller.ts b/backend/src/version_control/version_control.controller.ts index 40ef745b..44f8c167 100644 --- a/backend/src/version_control/version_control.controller.ts +++ b/backend/src/version_control/version_control.controller.ts @@ -31,30 +31,39 @@ export class VersionControlController { ///===---------------------------------------------------- - @Post('get_diff') - getDiff(@Body() diffDTO: DiffDTO) { - return this.versionControlService.getDiff( - diffDTO, - ); - } + // @Post('get_diff') + // getDiff(@Body() diffDTO: DiffDTO) { + // return this.versionControlService.getDiff( + // diffDTO, + // ); + // } + + // ///===---------------------------------------------------- + + // @Post('get_all_diffs') + // getAllDiffs(@Body() snapshotDTO: SnapshotDTO) { + // return this.versionControlService.getAllDiffsForSnapshot( + // snapshotDTO, + // ); + // } ///===---------------------------------------------------- - @Post('get_all_diffs') - getAllDiffs(@Body() snapshotDTO: SnapshotDTO) { - return this.versionControlService.getAllDiffsForSnapshot( + @Post('get_diff_set') + getDiffSet(@Body() snapshotDTO: SnapshotDTO) { + return this.versionControlService.getDiffSetForSnapshot( snapshotDTO, ); } ///===---------------------------------------------------- - @Post('save_snapshot') - saveSnapshot(@Body() snapshotDTO: SnapshotDTO) { - this.versionControlService.saveSnapshot( - snapshotDTO, - ); - } + // @Post('save_snapshot') + // saveSnapshot(@Body() snapshotDTO: SnapshotDTO) { + // this.versionControlService.saveSnapshot( + // snapshotDTO, + // ); + // } ///===---------------------------------------------------- diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index b6f89a6d..288dfc00 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -37,11 +37,12 @@ export class VersionControlService { 0 && nextDiffID !== 0 ) { - // TODO @Dylan create snapshot + this.saveSnapshot(diffDTO); } await this.diffService.updateDiff( - diffDTO.DiffID, + diffDTO, + nextDiffID, ); await this.markdownFileService.incrementNextDiffID( @@ -61,29 +62,30 @@ export class VersionControlService { ///===----------------------------------------------------- - async saveSnapshot(snapshotDTO: SnapshotDTO) { + async saveSnapshot(diffDTO: DiffDTO) { const nextSnapshotID = await this.markdownFileService.getNextSnapshotID( - snapshotDTO.MarkdownID, + diffDTO.MarkdownID, ); this.s3Service.saveSnapshot( - snapshotDTO, + diffDTO, nextSnapshotID, ); await this.snapshotService.updateSnapshot( - snapshotDTO.SnapshotID, + diffDTO.MarkdownID, + nextSnapshotID, ); - await this.markdownFileService.incrementNextDiffID( - snapshotDTO.MarkdownID, + await this.markdownFileService.incrementNextSnapshotID( + diffDTO.MarkdownID, ); } ///===----------------------------------------------------- - getSnapshot() {} + getDiffSetForSnapshot(snapshot: SnapshotDTO) {} ///===----------------------------------------------------- @@ -131,6 +133,21 @@ export class VersionControlService { ///===---------------------------------------------------- // Helpers + getDiffSetIndices(snapshotID: number) { + const diffsPerSnap = parseInt( + process.env.DIFFS_PER_SNAPSHOT, + ); + const first = snapshotID * diffsPerSnap; + const last = first + diffsPerSnap; + const indices = Array.from( + { length: last - first }, + (_, index) => index + first, + ); + return indices; + } + + ///===---------------------------------------------------- + getLogicalIndex( s3Index: number, head: number, @@ -185,16 +202,22 @@ export class VersionControlService { ///===---------------------------------------------------- - async convertSnapshotsToSnapshotDTOs(snapshots: Snapshot[]) { + async convertSnapshotsToSnapshotDTOs( + snapshots: Snapshot[], + ) { const snapshotDTOs = []; for (let i = 0; i < snapshots.length; i++) { const snapshot = snapshots[i]; const snapshotDTO = new SnapshotDTO(); - snapshotDTO.SnapshotID = snapshot.SnapshotID; - snapshotDTO.MarkdownID = snapshot.MarkdownID; + snapshotDTO.SnapshotID = + snapshot.SnapshotID; + snapshotDTO.MarkdownID = + snapshot.MarkdownID; snapshotDTO.UserID = snapshot.UserID; - snapshotDTO.S3SnapshotID = snapshot.S3SnapshotID; - snapshotDTO.LastModified = snapshot.LastModified; + snapshotDTO.S3SnapshotID = + snapshot.S3SnapshotID; + snapshotDTO.LastModified = + snapshot.LastModified; snapshotDTOs.push(snapshotDTO); } return snapshotDTOs; From 77c349a940c7f5fc6fbcdd21453790abf713089d Mon Sep 17 00:00:00 2001 From: jakeweatherhead Date: Tue, 19 Sep 2023 15:15:01 +0200 Subject: [PATCH 096/186] Added functionality to match diffs to snapshots --- backend/src/diffs/diffs.service.ts | 14 ++++++++++++++ backend/src/diffs/entities/diffs.entity.ts | 3 +++ backend/src/file_manager/file_manager.service.ts | 5 +++-- backend/src/snapshots/snapshots.service.ts | 5 +++++ .../src/version_control/version_control.service.ts | 1 + 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/backend/src/diffs/diffs.service.ts b/backend/src/diffs/diffs.service.ts index 82334c75..bfa83b2b 100644 --- a/backend/src/diffs/diffs.service.ts +++ b/backend/src/diffs/diffs.service.ts @@ -33,8 +33,10 @@ export class DiffsService { async createDiffs( markdownFileDTO: MarkdownFileDTO, + snapshotIDs: string[], ) { const diffRecords = []; + let snapshotIndex = 0; for ( let i = 0; i < parseInt(process.env.MAX_DIFFS); @@ -46,12 +48,24 @@ export class DiffsService { i.toString(), ).toString(); + if ( + i % + parseInt( + process.env.DIFFS_PER_SNAPSHOT, + ) === + 0 && + i !== 0 + ) { + snapshotIndex++; + } + diffRecords.push({ DiffID: diffID, MarkdownID: markdownFileDTO.MarkdownID, UserID: markdownFileDTO.UserID, S3DiffID: i, HasBeenUsed: false, + SnapshotID: snapshotIDs[snapshotIndex], }); } await this.diffRepository.insert(diffRecords); diff --git a/backend/src/diffs/entities/diffs.entity.ts b/backend/src/diffs/entities/diffs.entity.ts index bef3518c..a128dca7 100644 --- a/backend/src/diffs/entities/diffs.entity.ts +++ b/backend/src/diffs/entities/diffs.entity.ts @@ -27,4 +27,7 @@ export class Diff { @Column() HasBeenUsed: boolean; + + @Column() + SnapshotID: string; } diff --git a/backend/src/file_manager/file_manager.service.ts b/backend/src/file_manager/file_manager.service.ts index 216dc3a4..bc1aa003 100644 --- a/backend/src/file_manager/file_manager.service.ts +++ b/backend/src/file_manager/file_manager.service.ts @@ -85,12 +85,13 @@ export class FileManagerService { markdownFileDTO, ); - await this.diffsService.createDiffs( + const snapshotIDs: string[] = await this.snapshotService.createSnapshots( markdownFileDTO, ); - await this.snapshotService.createSnapshots( + await this.diffsService.createDiffs( markdownFileDTO, + snapshotIDs, ); return await this.markdownFilesService.create( diff --git a/backend/src/snapshots/snapshots.service.ts b/backend/src/snapshots/snapshots.service.ts index 599a2419..69a5d783 100644 --- a/backend/src/snapshots/snapshots.service.ts +++ b/backend/src/snapshots/snapshots.service.ts @@ -17,6 +17,7 @@ export class SnapshotService { async createSnapshots( markdownFileDTO: MarkdownFileDTO, ) { + const snapshotIDs = []; const snapshotRecords = []; for ( let i = 0; @@ -36,10 +37,14 @@ export class SnapshotService { S3SnapshotID: i, HasBeenUsed: false, }); + + snapshotIDs.push(snapshotID); } await this.snapshotRepository.insert( snapshotRecords, ); + + return snapshotIDs; } ///===----------------------------------------------------- diff --git a/backend/src/version_control/version_control.service.ts b/backend/src/version_control/version_control.service.ts index 288dfc00..8f1762ec 100644 --- a/backend/src/version_control/version_control.service.ts +++ b/backend/src/version_control/version_control.service.ts @@ -235,6 +235,7 @@ export class VersionControlService { diffDTO.UserID = diff.UserID; diffDTO.S3DiffID = diff.S3DiffID; diffDTO.LastModified = diff.LastModified; + diffDTO.SnapshotID = diff.SnapshotID; diffDTOs.push(diffDTO); } return diffDTOs; From 95bb3cbf0252b91b2beebc5054f3dea1d5093e42 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:35:50 +0200 Subject: [PATCH 097/186] Handling of initial diffs --- frontend/src/app/edit/edit.component.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index db452195..b3b563c8 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -509,11 +509,18 @@ export class EditComponent implements AfterViewInit, OnInit { snapshot[i].ChildDiff = diff[j]; diff[j].LastModified = this.formatDate(diff[j].LastModified); diff[j].Name = "Diff " + j; + diff[j].hasSnapshot = true; } } } this.history=snapshot; - + for(let i=0;i Date: Tue, 19 Sep 2023 17:43:11 +0200 Subject: [PATCH 098/186] Changing to deep copy of response --- .../version_control.controller.ts | 1 + frontend/src/app/edit/edit.component.ts | 69 ++++++++++--------- .../app/services/version.control.service.ts | 2 +- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/backend/src/version_control/version_control.controller.ts b/backend/src/version_control/version_control.controller.ts index 44f8c167..75d429c1 100644 --- a/backend/src/version_control/version_control.controller.ts +++ b/backend/src/version_control/version_control.controller.ts @@ -111,6 +111,7 @@ export class VersionControlController { ); versionHistoryDTO.DiffHistory = diffDTOs; + console.log(versionHistoryDTO); return versionHistoryDTO; } } diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index b3b563c8..fcc50353 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -59,7 +59,7 @@ export class EditComponent implements AfterViewInit, OnInit { private clipboard: Clipboard, private messageService: MessageService, private versionControlService: VersionControlService - ) {} + ) { } @HostListener('window:beforeunload', ['$event']) beforeUnloadHandler(event: BeforeUnloadEvent) { @@ -119,9 +119,9 @@ export class EditComponent implements AfterViewInit, OnInit { ]; //get window width - this.isTouchScreen=window.matchMedia('(pointer: coarse)').matches; + this.isTouchScreen = window.matchMedia('(pointer: coarse)').matches; const width = window.innerWidth; - if (width < 800) + if (width < 800) this.hideSideBar(); const c = localStorage.getItem('content'); const m = localStorage.getItem('markdownID'); @@ -136,8 +136,8 @@ export class EditComponent implements AfterViewInit, OnInit { this.fileName = this.editService.getName(); this.history.push({ name: 'Latest', date: 'now', html: this.editService.getContent(), id: 'LATEST', isCurrent: true }); - this.history.push({name: 'Version 7', date: '01-01-1977', html: '', id: '8'}); - this.history.push({name: 'Version 6', date: '01-01-1976', html: '

Text added from V0 to V1.

More Text added from V1 to V2.

Addition from V3 to V4

', id: '7'}); + this.history.push({ name: 'Version 7', date: '01-01-1977', html: '', id: '8' }); + this.history.push({ name: 'Version 6', date: '01-01-1976', html: '

Text added from V0 to V1.

More Text added from V1 to V2.

Addition from V3 to V4

', id: '7' }); this.history.push({ name: 'Version 5', date: '01-01-1975', html: '

Text to be removed soon.

Text added from V0 to V1.

More Text added from V1 to V2.

Addition from V3 to V4

', id: '6' }); this.history.push({ name: 'Version 4', date: '01-01-1974', html: '

Text to be removed soon.

Text added from V0 to V1.

More Text added from V1 to V2.

Addition from V3 to V4

', id: '5' }); this.history.push({ name: 'Version 3', date: '01-01-1973', html: '

Text to be removed soon.

Text added from V0 to V1.

More Text added from V1 to V2.

', id: '4' }); @@ -258,17 +258,17 @@ export class EditComponent implements AfterViewInit, OnInit { console.log(this.editor.getData()); const diff = this.versionControlService.getReadablePatch(this.prevVersion as string, this.editor.getData()); console.log(diff); - this.versionControlService.saveDiff(this.editService.getMarkdownID() as string,diff, this.editor.getData()); + this.versionControlService.saveDiff(this.editService.getMarkdownID() as string, diff, this.editor.getData()); this.prevVersion = this.editor.getData(); let contents = this.editor.getData(); let pass = this.editService.getDocumentPassword(); - if(pass != '' && pass != undefined) { + if (pass != '' && pass != undefined) { this.fileService.saveDocument( this.fileService.encryptSafeLockDocument(contents, pass), this.editService.getMarkdownID(), this.editService.getPath(), this.editService.getSafeLock() - ); + ); } else { this.fileService.saveDocument( @@ -276,7 +276,7 @@ export class EditComponent implements AfterViewInit, OnInit { this.editService.getMarkdownID(), this.editService.getPath(), this.editService.getSafeLock() - ); + ); } } @@ -415,7 +415,7 @@ export class EditComponent implements AfterViewInit, OnInit { }), ]) .then( - () => {}, + () => { }, (error) => { console.error( 'Could not copy HTML data (image) to clipboard: ', @@ -497,30 +497,33 @@ export class EditComponent implements AfterViewInit, OnInit { async refreshSidebarHistory() { this.history = []; - const data=await this.versionControlService.retrieveAllHistory(this.editService.getMarkdownID() as string); - const snapshot=data.SnapshotHistory; - const diff=data.DiffHistory; - - for(let i = 0; i < snapshot.length; i++) { - snapshot[i].LastModified = this.formatDate(snapshot[i].LastModified); - snapshot[i].Name = "Snapshot " + i; - for(let j = 0; j < diff.length; j++) { - if(snapshot[i].SnapshotID === diff[j].SnapshotID) { - snapshot[i].ChildDiff = diff[j]; - diff[j].LastModified = this.formatDate(diff[j].LastModified); - diff[j].Name = "Diff " + j; - diff[j].hasSnapshot = true; + this.versionControlService.retrieveAllHistory(this.editService.getMarkdownID() as string).then((data) => { + console.log("Response body: ", data); + const snapshot = JSON.parse(JSON.stringify(data.SnapshotHistory)); + const diff = JSON.parse(JSON.stringify(data.DiffHistory)); + + for (let i = 0; i < snapshot.length; i++) { + snapshot[i].LastModified = this.formatDate(snapshot[i].LastModified); + snapshot[i].Name = "Snapshot " + i; + for (let j = 0; j < diff.length; j++) { + if (snapshot[i].SnapshotID === diff[j].SnapshotID) { + snapshot[i].ChildDiff = diff[j]; + diff[j].LastModified = this.formatDate(diff[j].LastModified); + diff[j].Name = "Diff " + j; + diff[j].hasSnapshot = true; + } } } - } - this.history=snapshot; - for(let i=0;i((resolve, reject) => { this.sendRetrieveAllHistory(markdownID).subscribe({ next: (response: HttpResponse) => { - console.log(response); + console.log("Backend data response: ",response); if (response.status === 200) { resolve(response.body); } else { From e3832798530cea979c47740598986bfd8b4af334 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 17:59:21 +0200 Subject: [PATCH 099/186] Added dropdown arrow --- frontend/src/app/edit/edit.component.html | 1 + frontend/src/app/edit/edit.component.scss | 23 ++++++++++++++++++++++- frontend/src/app/edit/edit.component.ts | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/edit/edit.component.html b/frontend/src/app/edit/edit.component.html index 14131593..067bcc45 100644 --- a/frontend/src/app/edit/edit.component.html +++ b/frontend/src/app/edit/edit.component.html @@ -248,6 +248,7 @@

History

+

{{obj.Name}}

{{obj.LastModified}}

diff --git a/frontend/src/app/edit/edit.component.scss b/frontend/src/app/edit/edit.component.scss index d2c32e52..e1c48cad 100644 --- a/frontend/src/app/edit/edit.component.scss +++ b/frontend/src/app/edit/edit.component.scss @@ -739,7 +739,7 @@ Preserve the relative scale, though. */ .historyObject { transition: 0.2s; display: grid; - grid-template-columns: 2fr 2fr 1fr; + grid-template-columns: 0.5fr 2fr 2fr 0.5fr; justify-content: space-around; width: $sidebar-content-width; border-radius: 8px; @@ -783,4 +783,25 @@ Preserve the relative scale, though. */ cursor: pointer; background-color: #ddf; transition: 0.5s; +} + +.dropdownArrow { + transition: transform 0.3s ease; + margin: 0; + margin: auto 0; + width: 20px; + height: 20px; + padding: 4px; + + border-radius: 5px; +} + +.dropdownArrow:hover { + cursor: pointer; + background-color: #ddf; +} + +.dropdownArrow.expanded { + transform: rotate(90deg); + /* Rotate 180 degrees when expanded */ } \ No newline at end of file diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index fcc50353..ac4f1919 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -645,4 +645,18 @@ export class EditComponent implements AfterViewInit, OnInit { this.history[i].isCurrent = false; } } + + expandSnapshot(snapshot: any, event: any) { + if (snapshot.expanded) { + snapshot.expanded = false; + } else { + snapshot.expanded = true; + } + + const arrowElement = event.target; + + arrowElement.classList.toggle('expanded'); + + event.stopPropagation(); + } } From e4e249f5e37e0281bd2aa7122cc3d2f2097ba390 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 18:11:57 +0200 Subject: [PATCH 100/186] Dropdown of snapshots to diffs now works --- frontend/src/app/edit/edit.component.html | 19 ++++++++++++++----- frontend/src/app/edit/edit.component.scss | 6 ++++++ frontend/src/app/edit/edit.component.ts | 5 ++++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/edit/edit.component.html b/frontend/src/app/edit/edit.component.html index 067bcc45..0a9ce6d3 100644 --- a/frontend/src/app/edit/edit.component.html +++ b/frontend/src/app/edit/edit.component.html @@ -247,12 +247,21 @@

History

-
- -

{{obj.Name}}

-

{{obj.LastModified}}

- +
+
+ +

{{obj.Name}}

+

{{obj.LastModified}}

+ +
+
+
+

{{diffObj.Name}}

+

{{diffObj.LastModified}}

+ +
+
diff --git a/frontend/src/app/edit/edit.component.scss b/frontend/src/app/edit/edit.component.scss index e1c48cad..ac3497b8 100644 --- a/frontend/src/app/edit/edit.component.scss +++ b/frontend/src/app/edit/edit.component.scss @@ -736,6 +736,7 @@ Preserve the relative scale, though. */ color: #000 } +.diffObject, .historyObject { transition: 0.2s; display: grid; @@ -755,12 +756,17 @@ Preserve the relative scale, though. */ user-select: none; } +.diffObject:hover, .historyObject:hover { cursor: pointer; // scale: 1.1; background-color: darken($light-grey, 10%); } +.diffObject{ + grid-template-columns: 2fr 2fr 1fr; +} + .selectedHistory { background-color: #dfd; } diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index ac4f1919..a7aa3fbd 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -505,9 +505,10 @@ export class EditComponent implements AfterViewInit, OnInit { for (let i = 0; i < snapshot.length; i++) { snapshot[i].LastModified = this.formatDate(snapshot[i].LastModified); snapshot[i].Name = "Snapshot " + i; + snapshot[i].ChildDiffs = []; for (let j = 0; j < diff.length; j++) { if (snapshot[i].SnapshotID === diff[j].SnapshotID) { - snapshot[i].ChildDiff = diff[j]; + snapshot[i].ChildDiffs.push(diff[j]); diff[j].LastModified = this.formatDate(diff[j].LastModified); diff[j].Name = "Diff " + j; diff[j].hasSnapshot = true; @@ -522,8 +523,10 @@ export class EditComponent implements AfterViewInit, OnInit { this.history.push(diff[i]); } } + console.log(this.history); }); + } pageBreak() { From c9f30744be7335a2bb72954a179fba4fb7a840fd Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 18:14:24 +0200 Subject: [PATCH 101/186] Better representation of snapshot --- frontend/src/app/edit/edit.component.scss | 3 ++- frontend/src/app/edit/edit.component.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/edit/edit.component.scss b/frontend/src/app/edit/edit.component.scss index ac3497b8..a985a5b2 100644 --- a/frontend/src/app/edit/edit.component.scss +++ b/frontend/src/app/edit/edit.component.scss @@ -764,7 +764,8 @@ Preserve the relative scale, though. */ } .diffObject{ - grid-template-columns: 2fr 2fr 1fr; + margin-left: 20px; + grid-template-columns: 2fr 2fr 0.5fr; } .selectedHistory { diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index a7aa3fbd..97c86ce1 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -510,7 +510,7 @@ export class EditComponent implements AfterViewInit, OnInit { if (snapshot[i].SnapshotID === diff[j].SnapshotID) { snapshot[i].ChildDiffs.push(diff[j]); diff[j].LastModified = this.formatDate(diff[j].LastModified); - diff[j].Name = "Diff " + j; + diff[j].Name = "Version " + j; diff[j].hasSnapshot = true; } } From 56c3700ef1f0a79a046aa707aa7d02f4d2a18e84 Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 18:46:01 +0200 Subject: [PATCH 102/186] Save confirmation --- frontend/src/app/edit/edit.component.html | 5 +++-- frontend/src/app/edit/edit.component.ts | 26 +++++++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/edit/edit.component.html b/frontend/src/app/edit/edit.component.html index 0a9ce6d3..01ac7980 100644 --- a/frontend/src/app/edit/edit.component.html +++ b/frontend/src/app/edit/edit.component.html @@ -1,9 +1,10 @@
+
-
+
+ (click)="exitToHome()">
diff --git a/frontend/src/app/edit/edit.component.ts b/frontend/src/app/edit/edit.component.ts index 97c86ce1..7dde3dd5 100644 --- a/frontend/src/app/edit/edit.component.ts +++ b/frontend/src/app/edit/edit.component.ts @@ -17,7 +17,7 @@ import { EditService } from '../services/edit.service'; import { AssetService } from '../services/asset.service'; import { VersionControlService } from '../services/version.control.service'; import { Inject } from '@angular/core'; -import { MessageService } from 'primeng/api'; +import { MessageService, ConfirmationService } from 'primeng/api'; import { set } from 'cypress/types/lodash'; import { PageBreak } from '@ckeditor/ckeditor5-page-break'; @@ -58,7 +58,8 @@ export class EditComponent implements AfterViewInit, OnInit { private assetService: AssetService, private clipboard: Clipboard, private messageService: MessageService, - private versionControlService: VersionControlService + private versionControlService: VersionControlService, + private confirmationService: ConfirmationService, ) { } @HostListener('window:beforeunload', ['$event']) @@ -250,6 +251,27 @@ export class EditComponent implements AfterViewInit, OnInit { this.router.navigate(['/camera'], { state: data }); } + exitToHome(){ + console.log("Exit To Home."); + this.confirmationService.confirm({ + message: 'Do you want to save before you leave?', + header: 'Save Confirmation', + icon: 'pi pi-exclamation-triangle', + acceptLabel: 'Exit and Save', + rejectLabel: 'Exit without Saving', + accept: () => { + this.editService.setContent(this.editor.getData()); + this.saveDocumentContents(); + this.router.navigate(['/home']); + }, + reject: (type: any) => { + if(type === 1) + this.router.navigate(['/home']); + } + + }); + } + saveDocumentContents() { // Save the document quill content to localStorage when changes occur // const editableArea: HTMLElement = this.elementRef.nativeElement.querySelector('.document-editor__editable'); From 2cc0a9f96e91ca882444e4850ccd31723172387b Mon Sep 17 00:00:00 2001 From: JulianPienaar <104741835+JulianPienaar@users.noreply.github.com> Date: Tue, 19 Sep 2023 18:55:57 +0200 Subject: [PATCH 103/186] Implemented Contrast adjustment --- frontend/src/app/camera/camera.component.html | 4 +- frontend/src/app/camera/camera.component.ts | 45 ++++++++++++++++--- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/camera/camera.component.html b/frontend/src/app/camera/camera.component.html index 30c3b933..c9063124 100644 --- a/frontend/src/app/camera/camera.component.html +++ b/frontend/src/app/camera/camera.component.html @@ -31,9 +31,11 @@
- +
+ +



Camera Not @@ -34,7 +34,16 @@

- +
+

Adjust Contrast

+ +

Adjust Brightness

+ +
+ + +
+