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,96 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { DocumentListComponent } from './document-list.component';
|
|
3
|
+
import { DocumentUploadService } from '../../services/document-upload.service';
|
|
4
|
+
import { DocumentHttpService } from '../../services/document-http.service';
|
|
5
|
+
import { of } from 'rxjs';
|
|
6
|
+
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
|
7
|
+
import { DocumentTypeModel } from '../../models/document-type.model';
|
|
8
|
+
import { DocumentModel } from '../../models/document.model';
|
|
9
|
+
import { SHARED } from '../../../../Shared/constant/SHARED';
|
|
10
|
+
|
|
11
|
+
describe('DocumentListComponent', () => {
|
|
12
|
+
let component: DocumentListComponent;
|
|
13
|
+
let fixture: ComponentFixture<DocumentListComponent>;
|
|
14
|
+
let documentUploadService: jasmine.SpyObj<DocumentUploadService>;
|
|
15
|
+
let documentHttpService: jasmine.SpyObj<DocumentHttpService>;
|
|
16
|
+
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
// Mock services
|
|
19
|
+
documentUploadService = jasmine.createSpyObj('DocumentUploadService', [
|
|
20
|
+
'getDocumentNameAndType',
|
|
21
|
+
'handleTemplatedUpload'
|
|
22
|
+
]);
|
|
23
|
+
documentHttpService = jasmine.createSpyObj('DocumentHttpService', ['getDocumentTypes', 'updateDocumentName']);
|
|
24
|
+
|
|
25
|
+
// Mock `getDocumentTypes` to return valid `DocumentTypeModel` objects
|
|
26
|
+
documentHttpService.getDocumentTypes.and.returnValue(
|
|
27
|
+
of([
|
|
28
|
+
{ _id: 1, label: 'Type 1', matchRules: [], name: 'Type 1', parentDocumentTypeId: null },
|
|
29
|
+
{ _id: 2, label: 'Type 2', matchRules: [], name: 'Type 2', parentDocumentTypeId: null }
|
|
30
|
+
] as unknown as DocumentTypeModel[])
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
await TestBed.configureTestingModule({
|
|
34
|
+
declarations: [DocumentListComponent],
|
|
35
|
+
providers: [
|
|
36
|
+
{ provide: DocumentUploadService, useValue: documentUploadService },
|
|
37
|
+
{ provide: DocumentHttpService, useValue: documentHttpService }
|
|
38
|
+
],
|
|
39
|
+
schemas: [NO_ERRORS_SCHEMA] // To suppress schema-related errors
|
|
40
|
+
}).compileComponents();
|
|
41
|
+
|
|
42
|
+
fixture = TestBed.createComponent(DocumentListComponent);
|
|
43
|
+
component = fixture.componentInstance;
|
|
44
|
+
fixture.detectChanges(); // Trigger lifecycle hooks and initial data binding
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should create', () => {
|
|
48
|
+
expect(component).toBeTruthy();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should fetch document types on initialization', () => {
|
|
52
|
+
expect(component.options).toEqual([
|
|
53
|
+
{ label: 'Type 1', value: 1 },
|
|
54
|
+
{ label: 'Type 2', value: 2 }
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should handle file upload click', () => {
|
|
59
|
+
const event = new MouseEvent('click');
|
|
60
|
+
spyOn(event, 'stopPropagation');
|
|
61
|
+
component.handleFileUploadClick(event);
|
|
62
|
+
expect(event.stopPropagation).toHaveBeenCalled();
|
|
63
|
+
expect(component.isSidebarVisible).toBeTrue();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should handle document click and open dialog', () => {
|
|
67
|
+
const mockDocument = { _id: "1", documentUrl: 'http://example.com/doc.pdf' } as DocumentModel;
|
|
68
|
+
|
|
69
|
+
component.handleClickForDocument(mockDocument);
|
|
70
|
+
expect(component.isdialogVisible).toBeTrue();
|
|
71
|
+
expect(component.selectedDocument).toBe(mockDocument);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should handle dialog close and reset selected document', () => {
|
|
75
|
+
component.selectedDocument = { _id: "1" };
|
|
76
|
+
component.handleCloseModal();
|
|
77
|
+
expect(component.selectedDocument).toEqual({ _id: "" });
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
expect(component.isdialogVisible).toBeFalse();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should update document name on handleSaveClick', () => {
|
|
84
|
+
component.fileName = 'New Document';
|
|
85
|
+
component.selectedDocument = { _id: '1' } as DocumentModel;
|
|
86
|
+
|
|
87
|
+
spyOn(console, 'log');
|
|
88
|
+
|
|
89
|
+
documentHttpService.updateDocumentName.and.returnValue(of({} as DocumentModel));
|
|
90
|
+
|
|
91
|
+
component.handleSaveClick();
|
|
92
|
+
expect(documentHttpService.updateDocumentName).toHaveBeenCalledWith('1', { fileName: 'New Document' });
|
|
93
|
+
expect(console.log).toHaveBeenCalledWith(`${SHARED.UPDATE_DOCUMENT_NAME} 1`);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
});
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
import { DocumentModel } from '../../models/document.model';
|
|
3
|
+
import { SHARED } from '../../../../Shared/constant/SHARED';
|
|
4
|
+
import { ERRORS } from '../../../../Shared/constant/ERROR';
|
|
5
|
+
import { DocumentHttpService } from '../../services/document-http.service';
|
|
6
|
+
import { DocumentTypeModel } from '../../models/document-type.model';
|
|
7
|
+
import { DocumentUploadService } from '../../services/document-upload.service';
|
|
8
|
+
import { Message } from 'primeng/api';
|
|
9
|
+
import { DocumentQuery } from '../../state/document.query';
|
|
10
|
+
import { DocumentStore } from '../../state/document.store';
|
|
11
|
+
import { PERMISSIONS } from '../../../../Shared/constant/PERMISSIONS';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* This component is responsible for displaying and managing a list of documents.
|
|
15
|
+
* Provides functionality for file upload, document selection, and dialog management.
|
|
16
|
+
* @class DocumentListComponent
|
|
17
|
+
*/
|
|
18
|
+
@Component({
|
|
19
|
+
selector: 'lib-document-list',
|
|
20
|
+
standalone: false,
|
|
21
|
+
templateUrl: './document-list.component.html',
|
|
22
|
+
styleUrls: ['./document-list.component.scss'],
|
|
23
|
+
encapsulation: ViewEncapsulation.None
|
|
24
|
+
})
|
|
25
|
+
export class DocumentListComponent implements OnInit{
|
|
26
|
+
|
|
27
|
+
@Output() onRefresh = new EventEmitter();
|
|
28
|
+
/**
|
|
29
|
+
* Represents the context ID for the document list.
|
|
30
|
+
* This value is passed from the parent component.
|
|
31
|
+
* @type {string}
|
|
32
|
+
* @memberof DocumentListComponent
|
|
33
|
+
*/
|
|
34
|
+
@Input() contextId: string = SHARED.EMPTY;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Default visibility of the upload button.
|
|
38
|
+
* @type {boolean}
|
|
39
|
+
* @memberof DocumentListComponent
|
|
40
|
+
*/
|
|
41
|
+
@Input() isUploadButtonVisible:boolean = SHARED.TRUE;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The currently selected document.
|
|
45
|
+
* @type {DocumentModel}
|
|
46
|
+
* @memberof DocumentListComponent
|
|
47
|
+
*/
|
|
48
|
+
selectedDocument!: DocumentModel;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Default visibility of the sidebar.
|
|
52
|
+
* @type {boolean}
|
|
53
|
+
* @memberof DocumentListComponent
|
|
54
|
+
*/
|
|
55
|
+
isSidebarVisible: boolean = SHARED.FALSE;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Default visibility of the Accordion.
|
|
59
|
+
* @type {boolean}
|
|
60
|
+
* @memberof DocumentListComponent
|
|
61
|
+
*/
|
|
62
|
+
@Input() isCollapsed: boolean = SHARED.FALSE;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Default visibility of the messages.
|
|
66
|
+
* @type {Message[]}
|
|
67
|
+
* @memberof DocumentListComponent
|
|
68
|
+
*/
|
|
69
|
+
messages: Message[] = SHARED.EMPTY_ARRAY;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Default visibility of the dialog.
|
|
73
|
+
* @type {boolean}
|
|
74
|
+
* @memberof DocumentListComponent
|
|
75
|
+
*/
|
|
76
|
+
isdialogVisible: boolean = SHARED.FALSE;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The list of documents to display.
|
|
80
|
+
* This value is passed from the parent component.
|
|
81
|
+
* @type {DocumentModel[]}
|
|
82
|
+
* @memberof DocumentListComponent
|
|
83
|
+
*/
|
|
84
|
+
@Input() documentList: DocumentModel[] = SHARED.EMPTY_ARRAY;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The name of the document being uploaded or managed.
|
|
88
|
+
* @type {string}
|
|
89
|
+
* @memberof DocumentListComponent
|
|
90
|
+
*/
|
|
91
|
+
documentName: string = SHARED.EMPTY;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Available document types for selection.
|
|
95
|
+
* @type {string[]}
|
|
96
|
+
* @memberof DocumentListComponent
|
|
97
|
+
*/
|
|
98
|
+
options : any[] = SHARED.EMPTY_ARRAY;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The selected option for the document type.
|
|
102
|
+
* @type {(string | null)}
|
|
103
|
+
* @memberof DocumentListComponent
|
|
104
|
+
*/
|
|
105
|
+
selectedOption: string | null = null;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The set of permissions available for this component.
|
|
109
|
+
*/
|
|
110
|
+
PERMISSION = PERMISSIONS;
|
|
111
|
+
/**
|
|
112
|
+
* The file name associated with the document.
|
|
113
|
+
* It may be undefined until a file is selected or loaded.
|
|
114
|
+
* @type {string | undefined}
|
|
115
|
+
*/
|
|
116
|
+
fileName!: string | undefined;
|
|
117
|
+
/**
|
|
118
|
+
* Creates an instance of DocumentListComponent.
|
|
119
|
+
* @class
|
|
120
|
+
* @param {DocumentUploadService} documentUploadService - The service responsible for uploading documents.
|
|
121
|
+
* @param {DocumentHttpService} documentHttpService - The service responsible for fetching documents from the server.
|
|
122
|
+
* @param {DocumentQuery} documentQuery - The service responsible for geting stored documents.
|
|
123
|
+
* @param {DocumentStore} documentStore - The service responsible for storing documents.
|
|
124
|
+
*/
|
|
125
|
+
constructor(public documentUploadService : DocumentUploadService ,public documentHttpService : DocumentHttpService, public documentQuery : DocumentQuery, public documentStore : DocumentStore) {
|
|
126
|
+
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Initializes the component by fetching the document type list.
|
|
131
|
+
*/
|
|
132
|
+
ngOnInit(): void {
|
|
133
|
+
this.getDocumentTypeList();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Handles the click event for file upload.
|
|
138
|
+
* Prevents event propagation and displays the sidebar.
|
|
139
|
+
* @param {MouseEvent} event - The click event triggered by the user.
|
|
140
|
+
* @memberof DocumentListComponent
|
|
141
|
+
*/
|
|
142
|
+
handleFileUploadClick(event: MouseEvent): void {
|
|
143
|
+
event.stopPropagation();
|
|
144
|
+
this.documentStore.setMessage(SHARED.EMPTY_ARRAY)
|
|
145
|
+
this.isSidebarVisible = SHARED.TRUE;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Handles the selection of an individual document.
|
|
150
|
+
* Opens a dialog to display or manage the selected document.
|
|
151
|
+
* @param {DocumentModel} document - The document that was clicked by the user.
|
|
152
|
+
* @memberof DocumentListComponent
|
|
153
|
+
*/
|
|
154
|
+
handleClickForDocument(document: DocumentModel): void {
|
|
155
|
+
this.isdialogVisible = SHARED.TRUE;
|
|
156
|
+
this.selectedDocument = document;
|
|
157
|
+
this.fileName = document.fileName;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Handles the save click event to update the document's file name.
|
|
162
|
+
* This method creates a payload with the updated file name and calls the
|
|
163
|
+
* updateDocumentName() method from the documentHttpService. On a successful update,
|
|
164
|
+
* it logs a message with the document's ID.
|
|
165
|
+
* @returns {void}
|
|
166
|
+
*/
|
|
167
|
+
handleSaveClick() {
|
|
168
|
+
const payload = { fileName: this.fileName };
|
|
169
|
+
this.documentHttpService.updateDocumentName(this.selectedDocument._id, payload)
|
|
170
|
+
.subscribe((res) => {
|
|
171
|
+
console.log(`${SHARED.UPDATE_DOCUMENT_NAME} ${this.selectedDocument._id}`);
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Closes the dialog and resets the selected document.
|
|
176
|
+
* @memberof DocumentListComponent
|
|
177
|
+
*/
|
|
178
|
+
handleCloseModal(): void {
|
|
179
|
+
this.selectedDocument = { _id: SHARED.EMPTY };
|
|
180
|
+
this.isdialogVisible = SHARED.FALSE;
|
|
181
|
+
this.onRefresh.emit();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Handles the upload action for a document.
|
|
186
|
+
* Validates if a document type is selected and logs the result.
|
|
187
|
+
* @memberof DocumentListComponent
|
|
188
|
+
*/
|
|
189
|
+
handleUploadDocument(): void {
|
|
190
|
+
if (this.selectedOption) {
|
|
191
|
+
this.documentUploadService.getDocumentNameAndType(this.selectedOption);
|
|
192
|
+
this.documentUploadService.handleTemplatedUpload();
|
|
193
|
+
this.documentQuery.selectMessages().subscribe((message:Message[])=>{
|
|
194
|
+
if(message.length > 0){
|
|
195
|
+
this.messages = message;
|
|
196
|
+
this.onRefresh.emit();
|
|
197
|
+
this.selectedOption = null;
|
|
198
|
+
setTimeout(() => {
|
|
199
|
+
this.messages = SHARED.EMPTY_ARRAY
|
|
200
|
+
this.handleOpenSideBar(false);
|
|
201
|
+
}, 1000);
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
} else {
|
|
205
|
+
console.error(ERRORS.INVALID_RECIPIENT);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Fetches the list of document types from the server.
|
|
211
|
+
* Updates the options array with the available document types.
|
|
212
|
+
* @memberof DocumentListComponent
|
|
213
|
+
* @returns {void}
|
|
214
|
+
*/
|
|
215
|
+
getDocumentTypeList() {
|
|
216
|
+
this.documentHttpService.getDocumentTypes().subscribe({
|
|
217
|
+
/**
|
|
218
|
+
* Handles the successful API response.
|
|
219
|
+
* @param {DocumentTypeModel[]} documentTypes - The list of document types returned by the API.
|
|
220
|
+
*/
|
|
221
|
+
next: (documentTypes: DocumentTypeModel[]) => {
|
|
222
|
+
if (documentTypes) {
|
|
223
|
+
this.options = documentTypes.map((doc) => ({
|
|
224
|
+
label: doc.label,
|
|
225
|
+
value: doc._id
|
|
226
|
+
}));
|
|
227
|
+
} else {
|
|
228
|
+
console.error(ERRORS.ERROR_ALLDOCUMENT_MISSING, documentTypes);
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
/**
|
|
232
|
+
* Handles errors if the request fails.
|
|
233
|
+
* @param {any} err - The error object returned by the server.
|
|
234
|
+
*/
|
|
235
|
+
error: (err: any) => {
|
|
236
|
+
console.error(ERRORS.ERROR_DOCUMENT_TYPES, err);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
handleOpenSideBar(isVisible : boolean){
|
|
242
|
+
this.isSidebarVisible = isVisible
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<div class="grid m-0">
|
|
2
|
+
<div
|
|
3
|
+
class="col-12 flex align-items-center justify-content-between md:col-12 xl:col-12"
|
|
4
|
+
>
|
|
5
|
+
<div
|
|
6
|
+
class="col-5 flex cursor-pointer align-items-center pl-0"
|
|
7
|
+
(click)="handleOpenDocument(document)"
|
|
8
|
+
>
|
|
9
|
+
<img src="../../../../assets/images/Frame.png" alt="" />
|
|
10
|
+
<span class="ml-4 file-name-wrapper document-text-wrapper">{{ document.fileName }}</span>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="col-4 flex align-items-center justify-content-center">
|
|
13
|
+
<span
|
|
14
|
+
[class]="'product-badge status-' + document.status?.toLowerCase()"
|
|
15
|
+
class="flex align-items-center justify-content-center pl-2 pr-2 pt-1 pb-1"
|
|
16
|
+
>
|
|
17
|
+
<ng-container *ngIf="document.status?.toLowerCase() === 'pending'">
|
|
18
|
+
<i class="pi pi-clock pr-1" style="font-size: 12px;"></i>
|
|
19
|
+
Pending
|
|
20
|
+
</ng-container>
|
|
21
|
+
<ng-container *ngIf="document.status?.toLowerCase() === 'verified'">
|
|
22
|
+
<i class="pi pi-check-circle pr-1" style="font-size: 12px;"></i>
|
|
23
|
+
Verified
|
|
24
|
+
</ng-container>
|
|
25
|
+
<ng-container *ngIf="document.status?.toLowerCase() === 'alert'">
|
|
26
|
+
<i class="pi pi-bell pr-1" style="font-size: 12px;"></i>
|
|
27
|
+
Alert
|
|
28
|
+
</ng-container>
|
|
29
|
+
</span>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="document-type file-name-wrapper document-text-wrapper">
|
|
32
|
+
{{document.documentTypeName}}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
.product-badge.status-pending {
|
|
2
|
+
background: #e9b127;
|
|
3
|
+
color: #ffffff;
|
|
4
|
+
border-radius: 4px;
|
|
5
|
+
}
|
|
6
|
+
.product-badge.status-verified {
|
|
7
|
+
background: #4caf50;
|
|
8
|
+
color: #ffffff;
|
|
9
|
+
border-radius: 4px;
|
|
10
|
+
}
|
|
11
|
+
.product-badge.status-alert {
|
|
12
|
+
background: #f57c00;
|
|
13
|
+
color: #ffffff;
|
|
14
|
+
border-radius: 4px;
|
|
15
|
+
}
|
|
16
|
+
.product-badge {
|
|
17
|
+
text-transform: none;
|
|
18
|
+
font-weight: 500;
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.file-name-wrapper{
|
|
24
|
+
font-size: 15px;
|
|
25
|
+
font-weight: 500;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.document-text-wrapper{
|
|
29
|
+
display: -webkit-box;
|
|
30
|
+
-webkit-line-clamp: 1;
|
|
31
|
+
-webkit-box-orient: vertical;
|
|
32
|
+
overflow: hidden;
|
|
33
|
+
text-overflow: ellipsis;
|
|
34
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { DocumentListItemComponent } from './document-list-item.component';
|
|
3
|
+
import { CommonModule } from '@angular/common';
|
|
4
|
+
import { By } from '@angular/platform-browser';
|
|
5
|
+
import { DocumentModel } from '../../models/document.model';
|
|
6
|
+
|
|
7
|
+
describe('DocumentListItemComponent', () => {
|
|
8
|
+
let component: DocumentListItemComponent;
|
|
9
|
+
let fixture: ComponentFixture<DocumentListItemComponent>;
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
await TestBed.configureTestingModule({
|
|
13
|
+
declarations: [DocumentListItemComponent],
|
|
14
|
+
imports: [CommonModule],
|
|
15
|
+
}).compileComponents();
|
|
16
|
+
|
|
17
|
+
fixture = TestBed.createComponent(DocumentListItemComponent);
|
|
18
|
+
component = fixture.componentInstance;
|
|
19
|
+
component.document = {
|
|
20
|
+
_id : "1",
|
|
21
|
+
fileName : 'test',
|
|
22
|
+
}
|
|
23
|
+
fixture.detectChanges();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should create', () => {
|
|
27
|
+
expect(component).toBeTruthy();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should emit the selected document when handleOpenDocument is called', () => {
|
|
31
|
+
spyOn(component.documentClick, 'emit');
|
|
32
|
+
const mockDocument = { _id: "1", fileName: 'test' } as DocumentModel;
|
|
33
|
+
component.handleOpenDocument(mockDocument);
|
|
34
|
+
expect(component.documentClick.emit).toHaveBeenCalledWith(mockDocument);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should log an error when handleOpenDocument is called with null', () => {
|
|
38
|
+
spyOn(console, 'error');
|
|
39
|
+
component.handleOpenDocument(null as unknown as DocumentModel);
|
|
40
|
+
|
|
41
|
+
expect(console.error).toHaveBeenCalledWith('Error: Document is null or undefined:', null);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should emit documentClick event when document is clicked', () => {
|
|
45
|
+
spyOn(component.documentClick, 'emit');
|
|
46
|
+
const clickableElement = fixture.debugElement.query(By.css('.cursor-pointer'));
|
|
47
|
+
clickableElement.triggerEventHandler('click', null);
|
|
48
|
+
|
|
49
|
+
expect(component.documentClick.emit).toHaveBeenCalledWith(component.document);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should display Pending status with the correct icon', () => {
|
|
53
|
+
component.document.status = 'Pending';
|
|
54
|
+
fixture.detectChanges();
|
|
55
|
+
|
|
56
|
+
const statusElement = fixture.debugElement.query(By.css('.status-pending')).nativeElement;
|
|
57
|
+
const iconElement = fixture.debugElement.query(By.css('.pi-clock')).nativeElement;
|
|
58
|
+
|
|
59
|
+
expect(statusElement.textContent).toContain('Pending');
|
|
60
|
+
expect(iconElement).toBeTruthy();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should display Verified status with the correct icon', () => {
|
|
64
|
+
component.document.status = 'Verified';
|
|
65
|
+
fixture.detectChanges();
|
|
66
|
+
|
|
67
|
+
const statusElement = fixture.debugElement.query(By.css('.status-verified')).nativeElement;
|
|
68
|
+
const iconElement = fixture.debugElement.query(By.css('.pi-check-circle')).nativeElement;
|
|
69
|
+
|
|
70
|
+
expect(statusElement.textContent).toContain('Verified');
|
|
71
|
+
expect(iconElement).toBeTruthy();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
|
+
import { DocumentModel } from '../../models/document.model';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* DocumentListItemComponent
|
|
6
|
+
*
|
|
7
|
+
* This component displays individual document items within a list.
|
|
8
|
+
* It accepts a list of documents as input and handles interactions with documents.
|
|
9
|
+
*/
|
|
10
|
+
@Component({
|
|
11
|
+
selector: 'lib-document-list-item',
|
|
12
|
+
standalone: false,
|
|
13
|
+
templateUrl: './document-list-item.component.html',
|
|
14
|
+
styleUrls: ['./document-list-item.component.scss']
|
|
15
|
+
})
|
|
16
|
+
export class DocumentListItemComponent {
|
|
17
|
+
/**
|
|
18
|
+
* Emit the selected document.
|
|
19
|
+
* @type {EventEmitter<DocumentModel>}
|
|
20
|
+
*/
|
|
21
|
+
@Output() documentClick = new EventEmitter<DocumentModel>();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The document to display.
|
|
25
|
+
* @type {DocumentModel[]}
|
|
26
|
+
*/
|
|
27
|
+
@Input() document!: DocumentModel;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Handles interactions with a document.
|
|
31
|
+
* @param {DocumentModel} document - The document to be opened or interacted with.
|
|
32
|
+
*/
|
|
33
|
+
handleOpenDocument(document: DocumentModel): void {
|
|
34
|
+
if (!document) {
|
|
35
|
+
console.error('Error: Document is null or undefined:', document);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.documentClick.emit(document);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<div class="grid">
|
|
2
|
+
<div class="col-12 md:col-12">
|
|
3
|
+
<p-fileUpload #fileUploader [multiple]="true" auto="true" accept="image/png,application/pdf" maxFileSize="26214400"
|
|
4
|
+
(onSelect)="onSelectedFiles($event)">
|
|
5
|
+
<ng-template pTemplate="header" let-chooseCallback="chooseCallback" let-clearCallback="clearCallback">
|
|
6
|
+
<div class="docHeader p-2 flex flex-wrap justify-content-between align-items-center flex-1 gap-2">
|
|
7
|
+
<div class="flex gap-2">
|
|
8
|
+
<p-button (onClick)="choose($event, chooseCallback)" icon="pi pi-images" [rounded]="true"
|
|
9
|
+
[outlined]="true" />
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</ng-template>
|
|
13
|
+
<ng-template pTemplate="content" let-removeFileCallback="removeFileCallback"
|
|
14
|
+
let-removeUploadedFileCallback="removeUploadedFileCallback">
|
|
15
|
+
<div class="col-12 md:col-12 p-0">
|
|
16
|
+
<div class="col-12 md:col-12 p-0" *ngIf="uploadedFiles.length > 0">
|
|
17
|
+
<div *ngFor="let uploadedFile of uploadedFiles; let i = index"
|
|
18
|
+
class="m-0 flex flex-column align-items-center gap-1 mt-3">
|
|
19
|
+
<div class="col-12 md:col-12 p-0 flex documentInfo">
|
|
20
|
+
<div class="documentImage">
|
|
21
|
+
<img src="../../../../assets/images/document.png" [alt]="uploadedFile.file.name" width="45" height="50"
|
|
22
|
+
class="object-contain" />
|
|
23
|
+
</div>
|
|
24
|
+
<div class="flex w-full flex-column mt-2 ml-2">
|
|
25
|
+
<div class="flex justify-content-between">
|
|
26
|
+
<div style=" font-weight: bold;font-size: 14px">
|
|
27
|
+
{{ uploadedFile.file.name }}
|
|
28
|
+
</div>
|
|
29
|
+
<i class="pi pi-times cursor-pointer" (click)="handleDocumentRemove(uploadedFile.file,i)"></i>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="flex justify-content-between mt-1">
|
|
32
|
+
<div style="color: #676B89; font-size: 12px; color: green;" class="pi pi-verified "> {{ uploadedFile.formattedSize }}</div>
|
|
33
|
+
<div class="white-space-nowrap" style="color: #0F8BFD; font-family: 14px;"> {{ uploadedFile.progress }} %</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="col-12 md:col-12 p-0">
|
|
38
|
+
<p-progressBar [value]="totalSizePercent" [showValue]="false" styleClass="h-1/2rem md:ml-auto relative"
|
|
39
|
+
[ngClass]="{ 'exceeded-progress-bar': totalSizePercent > 100 }">
|
|
40
|
+
</p-progressBar>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</ng-template>
|
|
46
|
+
<ng-template pTemplate="empty" let-chooseCallback="chooseCallback">
|
|
47
|
+
<div *ngIf="!uploadedFiles.length" class="flex align-items-center justify-content-center flex-column"
|
|
48
|
+
(click)="triggerFileUpload()">
|
|
49
|
+
<i class="pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400"></i>
|
|
50
|
+
<p class="mt-4 mb-0">Drag and drop files here to upload.</p>
|
|
51
|
+
</div>
|
|
52
|
+
</ng-template>
|
|
53
|
+
<ng-template pTemplate="file"> </ng-template>
|
|
54
|
+
</p-fileUpload>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.flex {
|
|
2
|
+
display: flex;
|
|
3
|
+
}
|
|
4
|
+
.items-center {
|
|
5
|
+
align-items: center;
|
|
6
|
+
}
|
|
7
|
+
.justify-center {
|
|
8
|
+
justify-content: center;
|
|
9
|
+
}
|
|
10
|
+
.flex-col {
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
}
|
|
13
|
+
.text-muted-color {
|
|
14
|
+
color: #6c757d; // Adjust to match your theme
|
|
15
|
+
}
|
|
16
|
+
.p-fileupload-buttonbar {
|
|
17
|
+
padding: 0px;
|
|
18
|
+
}
|
|
19
|
+
.p-fileupload-content {
|
|
20
|
+
background-color: #0f8bfd1a;
|
|
21
|
+
}
|
|
22
|
+
.p-fileupload {
|
|
23
|
+
.p-fileupload-content {
|
|
24
|
+
padding: 1rem 1rem;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
.docHeader{
|
|
29
|
+
.p-button-icon{
|
|
30
|
+
padding: 0.5rem;
|
|
31
|
+
}
|
|
32
|
+
}
|