203 lines
9.3 KiB
Markdown
203 lines
9.3 KiB
Markdown
# File Upload Component
|
|
The file upload component in ```/src/app/shared/file-upload``` allows for files to be uploaded to Azure Blob Storage for a given loan. Once the loan is created in ACTion it will upload the files to ACTion and show up in Attachments. An example of the component shown here:
|
|
|
|

|
|
|
|
## Enabling Employment Income/Other Income file uploads for a loan
|
|
Set ```showProofOfIncomeUploadForm``` value for the loan to true in ```src\app\shared\loan-type.ts```
|
|
|
|
## Adding the upload component to a form (see end of document for an example implementation)
|
|
1. Update interface by adding two variables: ```files``` and ```isUploading```, example in ```src\app\loan-wizard\field-groups\personal\personal-information.ts```
|
|
1. Add new values to form group in ```src\app\loan-wizard\field-groups\common-groups.ts```, see ```PERSONAL_INFO``` in this file for an example
|
|
1. Add the HTML to the form, example below and in ```src\app\loan-wizard\field-groups\personal\personal-info-form.component.html```
|
|
1. Update TS by adding variables needed, example below and in ```src\app\loan-wizard\field-groups\personal\personal-info-form.component.ts```
|
|
1. Update ```src\assets\i18n\en.json``` to have verbiage for uploading document
|
|
1. Update ```src\app\shared\loan-type.ts``` to set ```beforeYouBeginKey``` value on a given loan to the corresponding key in ```en.json``` to enable the checklist
|
|
1. Update the summary component to show files if they're present, example in ```src\app\loan-wizard\wizards\common\summary\personal-summary.component.html```
|
|
|
|
## Inputs
|
|
1. ```loanId``` _required_
|
|
- The CosmosDB loan ID that uploaded files will be associated with
|
|
1. ```section``` _optional_
|
|
- The section that the form is in, e.g. Collateral.
|
|
- If left blank, the description in ACTion will not include this.
|
|
1. ```sectionId``` _required_
|
|
- The sectionId is used to be more specific, when there are multiple upload components in a single form.
|
|
- An example would be the Income section that shows up to 3 upload components for any borrower on the loan, for which the ```sectionId``` is set to ```Primary Borrower-#```, where ```#``` would be which income section it is associated with, 1, 2, or 3.
|
|
1. ```description``` _required_
|
|
- Description that is used to set the attachment type in ACTion
|
|
- This text will be displayed in the component after "Upload"
|
|
- This text can be overridden by passing a value in for the ```label``` input
|
|
1. ```label``` _optional_
|
|
- This text will be displayed in the component after "Upload"
|
|
- This was added in after the verbiage requirements needed something more custom in certain areas to show something like ```Upload a copy of first mortgage balance statement``` instead of ```Upload Copy of first mortgage balance statement```.
|
|
- If ```label``` is not provided, ```description``` will be shown.
|
|
1. ```removeAllFilesSubject``` _optional_
|
|
- This input is used by passing in a ```Subject<boolean>``` and then triggered by calling the ```.next()``` function on the subject, which will remove all files and emit when completed.
|
|
- It is meant to be used along with the ```removedAllFiles``` output to notify the parent component that the files have been removed and the form can be updated.
|
|
|
|
## Outputs
|
|
1. ```sendFiles``` _required_
|
|
- Used to capture when files change and need to be updated on the parent component.
|
|
1. ```uploadingFiles``` _required_
|
|
- Used for form validation so that the Next button cannot be pressed while a file is being uploaded or deleted.
|
|
1. ```removedAllFiles``` _optional_
|
|
- Used when a form is closed/not needed and the files that were uploaded need to be deleted.
|
|
- Once ```removedAllFilesSubject``` is called and completed, this output is emitted so that the form can be updated as needed.
|
|
|
|
## Notes
|
|
- When the component loads, it creates two requests for the API: one for the files associated with the ```loanId``` and the other for the settings, which controls the file size and types.
|
|
- The ```<lw-file-upload>``` component should be surround with a ```div``` that controls the width and visibility, e.g.:
|
|
```html
|
|
<div *ngIf="showUploadForm" class="form-group col-lg-5 col-md-6 col-sm-12">
|
|
```
|
|
|
|
## ACTion
|
|
Files that are uploaded into ACTion will be given a type: Attachment, Proof of Income, or Title. This is done by using the ```description``` input and mapping it to a type on the backend API defined in ```appsettings.json```. If a description is mistyped or not found in ```appsettings.json```, it will default to Attachment.
|
|
|
|
The description within action is created with the inputs: ```section```, ```sectionId```, and ```description```.
|
|
|
|
If ```section``` is null or blank, it is not used as shown in the code and screenshot below.
|
|
|
|
```csharp
|
|
// Code segment from LoanWizardAPI/CRIF.ACTion/Files/AddAppFilesSection.cs
|
|
$"{file.Section} - {file.SectionId}: {file.Description}"
|
|
$"{file.SectionId}: {file.Description}"
|
|
```
|
|
|
|

