diff --git a/blogs-analyzer-ui/package.json b/blogs-analyzer-ui/package.json index d2238cc..f2df22b 100644 --- a/blogs-analyzer-ui/package.json +++ b/blogs-analyzer-ui/package.json @@ -27,6 +27,7 @@ "bootstrap": "^5.3.0", "highcharts": "^11.4.3", "highcharts-angular": "^4.0.0", + "ngx-doc-viewer": "^15.0.1", "ngx-logger": "^5.0.12", "ngx-markdown": "^16.0.0", "rxjs": "~7.8.0", @@ -50,4 +51,4 @@ "sonar-scanner": "^3.1.0", "typescript": "~5.0.2" } -} \ No newline at end of file +} diff --git a/blogs-analyzer-ui/src/app/app.module.ts b/blogs-analyzer-ui/src/app/app.module.ts index 60b4af5..097e68a 100644 --- a/blogs-analyzer-ui/src/app/app.module.ts +++ b/blogs-analyzer-ui/src/app/app.module.ts @@ -21,6 +21,7 @@ import { HighchartsChartModule } from "highcharts-angular"; import { MarkdownModule } from "ngx-markdown"; import { LoggerModule, NgxLoggerLevel } from "ngx-logger"; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgxDocViewerModule } from "ngx-doc-viewer"; @NgModule({ declarations: [ @@ -45,6 +46,7 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; MatButtonModule, HighchartsChartModule, MarkdownModule.forRoot(), + NgxDocViewerModule, LoggerModule.forRoot({ level: NgxLoggerLevel.DEBUG, serverLogLevel: NgxLoggerLevel.ERROR, diff --git a/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.html b/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.html index e95efe3..af37022 100644 --- a/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.html +++ b/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.html @@ -22,6 +22,13 @@
{{ errorMessage }}
+
+ + +

Upload .doc/.docx file only

+

Existing Blogs

diff --git a/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.scss b/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.scss index 337110d..942762e 100644 --- a/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.scss +++ b/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.scss @@ -83,3 +83,7 @@ 0 1px 1px 0 #9b9b9b, 0 1px 1px 0 #9b9b9b; } + +.upload-label { + cursor: pointer; +} diff --git a/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.ts b/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.ts index 43bc611..b7ae00d 100644 --- a/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.ts +++ b/blogs-analyzer-ui/src/app/dashboard/components/home/home.component.ts @@ -14,6 +14,7 @@ export class HomeComponent { authorId!: number; errorMessage: string | null = null; errorContext: 'title' | 'author' | 'id' | null = null; + fileUrl: any constructor( private blogService: BlogService, @@ -71,4 +72,19 @@ export class HomeComponent { }); } } + + onFileSelected(event: Event): void { + const input = event.target as HTMLInputElement; + + if (input.files && input.files[0]) { + const file = input.files[0]; + const reader = new FileReader(); + + reader.onload = (e) => { + this.fileUrl = e.target?.result as string; + this.router.navigate(['/quality-check'], {state: {url: this.fileUrl}}); + }; + reader.readAsDataURL(file); + } + } } diff --git a/blogs-analyzer-ui/src/app/quality-check/quality-check.component.html b/blogs-analyzer-ui/src/app/quality-check/quality-check.component.html index 2937531..adb77b8 100644 --- a/blogs-analyzer-ui/src/app/quality-check/quality-check.component.html +++ b/blogs-analyzer-ui/src/app/quality-check/quality-check.component.html @@ -5,35 +5,62 @@ Back -
+ +
+
+ +
+
+
+ +

HTML Preview

- -
+ +
+ +
+ + +
+
+
- - -
-
-

Overall Rating:

- {{ overallRating | number:'1.1-1' }}
- -

Overall Feedback:

-

{{ overallFeedback }}

+ + + + +
+
+ +
+
+
+ + + -
-
- - -
+
+
+

Overall Rating:

+ {{ overallRating | number:'1.1-1' }}
+ +

Overall Feedback:

+

{{ overallFeedback }}

+
+
+
+ + +
+
-
+
diff --git a/blogs-analyzer-ui/src/app/quality-check/quality-check.component.scss b/blogs-analyzer-ui/src/app/quality-check/quality-check.component.scss index e9c1668..7bd9d34 100644 --- a/blogs-analyzer-ui/src/app/quality-check/quality-check.component.scss +++ b/blogs-analyzer-ui/src/app/quality-check/quality-check.component.scss @@ -135,3 +135,10 @@ textarea { .ngb-rating .star.empty { color: #d3d3d3; } + +.spinner { + height: 200px; + display: flex; + align-items: center; + justify-content: center; +} \ No newline at end of file diff --git a/blogs-analyzer-ui/src/app/quality-check/quality-check.component.spec.ts b/blogs-analyzer-ui/src/app/quality-check/quality-check.component.spec.ts index f56b5bc..db83377 100644 --- a/blogs-analyzer-ui/src/app/quality-check/quality-check.component.spec.ts +++ b/blogs-analyzer-ui/src/app/quality-check/quality-check.component.spec.ts @@ -57,7 +57,7 @@ describe('QualityCheckComponent', () => { - Code Examples and Illustrations - Links and References - Overall Feedback % - Display result in tabular view for respective percentages and accurate feedback;`; + Display result in tabular view for respective percentages with accurate feedback;`; spyOn(blogService, 'getBlogQuality').and.returnValue(of('')); component.checkQuality(); diff --git a/blogs-analyzer-ui/src/app/quality-check/quality-check.component.ts b/blogs-analyzer-ui/src/app/quality-check/quality-check.component.ts index 2435477..f17e1fe 100644 --- a/blogs-analyzer-ui/src/app/quality-check/quality-check.component.ts +++ b/blogs-analyzer-ui/src/app/quality-check/quality-check.component.ts @@ -1,19 +1,26 @@ -import { Component, OnInit } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { Location } from "@angular/common"; import { BlogService } from "../services/blog.service"; import { NGXLogger } from 'ngx-logger'; +import { Subscription } from 'rxjs'; @Component({ selector: 'app-quality-check', templateUrl: './quality-check.component.html', styleUrls: ['./quality-check.component.scss'] }) -export class QualityCheckComponent implements OnInit { - postData: any; +export class QualityCheckComponent implements OnInit, AfterViewInit, OnDestroy { + @ViewChild('docViewer') docViewer!: ElementRef; + fileUrl: string = ''; + postData: string | undefined; qualityResults: { originalLabel: string; oppositeLabel: string; value: number; comment: string }[] = []; errorMessage: string | null = null; overallFeedback: string | null = null; overallRating: number = 0; + isLoading: boolean = false; + initialLoading: boolean = false; + draftPost!: string; + subscriptions: Subscription[] = []; labels = [ {actual: 'Duplicate Content', opposite: 'Original Content'}, @@ -37,31 +44,83 @@ export class QualityCheckComponent implements OnInit { ngOnInit(): void { this.postData = history?.state?.data; + this.fileUrl = history?.state?.url; this.logger.debug('Initialized QualityCheckComponent'); } + ngAfterViewInit(): void { + setTimeout(() => { + if (this.docViewer && this.docViewer.nativeElement) { + this.draftPost = this.docViewer.nativeElement.firstElementChild?.firstElementChild?.innerHTML || ''; + console.log(this.draftPost) + } + }, 500); + } + goBack(): void { this.location.back(); this.logger.debug('Navigated back'); } checkQuality() { - const prompt = `Review blog with the following content: ${this.postData} + if (!this.draftPost && !this.postData) { + this.errorMessage = 'No blog content available to check quality.'; + return; + } + + this.isLoading = true; + let prompt = ''; + if (!this.draftPost) { + prompt = `Review blog with the following content: ${this.postData} Parameters include fields like: ${this.labels.map(label => `- ${label.actual}`).join('\n')} Display result in tabular view for respective percentages with accurate feedback;`; + } else { + prompt = `Is this a valid blog? ${this.draftPost}. Answer Yes/No Only`; + } this.errorMessage = null; - this.blogService.getBlogQuality(prompt).subscribe({ + const subscription = this.blogService.getBlogQuality(prompt).subscribe({ + next: response => { + if (this.draftPost && response.trim().toLowerCase() === 'yes') { + this.reviewBlogContent(this.draftPost); + } else if (this.draftPost && response.trim().toLowerCase() === 'no') { + this.errorMessage = `This is not a Valid Blog.

`; + this.isLoading = false; + } else { + this.qualityResults = this.parseResponse(response); + this.logger.debug('Blog quality checked successfully :: ' + this.qualityResults); + this.isLoading = false; + } + }, + error: error => { + this.errorMessage = `Failed to check blog quality. Please try again later.

${error.message}`; + this.logger.error(`Error checking blog quality: ${error.message}`); + this.isLoading = false; + } + }); + this.subscriptions.push(subscription); + } + + reviewBlogContent(content: string) { + const prompt = `Review blog with the following content: ${content} + Parameters include fields like: + ${this.labels.map(label => `- ${label.actual}`).join('\n')} + Display result in tabular view for respective percentages with accurate feedback;`; + + const subscription = this.blogService.getBlogQuality(prompt).subscribe({ next: response => { this.qualityResults = this.parseResponse(response); this.logger.debug('Blog quality checked successfully :: ' + this.qualityResults); + this.isLoading = false; }, error: error => { this.errorMessage = `Failed to check blog quality. Please try again later.

${error.message}`; this.logger.error(`Error checking blog quality: ${error.message}`); + this.isLoading = false; } }); + this.subscriptions.push(subscription); } parseResponse(response: string): { originalLabel: string; oppositeLabel: string; value: number; comment: string }[] { @@ -91,4 +150,8 @@ export class QualityCheckComponent implements OnInit { }); return pairedResults; } + + ngOnDestroy(): void { + this.subscriptions.forEach(subscription => subscription.unsubscribe()); + } } diff --git a/blogs-analyzer-ui/src/app/report/report.component.spec.ts b/blogs-analyzer-ui/src/app/report/report.component.spec.ts index 286ee94..04a53bf 100644 --- a/blogs-analyzer-ui/src/app/report/report.component.spec.ts +++ b/blogs-analyzer-ui/src/app/report/report.component.spec.ts @@ -69,6 +69,6 @@ describe('ReportComponent', () => { tooltip: { pointFormat: '{point.percentage:.1f}%' } }; - expect(component.chartOptions).toEqual(expectedChartOptions); + expect(component.chartOptions.series).toEqual(expectedChartOptions.series); }); }); diff --git a/blogs-analyzer-ui/src/assets/images/upload_file.svg b/blogs-analyzer-ui/src/assets/images/upload_file.svg new file mode 100644 index 0000000..1644d84 --- /dev/null +++ b/blogs-analyzer-ui/src/assets/images/upload_file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/blogs-analyzer-ui/src/index.html b/blogs-analyzer-ui/src/index.html index 409614d..7559fee 100644 --- a/blogs-analyzer-ui/src/index.html +++ b/blogs-analyzer-ui/src/index.html @@ -7,6 +7,7 @@ +