check add person photo finish

This commit is contained in:
2025-10-27 16:23:06 +11:00
parent c62ae2cd42
commit cbb61b796f
28 changed files with 1084 additions and 86 deletions
+20
View File
@@ -0,0 +1,20 @@
<div class="card gap-2">
<div class="mt-4">
<input type="file" class="file-input hidden" (change)="onFileSelected($event)" #fileUpload multiple>
<div class="file-upload">
<label>{{fileName || "Photo upload:"}}</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 class="flex items-end justify-end mt-4">
@if (files)
{
<button pButton pRipple type="button" icon="pi pi-upload" label="Add Photo" class="p-button-sm mr-2"
(click)="upload($event)"></button>
}
<button pButton pRipple type="button" icon="pi pi-times" label="Cancel" class="p-button-sm"
(click)="cancel($event)"></button>
</div>
</div>
</div>
+171
View File
@@ -0,0 +1,171 @@
import { ChangeDetectorRef, Component, inject, Inject, OnDestroy, OnInit, signal } from '@angular/core';
import { DynamicDialogModule, DynamicDialogRef ,DynamicDialogConfig} from 'primeng/dynamicdialog';
import { LookupEdit } from '../models';
import { UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { Subject, Subscription } from 'rxjs';
import { ConfirmationService, MessageService } from 'primeng/api';
import { LookupService } from '../shares';
import { CommonModule } from '@angular/common';
import { CheckboxModule } from 'primeng/checkbox';
import { InputTextModule } from 'primeng/inputtext';
import { ButtonModule } from 'primeng/button';
@Component({
selector: 'add-photo',
imports: [CommonModule, ReactiveFormsModule,
ButtonModule, InputTextModule,
DynamicDialogModule, CheckboxModule],
templateUrl: './add.photo.html',
styleUrls: ['./add.photo.css'],
providers: [ConfirmationService]
})
export class AddPhoto implements OnInit, OnDestroy {
isChange = true; // disable use false//true for not disable. make sure it true is disable button.
selType = "";
_error = "";
downloadFile = signal(false);
files: File[] = [];
fileName = "";
disabled: boolean = true;
subChanged$ = new Subject<boolean>();
private formBuilder = inject(UntypedFormBuilder);
private cdr = inject(ChangeDetectorRef);
private subscription: Subscription = new Subscription();
lookupForm = this.formBuilder.group({
id: [0], //Validators.required
description: ['', [Validators.required, Validators.maxLength(50)]],
codeId: ['', [Validators.required]],
parentId: [0],
active: [false], //Validators.required
});
constructor(
private lookupService: LookupService,
private messageService: MessageService,
private confirmationService: ConfirmationService,
public ref: DynamicDialogRef, public config: DynamicDialogConfig) { }
ngOnInit(): void {
const id = this.config.data.id;
this.selType = this.config.data.type;
const maxcodeId = this.config.data.maxCodeId;
if (id > 0) {
this.lookupService.loadLookupById(id, this.selType).subscribe({
next: x => {
this.assignValue(x.data);
this.cdr.markForCheck();
this.subscription.add(this.lookupForm.valueChanges.subscribe(x => this.isChange = false));
this.subscription.add(this.subChanged$.subscribe(x => this.isChange = x));
},
error: e => {
console.error("error", e);
this.messageService.add({ severity: 'error', summary: 'Error on load cleaner ', detail: e.message });
}
});
}
else {
//new cleaner
const ward:LookupEdit = {
id: -1, description: '', codeId: maxcodeId, type: this.selType, active: true,
};
this.assignValue(ward);
this.subscription.add(this.lookupForm.valueChanges.subscribe(x => this.isChange = false));
this.subscription.add(this.subChanged$.subscribe(x => this.isChange = x));
}
}
getClassForRequire(prev: string, name: string) {
const notok = !this.lookupForm.controls[name].valid &&
this.lookupForm.controls[name].touched;
let str = prev;
if (notok)
str += " ng-invalid ng-dirty";
return str;
}
get isFieldsChange() {
const chan = this.isChange || !this.lookupForm.valid; // this disable so need true valid = true not
//console.log(this.msg + 'is fields change', chan);
return chan;
}
assignValue(item: LookupEdit): void {
this.lookupForm.patchValue({
id: item.id,
codeId: item.codeId,
description: item.description,
active: item.active,
});
// disable use false//true for not disable.
this.subChanged$.next(true);
}
validate(item: LookupEdit): boolean {
let result = true;
if (item.description!.trim() == "") {
this._error = "Description is empty or blank";
result = false;
}
return result;
}
deleteFile() : void {
//const filename = this.requestForm.value.attachmentFile;
// const data = { filename };
this.fileName ="";
//this.requestForm.patchValue({ attachmentFile: "" });
/*
const delete$ = this.tradePersonService.deleteUploadFile(data);
this.subscription.add(delete$.subscribe(
{
next: x => {
if (x.statusCode == 1) {
{
this.requestForm.patchValue({ attachmentFile: "" });
}
}
else {
this.messageService.add({ severity: 'error', summary: 'Error delete upload file', detail: 'Fail to delete upload file: ' + x.message });
}
},
error: e => {
this.messageService.add({ severity: 'error', summary: 'Error delete upload file', detail: 'Fail to delete upload file: ' + e });
}
}
));
*/
}
onFileSelected(event: any) {
let i =0;
for (i = 0; i < event.target.files.length; i++)
{
const file: File = event.target.files[i];
this.files.push(file);
if (this.fileName != "")
this.fileName = this.fileName + "," + file.name;
else
this.fileName = file.name;
this.subChanged$.next(false);
}
}
upload(e: Event): void {
e.preventDefault();
this.ref.close(this.files);
}
cancel(e: Event): void {
e.preventDefault();
this.ref.close(null);
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
+2
View File
@@ -0,0 +1,2 @@
export * from './photolist';
export * from './add.photo';
+46
View File
@@ -0,0 +1,46 @@
<div class="shadow-xl rounded-md p-2">
<div class="flex fex-row justify-between mb-2">
<p> please click save at the end</p>
<div class="flex items-end self-end">
<button pButton pRipple type="button" icon="pi pi-file" label="Attach Photo" class="p-button-sm"
(click)="newSupportDoc($event)"></button>
</div>
</div>
<div class="p-4">
<p-table [value]="FileList" sortMode="multiple" class="p-datatable-sm"
[loading]="loading">
<ng-template pTemplate="header">
<tr>
<th>Id</th>
<th pSortableColumn="description">Description<p-sortIcon field="description"></p-sortIcon>
</th>
<th>Action</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-item>
<tr>
<td>{{item.id}}</td>
<td >{{item.photo}}</td>
<td>
<button pButton type="button" icon="pi pi-times" class="p-button-rounded p-button-text p-button-raised"
(click)="remove(item.id)"></button>
@if (item.id > 0) {
<button pButton type="button" icon="pi pi-file" class="p-button-rounded p-button-text p-button-raised"
(click)="downloadAttachment(item.id)"></button>
}
</td>
</tr>
</ng-template>
</p-table>
<div class="flex items-end justify-end mt-4">
<button pButton pRipple type="button" icon="pi pi-times" label="Close" class="p-button-sm"
(click)="onClose($event)"></button>
</div>
</div>
+160
View File
@@ -0,0 +1,160 @@
//import { Component, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit, OnDestroy, inject, ChangeDetectorRef, signal, output } from '@angular/core';
import { catchError, EMPTY, finalize, Subscription } from 'rxjs';
import { CommonUtilities, HttpUtility, LookupService } from '../shares';
import { DialogService ,DynamicDialogConfig,DynamicDialogModule, DynamicDialogRef} from 'primeng/dynamicdialog';
import { MessageService } from 'primeng/api';
import { AddPhoto } from './add.photo';
import { LookupEdit, PersonPhotoDto } from '../models';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { TableModule } from 'primeng/table';
import { ButtonModule } from 'primeng/button';
import { AuthenticationService } from '../user-services';
import { HttpResponse } from '@angular/common/http';
import { PersonService } from '../person';
@Component({
selector: 'photo-list',
imports: [CommonModule, FormsModule, DynamicDialogModule,
ButtonModule, TableModule],
templateUrl: './photolist.html',
styleUrls: ['./photolist.css'],
providers: [DialogService]
})
export class PhotoList implements OnInit, OnDestroy {
FileList: PersonPhotoDto[] =[]
loading = false;
_id = -1;
deletePersonPhoto: number[] = [];
private authenticationService = inject(AuthenticationService);
private cdr = inject(ChangeDetectorRef);
private messageService = inject(MessageService);
private subscription: Subscription = new Subscription();
downloadFile = signal(false);
constructor(
private http: HttpUtility,
private personService: PersonService,
public ref: DynamicDialogRef, public config: DynamicDialogConfig,
public dialogService: DialogService
) { }
ngOnInit(): void {
const id = this.config.data.id;
const olist = this.config.data.personPhotos;
if (olist && olist.length > 0)
{
this.FileList = olist;
this.assignFileId(olist);
}
}
assignFileId(files: any[]): void {
let i = 0;
let id = -1;
let mx = 1;
for (i = 0; i < files.length; i++)
{
id = files[i].id;
if (id < mx)
{
mx = id;
}
}
this._id = -1 + mx;
}
downloadAttachment(id: number): void {
//GetReportFile
let typeofCall = "personId_" + id.toString();
let criteria:any ={id, fileName:''};
this.downloadFile.set(false);
this.http.getFileResponse("api/FileUpload/downloadPersonPhoto", criteria).pipe(
catchError(err => {
console.error(err.message);
return EMPTY;
}),
finalize(() => {
// this.toastr.success("download completed ok to view now");
this.downloadFile.set(false);
})).subscribe((response: HttpResponse<Blob>) => {
if (response) {
console.log("the download report response", response);
CommonUtilities.downloadFile(response, typeofCall);
}
});
}
onClose(event: Event): void {
const nlist = this.FileList.filter( x => x.id < 1);
this.ref.close({list: nlist, deleteIds: this.deletePersonPhoto});
}
newSupportDoc(event: Event): void {
this.showEdit(this._id--);
}
remove(id: number): void {
if (id < 0)
{
const nlist = this.FileList.filter(x => x.id != id);
this.FileList = [...nlist];
this.cdr.markForCheck();
}
else
{
const deletepersonPhoto$ = this.personService.deletePersonPhotoFile(id);
this.subscription.add(deletepersonPhoto$.subscribe(
{
next: x => {
if (x.statusCode == 1)
{
const nlist = this.FileList.filter(x => x.id != id);
this.FileList = [...nlist];
this.deletePersonPhoto.push(id);
this.cdr.markForCheck();
this.messageService.add({severity:'success', summary: 'delete person photo', detail: "person photo Id " + id });
}
},
error:e => console.error("error in client delete person photo", e)
}
));
}
}
showEdit(id: number) {
const ref = this.dialogService.open(AddPhoto, {
data: {
id,
},
header: 'Add File',
width: '70%',
maximizable: true,
draggable: true
});
if (ref)
{
ref.onClose.subscribe((list: File[]) => {
if (list) {
//console.log("after close ward edit", item);
this.messageService.add({ severity: 'success', summary: 'Attact File', detail: list.length.toString() });
let it = id;
for (let i = 0; i < list.length; i++)
{
const item = list[i];
this.FileList.push({id: it--, photo: item.name, photoType:'', file: item});
}
this.cdr.markForCheck();
}
});
}
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@@ -0,0 +1,12 @@
<form runat="server">
<input accept="image/*" type='file' id="imgInp" />
<img id="blah" src="#" alt="your image" />
</form>
imgInp.onchange = evt => {
const [file] = imgInp.files
if (file) {
blah.src = URL.createObjectURL(file)
}
}
+2 -1
View File
@@ -7,4 +7,5 @@ export * from './lookup';
export * from './staff';
export * from './person';
export * from './job';
export * from './relationship';
export * from './relationship';
export * from './personphotodto';
+2
View File
@@ -1,3 +1,4 @@
import { PersonPhotoDto } from "./personphotodto";
import { RelationShip } from "./relationship";
export interface FamilySearch {
@@ -24,6 +25,7 @@ export interface Person {
fatherName?:string |null;
motherName?:string |null;
relationShips?: RelationShip[];
personPhotos?: PersonPhotoDto[];
}
export interface PersonContainer
+6
View File
@@ -0,0 +1,6 @@
export interface PersonPhotoDto {
id: number;
photo:string|null | undefined;
photoType:string |null | undefined;
file: File | null | undefined;
}
+12 -1
View File
@@ -1,2 +1,13 @@
.profilePhotoBorder
{
border-color: gray;
border-width: 2px;
border-radius: 15%;
}
.profilePhotoWH
{
width: 150px;
height: 100px;
}
+72 -57
View File
@@ -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>
+187 -16
View File
@@ -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);
+17
View File
@@ -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);
}
}
+7 -1
View File
@@ -160,7 +160,13 @@ static formatNode(item:Person): TreeNode
return node;
}
static getFileExtension(filename: string): string {
const lastDotIndex = filename.lastIndexOf('.');
if (lastDotIndex !== -1 && lastDotIndex < filename.length - 1) { // Ensure a dot exists and is not the last character
return filename.substring(lastDotIndex + 1);
}
return ''; // No extension found
}
static getChildForParentId(proName: MyProName , pid: number,childressNodes: Person[]): TreeNode[] {
let result: TreeNode[] =[];
let tree_node_child: TreeNode[];