cat-documents-ng 0.1.28 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ng-package.json +11 -0
- package/package.json +20 -25
- package/{Shared/constant/ERROR.d.ts → src/Shared/constant/ERROR.ts} +38 -36
- package/src/Shared/constant/PERMISSIONS.ts +16 -0
- package/src/Shared/constant/SHARED.ts +312 -0
- package/{Shared/constant/URLS.d.ts → src/Shared/constant/URLS.ts} +65 -60
- package/src/Shared/services/app-config.service.spec.ts +19 -0
- package/src/Shared/services/app-config.service.ts +73 -0
- package/{Shared/services/global-error.handler.d.ts → src/Shared/services/global-error.handler.ts} +29 -27
- package/src/Shared/services/session.service.spec.ts +16 -0
- package/src/Shared/services/session.service.ts +76 -0
- package/src/assets/config/api.config.json +20 -0
- package/src/lib/document/components/document-container/document-container.component.html +14 -0
- package/src/lib/document/components/document-container/document-container.component.scss +8 -0
- package/src/lib/document/components/document-container/document-container.component.spec.ts +110 -0
- package/src/lib/document/components/document-container/document-container.component.ts +173 -0
- package/src/lib/document/components/document-list/document-list.component.html +81 -0
- package/src/lib/document/components/document-list/document-list.component.scss +82 -0
- package/src/lib/document/components/document-list/document-list.component.spec.ts +96 -0
- package/src/lib/document/components/document-list/document-list.component.ts +244 -0
- package/src/lib/document/components/document-list-item/document-list-item.component.html +36 -0
- package/src/lib/document/components/document-list-item/document-list-item.component.scss +34 -0
- package/src/lib/document/components/document-list-item/document-list-item.component.spec.ts +75 -0
- package/src/lib/document/components/document-list-item/document-list-item.component.ts +40 -0
- package/src/lib/document/components/document-upload/document-upload.component.html +56 -0
- package/src/lib/document/components/document-upload/document-upload.component.scss +32 -0
- package/src/lib/document/components/document-upload/document-upload.component.spec.ts +95 -0
- package/src/lib/document/components/document-upload/document-upload.component.ts +162 -0
- package/src/lib/document/components/document-viewer/document-viewer.component.html +98 -0
- package/src/lib/document/components/document-viewer/document-viewer.component.scss +54 -0
- package/src/lib/document/components/document-viewer/document-viewer.component.spec.ts +79 -0
- package/src/lib/document/components/document-viewer/document-viewer.component.ts +106 -0
- package/src/lib/document/components/folder-block/folder-block.component.html +46 -0
- package/src/lib/document/components/folder-block/folder-block.component.scss +9 -0
- package/src/lib/document/components/folder-block/folder-block.component.spec.ts +70 -0
- package/{lib/document/components/folder-block/folder-block.component.d.ts → src/lib/document/components/folder-block/folder-block.component.ts} +53 -37
- package/src/lib/document/components/folder-container/folder-container.component.html +2 -0
- package/src/lib/document/components/folder-container/folder-container.component.scss +0 -0
- package/src/lib/document/components/folder-container/folder-container.component.spec.ts +27 -0
- package/src/lib/document/components/folder-container/folder-container.component.ts +37 -0
- package/src/lib/document/components/linked-document/linked-document.component.html +23 -0
- package/src/lib/document/components/linked-document/linked-document.component.scss +10 -0
- package/src/lib/document/components/linked-document/linked-document.component.spec.ts +61 -0
- package/src/lib/document/components/linked-document/linked-document.component.ts +49 -0
- package/src/lib/document/directives/document.directive.ts +32 -0
- package/src/lib/document/directives/permission.directive.spec.ts +0 -0
- package/src/lib/document/directives/permission.directive.ts +66 -0
- package/src/lib/document/document.module.ts +241 -0
- package/{lib/document/models/document-alert.model.d.ts → src/lib/document/models/document-alert.model.ts} +45 -38
- package/src/lib/document/models/document-type.model.ts +44 -0
- package/src/lib/document/models/document.model.ts +53 -0
- package/{lib/document/models/folder.model.d.ts → src/lib/document/models/folder.model.ts} +35 -29
- package/src/lib/document/services/document-http.service.spec.ts +119 -0
- package/src/lib/document/services/document-http.service.ts +125 -0
- package/src/lib/document/services/document-upload.service.spec.ts +99 -0
- package/src/lib/document/services/document-upload.service.ts +127 -0
- package/src/lib/document/services/document.service.ts +29 -0
- package/src/lib/document/services/file-format.service.spec.ts +16 -0
- package/src/lib/document/services/file-format.service.ts +41 -0
- package/src/lib/document/state/document.query.ts +52 -0
- package/{lib/document/state/document.service.d.ts → src/lib/document/state/document.service.ts} +95 -64
- package/{lib/document/state/document.state.d.ts → src/lib/document/state/document.state.ts} +52 -36
- package/src/lib/document/state/document.store.ts +51 -0
- package/{public-api.d.ts → src/public-api.ts} +10 -6
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +15 -0
- package/Shared/constant/PERMISSIONS.d.ts +0 -15
- package/Shared/constant/SHARED.d.ts +0 -209
- package/Shared/services/app-config.service.d.ts +0 -51
- package/Shared/services/session.service.d.ts +0 -46
- package/fesm2022/cat-documents-ng.mjs +0 -2538
- package/fesm2022/cat-documents-ng.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/lib/document/components/document-container/document-container.component.d.ts +0 -85
- package/lib/document/components/document-list/document-list.component.d.ts +0 -160
- package/lib/document/components/document-list-item/document-list-item.component.d.ts +0 -28
- package/lib/document/components/document-upload/document-upload.component.d.ts +0 -120
- package/lib/document/components/document-viewer/document-viewer.component.d.ts +0 -73
- package/lib/document/components/folder-container/folder-container.component.d.ts +0 -29
- package/lib/document/components/linked-document/linked-document.component.d.ts +0 -38
- package/lib/document/directives/document.directive.d.ts +0 -20
- package/lib/document/directives/permission.directive.d.ts +0 -38
- package/lib/document/document.module.d.ts +0 -40
- package/lib/document/models/document-type.model.d.ts +0 -37
- package/lib/document/models/document.model.d.ts +0 -44
- package/lib/document/services/document-http.service.d.ts +0 -69
- package/lib/document/services/document-upload.service.d.ts +0 -67
- package/lib/document/services/document.service.d.ts +0 -20
- package/lib/document/services/file-format.service.d.ts +0 -23
- package/lib/document/state/document.query.d.ts +0 -42
- package/lib/document/state/document.store.d.ts +0 -29
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { DocumentUploadComponent } from './document-upload.component';
|
|
3
|
+
import { FileUploadModule } from 'primeng/fileupload';
|
|
4
|
+
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
|
5
|
+
import { MessageService, PrimeNGConfig } from 'primeng/api';
|
|
6
|
+
import { ChangeDetectorRef } from '@angular/core';
|
|
7
|
+
import { FileFormatService } from '../../services/file-format.service';
|
|
8
|
+
import { DocumentService } from '../../state/document.service';
|
|
9
|
+
import { DocumentUploadService } from '../../services/document-upload.service';
|
|
10
|
+
|
|
11
|
+
describe('DocumentUploadComponent', () => {
|
|
12
|
+
let component: DocumentUploadComponent;
|
|
13
|
+
let fixture: ComponentFixture<DocumentUploadComponent>;
|
|
14
|
+
let mockFileFormatService: jasmine.SpyObj<FileFormatService>;
|
|
15
|
+
let mockDocumentService: jasmine.SpyObj<DocumentService>;
|
|
16
|
+
let mockDocumentUploadService: jasmine.SpyObj<DocumentUploadService>;
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
mockFileFormatService = jasmine.createSpyObj('FileFormatService', ['formatFileSize']);
|
|
20
|
+
mockDocumentService = jasmine.createSpyObj('DocumentService', ['uploadDocument']);
|
|
21
|
+
mockDocumentUploadService = jasmine.createSpyObj('DocumentUploadService', ['getUploadFileData']);
|
|
22
|
+
|
|
23
|
+
await TestBed.configureTestingModule({
|
|
24
|
+
declarations: [DocumentUploadComponent],
|
|
25
|
+
imports: [FileUploadModule, HttpClientTestingModule],
|
|
26
|
+
providers: [
|
|
27
|
+
MessageService,
|
|
28
|
+
PrimeNGConfig,
|
|
29
|
+
ChangeDetectorRef,
|
|
30
|
+
{ provide: FileFormatService, useValue: mockFileFormatService },
|
|
31
|
+
{ provide: DocumentService, useValue: mockDocumentService },
|
|
32
|
+
{ provide: DocumentUploadService, useValue: mockDocumentUploadService },
|
|
33
|
+
],
|
|
34
|
+
}).compileComponents();
|
|
35
|
+
|
|
36
|
+
fixture = TestBed.createComponent(DocumentUploadComponent);
|
|
37
|
+
component = fixture.componentInstance;
|
|
38
|
+
fixture.detectChanges();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should create', () => {
|
|
42
|
+
expect(component).toBeTruthy();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should trigger file upload dialog when triggerFileUpload is called', () => {
|
|
46
|
+
spyOn(component.fileUploader, 'choose');
|
|
47
|
+
component.triggerFileUpload();
|
|
48
|
+
expect(component.fileUploader.choose).toHaveBeenCalled();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should handle file selection and upload', () => {
|
|
52
|
+
const mockFile = new File(['content'], 'test.pdf', { type: 'application/pdf' });
|
|
53
|
+
const event = { currentFiles: [mockFile] };
|
|
54
|
+
mockFileFormatService.formatFileSize.and.returnValue('10 KB');
|
|
55
|
+
component.onSelectedFiles(event);
|
|
56
|
+
expect(mockDocumentUploadService.getUploadFileData).toHaveBeenCalledWith(mockFile, component.contextId);
|
|
57
|
+
expect(component.uploadedFiles.length).toBe(1);
|
|
58
|
+
expect(component.uploadedFiles[0].file).toBe(mockFile);
|
|
59
|
+
expect(component.uploadedFiles[0].formattedSize).toBe('10 KB');
|
|
60
|
+
expect(component.uploadedFiles[0].progress).toBe(100);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should remove a file from the uploaded files list', () => {
|
|
64
|
+
const mockFile = new File(['content'], 'test.pdf', { type: 'application/pdf' });
|
|
65
|
+
component.uploadedFiles = [
|
|
66
|
+
{ file: mockFile, formattedSize: '10 KB', progress: 100 },
|
|
67
|
+
];
|
|
68
|
+
const fileProgressSpy = spyOn(component.fileProgress, 'delete');
|
|
69
|
+
component.handleDocumentRemove(mockFile, 0);
|
|
70
|
+
expect(component.uploadedFiles.length).toBe(0);
|
|
71
|
+
expect(fileProgressSpy).toHaveBeenCalledWith(mockFile);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should calculate and return file progress', () => {
|
|
75
|
+
const mockFile = new File(['content'], 'test.pdf', { type: 'application/pdf' });
|
|
76
|
+
component.fileProgress.set(mockFile, 75);
|
|
77
|
+
const progress = component.getProgress(mockFile);
|
|
78
|
+
expect(progress).toBe(75);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should format file size correctly', () => {
|
|
82
|
+
mockFileFormatService.formatFileSize.and.returnValue('10 KB');
|
|
83
|
+
component.formatSize(10240);
|
|
84
|
+
expect(component.fileSize).toBe('10 KB');
|
|
85
|
+
expect(mockFileFormatService.formatFileSize).toHaveBeenCalledWith(10240, jasmine.any(PrimeNGConfig));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should clear files after selection', () => {
|
|
89
|
+
spyOn(component.fileUploader, 'clear');
|
|
90
|
+
const mockFile = new File(['content'], 'test.pdf', { type: 'application/pdf' });
|
|
91
|
+
const event = { currentFiles: [mockFile] };
|
|
92
|
+
component.onSelectedFiles(event);
|
|
93
|
+
expect(component.fileUploader.clear).toHaveBeenCalled();
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { ChangeDetectorRef, Component, Input, ViewChild, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
import { FileUpload } from 'primeng/fileupload';
|
|
3
|
+
import { MessageService } from 'primeng/api';
|
|
4
|
+
import { PrimeNGConfig } from 'primeng/api';
|
|
5
|
+
import { SHARED } from '../../../../Shared/constant/SHARED';
|
|
6
|
+
import { FileFormatService } from '../../services/file-format.service';
|
|
7
|
+
import { DocumentService } from '../../state/document.service';
|
|
8
|
+
import { DocumentUploadService } from '../../services/document-upload.service';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A component for handling document uploads, including file selection, removal, and progress tracking.
|
|
12
|
+
* @class DocumentUploadComponent
|
|
13
|
+
*/
|
|
14
|
+
@Component({
|
|
15
|
+
selector: 'lib-document-upload',
|
|
16
|
+
templateUrl: './document-upload.component.html',
|
|
17
|
+
styleUrls: ['./document-upload.component.scss'],
|
|
18
|
+
standalone: false,
|
|
19
|
+
encapsulation: ViewEncapsulation.None
|
|
20
|
+
})
|
|
21
|
+
export class DocumentUploadComponent {
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Represents the file size.
|
|
26
|
+
* @type {number}
|
|
27
|
+
*/
|
|
28
|
+
fileSize: string = SHARED.EMPTY;
|
|
29
|
+
/**
|
|
30
|
+
* Represent contextId
|
|
31
|
+
* @type {string}
|
|
32
|
+
*/
|
|
33
|
+
@Input() contextId: string = SHARED.EMPTY
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* To make file explorer visible.
|
|
37
|
+
* @type {!FileUpload}
|
|
38
|
+
*/
|
|
39
|
+
@ViewChild('fileUploader') fileUploader!: FileUpload;
|
|
40
|
+
|
|
41
|
+
fileProgress: Map<File, number> = new Map();
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* List of files selected for upload.
|
|
45
|
+
* @type {File[]}
|
|
46
|
+
*/
|
|
47
|
+
uploadedFiles: { file: File; formattedSize: string; progress: number }[] = [];
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Percentage of the total size calculated for displaying upload progress.
|
|
52
|
+
* @type {number}
|
|
53
|
+
*/
|
|
54
|
+
totalSizePercent: number = SHARED.INITIAL_COUNT;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The current upload progress percentage (SHARED.INITIAL_VALUE-100).
|
|
58
|
+
* @type {number}
|
|
59
|
+
*/
|
|
60
|
+
uploadProgress: number = SHARED.INITIAL_COUNT;
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates an instance of DocumentUploadComponent.
|
|
65
|
+
* @class
|
|
66
|
+
* @param {DocumentUploadService} documentUpload - Service for handling document upload.
|
|
67
|
+
* @param {DocumentService} uploadService - Service for handling document upload.
|
|
68
|
+
* @param {PrimeNGConfig} config - PrimeNG configuration.
|
|
69
|
+
* @param {FileFormatService} fileFormatService - Service for formatting file sizes.
|
|
70
|
+
* @param {MessageService} messageService - Service for displaying messages.
|
|
71
|
+
* @param {ChangeDetectorRef} cdr - Service for detecting changes.
|
|
72
|
+
*/
|
|
73
|
+
constructor(public documentUpload : DocumentUploadService,public uploadService: DocumentService, private config: PrimeNGConfig, public fileFormatService: FileFormatService, public messageService: MessageService, public cdr: ChangeDetectorRef) { }
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Open the file explorer.
|
|
77
|
+
* @param {*} event - The triggering event.
|
|
78
|
+
* @param {() => void} callback - A callback function to execute.
|
|
79
|
+
* @returns {void} - No return value.
|
|
80
|
+
*/
|
|
81
|
+
choose(event: any, callback: () => void) {
|
|
82
|
+
callback();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Prepares the files for upload by creating a FormData object.
|
|
87
|
+
* This method appends each file to the FormData for submission.
|
|
88
|
+
* @param {File} file - The file to upload.
|
|
89
|
+
* @returns {void}
|
|
90
|
+
*/
|
|
91
|
+
handleTemplatedUpload(file: File) {
|
|
92
|
+
this.documentUpload.getUploadFileData(file, this.contextId)
|
|
93
|
+
const formattedSize = this.fileFormatService.formatFileSize(file.size, this.config);
|
|
94
|
+
const progress = 100;
|
|
95
|
+
this.uploadedFiles.push({ file, formattedSize, progress });
|
|
96
|
+
this.fileProgress.set(file, progress);
|
|
97
|
+
this.totalSizePercent = 100;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Handle the creation of formdata.
|
|
102
|
+
* @param {File} file - The file to append in formdata.
|
|
103
|
+
* @returns {*} - The formdata object.
|
|
104
|
+
*/
|
|
105
|
+
handleCreateFormData(file: File) {
|
|
106
|
+
const formData = new FormData();
|
|
107
|
+
formData.append(SHARED.FILE, file, file.name);
|
|
108
|
+
formData.append(SHARED.CONTEXT_ID, this.contextId)
|
|
109
|
+
return formData;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Handles the event when new files are selected.
|
|
113
|
+
* @param { { currentFiles: File[] } } event - The event containing the newly selected files.
|
|
114
|
+
* @returns {void} - No return value.
|
|
115
|
+
*/
|
|
116
|
+
onSelectedFiles(event: { currentFiles: File[] }): void {
|
|
117
|
+
event.currentFiles.forEach((file: File) => {
|
|
118
|
+
this.handleTemplatedUpload(file);
|
|
119
|
+
});
|
|
120
|
+
this.fileUploader.clear();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Formats the given file size in bytes into a readable format (e.g., KB, MB).
|
|
125
|
+
* @param {number} bytes - The size of the file in bytes.
|
|
126
|
+
* @returns {string} The formatted file size (e.g., '1.2 KB', '2.3 MB').
|
|
127
|
+
*/
|
|
128
|
+
formatSize(bytes: number) {
|
|
129
|
+
this.fileSize = this.fileFormatService.formatFileSize(bytes, this.config)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Handles the removal of a file from the uploaded files list.
|
|
134
|
+
* @param {File} file - The file to be removed.
|
|
135
|
+
* @param {number} index - The index of the file in the uploaded files list.
|
|
136
|
+
*/
|
|
137
|
+
handleDocumentRemove(file: File, index: number): void {
|
|
138
|
+
this.uploadedFiles.splice(index, 1);
|
|
139
|
+
this.fileProgress.delete(file);
|
|
140
|
+
this.cdr.detectChanges();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Major progress for the progress bar.
|
|
145
|
+
* @param {File} file - File to check progress for.
|
|
146
|
+
* @returns {number} - The progress percentage for the file.
|
|
147
|
+
*/
|
|
148
|
+
getProgress(file: File): number {
|
|
149
|
+
return this.fileProgress.get(file) || SHARED.INITIAL_COUNT;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Triggers the file upload dialog.
|
|
154
|
+
* Opens the file explorer for selecting files.
|
|
155
|
+
* @returns {void}
|
|
156
|
+
*/
|
|
157
|
+
triggerFileUpload() {
|
|
158
|
+
this.fileUploader.choose();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<div class="grid">
|
|
2
|
+
<div class="col-12">
|
|
3
|
+
<div class="p-fluid p-formgrid grid m-0">
|
|
4
|
+
<div class="col-12 md:col-12 md:flex justify-content-evenly">
|
|
5
|
+
@if(selectedDocument){
|
|
6
|
+
<div id="outerContainer col-12 md:col-7">
|
|
7
|
+
<div
|
|
8
|
+
*ngIf="isImage(selectedDocument?.contentType)"
|
|
9
|
+
class="img-container"
|
|
10
|
+
>
|
|
11
|
+
<img
|
|
12
|
+
[src]="selectedDocument?.documentUrl || ''"
|
|
13
|
+
class="uploadedImages"
|
|
14
|
+
alt="Document Image"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
@if(selectedDocument?.contentType && selectedDocument?.contentType === "application/pdf"){
|
|
18
|
+
<div class="pdf-container">
|
|
19
|
+
<pdf-viewer
|
|
20
|
+
[src]="selectedDocument?.documentUrl || ''"
|
|
21
|
+
[rotation]="0"
|
|
22
|
+
[original-size]="false"
|
|
23
|
+
[show-all]="true"
|
|
24
|
+
[fit-to-page]="false"
|
|
25
|
+
[zoom]="1"
|
|
26
|
+
[zoom-scale]="'page-width'"
|
|
27
|
+
[stick-to-page]="false"
|
|
28
|
+
[render-text]="true"
|
|
29
|
+
[external-link-target]="'blank'"
|
|
30
|
+
[autoresize]="true"
|
|
31
|
+
[show-borders]="false"
|
|
32
|
+
style="width: 50vw; height: 75vh"
|
|
33
|
+
></pdf-viewer>
|
|
34
|
+
</div>
|
|
35
|
+
}@else{
|
|
36
|
+
<div class="incorrect-docType">
|
|
37
|
+
ContentType is incorrect.
|
|
38
|
+
</div>
|
|
39
|
+
}
|
|
40
|
+
</div>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
<div class="left-part col-12 md:col-3 pt-0">
|
|
44
|
+
<div class="alerts mb-4 pb-1">
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
*ngIf="
|
|
48
|
+
(alertData?.status !== 'Pending' && !!alertData?.status) ||
|
|
49
|
+
alertData?.isAlert === false
|
|
50
|
+
"
|
|
51
|
+
class="bg-green-500 border-none border-round-md flex align-items-center mb-3 p-2 px-3"
|
|
52
|
+
>
|
|
53
|
+
<i
|
|
54
|
+
class="pi pi-verified mr-2 cursor-pointer"
|
|
55
|
+
[ngStyle]="{
|
|
56
|
+
color:
|
|
57
|
+
alertData?.status === 'Pending' &&
|
|
58
|
+
alertData?.isAlert !== false
|
|
59
|
+
? '#FFFFFF'
|
|
60
|
+
: '#8A8EA6'
|
|
61
|
+
}"
|
|
62
|
+
style="font-size: 20px"
|
|
63
|
+
></i>
|
|
64
|
+
<span class="font-semibold text-white">Verified</span>
|
|
65
|
+
</button>
|
|
66
|
+
<div
|
|
67
|
+
class="card mb-0"
|
|
68
|
+
[ngClass]="
|
|
69
|
+
(alertData?.status === 'Pending' || !alertData?.status) &&
|
|
70
|
+
alertData?.isAlert !== false
|
|
71
|
+
? 'alert-card'
|
|
72
|
+
: 'success-alert'
|
|
73
|
+
"
|
|
74
|
+
>
|
|
75
|
+
<div class="flex align-items-center mb-2 pb-1" *ngIf="alertData?.status !== 'Verified'">
|
|
76
|
+
<h4 class="mr-3 mt-0 mb-0 text-color font-bold" style="font-size: 21px; font-weight: bold; border-color: rgba(68, 72, 109, 0.2) ;" >Alerts</h4>
|
|
77
|
+
<i
|
|
78
|
+
class="pi pi-exclamation-triangle"
|
|
79
|
+
style="font-size: 20px"
|
|
80
|
+
[ngStyle]="{
|
|
81
|
+
color:
|
|
82
|
+
(alertData?.status === 'Pending' || !alertData?.status) &&
|
|
83
|
+
alertData?.isAlert !== false
|
|
84
|
+
? '#FB392D'
|
|
85
|
+
: '#8A8EA6'
|
|
86
|
+
}"
|
|
87
|
+
></i>
|
|
88
|
+
</div>
|
|
89
|
+
<p class="text-color mb-0">{{ alertData?.alertMessage }}</p>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<ng-content></ng-content>
|
|
93
|
+
<app-linked-document (selectedDocumentChange)="handleSelectedDocument($event)" [selectedDocument]="selectedDocument" [documentList]="documentList"></app-linked-document>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
.alert-card {
|
|
2
|
+
background-color: #fb392d1a;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.success-alert {
|
|
6
|
+
border-radius: 10px;
|
|
7
|
+
border: 1px solid rgba(251, 57, 45, 0.1);
|
|
8
|
+
background: linear-gradient(0deg, #dedede 0%, #dedede 100%), #fff;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.p-timeline-event-opposite {
|
|
12
|
+
display: none;
|
|
13
|
+
}
|
|
14
|
+
.decription {
|
|
15
|
+
color: #676b89;
|
|
16
|
+
}
|
|
17
|
+
.textAreaControl textarea {
|
|
18
|
+
width: 100%;
|
|
19
|
+
resize: vertical;
|
|
20
|
+
max-width: 100%;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.document-btn-wrapper {
|
|
24
|
+
.p-button-outlined {
|
|
25
|
+
color: #f57c00;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.document-viewer{
|
|
30
|
+
.p-dialog{
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
max-height: 100% !important;
|
|
34
|
+
box-shadow: none !important;
|
|
35
|
+
}
|
|
36
|
+
.p-dialog-header-close-icon{
|
|
37
|
+
height: 20px;
|
|
38
|
+
width: 20px;
|
|
39
|
+
}
|
|
40
|
+
.p-dialog-header{
|
|
41
|
+
background-color:#FFF;
|
|
42
|
+
border-radius: 0;
|
|
43
|
+
}
|
|
44
|
+
.p-dialog-content{
|
|
45
|
+
background-color:#FFF;
|
|
46
|
+
border-radius: 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.uploadedImages{
|
|
51
|
+
width: 95%;
|
|
52
|
+
height: 100%;
|
|
53
|
+
object-fit: contain;
|
|
54
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { DocumentViewerComponent } from './document-viewer.component';
|
|
3
|
+
import { TimelineModule } from 'primeng/timeline';
|
|
4
|
+
import { FormsModule } from '@angular/forms';
|
|
5
|
+
import { CheckboxModule } from 'primeng/checkbox';
|
|
6
|
+
import { HttpClientModule } from '@angular/common/http';
|
|
7
|
+
import { DocumentService } from '../../services/document.service';
|
|
8
|
+
import { DocumentHttpService } from '../../services/document-http.service';
|
|
9
|
+
import { of } from 'rxjs';
|
|
10
|
+
import { DocumentModel } from '../../models/document.model';
|
|
11
|
+
import { LinkedDocumentComponent } from '../linked-document/linked-document.component';
|
|
12
|
+
|
|
13
|
+
describe('DocumentViewerComponent', () => {
|
|
14
|
+
let component: DocumentViewerComponent;
|
|
15
|
+
let fixture: ComponentFixture<DocumentViewerComponent>;
|
|
16
|
+
let documentService: jasmine.SpyObj<DocumentService>;
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
const documentServiceSpy = jasmine.createSpyObj('DocumentService', ['set']);
|
|
20
|
+
|
|
21
|
+
await TestBed.configureTestingModule({
|
|
22
|
+
declarations: [DocumentViewerComponent, LinkedDocumentComponent],
|
|
23
|
+
imports: [TimelineModule, FormsModule, CheckboxModule, HttpClientModule],
|
|
24
|
+
providers: [
|
|
25
|
+
{ provide: DocumentService, useValue: documentServiceSpy },
|
|
26
|
+
DocumentHttpService,
|
|
27
|
+
],
|
|
28
|
+
}).compileComponents();
|
|
29
|
+
|
|
30
|
+
fixture = TestBed.createComponent(DocumentViewerComponent);
|
|
31
|
+
component = fixture.componentInstance;
|
|
32
|
+
documentService = TestBed.inject(DocumentService) as jasmine.SpyObj<DocumentService>;
|
|
33
|
+
fixture.detectChanges();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should create', () => {
|
|
37
|
+
expect(component).toBeTruthy();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should call set method of documentService on ngOnChanges when selectedDocument is set', () => {
|
|
41
|
+
const document: DocumentModel = { _id: '22', contentType: 'image/png', documentUrl: 'http://example.com/image.png', status: 'approved' };
|
|
42
|
+
component.selectedDocument = document;
|
|
43
|
+
component.ngOnChanges();
|
|
44
|
+
expect(documentService.set).toHaveBeenCalledWith(document);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should determine if content type is an image', () => {
|
|
48
|
+
const validImageType = 'image/png';
|
|
49
|
+
const invalidImageType = 'application/pdf';
|
|
50
|
+
expect(component.isImage(validImageType)).toBeTrue();
|
|
51
|
+
expect(component.isImage(invalidImageType)).toBeFalse();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should set selectedDocument correctly when handleSelectedDocument is called', () => {
|
|
55
|
+
const document: DocumentModel = { _id: '22', contentType: 'image/png', documentUrl: 'http://example.com/image.png' };
|
|
56
|
+
component.handleSelectedDocument(document);
|
|
57
|
+
expect(component.selectedDocument).toEqual(document);
|
|
58
|
+
expect(documentService.set).toHaveBeenCalledWith(document);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should display the document image if selectedDocument is an image', () => {
|
|
62
|
+
const imageDocument: DocumentModel = {
|
|
63
|
+
_id : "122",
|
|
64
|
+
contentType: 'image/png',
|
|
65
|
+
documentUrl: 'http://example.com/image.png',
|
|
66
|
+
};
|
|
67
|
+
component.selectedDocument = imageDocument;
|
|
68
|
+
fixture.detectChanges();
|
|
69
|
+
const imgElement = fixture.debugElement.nativeElement.querySelector('.img-container img');
|
|
70
|
+
expect(imgElement).toBeTruthy();
|
|
71
|
+
expect(imgElement.src).toContain('http://example.com/image.png');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should update isVerified flag', () => {
|
|
75
|
+
component.isVerified = true;
|
|
76
|
+
fixture.detectChanges();
|
|
77
|
+
expect(component.isVerified).toBeTrue();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Component,
|
|
3
|
+
Input,
|
|
4
|
+
OnChanges,
|
|
5
|
+
OnDestroy,
|
|
6
|
+
SimpleChanges,
|
|
7
|
+
ViewEncapsulation,
|
|
8
|
+
} from '@angular/core';
|
|
9
|
+
import { DynamicDialogRef } from 'primeng/dynamicdialog';
|
|
10
|
+
import { DocumentAlertList, DUMMYSUMMARY, SHARED, SUPPORTED_IMAGE_TYPES } from '../../../../Shared/constant/SHARED';
|
|
11
|
+
import { DocumentHttpService } from '../../services/document-http.service';
|
|
12
|
+
import { Subscription } from 'rxjs';
|
|
13
|
+
import { DocumentModel } from '../../models/document.model';
|
|
14
|
+
import { DocumentService } from '../../services/document.service';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Component for viewing and managing document details.
|
|
18
|
+
* @class DocumentViewerComponent
|
|
19
|
+
* @typedef {DocumentViewerComponent}
|
|
20
|
+
*/
|
|
21
|
+
@Component({
|
|
22
|
+
selector: 'document-viewer',
|
|
23
|
+
templateUrl: './document-viewer.component.html',
|
|
24
|
+
standalone : false,
|
|
25
|
+
styleUrl: './document-viewer.component.scss',
|
|
26
|
+
encapsulation: ViewEncapsulation.None,
|
|
27
|
+
})
|
|
28
|
+
export class DocumentViewerComponent implements OnChanges, OnDestroy {
|
|
29
|
+
/**
|
|
30
|
+
* Get the selected document by user.
|
|
31
|
+
* @type {*}
|
|
32
|
+
*/
|
|
33
|
+
@Input() selectedDocument?: DocumentModel; // <-- Made optional to prevent undefined issues
|
|
34
|
+
/**
|
|
35
|
+
* Get the selected document by user.
|
|
36
|
+
* @type {*}
|
|
37
|
+
*/
|
|
38
|
+
@Input() documentList?: DocumentModel[]; // <-- Made optional to prevent undefined issues
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Indicates whether a checkbox is selected.
|
|
42
|
+
* @type {boolean}
|
|
43
|
+
*/
|
|
44
|
+
checked: boolean = false;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Reference to the dynamic dialog used for displaying additional details.
|
|
48
|
+
* @type {(DynamicDialogRef | undefined)}
|
|
49
|
+
*/
|
|
50
|
+
ref: DynamicDialogRef | undefined;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Indicates whether the document has been verified.
|
|
54
|
+
* @type {boolean}
|
|
55
|
+
*/
|
|
56
|
+
isVerified: boolean = false;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Data used for displaying alert messages.
|
|
60
|
+
* @type {any}
|
|
61
|
+
*/
|
|
62
|
+
alertData!: any;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Holds the subscription to manage observable cleanup.
|
|
66
|
+
* @private
|
|
67
|
+
* @type {Subscription}
|
|
68
|
+
*/
|
|
69
|
+
private subscription: Subscription = new Subscription();
|
|
70
|
+
/**
|
|
71
|
+
* Initializes a new instance of the DocumentViewerComponent.
|
|
72
|
+
* @param {DocumentHttpService} documentHttpService - Handle the http service.
|
|
73
|
+
* @param {DocumentService} documentService - Handle the states.
|
|
74
|
+
*/
|
|
75
|
+
constructor(public documentHttpService : DocumentHttpService, private documentService: DocumentService) {}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Fetches the alerts for the selected document.
|
|
79
|
+
* @returns {void}
|
|
80
|
+
*/
|
|
81
|
+
ngOnChanges() {
|
|
82
|
+
if (this.selectedDocument) {
|
|
83
|
+
this.documentService.set(this.selectedDocument);
|
|
84
|
+
this.alertData = DocumentAlertList.find((res: any) => res.status === this.selectedDocument?.status);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
handleSelectedDocument(document:DocumentModel){
|
|
89
|
+
this.selectedDocument = document
|
|
90
|
+
this.documentService.set(this.selectedDocument);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Determines if the given content type is an image.
|
|
95
|
+
* @param {string | undefined} contentType - The MIME type of the content.
|
|
96
|
+
* @returns {boolean} `true` if the content type is an image; otherwise, `false`.
|
|
97
|
+
*/
|
|
98
|
+
isImage(contentType?: string): boolean {
|
|
99
|
+
return contentType ? SUPPORTED_IMAGE_TYPES.includes(contentType) : false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
ngOnDestroy(): void {
|
|
103
|
+
this.subscription.unsubscribe();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<div class="card p-0 folder-info">
|
|
2
|
+
<div class="text-900 text-xl font-semibold ml-2 mb-1">Folders</div>
|
|
3
|
+
<div class="grid m-0">
|
|
4
|
+
<div *ngFor="let folder of folderList" class="col-12 md:col-6 xl:col-4 container-wrapper">
|
|
5
|
+
<div
|
|
6
|
+
class="p-3 border-1 h-full surface-border flex flex-column justify-content-between hover:surface-100 cursor-pointer border-round"
|
|
7
|
+
(click)="handleClickForFilter(folder._id)"
|
|
8
|
+
>
|
|
9
|
+
<div class="icon">
|
|
10
|
+
<img src="../../../../assets/images/FolderImg.png" alt="" />
|
|
11
|
+
</div>
|
|
12
|
+
<div class="flex flex-column">
|
|
13
|
+
<span class="text-600 mt-2"> {{ folder.documentCount }} Files </span>
|
|
14
|
+
<span class="text-900 text-lg mt-2 mb-2 font-semibold font-medium">
|
|
15
|
+
{{ folder.folderName }}
|
|
16
|
+
</span>
|
|
17
|
+
</div>
|
|
18
|
+
<hr />
|
|
19
|
+
<div class="flex justify-content-between">
|
|
20
|
+
<div class="flex flex-column">
|
|
21
|
+
<span>Missing</span>
|
|
22
|
+
<span
|
|
23
|
+
[ngClass]="{
|
|
24
|
+
'text-pink-500': missingFileCount > 0,
|
|
25
|
+
'text-green-500': missingFileCount === 0
|
|
26
|
+
}"
|
|
27
|
+
>
|
|
28
|
+
{{ missingFileCount }}
|
|
29
|
+
</span>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="flex flex-column">
|
|
32
|
+
<span>Pending</span>
|
|
33
|
+
<span
|
|
34
|
+
[ngClass]="{
|
|
35
|
+
'text-yellow-500': pendingFileCount > 0,
|
|
36
|
+
'text-green-500': pendingFileCount === 0
|
|
37
|
+
}"
|
|
38
|
+
>
|
|
39
|
+
{{ pendingFileCount }}
|
|
40
|
+
</span>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|