check add person photo finish
This commit is contained in:
@@ -1,2 +1,13 @@
|
||||
.profilePhotoBorder
|
||||
{
|
||||
|
||||
border-color: gray;
|
||||
border-width: 2px;
|
||||
border-radius: 15%;
|
||||
}
|
||||
|
||||
|
||||
.profilePhotoWH
|
||||
{
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
}
|
||||
@@ -1,28 +1,69 @@
|
||||
<div class=" mt-2">
|
||||
|
||||
<form [formGroup]="adminuserForm" (ngSubmit)="onSubmit($event)" >
|
||||
<div class="ml-2 grid md:grid-cols-2 gap-3 p-2">
|
||||
<div class="">
|
||||
<label for="lastname1">Surname<strong class="app-require">*</strong></label>
|
||||
<input id="lastname1" pInputText formControlName="lastname" type="text"
|
||||
[class]="getClassForRequire('inputfield w-full p-inputtext-sm','lastname')">
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="firstname">First Name<strong class="app-require">*</strong></label>
|
||||
<input id="firstname" pInputText formControlName="firstname" type="text"
|
||||
[class]="getClassForRequire('inputfield w-full p-inputtext-sm','firstname')">
|
||||
</div>
|
||||
<div class="">
|
||||
<label class="flex w-full">Sex <strong class="app-require">*</strong></label>
|
||||
<p-select [options]="sexList" optionLabel="name" optionValue="status" placeholder="Select Gender"
|
||||
formControlName="sex"
|
||||
[class]="getClassForRequire('inputfield w-full p-inputtext-sm','sex')"
|
||||
class="w-full p-inputtext-sm mr-1"></p-select >
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="dob" class="flex w-full">DOB</label>
|
||||
<p-datepicker ariaLabelledBy="dob" formControlName="dob" [iconDisplay]="'input'" [showIcon]="true" dateFormat="dd/mm/yy" ></p-datepicker>
|
||||
<div class="ml-2 grid md:grid-cols-2 gap-3 p-2">
|
||||
<div>
|
||||
<div class="">
|
||||
<label for="lastname1">Surname<strong class="app-require">*</strong></label>
|
||||
<input id="lastname1" pInputText formControlName="lastname" type="text" [pAutoFocus]="true"
|
||||
[class]="getClassForRequire('inputfield w-full p-inputtext-sm','lastname')">
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="firstname">First Name<strong class="app-require">*</strong></label>
|
||||
<input id="firstname" pInputText formControlName="firstname" type="text"
|
||||
[class]="getClassForRequire('inputfield w-full p-inputtext-sm','firstname')">
|
||||
</div>
|
||||
</div>
|
||||
<!--put here photo of person-->
|
||||
<div class="flex flex-row gap-2">
|
||||
<div>
|
||||
<div class="">
|
||||
<label for="dob" class="flex w-full">DOB</label>
|
||||
<p-datepicker ariaLabelledBy="dob" formControlName="dob" [iconDisplay]="'input'" [showIcon]="true"
|
||||
dateFormat="dd/mm/yy" ></p-datepicker>
|
||||
</div>
|
||||
<div class="">
|
||||
<label class="flex w-full">Sex <strong class="app-require">*</strong></label>
|
||||
<p-select [options]="sexList" optionLabel="name" optionValue="status" placeholder="Select Gender"
|
||||
formControlName="sex"
|
||||
[class]="getClassForRequire('inputfield w-full p-inputtext-sm','sex')"
|
||||
class="w-full p-inputtext-sm mr-1"></p-select >
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row shadow-md rounded-xl border-gray-100 border-1 p-4">
|
||||
<!--a href="{{hostsite}}/{{adminuserForm.value.image}}" target="_blank" class="text-blue-400">View Attachment
|
||||
</a-->
|
||||
<input type="file" class="file-input hidden" (change)="onFileSelected($event)" #fileUpload>
|
||||
@if (adminuserForm.value.image != "" && adminuserForm.value.image != null)
|
||||
{
|
||||
<img id="blah" [src]= "dislayImage()" alt="your image"
|
||||
class="profilePhotoWH profilePhotoBorder" (click)="doViewImage(adminuserForm.value.image)" />
|
||||
|
||||
}
|
||||
@else
|
||||
{
|
||||
<div class="file-upload profilePhotoBorder profilePhotoWH text-center flex justify-center items-center ">
|
||||
<label class="">{{ adminuserForm.value.image || "No Profile Photo."}}</label>
|
||||
</div>
|
||||
}
|
||||
<div class="flex flex-col gap-2">
|
||||
@if (adminuserForm.value.image != "" && adminuserForm.value.image != null)
|
||||
{
|
||||
<button pButton type="button" icon="pi pi-times" pTooltip="remove profile photo"
|
||||
class="p-button-rounded p-button-text text-red-500 p-button-raised ml-2"
|
||||
(click)="deleteFile()"></button>
|
||||
}
|
||||
<button pButton type="button" icon="pi pi-paperclip"
|
||||
class="self-end p-button-rounded p-button-text p-button-raised ml-2" pTooltip="load photo"
|
||||
(click)="fileUpload.click()"></button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
|
||||
<div class="">
|
||||
<label for="login">Email</label>
|
||||
<input id="login" [attr.disabled]="!isNew?true:null" pInputText formControlName="email"
|
||||
@@ -49,42 +90,16 @@
|
||||
<label for="alive" class="ml-2 w-full">Alive</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="field col-12 md:col-6 sm:col-8">
|
||||
<div class="shadow-md rounded-xl border-gray-100 border-1 p-4">
|
||||
@if (adminuserForm.value.image != "" && adminuserForm.value.image != null)
|
||||
{
|
||||
<div class="ml-6 file-upload">
|
||||
<!--a href="{{hostsite}}/{{adminuserForm.value.image}}" target="_blank" class="text-blue-400">View Attachment
|
||||
</a-->
|
||||
<button pButton type="button" icon="pi pi-image"
|
||||
class ="p-ripple p-button p-button-raised p-button-text p-button-warn p-component"
|
||||
pTooltip="view Image" (click)="doViewImage(adminuserForm.value.image)"></button>
|
||||
<button pButton type="button" icon="pi pi-times" pTooltip="remove attach file"
|
||||
class="p-button-rounded p-button-text text-red-500 p-button-raised ml-2"
|
||||
(click)="deleteFile()"></button>
|
||||
</div>
|
||||
}
|
||||
@else
|
||||
{
|
||||
<div class="ml-6 ">
|
||||
<input type="file" class="file-input" (change)="onFileSelected($event)" #fileUpload>
|
||||
<div class="file-upload">
|
||||
<label>{{ adminuserForm.value.image || "No attachment file uploaded yet."}}</label>
|
||||
<button pButton type="button" icon="pi pi-paperclip"
|
||||
class="p-button-rounded p-button-text p-button-raised ml-2" pTooltip="attach file"
|
||||
(click)="fileUpload.click()"></button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 w-full">
|
||||
<p-button class="flex justify-end mr-2" icon="pi pi-user" [raised]="true" severity="info" label="Add Partner"
|
||||
(onClick)="addPartner()"/>
|
||||
</div>
|
||||
<div class="mt-2 w-full">
|
||||
<div class="flex flex-row justify-between">
|
||||
<p-button icon="pi pi-images" [raised]="true"
|
||||
badge="{{photoList.length}}"
|
||||
severity="success" label="Attach Photos"
|
||||
(onClick)="viewAttachment()"/>
|
||||
<p-button icon="pi pi-user" [raised]="true" severity="info" label="Add Partner"
|
||||
(onClick)="addPartner()"/>
|
||||
</div>
|
||||
<div class="shadow rounded mt-2 mb-2">
|
||||
<p-table [value]="partners()">
|
||||
<ng-template #header>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { FormControl, ReactiveFormsModule, UntypedFormBuilder, Validators } from
|
||||
import { Subject, Subscription} from 'rxjs';
|
||||
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||
import { DatePickerModule } from 'primeng/datepicker';
|
||||
import { Code, RelationShipView, Person, mState, RelationShip} from '../models';
|
||||
import { Code, RelationShipView, Person, mState, RelationShip, PersonPhotoDto} from '../models';
|
||||
import { AppSettingService, LookupService, Utils } from '../shares';
|
||||
import { PersonService } from './person.service';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
@@ -19,6 +19,9 @@ import { TableModule } from 'primeng/table';
|
||||
import { Pickperson } from '../pickperson/pickperson';
|
||||
import { ImageDisplayComponent } from '../pickperson/image.display';
|
||||
import { TooltipModule } from 'primeng/tooltip';
|
||||
import { AutoFocusModule } from 'primeng/autofocus';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { PhotoList } from '../attachphoto/photolist';
|
||||
|
||||
export interface FileUploadEvent {
|
||||
originalEvent: HttpEvent<any>;
|
||||
@@ -32,6 +35,7 @@ export interface FileUploadHandlerEvent {
|
||||
templateUrl: 'person.edit.html',
|
||||
selector: 'person-edit',
|
||||
imports:[ButtonModule,TableModule,ReactiveFormsModule,TooltipModule,
|
||||
AutoFocusModule,
|
||||
SelectModule,CheckboxModule, InputTextModule,DatePickerModule],
|
||||
styleUrls: ['person.edit.css'],
|
||||
providers: [DialogService]
|
||||
@@ -39,6 +43,8 @@ providers: [DialogService]
|
||||
})
|
||||
export class PersonEdit implements OnInit, OnDestroy {
|
||||
editRef: DynamicDialogRef | undefined;
|
||||
private sanitizer = inject(DomSanitizer);
|
||||
imageDataUrl = signal<string>("");
|
||||
returnUrl ='';
|
||||
loginUser ='';
|
||||
hostsite ='';
|
||||
@@ -49,8 +55,9 @@ export class PersonEdit implements OnInit, OnDestroy {
|
||||
motherList: Code[] =[];
|
||||
sexList:Code[] =[];
|
||||
familyList: Person[] =[];
|
||||
file: File | null = null;
|
||||
fileName = '';
|
||||
profileFile: File | null = null;
|
||||
photoList: PersonPhotoDto[] = [];
|
||||
fileName = '';
|
||||
isNew = false;
|
||||
validationPoints?: Code[];
|
||||
partners = signal<RelationShipView[]>([]);
|
||||
@@ -126,15 +133,27 @@ getClassForRequire(prev:string,name:string){
|
||||
str += " ng-invalid ng-dirty";
|
||||
return str;
|
||||
}
|
||||
dislayImage(): any {
|
||||
if (this.profileFile)
|
||||
{
|
||||
return URL.createObjectURL(this.profileFile);
|
||||
}
|
||||
else if (this.imageDataUrl() != "")
|
||||
{
|
||||
return this.imageDataUrl();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
onFileSelected(event: any) {
|
||||
|
||||
const file: File = event.target.files[0];
|
||||
|
||||
if (file) {
|
||||
this.file = file;
|
||||
this.profileFile = file;
|
||||
//this.messageService.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded!' });
|
||||
this.adminuserForm.patchValue({ image: this.file.name });
|
||||
this.adminuserForm.patchValue({ image: this.profileFile.name });
|
||||
this.fileName = file.name;
|
||||
this.subChanged$.next(false);
|
||||
}
|
||||
@@ -165,6 +184,14 @@ deleteFile(): void {
|
||||
|
||||
doDeleteFile(): void {
|
||||
const fileName = this.adminuserForm.value.image;
|
||||
if (fileName)
|
||||
{
|
||||
this.doDeleteImage(fileName);
|
||||
}
|
||||
else if (this.profileFile)
|
||||
this.profileFile = null;
|
||||
}
|
||||
doDeleteImage(fileName:string) : void {
|
||||
const familyId = this.adminuserForm.value.id;
|
||||
const data = { fileName, familyId };
|
||||
const delete$ = this.personService.deleteUploadFile(data);
|
||||
@@ -187,8 +214,6 @@ doDeleteFile(): void {
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
}
|
||||
|
||||
getFileToSave(file: File): FormData {
|
||||
@@ -284,8 +309,7 @@ doViewImage(imageName:string): void {
|
||||
const ref = this.dialogService.open(ImageDisplayComponent, {
|
||||
data: {
|
||||
imageName,
|
||||
},
|
||||
|
||||
},
|
||||
header: 'View Image',
|
||||
draggable: true,
|
||||
width: '70%',
|
||||
@@ -308,6 +332,10 @@ assignValue(item:Person): void {
|
||||
this.fileName = item.image!;
|
||||
if (item.relationShips)
|
||||
this.populatePartner(item.relationShips, item.id);
|
||||
if (item.personPhotos)
|
||||
{
|
||||
this.photoList = item.personPhotos;
|
||||
}
|
||||
this.adminuserForm.patchValue({
|
||||
id: item.id,
|
||||
email: item.email,
|
||||
@@ -328,12 +356,42 @@ assignValue(item:Person): void {
|
||||
dob: moment(dob).toDate()
|
||||
});
|
||||
}
|
||||
if (item.image && item.image.length > 0)
|
||||
{
|
||||
this.loadImage(item.image);
|
||||
}
|
||||
// disable use false//true for not disable.
|
||||
this.subChanged$.next(true);
|
||||
}
|
||||
|
||||
// convenience getter for easy access in form fields
|
||||
get f() { return this.adminuserForm.controls;}
|
||||
|
||||
loadImage(fileName: string| null): void {
|
||||
const download = this.personService.downloadFile(fileName!);
|
||||
this.subscription.add(download.subscribe({
|
||||
next: x => {
|
||||
if (x.statusCode == 1)
|
||||
{
|
||||
|
||||
this.displayIamge64(x.data);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("error in download in api ", x.message);
|
||||
}
|
||||
},
|
||||
error: e => console.error("error in download image", e)
|
||||
}));
|
||||
}
|
||||
displayIamge64(baseImage: string): void
|
||||
{
|
||||
const changeUrl = (this.sanitizer.bypassSecurityTrustResourceUrl(baseImage) as any).changingThisBreaksApplicationSecurity;
|
||||
console.log('this is bypassSecurityTrustResourceUrl', changeUrl);
|
||||
const fullDataUri = `data:image/png;base64,${changeUrl}`;
|
||||
this.imageDataUrl.set(fullDataUri);
|
||||
}
|
||||
validate(adminuser:Person): boolean {
|
||||
let result = true;
|
||||
console.log("validate", adminuser);
|
||||
@@ -383,8 +441,6 @@ assignValue(item:Person): void {
|
||||
}
|
||||
console.log("get partner for save in partner list ", vitem);
|
||||
}
|
||||
|
||||
|
||||
return rlist;
|
||||
}
|
||||
|
||||
@@ -423,10 +479,10 @@ assignValue(item:Person): void {
|
||||
let container:any = {
|
||||
person: item
|
||||
};
|
||||
if (this.file != null)
|
||||
if (this.profileFile != null)
|
||||
{
|
||||
container.formData = await Utils.toBase64(this.file);
|
||||
container.fileName = this.file.name;
|
||||
container.formData = await Utils.toBase64(this.profileFile);
|
||||
container.fileName = this.profileFile.name;
|
||||
console.log('image as base64 ', container);
|
||||
}
|
||||
container.person.relationShips = this.getPartnerForSave();
|
||||
@@ -439,7 +495,13 @@ assignValue(item:Person): void {
|
||||
// this.messageService.add({severity:'success', summary: 'Save user', detail: item.firstName + " " + item.lastName });
|
||||
//this.router.navigate([this.returnUrl]);
|
||||
console.log("the person after save", item);
|
||||
this.ref.close(item);
|
||||
const list = this.getPhotoListforSave();
|
||||
if (list.length > 0)
|
||||
{
|
||||
this.savePhotoList(list, item);
|
||||
}
|
||||
else
|
||||
this.ref.close(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -498,7 +560,9 @@ populatePartner(list: RelationShip[], personId: number): void {
|
||||
if (vlist.length > 0)
|
||||
this.partners.set(vlist);
|
||||
}
|
||||
|
||||
viewAttachment(): void {
|
||||
this.showAttachment("Add family photo or other");
|
||||
}
|
||||
|
||||
addPartner(): void {
|
||||
const title = "Partner";
|
||||
@@ -575,6 +639,113 @@ showPickPerson(title:string, callback:(id: Person) => void) :void {
|
||||
});
|
||||
}
|
||||
|
||||
showAttachment(title:string): void {
|
||||
const ref = this.dialogService.open(PhotoList, {
|
||||
data: {
|
||||
id: this._id,
|
||||
personPhotos: this.photoList
|
||||
},
|
||||
header: title,
|
||||
width: '80%',
|
||||
draggable: true,
|
||||
maximizable: true
|
||||
});
|
||||
|
||||
ref.onClose.subscribe((ritem: any) => {
|
||||
const item = ritem.list;
|
||||
const deleteIds = ritem.deleteIds;
|
||||
if (item) {
|
||||
console.log("after close " + title, item);
|
||||
this.messageService.add({severity:'success', summary: title, detail: "photo attachment " + item.length});
|
||||
//update the current list
|
||||
// callback(item);
|
||||
this.updatePhotoList(item);
|
||||
}
|
||||
if (deleteIds && deleteIds.length > 0)
|
||||
{
|
||||
let j = 0;
|
||||
|
||||
for (let i = 0; i < deleteIds.length; i++)
|
||||
{
|
||||
const id = deleteIds[i];
|
||||
j = this.photoList.findIndex(x => x.id == id);
|
||||
if (j > -1)
|
||||
{
|
||||
this.photoList.splice(j,1);
|
||||
}
|
||||
|
||||
}
|
||||
this.cdr.markForCheck();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
updatePhotoList(list: PersonPhotoDto[]): void {
|
||||
for (let i = 0; i < list.length; i++)
|
||||
{
|
||||
const item = list[i];
|
||||
const idx = this.photoList.findIndex(x => x.id == item.id);
|
||||
if (idx && idx < 0)
|
||||
this.photoList.push(item);
|
||||
else
|
||||
{
|
||||
let eitem = this.photoList[idx];
|
||||
eitem.photo = item.photo;
|
||||
eitem.photoType = item.photoType;
|
||||
eitem.file = item.file;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("the photos after close", this.photoList);
|
||||
this.subChanged$.next(false);//make save button to enable.
|
||||
this.cdr.markForCheck();
|
||||
}
|
||||
|
||||
getPhotoListforSave(): PersonPhotoDto[] {
|
||||
let result: PersonPhotoDto[] =[];
|
||||
for (let i = 0; i < this.photoList.length; i++)
|
||||
{
|
||||
if (this.photoList[i].id < 0)
|
||||
{
|
||||
result.push(this.photoList[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
savePhotoList(list: PersonPhotoDto[], item:Person): void {
|
||||
|
||||
const formData = new FormData();
|
||||
for (let i = 0; i < list.length; i++)
|
||||
{
|
||||
const file = list[i].file;
|
||||
if (file)
|
||||
formData.append("files", file, file.name);
|
||||
}
|
||||
formData.append('personId', this._id.toString());
|
||||
|
||||
const personPhoto$ = this.personService.savePersonPhotoList(formData);
|
||||
this.subscription.add(personPhoto$.subscribe(
|
||||
{
|
||||
next: x => {
|
||||
if (x.statusCode == 1) {
|
||||
//const filename = x.data;
|
||||
//this.adminuserForm.patchValue({ image: filename });
|
||||
this.ref.close(item);
|
||||
//this.cdr.detectChanges();
|
||||
}
|
||||
else
|
||||
this.messageService.add({ severity: 'error', summary: 'Error save attach photos files', detail: 'Fail to photos file: ' + x.message });
|
||||
},
|
||||
error: e =>
|
||||
this.messageService.add({ severity: 'error', summary: 'Error attach photos file', detail: 'Fail to photos file: ' })
|
||||
|
||||
}
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
cancel(e:Event):void {
|
||||
e.preventDefault();
|
||||
this.ref.close(null);
|
||||
|
||||
@@ -89,4 +89,21 @@ export class PersonService {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/DeleteUploadFile";
|
||||
return this.http.post<ResultModel<number>>(baseUrl, data);
|
||||
}
|
||||
deletePersonPhotoFile(id: number): Observable<ResultModel<number>> {
|
||||
const data ={id, fileName:''};
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DeletePersonPhoto";
|
||||
return this.http.post<ResultModel<number>>(baseUrl, data);
|
||||
}
|
||||
savePersonPhotoList(data:FormData): Observable<ResultModel<number>> {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/SavePersonPhoto";
|
||||
return this.http.post<ResultModel<number>>(baseUrl, data);
|
||||
}
|
||||
downloadPersonPhoto(id: number): Observable<ResultModel<string>> {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DownloadPersonPhoto";
|
||||
const data = {
|
||||
id,
|
||||
fileName: ''
|
||||
};
|
||||
return this.http.post<ResultModel<string>>(baseUrl, data);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user