put in ignore file
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mat-form-field {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
td.mat-column-edit, .mat-column-delete {
|
||||
width: 35px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<div class="shadow-2xl rounded p-2 mt-2">
|
||||
<h3>Family Tree</h3>
|
||||
<div>
|
||||
<div >
|
||||
<p-organization-chart [value]="familyTree()" selectionMode="multiple" [(selection)]="selectedNodes" [collapsible]="true">
|
||||
<ng-template let-node pTemplate="default">
|
||||
<div class="flex flex-col items-center">
|
||||
<!--img src="https://primefaces.org/cdn/primeng/images/flag/flag_placeholder.png" [alt]="node.label" [class]="'flag' + ' flag-' + node.data" width="32" /-->
|
||||
<div class="mt-4 font-medium text-lg">{{ node.label }}</div>
|
||||
<div>{{ node.data }}</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</p-organization-chart>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<button pButton pRipple class="p-button-sm mr-2 p-button-success" type="button" icon="pi pi-sign-in" label="Close"
|
||||
(click)="close()"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
import { Component, OnInit, OnDestroy, inject, ChangeDetectorRef, signal} from '@angular/core';
|
||||
|
||||
import { StaffView ,StaffSearch, Person, RelationShip } from '../models';
|
||||
import { OrganizationChartModule } from 'primeng/organizationchart';
|
||||
|
||||
import { take } from 'rxjs/operators';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Router } from '@angular/router';
|
||||
import { PersonService } from './person.service';
|
||||
import { AuthenticationService } from '../user-services';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { TreeNode } from 'primeng/api';
|
||||
import { InputTextModule } from 'primeng/inputtext';
|
||||
import { DialogService, DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
|
||||
import { PersonEdit } from './person.edit';
|
||||
import { MessageService } from 'primeng/api';
|
||||
import { TreeModule, TreeNodeDoubleClickEvent, TreeNodeSelectEvent } from 'primeng/tree';
|
||||
import { Utils } from '../shares';
|
||||
|
||||
@Component({
|
||||
selector: 'family-orga',
|
||||
templateUrl: './family.orga.html',
|
||||
imports:[TableModule,FormsModule,TreeModule, OrganizationChartModule,CommonModule,ButtonModule,InputTextModule],
|
||||
styleUrls: ['./family.orga.css'],
|
||||
providers: [DialogService]
|
||||
})
|
||||
export class FamilyOrga implements OnInit, OnDestroy{
|
||||
|
||||
private subscription:Subscription = new Subscription();
|
||||
person!: Person;
|
||||
selectedNode!: TreeNode;
|
||||
selectedNodes!: TreeNode[];
|
||||
private cd = inject(ChangeDetectorRef);
|
||||
familyTree = signal<TreeNode[]>([]);
|
||||
relations: RelationShip[] =[];
|
||||
_id = -10;
|
||||
loading = false;
|
||||
familyList:Person[] = [];
|
||||
msg ="[Person organise component]";
|
||||
private messageService = inject(MessageService);
|
||||
/*
|
||||
private store: Store<appValidationState>
|
||||
*/
|
||||
constructor(
|
||||
public dialogService: DialogService,
|
||||
private personService: PersonService,
|
||||
|
||||
public ref: DynamicDialogRef, public config: DynamicDialogConfig,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
const id = this.config.data.id;
|
||||
this.familyList = this.config.data.familyList;
|
||||
const item = this.familyList.find(x => x.id == id);
|
||||
if (item != undefined)
|
||||
this.person = item;
|
||||
this.loadPersonFamilyTree(id);
|
||||
// this. populateTree();
|
||||
|
||||
}
|
||||
populateTree() : void {
|
||||
const tree = [
|
||||
{
|
||||
label: 'F.C Barcelona',
|
||||
expanded: true,
|
||||
children: [
|
||||
{
|
||||
label: 'Argentina',
|
||||
expanded: true,
|
||||
children: [
|
||||
{
|
||||
label: 'Argentina'
|
||||
},
|
||||
{
|
||||
label: 'France'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'France',
|
||||
expanded: true,
|
||||
children: [
|
||||
{
|
||||
label: 'France'
|
||||
},
|
||||
{
|
||||
label: 'Morocco'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
this.familyTree.set(tree);
|
||||
}
|
||||
loadPersonFamilyTree(id: number): void {
|
||||
const relationShip$ = this.personService.loadPersonFamily(id);
|
||||
this.subscription.add(relationShip$.subscribe(
|
||||
{
|
||||
next: x => {
|
||||
if (x.statusCode == 1)
|
||||
{
|
||||
let tree : TreeNode[] =[];
|
||||
tree.push(x.data);
|
||||
this.familyTree.set(tree);
|
||||
console.log("load person family", this.familyTree());
|
||||
|
||||
}
|
||||
},
|
||||
error: e => {
|
||||
console.error("error load loadPersonFamily by personId", id);
|
||||
this.messageService.add({severity:'error', summary: 'error load loadPersonFamily by personId', detail: e.message});
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
nodeSelect(event: TreeNodeSelectEvent) {
|
||||
// this.messageService.add({ severity: 'info', summary: 'Node Selected', detail: event.node.label });
|
||||
}
|
||||
nodeDoubleSelect(event:TreeNodeDoubleClickEvent) : void {
|
||||
// console.log("double click node", event.node.key);
|
||||
const id = event.node.key;
|
||||
this.edit(Number(id));
|
||||
}
|
||||
|
||||
getName(id:number): string
|
||||
{
|
||||
let result ="";
|
||||
const item = this.familyList.find(x => x.id == id);
|
||||
if (item)
|
||||
result = item.lastName + " " + item.firstName;
|
||||
return result;
|
||||
}
|
||||
updateParent(list:Person[]):void {
|
||||
let i = 0;
|
||||
let item:Person;
|
||||
for (i = 0; i< list.length; i++)
|
||||
{
|
||||
item = list[i];
|
||||
if (item.fatherId && item.fatherId > 0)
|
||||
{
|
||||
item.fatherName = this.getName(item.fatherId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newFamily():void {
|
||||
//console.log("add new employee");
|
||||
this.personService.parentList = this.familyList;
|
||||
// this.router.navigate( ['/family/new'], { queryParams: {returnUrl:'/family' } });
|
||||
this.showEdit(this._id--);
|
||||
}
|
||||
edit(id: number) : void {
|
||||
//console.log("edit family", id);
|
||||
this.personService.parentList = this.familyList;
|
||||
// this.router.navigate( ['/family/'+id], { queryParams: {returnUrl:'/family' } });
|
||||
this.showEdit(id);
|
||||
}
|
||||
showEdit(id:number) {
|
||||
const ref = this.dialogService.open(PersonEdit, {
|
||||
data: {
|
||||
id,
|
||||
familyList: this.familyList,
|
||||
},
|
||||
header: 'Family',
|
||||
width: '80%',
|
||||
maximizable: true
|
||||
});
|
||||
|
||||
ref.onClose.subscribe((item: Person) => {
|
||||
if (item) {
|
||||
//console.log("after close ward edit", item);
|
||||
this.messageService.add({severity:'success', summary: 'Save Family', detail: item.firstName!});
|
||||
//update the current list
|
||||
this.updateList(item);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
updateList(item: Person) :void {
|
||||
const idx = this.familyList.findIndex( x => x.id == item.id);
|
||||
if (item.fatherId && item.fatherId > 0)
|
||||
item.fatherName = this.getName(item.fatherId);
|
||||
if (item.motherId && item.motherId > 0)
|
||||
item.motherName = this.getName(item.motherId);
|
||||
if (idx < 0)
|
||||
{
|
||||
|
||||
const olist = [... this.familyList, item];
|
||||
this.familyList = olist;
|
||||
}
|
||||
else
|
||||
{
|
||||
const oitem = this.familyList[idx];
|
||||
oitem.firstName = item.firstName;
|
||||
oitem.lastName = item.lastName;
|
||||
oitem.address = item.address;
|
||||
oitem.alive = item.alive;
|
||||
oitem.dob = item.dob;
|
||||
oitem.email = item.email;
|
||||
oitem.fatherId = item.fatherId;
|
||||
oitem.motherId = item.motherId;
|
||||
oitem.motherName = item.motherName;
|
||||
oitem.fatherName = item.fatherName;
|
||||
|
||||
}
|
||||
}
|
||||
deleteItem(id: number): void {
|
||||
this.personService.deletePerson(id)
|
||||
.pipe(take(1))
|
||||
.subscribe({ next: result => {
|
||||
console.log(this.msg + " deleteItem success", result);
|
||||
|
||||
const nlist = this.familyList.filter(d => d.id !== id);
|
||||
this.familyList = nlist;
|
||||
},
|
||||
error: e => console.error(e)
|
||||
});
|
||||
//console.log(this.msg + "click button to delete");
|
||||
}
|
||||
close() :void {
|
||||
this.ref.close(null);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mat-form-field {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
td.mat-column-edit, .mat-column-delete {
|
||||
width: 35px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<div class="shadow-2xl rounded p-2 mt-2">
|
||||
<h3>Family Tree</h3>
|
||||
<div>
|
||||
<form>
|
||||
<div class="grid grid-cols-4 gap-2">
|
||||
<div class="">
|
||||
<label for="login">Email</label>
|
||||
<input id="login" pInputText name="login" type="text" [(ngModel)]="email"
|
||||
class="inputfield w-full p-inputtext-sm">
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="lastname1">Surname</label>
|
||||
<input id="lastname1" pInputText name="lastname" type="text" [(ngModel)]="lastname"
|
||||
class="inputfield w-full p-inputtext-sm">
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="firstname">First Name</label>
|
||||
<input id="firstname" name="firstname" pInputText type="text" [(ngModel)]="firstname"
|
||||
class="inputfield w-full p-inputtext-sm">
|
||||
</div>
|
||||
<div class="flex items-end">
|
||||
<button pButton pRipple class="p-button-sm mr-2 " type="submit" icon="pi pi-search" iconPos="left" label="Search"
|
||||
(click)="search()"></button>
|
||||
<button pButton pRipple class="p-button-sm " type="button" icon="pi pi-user-plus" iconPos="left" label="New Family"
|
||||
(click)="newFamily()"></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
<p-tree [value]="familyTree" class="w-full md:w-[30rem]"
|
||||
(onNodeDoubleClick)="nodeDoubleSelect($event)"
|
||||
selectionMode="single" [(selection)]="selectedNode" (onNodeSelect)="nodeSelect($event)" />
|
||||
<!--div class="card flex justify-center overflow-x-auto">
|
||||
<p-organization-chart [value]="familyTree" selectionMode="multiple" [(selection)]="selectedNodes" [collapsible]="true">
|
||||
<ng-template let-node pTemplate="person">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col items-center">
|
||||
<img [src]="node.data.image" class="mb-4 w-12 h-12" />
|
||||
<div class="font-bold mb-2">{{ node.data.name }}</div>
|
||||
<div>{{ node.data.title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</p-organization-chart>
|
||||
</div-->
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
import { Component, OnInit, OnDestroy, inject, ChangeDetectorRef} from '@angular/core';
|
||||
|
||||
import { StaffView ,StaffSearch, Person } from '../models';
|
||||
import { OrganizationChartModule } from 'primeng/organizationchart';
|
||||
|
||||
import { take } from 'rxjs/operators';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Router } from '@angular/router';
|
||||
import { PersonService } from './person.service';
|
||||
import { AuthenticationService } from '../user-services';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { TreeNode } from 'primeng/api';
|
||||
import { InputTextModule } from 'primeng/inputtext';
|
||||
import { DialogService } from 'primeng/dynamicdialog';
|
||||
import { PersonEdit } from './person.edit';
|
||||
import { MessageService } from 'primeng/api';
|
||||
import { TreeModule, TreeNodeDoubleClickEvent, TreeNodeSelectEvent } from 'primeng/tree';
|
||||
import { Utils } from '../shares';
|
||||
|
||||
@Component({
|
||||
selector: 'family-tree',
|
||||
templateUrl: './family.tree.html',
|
||||
imports:[TableModule,FormsModule,TreeModule, OrganizationChartModule,CommonModule,ButtonModule,InputTextModule],
|
||||
styleUrls: ['./family.tree.css'],
|
||||
providers: [DialogService]
|
||||
})
|
||||
export class FamilyTree implements OnInit, OnDestroy{
|
||||
|
||||
private subscription:Subscription = new Subscription();
|
||||
firstname = '';
|
||||
selectedNode!: TreeNode;
|
||||
private cd = inject(ChangeDetectorRef);
|
||||
familyTree: TreeNode[] = [];
|
||||
email = '';
|
||||
lastname = '';
|
||||
_id = -10;
|
||||
loading = false;
|
||||
familyList:Person[] = [];
|
||||
msg ="[Person tree component]";
|
||||
private messageService = inject(MessageService);
|
||||
/*
|
||||
private store: Store<appValidationState>
|
||||
*/
|
||||
constructor(
|
||||
public dialogService: DialogService,
|
||||
private personService: PersonService,
|
||||
private authenticationService: AuthenticationService,
|
||||
private router: Router
|
||||
) {}
|
||||
getSearchCiteria(): StaffSearch {
|
||||
let criteria:StaffSearch = {
|
||||
email: this.email,
|
||||
firstName: this.firstname,
|
||||
lastName: this.lastname,
|
||||
};
|
||||
|
||||
return criteria;
|
||||
|
||||
}
|
||||
canSearch():boolean {
|
||||
let result = false;
|
||||
result = this.email !== "";
|
||||
result = result || this.lastname !== "";
|
||||
result = result || this.firstname !== "";
|
||||
return result;
|
||||
}
|
||||
ngOnInit(): void
|
||||
{
|
||||
this.authenticationService.isHome = false;
|
||||
this.authenticationService.isReport = false;
|
||||
const prev = this.personService.searchCriteria;
|
||||
let goload = true;
|
||||
if (prev.lastName !== '')
|
||||
{
|
||||
this.lastname = prev.lastName;
|
||||
goload = true;
|
||||
}
|
||||
if (prev.firstName !== '')
|
||||
{
|
||||
this.firstname = prev.firstName;
|
||||
goload = true;
|
||||
}
|
||||
if (prev.email !== '')
|
||||
{
|
||||
this.email = prev.email;
|
||||
goload = true;
|
||||
}
|
||||
if (goload)
|
||||
{
|
||||
this.search();
|
||||
}
|
||||
}
|
||||
getActive(active:boolean):string {
|
||||
let result = 'false-icon pi-times-circle';
|
||||
if (active)
|
||||
result = 'true-icon pi-check-circle';
|
||||
return result;
|
||||
}
|
||||
search():void {
|
||||
const canSearch = true; // this.canSearch();
|
||||
if (canSearch)
|
||||
{
|
||||
this.loading = true;
|
||||
//const criteria = this.getSearchCiteria();
|
||||
// this.personService.searchCriteria = criteria;
|
||||
this.subscription.add(
|
||||
this.personService.loadPersonFamilyTree(true, false).subscribe(
|
||||
{
|
||||
next: x => {
|
||||
if (x.statusCode == 1)
|
||||
{
|
||||
this.familyTree = x.data;
|
||||
this.loading = false;
|
||||
this.cd.detectChanges();
|
||||
console.log("the family tree", this.familyTree);
|
||||
}
|
||||
},
|
||||
|
||||
error: e => {
|
||||
const message = e || e.message;
|
||||
// this.toastr.error(message);
|
||||
this.loading = false;
|
||||
console.log("error ", e);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
/*
|
||||
this.personService.searchPersons(criteria).subscribe( {
|
||||
next: result => {
|
||||
// console.log(this.msg + "search load Data", result);
|
||||
this.familyList = result.data;
|
||||
this.familyTree = Utils.populateNode( "fatherId", this.familyList);
|
||||
this.loading = false;
|
||||
this.cd.detectChanges();
|
||||
}
|
||||
},
|
||||
|
||||
error: e => {
|
||||
const message = e || e.message;
|
||||
// this.toastr.error(message);
|
||||
this.loading = false;
|
||||
console.log("error ", e);
|
||||
}
|
||||
})
|
||||
);
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
nodeSelect(event: TreeNodeSelectEvent) {
|
||||
// this.messageService.add({ severity: 'info', summary: 'Node Selected', detail: event.node.label });
|
||||
}
|
||||
nodeDoubleSelect(event:TreeNodeDoubleClickEvent) : void {
|
||||
// console.log("double click node", event.node.key);
|
||||
const id = event.node.key;
|
||||
this.edit(Number(id));
|
||||
}
|
||||
|
||||
getName(id:number): string
|
||||
{
|
||||
let result ="";
|
||||
const item = this.familyList.find(x => x.id == id);
|
||||
if (item)
|
||||
result = item.lastName + " " + item.firstName;
|
||||
return result;
|
||||
}
|
||||
updateParent(list:Person[]):void {
|
||||
let i = 0;
|
||||
let item:Person;
|
||||
for (i = 0; i< list.length; i++)
|
||||
{
|
||||
item = list[i];
|
||||
if (item.fatherId && item.fatherId > 0)
|
||||
{
|
||||
item.fatherName = this.getName(item.fatherId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newFamily():void {
|
||||
//console.log("add new employee");
|
||||
this.personService.parentList = this.familyList;
|
||||
// this.router.navigate( ['/family/new'], { queryParams: {returnUrl:'/family' } });
|
||||
this.showEdit(this._id--);
|
||||
}
|
||||
edit(id: number) : void {
|
||||
//console.log("edit family", id);
|
||||
this.personService.parentList = this.familyList;
|
||||
// this.router.navigate( ['/family/'+id], { queryParams: {returnUrl:'/family' } });
|
||||
this.showEdit(id);
|
||||
}
|
||||
showEdit(id:number) {
|
||||
const ref = this.dialogService.open(PersonEdit, {
|
||||
data: {
|
||||
id,
|
||||
familyList: this.familyList,
|
||||
},
|
||||
header: 'Family',
|
||||
width: '80%',
|
||||
maximizable: true
|
||||
});
|
||||
|
||||
ref.onClose.subscribe((item: Person) => {
|
||||
if (item) {
|
||||
//console.log("after close ward edit", item);
|
||||
this.messageService.add({severity:'success', summary: 'Save Family', detail: item.firstName!});
|
||||
//update the current list
|
||||
this.updateList(item);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
updateList(item: Person) :void {
|
||||
const idx = this.familyList.findIndex( x => x.id == item.id);
|
||||
if (item.fatherId && item.fatherId > 0)
|
||||
item.fatherName = this.getName(item.fatherId);
|
||||
if (item.motherId && item.motherId > 0)
|
||||
item.motherName = this.getName(item.motherId);
|
||||
if (idx < 0)
|
||||
{
|
||||
|
||||
const olist = [... this.familyList, item];
|
||||
this.familyList = olist;
|
||||
}
|
||||
else
|
||||
{
|
||||
const oitem = this.familyList[idx];
|
||||
oitem.firstName = item.firstName;
|
||||
oitem.lastName = item.lastName;
|
||||
oitem.address = item.address;
|
||||
oitem.alive = item.alive;
|
||||
oitem.dob = item.dob;
|
||||
oitem.email = item.email;
|
||||
oitem.fatherId = item.fatherId;
|
||||
oitem.motherId = item.motherId;
|
||||
oitem.motherName = item.motherName;
|
||||
oitem.fatherName = item.fatherName;
|
||||
|
||||
}
|
||||
}
|
||||
deleteItem(id: number): void {
|
||||
this.personService.deletePerson(id)
|
||||
.pipe(take(1))
|
||||
.subscribe({ next: result => {
|
||||
console.log(this.msg + " deleteItem success", result);
|
||||
|
||||
const nlist = this.familyList.filter(d => d.id !== id);
|
||||
this.familyList = nlist;
|
||||
},
|
||||
error: e => console.error(e)
|
||||
});
|
||||
//console.log(this.msg + "click button to delete");
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mat-form-field {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
td.mat-column-edit, .mat-column-delete {
|
||||
width: 35px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<div class="shadow-2xl rounded p-2 mt-2">
|
||||
<h3>Person List</h3>
|
||||
<div>
|
||||
<form>
|
||||
<div class="grid grid-cols-4 gap-2">
|
||||
<div class="">
|
||||
<label for="login">Email</label>
|
||||
<input id="login" pInputText name="login" type="text" [(ngModel)]="email"
|
||||
class="inputfield w-full p-inputtext-sm">
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="lastname1">Surname</label>
|
||||
<input id="lastname1" pInputText name="lastname" type="text" [(ngModel)]="lastname"
|
||||
class="inputfield w-full p-inputtext-sm">
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="firstname">First Name</label>
|
||||
<input id="firstname" name="firstname" pInputText type="text" [(ngModel)]="firstname"
|
||||
class="inputfield w-full p-inputtext-sm">
|
||||
</div>
|
||||
<div class="flex items-end">
|
||||
<button pButton pRipple class="p-button-sm mr-2 " type="submit" icon="pi pi-search" iconPos="left" label="Search"
|
||||
(click)="search()"></button>
|
||||
<button pButton pRipple class="p-button-sm " type="button" icon="pi pi-user-plus" iconPos="left" label="New Person"
|
||||
(click)="newFamily()"></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
<p-table [value]="familyList()" sortMode="multiple" dataKey="id" class="p-datatable-sm"
|
||||
class="p-datatable-sm" selectionMode="single" [(selection)]="selectedPerson"
|
||||
[paginator]="true" rowHover="true" [globalFilterFields]="['lastName', 'firstName', 'email', 'fatherName', 'motherName']"
|
||||
[rows]="20" [rowsPerPageOptions]="[10,20,50,100]"
|
||||
[loading]="loading">
|
||||
<ng-template #caption>
|
||||
<div class="flex">
|
||||
<p-iconfield iconPosition="left" class="ml-auto">
|
||||
<p-inputicon>
|
||||
<i class="pi pi-search"></i>
|
||||
</p-inputicon>
|
||||
<input pInputText type="text" (input)="handleInput($event)" placeholder="Search keyword" />
|
||||
</p-iconfield>
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
|
||||
<th pSortableColumn="lastName">Last Name <p-sortIcon field="lastName"></p-sortIcon>
|
||||
</th>
|
||||
<th pSortableColumn="firstName">First Name <p-sortIcon field="firstName"></p-sortIcon>
|
||||
</th>
|
||||
<th pSortableColumn="sex">Sex <p-sortIcon field="sex"></p-sortIcon></th>
|
||||
<th pSortableColumn="fatherName">Father<p-sortIcon field="fatherName"></p-sortIcon>
|
||||
</th>
|
||||
<th pSortableColumn="motherName">Mother<p-sortIcon field="motherName"></p-sortIcon>
|
||||
</th>
|
||||
|
||||
<th>Edit</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body" let-user>
|
||||
<tr>
|
||||
<td>{{user.lastName}}</td>
|
||||
<td>{{user.firstName}}</td>
|
||||
<td>{{user.sex}}</td>
|
||||
<td>{{user.fatherName}}</td>
|
||||
<td>{{user.motherName}}</td>
|
||||
|
||||
<td>
|
||||
<p-button type="button" icon="pi pi-ellipsis-v"
|
||||
[rounded]="true" [text]="true" [raised]="true"
|
||||
class="p-button-rounded p-button-text"
|
||||
(onClick)="actionClick(user.id,$event)"></p-button>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
<p-menu #rowmenu [model]="items" [popup]="true" (onShow)="onMenuShow()" />
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
import { Component, OnInit, OnDestroy, inject, ChangeDetectorRef, signal, ViewChild} from '@angular/core';
|
||||
|
||||
import { StaffView ,StaffSearch, Person } from '../models';
|
||||
|
||||
|
||||
import { take } from 'rxjs/operators';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Router } from '@angular/router';
|
||||
import { PersonService } from './person.service';
|
||||
import { AuthenticationService } from '../user-services';
|
||||
import { Table, TableModule } from 'primeng/table';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { InputTextModule } from 'primeng/inputtext';
|
||||
import { DialogService } from 'primeng/dynamicdialog';
|
||||
import { PersonEdit } from './person.edit';
|
||||
import { ConfirmationService, MenuItem, MessageService } from 'primeng/api';
|
||||
import { IconFieldModule } from 'primeng/iconfield';
|
||||
import { InputIconModule } from 'primeng/inputicon';
|
||||
import { Menu, MenuModule } from 'primeng/menu';
|
||||
import { FamilyOrga } from './family.orga';
|
||||
@Component({
|
||||
selector: 'family-list',
|
||||
templateUrl: './familylist.html',
|
||||
imports:[TableModule,FormsModule,CommonModule,ButtonModule,MenuModule,
|
||||
InputTextModule,IconFieldModule,InputIconModule],
|
||||
styleUrls: ['./familylist.css'],
|
||||
providers: [DialogService]
|
||||
})
|
||||
export class FamilyList implements OnInit, OnDestroy{
|
||||
|
||||
private subscription:Subscription = new Subscription();
|
||||
//private cd = inject(ChangeDetectorRef);
|
||||
items: MenuItem[] | undefined;
|
||||
selectedPerson!: Person;
|
||||
firstname = '';
|
||||
email = '';
|
||||
lastname = '';
|
||||
_id = -10;
|
||||
selectId = -1;
|
||||
loading = false;
|
||||
familyList = signal<Person[]>([]);
|
||||
msg ="[Person component]";
|
||||
@ViewChild(Table) dt2!: Table;
|
||||
@ViewChild('rowmenu') popMenu?: Menu;
|
||||
private messageService = inject(MessageService);
|
||||
public dialogService= inject( DialogService);
|
||||
private personService= inject( PersonService);
|
||||
private confirmationService = inject(ConfirmationService);
|
||||
private cd = inject(ChangeDetectorRef);
|
||||
private authenticationService= inject( AuthenticationService);
|
||||
private router= inject( Router);
|
||||
constructor() {}
|
||||
getSearchCiteria(): StaffSearch {
|
||||
let criteria:StaffSearch = {
|
||||
email: this.email,
|
||||
firstName: this.firstname,
|
||||
lastName: this.lastname,
|
||||
};
|
||||
console.log("get search citeria", criteria);
|
||||
return criteria;
|
||||
|
||||
}
|
||||
initMenu(): void {
|
||||
this.items = [
|
||||
{
|
||||
label: 'Edit',
|
||||
icon: 'pi pi-pencil',
|
||||
command: () => {
|
||||
this.edit(this.selectId);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Delete',
|
||||
icon: 'pi pi-times',
|
||||
command: () => {
|
||||
this.delete(this.selectId);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Show Organization',
|
||||
icon: 'pi pi-sitemap',
|
||||
command: () => {
|
||||
this.showChildren(this.selectId);
|
||||
}
|
||||
}
|
||||
|
||||
];
|
||||
}
|
||||
actionClick(id: number, event:Event): void {
|
||||
// console.log("action edit "+ id);
|
||||
this.selectId = id;
|
||||
this.popMenu!.toggle(event);
|
||||
}
|
||||
showChildren(id: number): void {
|
||||
console.log("show children of id", id);
|
||||
this.showOrganise(id);
|
||||
|
||||
}
|
||||
handleInput(event: Event) {
|
||||
const value = (event.target as HTMLInputElement).value;
|
||||
this.dt2.filterGlobal(value, 'contains');
|
||||
}
|
||||
canSearch():boolean {
|
||||
let result = false;
|
||||
result = this.email !== "";
|
||||
result = result || this.lastname !== "";
|
||||
result = result || this.firstname !== "";
|
||||
return result;
|
||||
}
|
||||
onMenuShow(): void {
|
||||
console.log("this is show", this.selectedPerson);
|
||||
}
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
this.initMenu();
|
||||
this.authenticationService.isHome = false;
|
||||
this.authenticationService.isReport = false;
|
||||
const prev = this.personService.searchCriteria;
|
||||
let goload = true;
|
||||
if (prev.lastName !== '')
|
||||
{
|
||||
this.lastname = prev.lastName;
|
||||
goload = true;
|
||||
}
|
||||
if (prev.firstName !== '')
|
||||
{
|
||||
this.firstname = prev.firstName;
|
||||
goload = true;
|
||||
}
|
||||
if (prev.email !== '')
|
||||
{
|
||||
this.email = prev.email;
|
||||
goload = true;
|
||||
}
|
||||
if (goload)
|
||||
{
|
||||
this.search();
|
||||
}
|
||||
}
|
||||
getActive(active:boolean):string {
|
||||
let result = 'false-icon pi-times-circle';
|
||||
if (active)
|
||||
result = 'true-icon pi-check-circle';
|
||||
return result;
|
||||
}
|
||||
search():void {
|
||||
const canSearch = true; // this.canSearch();
|
||||
if (canSearch)
|
||||
{
|
||||
this.loading = true;
|
||||
const criteria = this.getSearchCiteria();
|
||||
this.personService.searchCriteria = criteria;
|
||||
this.subscription.add(
|
||||
this.personService.searchPersons(criteria).subscribe( {
|
||||
next: result => {
|
||||
// console.log(this.msg + "search load Data", result);
|
||||
const familyList = result.data;
|
||||
this.familyList.set(familyList);
|
||||
this.updateParent( this.familyList());
|
||||
//this.familyList.set(familyList);
|
||||
|
||||
console.log("the person from load", this.familyList());
|
||||
this.loading = false;
|
||||
this.cd.detectChanges();
|
||||
},
|
||||
error: e => {
|
||||
const message = e || e.message;
|
||||
// this.toastr.error(message);
|
||||
this.loading = false;
|
||||
console.log("error ", e);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
getName(id:number): string
|
||||
{
|
||||
let result ="";
|
||||
const item = this.familyList().find(x => x.id == id);
|
||||
if (item)
|
||||
result = item.lastName + " " + item.firstName;
|
||||
return result;
|
||||
}
|
||||
updateParent(list:Person[]):void {
|
||||
let i = 0;
|
||||
let item:Person;
|
||||
for (i = 0; i< list.length; i++)
|
||||
{
|
||||
item = list[i];
|
||||
if (item.fatherId && item.fatherId > 0)
|
||||
{
|
||||
item.fatherName = this.getName(item.fatherId);
|
||||
}
|
||||
if (item.motherId && item.motherId > 0)
|
||||
{
|
||||
item.motherName = this.getName(item.motherId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete(id: number): void {
|
||||
this.confirmationService.confirm({
|
||||
|
||||
message: 'Do you want to delete this record?',
|
||||
header: 'Confirmation Delete',
|
||||
icon: 'pi pi-info-circle',
|
||||
rejectLabel: 'Cancel',
|
||||
rejectButtonProps: {
|
||||
label: 'Cancel',
|
||||
severity: 'secondary',
|
||||
outlined: true,
|
||||
},
|
||||
acceptButtonProps: {
|
||||
label: 'Delete',
|
||||
severity: 'danger',
|
||||
},
|
||||
|
||||
accept: () => {
|
||||
this.deleteItem(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
deleteItem(id: number): void {
|
||||
this.personService.deletePerson(id)
|
||||
.pipe(take(1))
|
||||
.subscribe({ next: result => {
|
||||
console.log(this.msg + " deleteItem success", result);
|
||||
|
||||
const nlist = this.familyList().filter(d => d.id !== id);
|
||||
this.familyList.set(nlist);
|
||||
},
|
||||
error: e => console.error(e)
|
||||
});
|
||||
//console.log(this.msg + "click button to delete");
|
||||
}
|
||||
|
||||
newFamily():void {
|
||||
//console.log("add new employee");
|
||||
this.personService.parentList = this.familyList();
|
||||
// this.router.navigate( ['/family/new'], { queryParams: {returnUrl:'/family' } });
|
||||
this.showEdit(this._id--);
|
||||
}
|
||||
edit(id: number) : void {
|
||||
//console.log("edit family", id);
|
||||
this.personService.parentList = this.familyList();
|
||||
// this.router.navigate( ['/family/'+id], { queryParams: {returnUrl:'/family' } });
|
||||
this.showEdit(id);
|
||||
}
|
||||
showEdit(id:number) {
|
||||
const ref = this.dialogService.open(PersonEdit, {
|
||||
data: {
|
||||
id,
|
||||
familyList: this.familyList(),
|
||||
},
|
||||
header: 'Person',
|
||||
width: '80%',
|
||||
maximizable: true
|
||||
});
|
||||
|
||||
ref.onClose.subscribe((item: Person) => {
|
||||
if (item) {
|
||||
//console.log("after close ward edit", item);
|
||||
// this.messageService.add({severity:'success', summary: 'Save Family', detail: item.firstName!});
|
||||
//update the current list
|
||||
this.updateList(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showOrganise(id:number) {
|
||||
const ref = this.dialogService.open(FamilyOrga, {
|
||||
data: {
|
||||
id,
|
||||
familyList: this.familyList(),
|
||||
},
|
||||
header: 'Children',
|
||||
width: '80%',
|
||||
maximizable: true
|
||||
});
|
||||
|
||||
ref.onClose.subscribe((item: Person) => {
|
||||
if (item) {
|
||||
//console.log("after close ward edit", item);
|
||||
// this.messageService.add({severity:'success', summary: 'Save Family', detail: item.firstName!});
|
||||
//update the current list
|
||||
//this.updateList(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateList(item: Person) :void {
|
||||
const idx = this.familyList().findIndex( x => x.id == item.id);
|
||||
if (item.fatherId && item.fatherId > 0)
|
||||
item.fatherName = this.getName(item.fatherId);
|
||||
if (item.motherId && item.motherId > 0)
|
||||
item.motherName = this.getName(item.motherId);
|
||||
if (idx < 0)
|
||||
{
|
||||
const olist = [... this.familyList(), item];
|
||||
this.familyList.set(olist);
|
||||
}
|
||||
else
|
||||
{
|
||||
const oitem = this.familyList()[idx];
|
||||
oitem.firstName = item.firstName;
|
||||
oitem.lastName = item.lastName;
|
||||
oitem.address = item.address;
|
||||
oitem.alive = item.alive;
|
||||
oitem.dob = item.dob;
|
||||
oitem.sex = item.sex;
|
||||
oitem.email = item.email;
|
||||
oitem.fatherId = item.fatherId;
|
||||
oitem.motherId = item.motherId;
|
||||
oitem.fatherName = item.fatherName;
|
||||
oitem.motherName = item.motherName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export * from './familylist';
|
||||
export * from './person.edit';
|
||||
export * from './family.tree';
|
||||
export * from './person.service';
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
<div class=" mt-2">
|
||||
|
||||
<form [formGroup]="adminuserForm" (ngSubmit)="onSubmit($event)" >
|
||||
<div class="ml-2 grid 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')"
|
||||
styleClass="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"></p-datepicker>
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="login">Email</label>
|
||||
<input id="login" [attr.disabled]="!isNew?true:null" pInputText formControlName="email"
|
||||
type="text" class="inputfield w-full">
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="phone" class="w-full">Phone</label>
|
||||
<input class="w-full" id="phone" pInputText formControlName="phone" type="text" >
|
||||
</div>
|
||||
<div class="">
|
||||
<label class="flex w-full">Father</label>
|
||||
<p-select [filter]="true" filterBy="name" [options]="fatherList" optionLabel="name" appendTo="body" optionValue="id" placeholder="Select Parent"
|
||||
formControlName="fatherId" class="w-full p-inputtext-sm mr-1"></p-select >
|
||||
</div>
|
||||
<div class="">
|
||||
<label class="flex w-full">Mother</label>
|
||||
<p-select [options]="motherList" [filter]="true" filterBy="name" optionLabel="name" appendTo="body" optionValue="id" placeholder="Select Parent"
|
||||
formControlName="motherId" class="w-full p-inputtext-sm mr-1"></p-select >
|
||||
</div>
|
||||
|
||||
<div class="grid align-end">
|
||||
<div class="p-field-checkbox">
|
||||
<p-checkbox inputId="alive" formControlName="alive" [binary]="true"></p-checkbox>
|
||||
<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">
|
||||
@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-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 class="mt-2 w-full">
|
||||
<p-button class="flex justify-end mr-2" icon="pi pi-user" label="Add Partner"
|
||||
severity="warn" (onClick)="addPartner()"/>
|
||||
<div class="shadow rounded mt-2 mb-2">
|
||||
<p-table [value]="partners()">
|
||||
<ng-template #header>
|
||||
<tr>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Sex</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #body let-user>
|
||||
<tr>
|
||||
<td>{{ user.pfirstName }}</td>
|
||||
<td>{{ user.plastName }}</td>
|
||||
<td>{{ user.sex }}</td>
|
||||
<td>
|
||||
<button pButton type="button" icon="pi pi-times" class="p-button-rounded p-button-text p-button-danger"
|
||||
(click)="onDeletePartner(user)"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end mr-2 mb-2 p-2">
|
||||
<button pButton type="submit" class="p-button-sm mr-2" icon="pi pi-check" label="Save" [disabled]="isFieldsChange"></button>
|
||||
<button pButton pRipple class="p-button-sm p-button-secondary" type="button" icon="pi pi-times" label="Cancel" (click)="cancel($event)"></button>
|
||||
</div>
|
||||
</form>
|
||||
<!--pre>{{ adminuserForm.value|json}}</pre-->
|
||||
</div>
|
||||
@@ -0,0 +1,561 @@
|
||||
import { ChangeDetectorRef, Component, inject, OnDestroy, OnInit, signal, ViewChild } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import {DialogService, DynamicDialogRef} from 'primeng/dynamicdialog';
|
||||
import {DynamicDialogConfig} from 'primeng/dynamicdialog';
|
||||
import { FormControl, ReactiveFormsModule, UntypedFormBuilder, Validators } from '@angular/forms';
|
||||
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 { AppSettingService, LookupService, Utils } from '../shares';
|
||||
import { PersonService } from './person.service';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { SelectModule } from 'primeng/select';
|
||||
import { CheckboxModule } from 'primeng/checkbox';
|
||||
import { InputTextModule } from 'primeng/inputtext';
|
||||
import moment from 'moment';
|
||||
import { HttpEvent } from '@angular/common/http';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { Pickperson } from '../pickperson/pickperson';
|
||||
|
||||
|
||||
export interface FileUploadEvent {
|
||||
originalEvent: HttpEvent<any>;
|
||||
files: File[];
|
||||
};
|
||||
export interface FileUploadHandlerEvent {
|
||||
files: File[];
|
||||
};
|
||||
|
||||
@Component({
|
||||
templateUrl: 'person.edit.html',
|
||||
selector: 'person-edit',
|
||||
imports:[ButtonModule,TableModule,ReactiveFormsModule,SelectModule,CheckboxModule, InputTextModule,DatePickerModule],
|
||||
styleUrls: ['person.edit.css'],
|
||||
providers: [DialogService]
|
||||
|
||||
})
|
||||
export class PersonEdit implements OnInit, OnDestroy {
|
||||
editRef: DynamicDialogRef | undefined;
|
||||
returnUrl ='';
|
||||
loginUser ='';
|
||||
hostsite ='';
|
||||
_error ='';
|
||||
_id= -1;
|
||||
_partnerId = -1;
|
||||
fatherList: Code[] =[];
|
||||
motherList: Code[] =[];
|
||||
sexList:Code[] =[];
|
||||
familyList: Person[] =[];
|
||||
file: File | null = null;
|
||||
fileName = '';
|
||||
isNew = false;
|
||||
validationPoints?: Code[];
|
||||
partners = signal<RelationShipView[]>([]);
|
||||
deletePartner: RelationShipView[] =[];
|
||||
msg="[Family Edit Component] ";
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private personService = inject(PersonService);
|
||||
private messageService = inject(MessageService);
|
||||
private confirmationService = inject(ConfirmationService);
|
||||
//for focus input
|
||||
// @ViewChild('mystaffid') mystaffNo!: MatInput;
|
||||
isChange = true; // disable use false//true for not disable. make sure it true is disable button.
|
||||
private subscription:Subscription = new Subscription();
|
||||
subChanged$ = new Subject<boolean>();
|
||||
adminuserForm = this.formBuilder.group({
|
||||
id: [0], //Validators.required
|
||||
email: [''], //Validators.required
|
||||
firstname: ['',Validators.required], //Validators.required
|
||||
lastname: ['',Validators.required], //Validators.required
|
||||
phone: [''], //Validators.required
|
||||
address: [''],
|
||||
sex:['M',Validators.required],
|
||||
image: [''],
|
||||
dob: new FormControl<Date|null>(null),
|
||||
alive: [false], //Validators.required
|
||||
fatherId:[0],
|
||||
motherId:[0]
|
||||
|
||||
|
||||
|
||||
});
|
||||
constructor( private cdr: ChangeDetectorRef,public dialogService: DialogService,
|
||||
public ref: DynamicDialogRef, public config: DynamicDialogConfig,
|
||||
|
||||
private router: Router, private route: ActivatedRoute,
|
||||
private appSetting: AppSettingService,
|
||||
) {
|
||||
this.hostsite = this.appSetting.appSetting.attachment;
|
||||
}
|
||||
loadParentList( list: Person[], selfId: number): void {
|
||||
this.familyList = list;
|
||||
let i = 0;
|
||||
let item: Code;
|
||||
let family: Person;
|
||||
//const list = this.familyService.parentList;
|
||||
for (i = 0; i < list.length; i++)
|
||||
{
|
||||
family= list[i];
|
||||
if (family.id != selfId)
|
||||
{
|
||||
item = { id: family.id,
|
||||
name: family.firstName! + " " + family.lastName!,
|
||||
status: family.lastName!,
|
||||
active: family.alive!
|
||||
|
||||
};
|
||||
if (family.sex == 'F')
|
||||
this.motherList.push(item);
|
||||
else
|
||||
this.fatherList.push(item);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
getClassForRequire(prev:string,name:string){
|
||||
const notok = !this.adminuserForm.controls[name].valid &&
|
||||
this.adminuserForm.controls[name].touched;
|
||||
let str =prev;
|
||||
if (notok)
|
||||
str += " ng-invalid ng-dirty";
|
||||
return str;
|
||||
}
|
||||
|
||||
onFileSelected(event: any) {
|
||||
|
||||
const file: File = event.target.files[0];
|
||||
|
||||
if (file) {
|
||||
this.file = file;
|
||||
//this.messageService.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded!' });
|
||||
// this.courseForm.patchValue({ attachmenFile: this.file.name });
|
||||
this.fileName = file.name;
|
||||
this.subChanged$.next(false);
|
||||
}
|
||||
}
|
||||
|
||||
deleteFile(): void {
|
||||
this.confirmationService.confirm({
|
||||
|
||||
message: 'Are you sure that you want to delete image?',
|
||||
header: 'Confirmation',
|
||||
closable: true,
|
||||
closeOnEscape: true,
|
||||
icon: 'pi pi-exclamation-triangle',
|
||||
rejectButtonProps: {
|
||||
label: 'Cancel',
|
||||
severity: 'secondary',
|
||||
outlined: true,
|
||||
},
|
||||
acceptButtonProps: {
|
||||
label: 'Delete',
|
||||
},
|
||||
accept: () => {
|
||||
this.doDeleteFile();
|
||||
},
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
doDeleteFile(): void {
|
||||
const fileName = this.adminuserForm.value.image;
|
||||
const familyId = this.adminuserForm.value.id;
|
||||
const data = { fileName, familyId };
|
||||
const delete$ = this.personService.deleteUploadFile(data);
|
||||
this.subscription.add(delete$.subscribe(
|
||||
{
|
||||
next: x => {
|
||||
if (x.statusCode == 1) {
|
||||
{
|
||||
this.adminuserForm.patchValue({ image: "" });
|
||||
this.cdr.detectChanges();
|
||||
this.messageService.add({ severity: 'success', summary: 'Delete image all ok', detail: 'file: ' + fileName });
|
||||
}
|
||||
}
|
||||
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 });
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
}
|
||||
|
||||
getFileToSave(file: File): FormData {
|
||||
|
||||
//const familyId = this.adminuserForm.value.id!;
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
return formData;
|
||||
}
|
||||
// formData.append("familyId", familyId.toString());
|
||||
// console.log("upload file", familyId, file);
|
||||
saveFile(formData: FormData)
|
||||
{
|
||||
const upload$ = this.personService.uploadFile(formData);
|
||||
this.subscription.add(upload$.subscribe(
|
||||
{
|
||||
next: x => {
|
||||
if (x.statusCode == 1) {
|
||||
const filename = x.data;
|
||||
//this.messageService.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded to server API: ' + x.data });
|
||||
this.adminuserForm.patchValue({ image: filename });
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
else
|
||||
this.messageService.add({ severity: 'error', summary: 'Error upload file', detail: 'Fail to upload file: ' + x.message });
|
||||
},
|
||||
error: e =>
|
||||
this.messageService.add({ severity: 'error', summary: 'Error upload file', detail: 'Fail to upload file: ' })
|
||||
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
populateSex(): void {
|
||||
let item: Code;
|
||||
item = {
|
||||
id:1,
|
||||
name:"Female",
|
||||
status:'F'
|
||||
};
|
||||
this.sexList.push(item);
|
||||
item = {
|
||||
id:2,
|
||||
name:"Male",
|
||||
status:'M'
|
||||
};
|
||||
this.sexList.push(item);
|
||||
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
this.populateSex();
|
||||
const id = this.config.data.id;
|
||||
console.log("family edit", this.config);
|
||||
this.loadParentList(this.config.data.familyList, id);
|
||||
//this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
|
||||
// const id = Number(this.route.snapshot.paramMap.get('id'));
|
||||
// now load thing up
|
||||
const user = Utils.getCurrentUser();
|
||||
// console.log(this.msg + "current login user ", user);
|
||||
if (user.username === '')
|
||||
alert("you are not login.");
|
||||
else
|
||||
this.loginUser = user.firstName;
|
||||
this._id = id;
|
||||
//console.log(this.msg + " " + id );
|
||||
this.subscription.add(this.adminuserForm.valueChanges.subscribe(x => this.isChange = false));
|
||||
this.subscription.add(this.subChanged$.subscribe(x => this.isChange = x));
|
||||
if (id > 0)
|
||||
{
|
||||
this.isNew = false;
|
||||
this.subscription.add(
|
||||
this.personService.loadPersonById(id).subscribe({
|
||||
next: x => this.assignValue(x.data),
|
||||
error: e => console.log(e)
|
||||
})
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.isNew = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// this for disable submit button
|
||||
get isFieldsChange() {
|
||||
const chan = this.isChange || !this.adminuserForm.valid; // this disable so need true valid = true not
|
||||
//console.log(this.msg + 'is fields change', chan);
|
||||
return chan;
|
||||
}
|
||||
|
||||
assignValue(item:Person): void {
|
||||
this._id = item.id;
|
||||
this.fileName = item.image!;
|
||||
if (item.relationShips)
|
||||
this.populatePartner(item.relationShips, item.id);
|
||||
this.adminuserForm.patchValue({
|
||||
id: item.id,
|
||||
email: item.email,
|
||||
firstname: item.firstName,
|
||||
lastname: item.lastName,
|
||||
alive: item.alive,
|
||||
phone: item.phone,
|
||||
address: item.address,
|
||||
fatherId: item.fatherId,
|
||||
motherId: item.motherId,
|
||||
sex: item.sex,
|
||||
image: item.image
|
||||
});
|
||||
const dob = item.dob;
|
||||
if (dob)
|
||||
{
|
||||
this.adminuserForm.patchValue({
|
||||
dob: moment(dob).toDate()
|
||||
});
|
||||
}
|
||||
// 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;}
|
||||
validate(adminuser:Person): boolean {
|
||||
let result = true;
|
||||
console.log("validate", adminuser);
|
||||
if (!adminuser.firstName)
|
||||
{
|
||||
this._error = 'firstname is blank or empty';
|
||||
result = false;
|
||||
}
|
||||
else if (adminuser.lastName == '')
|
||||
{
|
||||
this._error = 'lastname is blank or empty';
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
getPartnerForSave(): RelationShip[] {
|
||||
let rlist: RelationShip[]= [];
|
||||
let i =0;
|
||||
let vitem: RelationShipView;
|
||||
let item: RelationShip;
|
||||
for (i = 0; i < this.deletePartner.length; i++)
|
||||
{
|
||||
vitem = this.deletePartner[i];
|
||||
item = {
|
||||
id: vitem.id,
|
||||
personId: vitem.personId,
|
||||
state: mState.Delete,
|
||||
relatePersonId: vitem.relatePersonId
|
||||
};
|
||||
rlist.push(item);
|
||||
console.log("get partner for save delete list ", vitem);
|
||||
}
|
||||
console.log("get partner for save before loop this.partners ", i);
|
||||
for (i = 0; i < this.partners().length; i++)
|
||||
{
|
||||
vitem = this.partners()[i];
|
||||
if (vitem.state == mState.New || vitem.state == mState.Modified)
|
||||
{
|
||||
item = {
|
||||
id: vitem.id,
|
||||
personId: vitem.personId,
|
||||
state: vitem.state,
|
||||
relatePersonId: vitem.relatePersonId
|
||||
};
|
||||
rlist.push(item);
|
||||
}
|
||||
console.log("get partner for save in partner list ", vitem);
|
||||
}
|
||||
|
||||
|
||||
return rlist;
|
||||
}
|
||||
|
||||
async onSubmit(e:Event): Promise<void> {
|
||||
e.preventDefault();
|
||||
// if form valid then go save
|
||||
//make sure
|
||||
const okToSave = this.adminuserForm.valid;
|
||||
if (okToSave)
|
||||
{
|
||||
let adminuserValue = this.adminuserForm.value;
|
||||
|
||||
let item:Person = {
|
||||
id: adminuserValue.id,
|
||||
email: adminuserValue.email,
|
||||
firstName: adminuserValue.firstname,
|
||||
lastName: adminuserValue.lastname,
|
||||
alive: adminuserValue.alive,
|
||||
phone: adminuserValue.phone,
|
||||
address: adminuserValue.address,
|
||||
image:adminuserValue.image,
|
||||
fatherId: adminuserValue.fatherId,
|
||||
motherId: adminuserValue.motherId,
|
||||
sex: adminuserValue.sex
|
||||
};
|
||||
|
||||
if (adminuserValue.dob)
|
||||
{
|
||||
item.dob = moment(adminuserValue.dob).format("YYYY-MM-DD");
|
||||
}
|
||||
|
||||
this._error ='';
|
||||
const allOK = this.validate(item);
|
||||
if (allOK)
|
||||
{
|
||||
let container:any = {
|
||||
person: item
|
||||
};
|
||||
if (this.file != null)
|
||||
{
|
||||
container.formData = await Utils.toBase64(this.file);
|
||||
container.fileName = this.file.name;
|
||||
console.log('image as base64 ', container);
|
||||
}
|
||||
container.person.relationShips = this.getPartnerForSave();
|
||||
this.subscription.add (
|
||||
this.personService.savePerson(container).subscribe({
|
||||
next: x => {
|
||||
if (x.statusCode >= 1)
|
||||
{
|
||||
item.id = x.data;
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.messageService.add({severity:'error', summary: 'Error', detail: x.message });
|
||||
}
|
||||
},
|
||||
error: e => {
|
||||
const message = e.message;
|
||||
this.messageService.add({severity:'error', summary: 'Error', detail: message });
|
||||
console.error("error ", e);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
else
|
||||
this.messageService.add({severity:'error', summary: 'Error', detail: this._error });
|
||||
}
|
||||
}
|
||||
getFamilyById(id: number): Person | undefined {
|
||||
let result:Person |undefined;
|
||||
result = this.familyList.find(x => x.id == id);
|
||||
return result;
|
||||
}
|
||||
populatePartner(list: RelationShip[], personId: number): void {
|
||||
let item: RelationShip;
|
||||
let vitem: RelationShipView;
|
||||
let vlist: RelationShipView[] =[];
|
||||
let i = 0;
|
||||
let family:Person|undefined;
|
||||
for (i = 0; i < list.length; i++)
|
||||
{
|
||||
item = list[i];
|
||||
if (item.relatePersonId != personId)
|
||||
{
|
||||
family = this.getFamilyById(item.relatePersonId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
family = this.getFamilyById(item.personId);
|
||||
}
|
||||
if (family)
|
||||
{
|
||||
vitem = {
|
||||
id: item.id,
|
||||
personId: item.personId,
|
||||
relatePersonId: item.relatePersonId,
|
||||
pfirstName: family.firstName,
|
||||
plastName: family.lastName,
|
||||
sex: family.sex,
|
||||
state:mState.NoChange
|
||||
};
|
||||
vlist.push(vitem);
|
||||
}
|
||||
}
|
||||
if (vlist.length > 0)
|
||||
this.partners.set(vlist);
|
||||
}
|
||||
|
||||
|
||||
addPartner(): void {
|
||||
const title = "Partner";
|
||||
this.showPickPerson(title, (sfamily: Person) => {
|
||||
let item: RelationShipView = {
|
||||
id: this._partnerId--,
|
||||
state: mState.New,
|
||||
personId: this._id,
|
||||
relatePersonId: sfamily.id,
|
||||
pfirstName: sfamily.firstName,
|
||||
plastName: sfamily.lastName,
|
||||
sex: sfamily.sex,
|
||||
};
|
||||
const fm = this.partners();
|
||||
fm.push(item);
|
||||
this.partners.set(fm);
|
||||
this.subChanged$.next(false);
|
||||
console.log("after put in partners list", this.partners());
|
||||
});
|
||||
}
|
||||
|
||||
onDeletePartner(item:RelationShipView): void {
|
||||
this.confirmationService.confirm({
|
||||
|
||||
message: 'Are you sure that you want to delete partner?',
|
||||
header: 'Confirmation',
|
||||
closable: true,
|
||||
closeOnEscape: true,
|
||||
icon: 'pi pi-exclamation-triangle',
|
||||
rejectButtonProps: {
|
||||
label: 'Cancel',
|
||||
severity: 'secondary',
|
||||
outlined: true,
|
||||
},
|
||||
acceptButtonProps: {
|
||||
label: 'Delete',
|
||||
},
|
||||
accept: () => {
|
||||
this.doDeletePartner(item);
|
||||
},
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
doDeletePartner(item:RelationShipView): void {
|
||||
if (item.id > 0)
|
||||
{
|
||||
this.deletePartner.push(item);
|
||||
}
|
||||
const dlist = this.partners().filter(x => x.id != item.id);
|
||||
this.partners.set(dlist);
|
||||
console.log("after delete partners list", this.partners());
|
||||
this.subChanged$.next(false);
|
||||
}
|
||||
|
||||
showPickPerson(title:string, callback:(id: Person) => void) :void {
|
||||
const ref = this.dialogService.open(Pickperson, {
|
||||
data: {
|
||||
familyList: this.familyList,
|
||||
},
|
||||
header: title,
|
||||
width: '80%',
|
||||
|
||||
maximizable: true
|
||||
});
|
||||
|
||||
ref.onClose.subscribe((item: Person) => {
|
||||
if (item) {
|
||||
//console.log("after close ward edit", item);
|
||||
this.messageService.add({severity:'success', summary: 'Select', detail: item.firstName!});
|
||||
//update the current list
|
||||
callback(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cancel(e:Event):void {
|
||||
e.preventDefault();
|
||||
this.ref.close(null);
|
||||
}
|
||||
ngOnDestroy() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Staff,StaffSearch, StaffView, ResultModel,ConfigureUrl,ResetPassword, Person, PersonContainer, RelationShip } from '../models';
|
||||
import { AppSettingService } from '../shares';
|
||||
import { TreeNode } from 'primeng/api';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PersonService {
|
||||
public searchCriteria: StaffSearch;
|
||||
public parentList: Person[] =[];
|
||||
constructor(private http: HttpClient,
|
||||
|
||||
private appSetting :AppSettingService
|
||||
) {
|
||||
this.searchCriteria = {
|
||||
email:'',
|
||||
firstName: '',
|
||||
lastName:''
|
||||
};
|
||||
|
||||
}
|
||||
searchPersons(criteria: StaffSearch): Observable<ResultModel<Person[]>> {
|
||||
let config = { headers : { 'Content-Type': 'application/json' } };
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.personUrl + "/SearchPerson";
|
||||
return this.http.post<ResultModel<Person[]>>(baseUrl, criteria, config);
|
||||
}
|
||||
|
||||
loadPersonById(id:number): Observable<ResultModel<Person>> {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.personUrl;
|
||||
/*
|
||||
const params = new HttpParams().set("id", ""+id);
|
||||
const headers = new HttpHeaders().set('Content-Type', 'application/json');
|
||||
const options = {
|
||||
headers: headers,
|
||||
params: params
|
||||
};
|
||||
*/
|
||||
|
||||
return this.http.get<ResultModel<Person>>(baseUrl + "/GetById/" + id);
|
||||
}
|
||||
loadPersonFamily(id: number): Observable<ResultModel<TreeNode>> {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.personUrl;
|
||||
return this.http.get<ResultModel<TreeNode>>(baseUrl + "/GetByPersonFamily/" + id);
|
||||
}
|
||||
|
||||
loadPersonFamilyTree(useFather: boolean, useMother: boolean): Observable<ResultModel<TreeNode[]>> {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.personUrl;
|
||||
const data = {useFather,useMother};
|
||||
return this.http.post<ResultModel<TreeNode[]>>(baseUrl + "/GetFamilyTreeBy", data);
|
||||
}
|
||||
|
||||
loadChildrenById(fatherId:number, motherId: number): Observable<ResultModel<Person[]>> {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.personUrl;
|
||||
const data = {fatherId,motherId};
|
||||
|
||||
return this.http.post<ResultModel<Person[]>>(baseUrl + "/GetChildress/" ,data);
|
||||
}
|
||||
loadRelationshipById(personId:number): Observable<ResultModel<RelationShip[]>> {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.relationShipUrl;
|
||||
return this.http.get<ResultModel<RelationShip[]>>(baseUrl + "/GetByPersonId/" +personId);
|
||||
}
|
||||
savePerson(data:PersonContainer): Observable<ResultModel<number>> { //insert Adminuser
|
||||
let config = { headers : { 'Content-Type': 'application/json' } };
|
||||
console.log("save family", data);
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.personUrl +"/SavePerson";
|
||||
return this.http.post<ResultModel<number>>(baseUrl, data, config);
|
||||
}
|
||||
|
||||
deletePerson(id:number): Observable<ResultModel<number>>{
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.personUrl;
|
||||
const data = {id};
|
||||
return this.http.post<ResultModel<number>>(baseUrl + "/DeleteById" ,data);
|
||||
}
|
||||
uploadFile(data: any): Observable<ResultModel<string>> {
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/UploadImage";
|
||||
return this.http.post<ResultModel<string>>(baseUrl, data);
|
||||
}
|
||||
deleteUploadFile(data: any): Observable<ResultModel<number>> {
|
||||
//data ={filename};
|
||||
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/DeleteUploadFile";
|
||||
return this.http.post<ResultModel<number>>(baseUrl, data);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user