@@ -18,6 +18,7 @@ | |||||
"@angular/platform-browser": "~12.2.0", | "@angular/platform-browser": "~12.2.0", | ||||
"@angular/platform-browser-dynamic": "~12.2.0", | "@angular/platform-browser-dynamic": "~12.2.0", | ||||
"@angular/router": "~12.2.0", | "@angular/router": "~12.2.0", | ||||
"ng2-file-upload": "^1.4.0", | |||||
"rxjs": "~6.6.0", | "rxjs": "~6.6.0", | ||||
"tslib": "^2.3.0", | "tslib": "^2.3.0", | ||||
"zone.js": "~0.11.4" | "zone.js": "~0.11.4" | ||||
@@ -1,5 +1,6 @@ | |||||
import { NgModule } from '@angular/core'; | import { NgModule } from '@angular/core'; | ||||
import { BrowserModule } from '@angular/platform-browser'; | import { BrowserModule } from '@angular/platform-browser'; | ||||
import { FileUploadModule } from 'ng2-file-upload'; | |||||
import { AppRoutingModule } from './app-routing.module'; | import { AppRoutingModule } from './app-routing.module'; | ||||
import { AppComponent } from './app.component'; | import { AppComponent } from './app.component'; | ||||
@@ -22,6 +23,8 @@ import { InvestigateBusinessEntitiesAndIndividualsComponent } from './pages/inve | |||||
import { ViewCaseDetailsComponent } from './pages/investigate-business-entities-and-individuals/view-case-details/view-case-details.component'; | import { ViewCaseDetailsComponent } from './pages/investigate-business-entities-and-individuals/view-case-details/view-case-details.component'; | ||||
import { ModifyCaseDetailsComponent } from './pages/investigate-business-entities-and-individuals/modify-case-details/modify-case-details.component'; | import { ModifyCaseDetailsComponent } from './pages/investigate-business-entities-and-individuals/modify-case-details/modify-case-details.component'; | ||||
import { AssignPanelComponent } from './pages/investigate-business-entities-and-individuals/assign-panel/assign-panel.component'; | import { AssignPanelComponent } from './pages/investigate-business-entities-and-individuals/assign-panel/assign-panel.component'; | ||||
import { TextareaComponent } from './widgets/form/textarea/textarea.component'; | |||||
import { MultiFileUploadComponent } from './widgets/form/multi-file-upload/multi-file-upload.component'; | |||||
@NgModule({ | @NgModule({ | ||||
declarations: [ | declarations: [ | ||||
@@ -43,12 +46,15 @@ import { AssignPanelComponent } from './pages/investigate-business-entities-and- | |||||
InvestigateBusinessEntitiesAndIndividualsComponent, | InvestigateBusinessEntitiesAndIndividualsComponent, | ||||
ViewCaseDetailsComponent, | ViewCaseDetailsComponent, | ||||
ModifyCaseDetailsComponent, | ModifyCaseDetailsComponent, | ||||
AssignPanelComponent | |||||
AssignPanelComponent, | |||||
TextareaComponent, | |||||
MultiFileUploadComponent | |||||
], | ], | ||||
imports: [ | imports: [ | ||||
BrowserModule, | BrowserModule, | ||||
AppRoutingModule, | AppRoutingModule, | ||||
FormsModule | |||||
FormsModule, | |||||
FileUploadModule, | |||||
], | ], | ||||
providers: [], | providers: [], | ||||
bootstrap: [AppComponent] | bootstrap: [AppComponent] | ||||
@@ -17,7 +17,7 @@ export class InvestigateBusinessEntitiesAndIndividualsComponent implements OnIni | |||||
proceed() { | proceed() { | ||||
this.stateHistory.push(this.state); | this.stateHistory.push(this.state); | ||||
switch (this.state) { | switch (this.state) { | ||||
case 'VIEW INITIAL DETAILS': | case 'VIEW INITIAL DETAILS': | ||||
if (this.hasEnoughData) { | if (this.hasEnoughData) { | ||||
@@ -25,6 +25,10 @@ export class InvestigateBusinessEntitiesAndIndividualsComponent implements OnIni | |||||
} else { | } else { | ||||
this.state = 'ENTER MORE DETAILS'; | this.state = 'ENTER MORE DETAILS'; | ||||
} | } | ||||
break; | |||||
case 'ENTER MORE DETAILS': | |||||
this.state = 'ASSIGN COMMITTEE'; | |||||
break; | |||||
} | } | ||||
} | } | ||||
@@ -1 +1,17 @@ | |||||
<p>modify-case-details works!</p> | |||||
<div class="form-holder"> | |||||
<h3>Add further information for the case</h3> | |||||
<div class="two-column-holder"> | |||||
<app-date-input | |||||
label="Date of contacting source" | |||||
></app-date-input> | |||||
<app-generic-input | |||||
type="text" | |||||
label="Name of source" | |||||
placeholder="e.g. Jermey Stevens" | |||||
></app-generic-input> | |||||
</div> | |||||
<app-textarea | |||||
label="Remarks" | |||||
></app-textarea> | |||||
<app-multi-file-upload label="Documents"></app-multi-file-upload> | |||||
</div> |
@@ -0,0 +1,22 @@ | |||||
.form-holder { | |||||
width: calc(70% - 2rem); | |||||
padding: 4rem; | |||||
margin: 0 auto; | |||||
} | |||||
h3 { | |||||
font-size: 2rem; | |||||
color: var(--dark-grey); | |||||
filter: brightness(80%); | |||||
font-weight: 500; | |||||
margin: 2rem 0; | |||||
} | |||||
.two-column-holder { | |||||
display: grid; | |||||
grid-template-columns: 1fr 1fr; | |||||
& > * { | |||||
width: calc(100% - 2rem); | |||||
} | |||||
} |
@@ -1,4 +1,5 @@ | |||||
import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||
import { FileUploader } from 'ng2-file-upload'; | |||||
@Component({ | @Component({ | ||||
selector: 'app-modify-case-details', | selector: 'app-modify-case-details', | ||||
@@ -6,10 +7,17 @@ import { Component, OnInit } from '@angular/core'; | |||||
styleUrls: ['./modify-case-details.component.scss'] | styleUrls: ['./modify-case-details.component.scss'] | ||||
}) | }) | ||||
export class ModifyCaseDetailsComponent implements OnInit { | export class ModifyCaseDetailsComponent implements OnInit { | ||||
uploader: FileUploader = new FileUploader({ | |||||
url: '' | |||||
}); | |||||
constructor() { } | |||||
constructor() { } | |||||
ngOnInit(): void { | |||||
} | |||||
ngOnInit(): void { | |||||
} | |||||
handleFilesDrop(files: Array<File>) { | |||||
console.log(files); | |||||
} | |||||
} | } |
@@ -24,7 +24,7 @@ | |||||
<div class="prompt-data-outreach"> | <div class="prompt-data-outreach"> | ||||
<label> | <label> | ||||
<input type="checkbox" [(ngModel)]="hasEnoughData" (ngModelChange)="toggleHasData($event)"> | <input type="checkbox" [(ngModel)]="hasEnoughData" (ngModelChange)="toggleHasData($event)"> | ||||
<span>Is this data enough to proceed with investigation?</span> | |||||
<span>There is enough data to proceed with investigation</span> | |||||
</label> | </label> | ||||
</div> | </div> | ||||
</div> | </div> |
@@ -1,5 +1,5 @@ | |||||
<div class="input-holder"> | <div class="input-holder"> | ||||
<input [type]="type" [placeholder]="placeholder"> | |||||
<input [type]="type" [placeholder]="placeholder ? placeholder : ''"> | |||||
<label> {{ label }}: </label> | <label> {{ label }}: </label> | ||||
</div> | </div> |
@@ -0,0 +1,25 @@ | |||||
<div class="input-holder"> | |||||
<div class="label"> {{ label }}: </div> | |||||
<div class="files-holder"> | |||||
<div *ngFor="let file of uploadedFiles" class="file-holder"> | |||||
<app-file | |||||
[name]="file.name" | |||||
[sizeInBytes]="file.sizeInBytes" | |||||
[extension]="file.extension" | |||||
></app-file> | |||||
</div> | |||||
<label> | |||||
<input class="hidden-file-input" type="file" ng2FileSelect [uploader]="uploader" multiple (onFileSelected)="handleFilesDrop($event)" /> | |||||
<div class="add-button"> | |||||
<img src="../../../../assets/icons/plus.svg" alt="Add file"> | |||||
</div> | |||||
</label> | |||||
</div> | |||||
<div ng2FileDrop | |||||
[uploader]="uploader" | |||||
(onFileDrop)="handleFilesDrop($event)" | |||||
class="file-drop-zone" | |||||
> | |||||
Drag and drop files | |||||
</div> | |||||
</div> |
@@ -0,0 +1,51 @@ | |||||
.label { | |||||
font-size: 1.4rem; | |||||
color: var(--primary); | |||||
font-weight: 400; | |||||
letter-spacing: 0.5px; | |||||
margin-bottom: 5px; | |||||
} | |||||
.input-holder { | |||||
width: 100%; | |||||
margin: 1.5rem 0; | |||||
position: relative; | |||||
} | |||||
.hidden-file-input { | |||||
display: none; | |||||
} | |||||
.add-button { | |||||
display: inline-flex; | |||||
justify-content: center; | |||||
border: 1px solid var(--border-grey); | |||||
border-radius: 1rem; | |||||
width: 5.5rem; | |||||
height: 7rem; | |||||
margin-bottom: 15px; | |||||
cursor: pointer; | |||||
img { | |||||
width: 40%; | |||||
height: auto; | |||||
} | |||||
} | |||||
.file-drop-zone { | |||||
border: 2px dotted var(--secondary); | |||||
padding: 35px; | |||||
font-size: 16px; | |||||
color: var(--secondary); | |||||
text-align: center; | |||||
} | |||||
.files-holder { | |||||
display: flex; | |||||
flex-wrap: wrap; | |||||
.file-holder { | |||||
margin-right: 15px; | |||||
margin-bottom: 15px; | |||||
} | |||||
} |
@@ -0,0 +1,25 @@ | |||||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||||
import { MultiFileUploadComponent } from './multi-file-upload.component'; | |||||
describe('MultiFileUploadComponent', () => { | |||||
let component: MultiFileUploadComponent; | |||||
let fixture: ComponentFixture<MultiFileUploadComponent>; | |||||
beforeEach(async () => { | |||||
await TestBed.configureTestingModule({ | |||||
declarations: [ MultiFileUploadComponent ] | |||||
}) | |||||
.compileComponents(); | |||||
}); | |||||
beforeEach(() => { | |||||
fixture = TestBed.createComponent(MultiFileUploadComponent); | |||||
component = fixture.componentInstance; | |||||
fixture.detectChanges(); | |||||
}); | |||||
it('should create', () => { | |||||
expect(component).toBeTruthy(); | |||||
}); | |||||
}); |
@@ -0,0 +1,47 @@ | |||||
import { Component, Input, OnInit } from '@angular/core'; | |||||
import { FileUploader } from 'ng2-file-upload'; | |||||
interface FileInfo { | |||||
name: string, | |||||
sizeInBytes: number, | |||||
extension: string, | |||||
link?: string, | |||||
} | |||||
@Component({ | |||||
selector: 'app-multi-file-upload', | |||||
templateUrl: './multi-file-upload.component.html', | |||||
styleUrls: ['./multi-file-upload.component.scss'] | |||||
}) | |||||
export class MultiFileUploadComponent implements OnInit { | |||||
@Input() label = ''; | |||||
uploader: FileUploader = new FileUploader({ | |||||
url: '' | |||||
}); | |||||
uploadedFiles: Array<FileInfo> = []; | |||||
constructor() { } | |||||
ngOnInit(): void { | |||||
} | |||||
handleFilesDrop(files: Array<File>) { | |||||
for (const file of files) { | |||||
const fileName = file.name; | |||||
const extensionSeparatorIndex = fileName.lastIndexOf('.'); | |||||
const name = fileName.substring(0, extensionSeparatorIndex); | |||||
const extension = fileName.substring(extensionSeparatorIndex + 1); | |||||
const sizeInBytes = file.size; | |||||
this.uploadedFiles.push({ | |||||
name, | |||||
extension, | |||||
sizeInBytes, | |||||
}); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,4 @@ | |||||
<div class="input-holder"> | |||||
<label> {{ label }}: </label> | |||||
<textarea [placeholder]="placeholder ? placeholder : ''"></textarea> | |||||
</div> |
@@ -0,0 +1,50 @@ | |||||
.input-holder { | |||||
width: 100%; | |||||
margin: 1.5rem 0; | |||||
position: relative; | |||||
display: flex; | |||||
align-items: center; | |||||
justify-content: flex-start; | |||||
label { | |||||
font-size: 1.4rem; | |||||
background-color: white; | |||||
color: var(--primary); | |||||
position: absolute; | |||||
top: 2.2rem; | |||||
left: -0.5rem; | |||||
padding: 0 0.5rem; | |||||
font-weight: 400; | |||||
letter-spacing: 0.5px; | |||||
transform: translate(2.5rem, -3rem); | |||||
} | |||||
textarea { | |||||
display: block; | |||||
width: 100%; | |||||
border-radius: 2rem; | |||||
height: 8rem; | |||||
border: 1px solid var(--border-grey); | |||||
padding: 1rem 2rem; | |||||
font-size: 1.5rem; | |||||
letter-spacing: 0.5px; | |||||
color: var(--dark-grey); | |||||
background-color: white; | |||||
resize: vertical; | |||||
&:focus { | |||||
border-color: var(--highlight); | |||||
&~label { | |||||
color: var(--highlight); | |||||
} | |||||
} | |||||
} | |||||
img { | |||||
position: relative; | |||||
transform: translateX(-4rem); | |||||
pointer-events: none; | |||||
background-color: white; | |||||
} | |||||
} |
@@ -0,0 +1,25 @@ | |||||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||||
import { TextareaComponent } from './textarea.component'; | |||||
describe('TextareaComponent', () => { | |||||
let component: TextareaComponent; | |||||
let fixture: ComponentFixture<TextareaComponent>; | |||||
beforeEach(async () => { | |||||
await TestBed.configureTestingModule({ | |||||
declarations: [ TextareaComponent ] | |||||
}) | |||||
.compileComponents(); | |||||
}); | |||||
beforeEach(() => { | |||||
fixture = TestBed.createComponent(TextareaComponent); | |||||
component = fixture.componentInstance; | |||||
fixture.detectChanges(); | |||||
}); | |||||
it('should create', () => { | |||||
expect(component).toBeTruthy(); | |||||
}); | |||||
}); |
@@ -0,0 +1,17 @@ | |||||
import { Component, Input, OnInit } from '@angular/core'; | |||||
@Component({ | |||||
selector: 'app-textarea', | |||||
templateUrl: './textarea.component.html', | |||||
styleUrls: ['./textarea.component.scss'] | |||||
}) | |||||
export class TextareaComponent implements OnInit { | |||||
@Input() label = ''; | |||||
@Input() placeholder: string|undefined; | |||||
constructor() { } | |||||
ngOnInit(): void { | |||||
} | |||||
} |
@@ -0,0 +1,6 @@ | |||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"> | |||||
<g id="Group_82" data-name="Group 82" transform="translate(1 1)"> | |||||
<line id="Line_36" data-name="Line 36" y2="10" transform="translate(5)" fill="none" stroke="#6d654e" stroke-linecap="round" stroke-width="2"/> | |||||
<line id="Line_37" data-name="Line 37" y2="10" transform="translate(10 5) rotate(90)" fill="none" stroke="#6d654e" stroke-linecap="round" stroke-width="2"/> | |||||
</g> | |||||
</svg> |