|
|
|
|
# Example Implementation
|
|
## HTML
|
|
```html
|
|
<div *ngIf="showUploadForm" class="form-group col-lg-5 col-md-6 col-sm-12">
|
|
<lw-file-upload
|
|
[loanId]="loanId"
|
|
section=""
|
|
sectionId="Personal Information"
|
|
description="Proof of being a student"
|
|
label="proof that you are a student"
|
|
[removeAllFilesSubject]="removeAllFilesSubject"
|
|
(sendFiles)="handleFiles($event)"
|
|
(uploadingFiles)="handleUploadingFiles($event)"
|
|
(removedAllFiles)="handleRemovedAllFiles($event)">
|
|
</lw-file-upload>
|
|
</div>
|
|
```
|
|
|
|
## TypeScript
|
|
```ts
|
|
@Input()
|
|
public group: FormGroup;
|
|
|
|
public loanId: string;
|
|
|
|
public showUploadForm: boolean;
|
|
|
|
public removeAllFilesSubject: Subject<boolean>;
|
|
|
|
constructor(private collateralInfoService: CollateralInfoFormService) {
|
|
this.loanId = collateralInfoService.getLoanId(); // not real, just an example
|
|
this.showUploadForm = true;
|
|
this.removeAllFilesSubject = new Subject<boolean>();
|
|
}
|
|
|
|
// Somewhat of a contrived example, but essentially when the form is supposed to be deleted, the .next() should be called.
|
|
// Once files are removed, the removedAllFiles output of the component will emit and call the function to complete removing the form handleRemovedAllFiles (below)
|
|
public closeForm() {
|
|
this.removeAllFilesSubject.next();
|
|
}
|
|
|
|
// Sets the files value of the group, called when component is initialized and when all files have been removed.
|
|
public handleFiles(files: any[]): void {
|
|
this.group.patchValue({ 'files': files });
|
|
}
|
|
|
|
// Sets a boolean to true/false for form validation so that Next is disabled
|
|
public handleUploadingFiles(isUploading: boolean): void {
|
|
this.group.patchValue({ 'isUploading': isUploading });
|
|
}
|
|
|
|
public handleRemovedAllFiles(removedAllFiles: boolean): void {
|
|
if(removedAllFiles) {
|
|
// Code to clear/delete form here...
|
|
}
|
|
}
|
|
```
|
|
|
|
|
|
## Interface
|
|
This is the interface that the files variable should be added to. If it is in the Personal Info section, it would be added to ```src\app\loan-wizard\field-groups\personal\personal-information.ts```
|
|
|
|
```ts
|
|
{
|
|
...
|
|
// not all variables shown
|
|
files?: any[];
|
|
isUploading?: boolean;
|
|
...
|
|
}
|
|
```
|
|
|
|
## src\app\loan-wizard\field-groups\common-groups.ts
|
|
This file is where the form group for the page is generated. It will also need to have both variables added to the correct section so they can be used with the validators.
|
|
```ts
|
|
{
|
|
...
|
|
// not all variables shown
|
|
{
|
|
field: 'files',
|
|
validation: [WizardValidators.FileValidator]
|
|
},
|
|
{
|
|
field: 'isUploading',
|
|
validation: [WizardValidators.MustBeFalse]
|
|
}
|
|
...
|
|
}
|
|
```
|
|
|
|
## src\assets\i18n\en.json
|
|
```ts
|
|
{
|
|
...
|
|
// not all variables shown
|
|
"BEFOREYOUBEGIN": {
|
|
"EXAMPLE": {
|
|
"INTRO": "Before you begin the process, you should have the following documents:",
|
|
"HEADINGS": [
|
|
{
|
|
"HEADING": "Documents to Upload",
|
|
"VALUES": [
|
|
"Proof of income (i.e. most recent payroll check stub, 1040s for self-employed borrowers, bank statement).",
|
|
"Proof that you are a student (i.e. Student ID from current school year or current enrollment documentation such as a class schedule)."
|
|
]
|
|
}
|
|
]
|
|
},
|
|
...
|
|
}
|
|
}
|
|
```
|
|
|
|
## src\app\shared\loan-type.ts
|
|
Add needed keys for checklist component, coming from en.json (see above)
|
|
```js
|
|
{
|
|
...
|
|
// not all variables shown
|
|
beforeYouBeginKey: 'BEFOREYOUBEGIN.EXAMPLE', // Should be added/updated whenever the upload form is added
|
|
showProofOfIncomeUploadForm: true // Set to true if the proof of income file uploads should show, be sure to update en.json!
|
|
...
|
|
}
|
|
```
|
|
|
|
## Summary component
|
|
Add ```divs``` to display files. The description can be pulled from the first file, as shown (it is done with income files as there are multiple sections and borrowers), or the description can be hard coded. The files array is passed into the ```uploadedFiles``` pipe which parses them into a comma-separated list. The pipe is located at ```src\app\shared\pipes\uploaded-files.pipe.ts```
|
|
```html
|
|
<div class="row summary-card" *ngIf="personalInformation">
|
|
<!-- full code of component not shown -->
|
|
<div *ngIf="personalInformation?.files?.length > 0" class="col-md-4 col-sm-12 summary-card-field-title">{{personalInformation.files[0].description}} document(s)</div>
|
|
<div *ngIf="personalInformation?.files?.length > 0" class="col-md-8 col-sm-12">{{personalInformation.files | uploadedFiles}}</div>
|
|
</div>
|
|
``` |