From 502945ca2ba1c580b9c5dfc6e536dbbbc5c71936 Mon Sep 17 00:00:00 2001 From: "kham.vilaythong" Date: Sun, 9 Nov 2025 16:40:29 +1100 Subject: [PATCH] on the server too --- API/FamilyTreeAPI/Entities/TreeNode.cs | 5 + API/FamilyTreeAPI/Interface/IPerson.cs | 4 +- .../Repository/PersonRepository.cs | 175 ++++++++++++------ .../Repository/PersonRepository.tree.cs | 21 ++- API/FamilyTreeAPI/Repository/TextFile.txt | 16 ++ API/FamilyTreeAPI/appsettings.json | 4 +- 6 files changed, 152 insertions(+), 73 deletions(-) diff --git a/API/FamilyTreeAPI/Entities/TreeNode.cs b/API/FamilyTreeAPI/Entities/TreeNode.cs index 531ba35..76f00dc 100644 --- a/API/FamilyTreeAPI/Entities/TreeNode.cs +++ b/API/FamilyTreeAPI/Entities/TreeNode.cs @@ -1,5 +1,10 @@ namespace FamilyTreeAPI.Entities; +public class TreeData +{ + public string? Sex { get; set; } + public string? Image { get; set; } +} public class TreeNode { public string? Label { get; set; } diff --git a/API/FamilyTreeAPI/Interface/IPerson.cs b/API/FamilyTreeAPI/Interface/IPerson.cs index 1058b50..c2ef4fb 100644 --- a/API/FamilyTreeAPI/Interface/IPerson.cs +++ b/API/FamilyTreeAPI/Interface/IPerson.cs @@ -4,8 +4,8 @@ namespace FamilyTreeAPI.Interface; public interface IPerson { - Task>> GetByFamilyAsync(int id); - Task>>> GetFamilyTreeBy(FamilyCriteria criteria); + Task>> GetByFamilyAsync(int id); + Task>>> GetFamilyTreeBy(FamilyCriteria criteria); Task>> GetChildren(ChildCriteria criteria); Task>> GetPerson(PersonCriteria criteria); Task>> GetDicFamily(); diff --git a/API/FamilyTreeAPI/Repository/PersonRepository.cs b/API/FamilyTreeAPI/Repository/PersonRepository.cs index 9dcff79..57d9b4b 100644 --- a/API/FamilyTreeAPI/Repository/PersonRepository.cs +++ b/API/FamilyTreeAPI/Repository/PersonRepository.cs @@ -22,10 +22,13 @@ public partial class PersonRepository : IPerson private readonly IHttpContextAccessor _httpContext; private readonly IPersonPhoto _personPhoto; private readonly IConfiguration _config; + private readonly ImportPersonRepository _importPersonRepository; const string dateFormat = "yyyy-MM-dd"; + public PersonRepository(IConfiguration config, FamilyTreeDBContext context, IRelationShipd relationship, IPersonPhoto personPhoto, + ImportPersonRepository importPersonRepository, IHttpContextAccessor httpContext) { _personPhoto = personPhoto; @@ -33,9 +36,10 @@ public partial class PersonRepository : IPerson _relationship = relationship; _config = config; _httpContext = httpContext; + _importPersonRepository = importPersonRepository; } - private PersonDto FillDto(Person model) + private PersonDto FillDto(Person model) { PersonDto dto = new(); dto.Id = model.Id; @@ -52,13 +56,14 @@ public partial class PersonRepository : IPerson dto.dob = Helpers.DateToStr(model.dob); /* dto.AddedOn = model.AddedOn; - + dto.RoleType = model.RoleType; - + */ - + return dto; } + private Person FillModel(Person model, PersonDto dto) { @@ -73,7 +78,7 @@ public partial class PersonRepository : IPerson model.MotherId = dto.MotherId; model.Sex = dto.Sex; model.dob = Helpers.DateToDateTime(dto.dob); - + return model; } @@ -93,19 +98,21 @@ public partial class PersonRepository : IPerson { jitem = jlist[i]; item = FillDto(jitem); - list.Add(item.Id,item); + list.Add(item.Id, item); } + statuscode = 1; //list.Sort((x, y) => x.Code.CompareTo(y.Code)); } catch (Exception ex) { - + error = ex.ToString(); statuscode = -1; - + } - return new ResultModel< Dictionary > () + + return new ResultModel>() { Data = list, StatusCode = statuscode, @@ -119,7 +126,7 @@ public partial class PersonRepository : IPerson PersonDto item; Person jitem; var jlist = await _context.Persons.Where(x => - (x.MotherId == FatherId && x.FatherId == MotherId) || + (x.MotherId == FatherId && x.FatherId == MotherId) || (x.FatherId == FatherId && x.MotherId == MotherId)).ToListAsync(); for (int i = 0; i < jlist.Count; i++) { @@ -127,8 +134,10 @@ public partial class PersonRepository : IPerson item = FillDto(jitem); list.Add(item); } + return list; } + public async Task>> GetChildren(ChildCriteria criteria) { List list = new(); @@ -145,11 +154,12 @@ public partial class PersonRepository : IPerson } catch (Exception ex) { - + error = ex.ToString(); statuscode = -1; - + } + return new ResultModel>() { Data = list, @@ -176,35 +186,38 @@ public partial class PersonRepository : IPerson if (!string.IsNullOrEmpty(firstName)) { firstName = firstName.ToLower(); - jlist = await _context.Persons.Where(x => - EF.Functions.Like(x.FirstName.ToLower(),firstName + "%")).ToListAsync(); + jlist = await _context.Persons.Where(x => + EF.Functions.Like(x.FirstName.ToLower(), firstName + "%")).ToListAsync(); } else if (!string.IsNullOrEmpty(firstName) && !string.IsNullOrEmpty(lastName)) { firstName = firstName.ToLower(); - lastName = lastName.ToLower(); - jlist = await _context.Persons.Where(x => EF.Functions.Like(x.FirstName.ToLower(),firstName + "%") - && EF.Functions.Like(x.LastName.ToLower(),lastName + "%")).ToListAsync(); + lastName = lastName.ToLower(); + jlist = await _context.Persons.Where(x => EF.Functions.Like(x.FirstName.ToLower(), firstName + "%") + && EF.Functions.Like(x.LastName.ToLower(), lastName + "%")) + .ToListAsync(); } else jlist = await _context.Persons.ToListAsync(); - + for (int i = 0; i < jlist.Count; i++) { jitem = jlist[i]; item = FillDto(jitem); list.Add(item); } + statuscode = 1; //list.Sort((x, y) => x.Code.CompareTo(y.Code)); } catch (Exception ex) { - + error = ex.ToString(); statuscode = -1; - + } + return new ResultModel>() { Data = list, @@ -216,14 +229,14 @@ public partial class PersonRepository : IPerson private async Task GetPerson(int id) { Person rval = await _context.Persons.FindAsync(id); - return rval; + return rval; } private string getStyleClass(string va) { string result = ""; //result = "bg-indigo-500 text-black"; - + if (va == "T") { result = "bg-indigo-500 text-white"; @@ -236,10 +249,12 @@ public partial class PersonRepository : IPerson else if (va == "C") { result = "bg-teal-500 text-white"; - } + } + return result; } - public async Task>> GetByFamilyAsync(int id) + + public async Task>> GetByFamilyAsync(int id) { int statuscode = 0; string error = ""; @@ -248,9 +263,10 @@ public partial class PersonRepository : IPerson string type = "default"; string pName = ""; Person person; - TreeNode citem; - TreeNode child; - TreeNode node = new(); + TreeNode citem; + TreeNode child; + TreeNode node = new(); + node.Data = new(); node.Children = new(); PersonDto dto = new(); try @@ -262,14 +278,17 @@ public partial class PersonRepository : IPerson } else { - + node.Label = item.FirstName; node.Key = item.Id.ToString(); node.Type = type; - node.Icon = "T"; + if (item.Image != null) + node.Data.Image = await LoadPersonImage(item.Image); + + node.Icon = "T"; node.StyleClass = getStyleClass(node.Icon); node.Expanded = true; - node.Data = item.Sex; + node.Data.Sex = item.Sex; statuscode = 1; dto = FillDto(item); await GetPartnerChildrens(dto, node); @@ -279,9 +298,10 @@ public partial class PersonRepository : IPerson { error = ex.ToString(); statuscode = -1; - + } - return new ResultModel> () + + return new ResultModel>() { Data = node, StatusCode = statuscode, @@ -289,21 +309,22 @@ public partial class PersonRepository : IPerson }; } - private async Task GetPartnerChildrens(PersonDto person, TreeNode node) + private async Task GetPartnerChildrens(PersonDto person, TreeNode node) { /*****************************/ ResultModel> rlist = await _relationship.GetByPersonIdAsync(person.Id); List relationShips = rlist.Data; RelationShipDto relate; string type = node.Type; - TreeNode child; + TreeNode child; PersonDto dto; Person pe; int fatherId, motherId; fatherId = motherId = 0; string data = person.Sex; - TreeNode citem; + TreeNode citem; string pName = ""; + string? image = ""; string key = ""; for (int i = 0; i < relationShips.Count; i++) { @@ -314,11 +335,11 @@ public partial class PersonRepository : IPerson { fatherId = relate.PersonId; motherId = relate.RelatePersonId; - + } else { - + fatherId = relate.RelatePersonId; motherId = relate.PersonId; } @@ -336,6 +357,7 @@ public partial class PersonRepository : IPerson motherId = relate.RelatePersonId; } } + //get children List children = await GetChildrens(fatherId, motherId); if (children.Count > 0) @@ -347,6 +369,7 @@ public partial class PersonRepository : IPerson { pe = await GetPerson(motherId); pName = pe.FirstName; + image = pe.Image; key = motherId.ToString(); data = pe.Sex; } @@ -357,32 +380,43 @@ public partial class PersonRepository : IPerson { pe = await GetPerson(fatherId); pName = pe.FirstName; + image = pe.Image; key = fatherId.ToString(); data = pe.Sex; } } - citem = new TreeNode(); + citem = new TreeNode(); + citem.Data = new(); citem.Label = pName; - citem.Icon = "P"; + if (image != null) + citem.Data.Image = await LoadPersonImage(image); + + citem.Icon = "P"; + + // citem.Icon = "P"; citem.StyleClass = getStyleClass(citem.Icon); citem.Expanded = true; - citem.Data = data; + citem.Data.Sex = data; citem.Type = type; citem.Key = key; - citem.Children = new List>(); + citem.Children = new List>(); node.Children.Add(citem); for (int j = 0; j < children.Count; j++) { dto = children[j]; - child = new TreeNode(); + child = new TreeNode(); + child.Data = new(); child.Expanded = true; child.Type = type; + image = dto.Image; + if (image != null) + child.Data.Image = await LoadPersonImage(image); child.Icon = "C"; child.StyleClass = getStyleClass(child.Icon); child.Label = dto.FirstName; child.Key = dto.Id.ToString(); - child.Data = dto.Sex; + child.Data.Sex = dto.Sex; child.Children = new(); citem.Children.Add(child); //get child partner and repeat this. @@ -423,8 +457,9 @@ public partial class PersonRepository : IPerson { error = ex.ToString(); statuscode = -1; - + } + return new ResultModel() { Data = dto, @@ -432,6 +467,7 @@ public partial class PersonRepository : IPerson Message = error }; } + private string GetDateTimeNow() { return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); @@ -447,26 +483,27 @@ public partial class PersonRepository : IPerson private string SaveFile(string fileName, int familyId, string base64) { string path = ""; - + int statusCode = 0; string error = ""; string sdate = GetCurrentDateTime(); string filename, extention; filename = extention = ""; - int first = base64.IndexOf("base64,") +"base64,".Length; + int first = base64.IndexOf("base64,") + "base64,".Length; int last = base64.Length; string rbase = base64.Substring(first, last - first); - + byte[] newBytes = Convert.FromBase64String(rbase); path = _config["AppSettings:ImageFolder"]; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } + extention = System.IO.Path.GetExtension(fileName); - filename = familyId + "_" + sdate + extention; + filename = familyId + "_" + sdate + extention; string fullpath = System.IO.Path.Combine(path, filename); - /* + /* using (var fileStream = new FileStream(fullpath, FileMode.Create)) { StreamWriter writer = new StreamWriter(fileStream); @@ -490,6 +527,7 @@ public partial class PersonRepository : IPerson return filename; } + public async Task> SaveAsync(PersonForSave container) { int result = default(int); @@ -504,11 +542,12 @@ public partial class PersonRepository : IPerson if (user != null) loginName = user.FirstName + " " + user.LastName; } + PersonDto item = container.Person; try { - + Person model; if (item.Id < 1) { @@ -523,7 +562,7 @@ public partial class PersonRepository : IPerson result = model.Id; if (!string.IsNullOrEmpty(container.FileName)) { - + string image = SaveFile(container.FileName, result, container.FormData); // update the image in table to new model.Image = image; @@ -544,6 +583,7 @@ public partial class PersonRepository : IPerson // update the image in table to new model1.Image = image; } + var successid = await _context.SaveChangesAsync(); } // model.LastModified = DateTime.Now; @@ -563,6 +603,7 @@ public partial class PersonRepository : IPerson error = ex.ToString(); statuscode = -1; } + //var dto = await Task.Run(() => result); return new ResultModel() { @@ -581,7 +622,7 @@ public partial class PersonRepository : IPerson { var model = await _context.Persons.FindAsync(id); if (model != null) - _context.Persons.Remove(model); + _context.Persons.Remove(model); var successCount = await _context.SaveChangesAsync(); statuscode = 1; @@ -591,8 +632,9 @@ public partial class PersonRepository : IPerson { error = ex.ToString(); statuscode = -1; - + } + //var dto = await Task.Run(() => result); return new ResultModel() { @@ -602,7 +644,8 @@ public partial class PersonRepository : IPerson }; } - public Task> UploadImage(UploadCriteria criteria) { + public Task> UploadImage(UploadCriteria criteria) + { return UploadImagep(criteria); } @@ -615,7 +658,7 @@ public partial class PersonRepository : IPerson private async Task> UploadImagep(UploadCriteria criteria) { string path = ""; - + int statusCode = 0; string error = ""; string sdate = GetCurrentDateTime(); @@ -630,19 +673,20 @@ public partial class PersonRepository : IPerson { Directory.CreateDirectory(path); } + extention = System.IO.Path.GetExtension(criteria.FileName); - filename = criteria.PersonId + "_" + sdate + extention; + filename = criteria.PersonId + "_" + sdate + extention; using (var fileStream = new FileStream(System.IO.Path.Combine(path, filename), FileMode.Create)) { await criteria.File.CopyToAsync(fileStream); } - + statusCode = 1; } else { - + statusCode = -1; error = "file contain is empty"; } @@ -662,6 +706,17 @@ public partial class PersonRepository : IPerson }; } + private async Task LoadPersonImage(string filename) + { + string result = ""; + + DownloadFileCriteria criteria = new() { FileName = filename }; + var resultModel = await _importPersonRepository.DownloadFile(criteria); + if (!string.IsNullOrEmpty((resultModel.Data))) + result = "data:image/png;base64," + resultModel.Data; + return result; + } + public ResultModel DeleteUploadFile(DeleteFileCriteria criteria) { int result = -1; @@ -673,7 +728,7 @@ public partial class PersonRepository : IPerson { File.Delete(myfile); result = 1; - + statusCode = 1; Person? model = _context.Persons.Find(criteria.Id); if (model != null) @@ -688,6 +743,7 @@ public partial class PersonRepository : IPerson statusCode = -1; error += e.Message; } + return new ResultModel() { Data = result, @@ -696,3 +752,4 @@ public partial class PersonRepository : IPerson }; } } + diff --git a/API/FamilyTreeAPI/Repository/PersonRepository.tree.cs b/API/FamilyTreeAPI/Repository/PersonRepository.tree.cs index 64afaff..1b537ed 100644 --- a/API/FamilyTreeAPI/Repository/PersonRepository.tree.cs +++ b/API/FamilyTreeAPI/Repository/PersonRepository.tree.cs @@ -6,11 +6,12 @@ namespace FamilyTreeAPI.Repository; public partial class PersonRepository { - private TreeNode PopulateItem(Person model) + private TreeNode PopulateItem(Person model) { - TreeNode treeNode = new(); + TreeNode treeNode = new(); + treeNode.Data = new(); treeNode.Label = model.FirstName; - treeNode.Data = model.Id.ToString(); + // treeNode.Key= model.Id.ToString(); treeNode.Key = model.Id.ToString(); treeNode.Expanded = false; treeNode.Children = new(); @@ -86,11 +87,11 @@ public partial class PersonRepository return result; } - private List> PopulateChild(FamilyCriteria criteria,int id, List childList, Func conditionFn) + private List> PopulateChild(FamilyCriteria criteria,int id, List childList, Func conditionFn) { Person person; - TreeNode treeNode; - List> list = new(); + TreeNode treeNode; + List> list = new(); List children = GetParentId(childList,id, criteria, conditionFn); for (int i = 0; i < children.Count; i++) { @@ -102,13 +103,13 @@ public partial class PersonRepository } return list; } - public async Task>> > GetFamilyTreeBy(FamilyCriteria criteria) + public async Task>> > GetFamilyTreeBy(FamilyCriteria criteria) { int statusCode = -1; string error = ""; Person person; - TreeNode treeNode; - List> data = new(); + TreeNode treeNode; + List> data = new(); try { var personList = await _context.Persons.ToListAsync(); @@ -129,7 +130,7 @@ public partial class PersonRepository statusCode = -1; } - return new ResultModel>> + return new ResultModel>> { Data = data, StatusCode = statusCode, diff --git a/API/FamilyTreeAPI/Repository/TextFile.txt b/API/FamilyTreeAPI/Repository/TextFile.txt index edf2cb4..4992b15 100644 --- a/API/FamilyTreeAPI/Repository/TextFile.txt +++ b/API/FamilyTreeAPI/Repository/TextFile.txt @@ -249,3 +249,19 @@ begin ; end; $BODY$; + + +kham +v2 + +CREATE TABLE IF NOT EXISTS "personphoto" ( + "id" serial NOT NULL, + "personid" INTEGER NOT NULL, + "photo" TEXT NOT NULL, + "imagephot" BYTEA NOT NULL, + "phototype" VARCHAR(20) NULL DEFAULT NULL, + PRIMARY KEY ("id") +); + +ALTER TABLE personphoto +alter column id ADD GENERATED BY DEFAULT AS IDENTITY ; \ No newline at end of file diff --git a/API/FamilyTreeAPI/appsettings.json b/API/FamilyTreeAPI/appsettings.json index 313267d..6b0c9ba 100644 --- a/API/FamilyTreeAPI/appsettings.json +++ b/API/FamilyTreeAPI/appsettings.json @@ -2,8 +2,8 @@ "AppSettings": { "Secret": "Nepean Blue Mountain Super Secret SIGN AND VERIFY JWT TOKENS, BEARER TOKEN USE WHEN CALLING THIS API.", - "SQLConnectionString": "host=localhost;port=5432;database=FamilyTreeDB;username=postgres;password=Positive~1;", - "SQLConnectionString_25": "host=192.168.1.100;port=5432;database=FamilyTreeDB;username=postgres;password=Positive~1;", + "SQLConnectionString_o": "host=localhost;port=5432;database=FamilyTreeDB;username=postgres;password=Positive~1;", + "SQLConnectionString": "host=192.168.1.123;port=5432;database=FamilyTreeDB;username=postgres;password=Positive~1;", "ImageFolder": "c:\\temp\\Family", "ImportFolder": "c:\\temp"