check in display image using api now

This commit is contained in:
2025-09-10 11:15:56 +10:00
parent 6cea606cc2
commit ff45c461a5
23 changed files with 335 additions and 59 deletions
@@ -22,7 +22,7 @@ public class FileUploadController : ControllerBase
_config = config; _config = config;
} }
[HttpPost("UploadFile")] [HttpPost("[action]")]
public async Task<IActionResult> UploadFile(IFormFile file) public async Task<IActionResult> UploadFile(IFormFile file)
{ {
List<CodeDto<string>> output = new (); List<CodeDto<string>> output = new ();
@@ -36,7 +36,7 @@ public class FileUploadController : ControllerBase
// Define the upload directory // Define the upload directory
// var uploadsFolder = Path.Combine(_hostingEnvironment.WebRootPath, "uploads"); // var uploadsFolder = Path.Combine(_hostingEnvironment.WebRootPath, "uploads");
string importFolder = _config.GetValue<string>("ImportFolder"); string importFolder = _config.GetValue<string>("AppSettings:ImportFolder");
var uploadsFolder = Path.Combine(_hostingEnvironment.ContentRootPath, importFolder); var uploadsFolder = Path.Combine(_hostingEnvironment.ContentRootPath, importFolder);
if (!Directory.Exists(uploadsFolder)) if (!Directory.Exists(uploadsFolder))
{ {
@@ -72,4 +72,11 @@ public class FileUploadController : ControllerBase
return StatusCode(500, $"Internal server error: {ex.Message}"); return StatusCode(500, $"Internal server error: {ex.Message}");
} }
} }
[HttpPost("[action]")]
public async Task<IActionResult> DownloadFile(DownloadFileCriteria criteria)
{
var rev = await _importPersonRepository.DownloadFile(criteria);
return Ok(rev);
}
} }
+5 -6
View File
@@ -1,12 +1,11 @@
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. # See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
# This stage is used when running from VS in fast mode (Default for Debug configuration) # This stage is used when running from VS in fast mode (Default for Debug configuration)
#FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base #FROM mcr.microsoft.com/dotnet/aspnet:9::.0 AS base
ARG BUILD_CONFIGURATION=Release ARG BUILD_CONFIGURATION=Release
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src WORKDIR /src
COPY ["FamilyTreeAPI/FamilyTreeAPI.csproj", "FamilyTreeAPI/"] COPY ["FamilyTreeAPI/FamilyTreeAPI.csproj", "FamilyTreeAPI/"]
COPY ["CommonAD/CommonAD.csproj", "CommonAD/"]
RUN dotnet restore "./FamilyTreeAPI/FamilyTreeAPI.csproj" RUN dotnet restore "./FamilyTreeAPI/FamilyTreeAPI.csproj"
COPY . . COPY . .
WORKDIR "/src/FamilyTreeAPI" WORKDIR "/src/FamilyTreeAPI"
@@ -18,9 +17,9 @@ FROM build AS publish
RUN dotnet publish "./FamilyTreeAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false RUN dotnet publish "./FamilyTreeAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) # This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app WORKDIR /app
ENV ASPNETCORE_HTTP_PORTS=80 ENV ASPNETCORE_HTTP_PORTS=8080
EXPOSE 80 EXPOSE 8080
COPY --from=publish /app/publish . COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "FamilyTreeAPI.dll"] ENTRYPOINT ["dotnet", "FamilyTreeAPI.dll"]
@@ -10,6 +10,10 @@ public class FileContent
public byte[] Content { get; set; } public byte[] Content { get; set; }
public string FileName { get; set; } public string FileName { get; set; }
} }
public class DownloadFileCriteria
{
public string FileName { get; set; }
}
public class UploadCriteria public class UploadCriteria
{ {
public string FileName { get; set; } public string FileName { get; set; }
+35
View File
@@ -0,0 +1,35 @@
The family Tree
Man and Woman
top level
1) TAM (M) has partner Jenny (F)
had child CAO (M)
had Child Emmy (F)
has Child Loan (F)
2) CAO (M) has partner Lin (F)
has child Joe (M)
has child TOM (M)
3) Joe has partner Sophia (F)
has child Olivia (F)
has child Mai (F)
4) Henry has partner Loan (F)
has child Enya (F)
has child Thanh (M)
has child Chuong (M)
5) Henry has partner Brisa (F)
has child Fern (F)
has child Tim (M)
@@ -8,7 +8,7 @@
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
}, },
"dotnetRunMessages": true, "dotnetRunMessages": true,
"applicationUrl": "http://localhost:5015", "applicationUrl": "http://localhost:5016",
"applicationUrl1": "http://192.168.8.188:5015" "applicationUrl1": "http://192.168.8.188:5015"
}, },
"IIS Express": { "IIS Express": {
@@ -37,7 +37,67 @@ public class ImportPersonRepository
_config = config; _config = config;
_httpContext = httpContext; _httpContext = httpContext;
} }
public async Task<string> GetImageAsBase64String(string imagePath)
{
try
{
// Read the image file into a byte array
//byte[] imageBytes = File.ReadAllBytes(imagePath);
byte[] imageBytes = await File.ReadAllBytesAsync(imagePath);
// Convert the byte array to a Base64 string
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
catch (FileNotFoundException)
{
Console.WriteLine($"Error: The file at '{imagePath}' was not found.");
return null;
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
return null;
}
}
public async Task<ResultModel<string>> DownloadFile(DownloadFileCriteria criteria)
{
int statusCode = -1;
string result = "";
string error = "";
try
{
string imagePath = _config.GetValue<string>("AppSettings:ImageFolder");
string imageUrl = System.IO.Path.Combine(imagePath, criteria.FileName);
if (System.IO.File.Exists(imageUrl))
{
result = await this.GetImageAsBase64String(imageUrl);
statusCode = 1;
}
else
{
error = "error filename " + criteria.FileName + " can not find";
statusCode = -1;
}
}
catch (Exception ex)
{
statusCode = -1;
error = ex.Message;
}
return new ResultModel<string>
{
Data = result,
StatusCode = statusCode,
Message = error
};
}
public async Task<List<CodeDto<string>>> ImportPerson(MemoryStream fileStream, string sheetName) public async Task<List<CodeDto<string>>> ImportPerson(MemoryStream fileStream, string sheetName)
{ {
Dictionary<string, ImportRelation> relationDic = new(); Dictionary<string, ImportRelation> relationDic = new();
+1 -1
View File
@@ -17,7 +17,7 @@
} }
}, },
"AllowedHosts": "*", "AllowedHosts": "*",
"Kestrel": { "Kestrel_not_use": {
"Endpoints": { "Endpoints": {
"Http": { "Http": {
"Url": "http://*:5015" "Url": "http://*:5015"
+3 -4
View File
@@ -29,7 +29,7 @@ services:
PGADMIN_DEFAULT_EMAIL: postgres@domain.com PGADMIN_DEFAULT_EMAIL: postgres@domain.com
PGADMIN_DEFAULT_PASSWORD: Positive~1 PGADMIN_DEFAULT_PASSWORD: Positive~1
ports: ports:
- "5050:80" - "5050:5050"
networks: networks:
- dev - dev
familytreeui: familytreeui:
@@ -41,7 +41,7 @@ services:
build: build:
context: UI context: UI
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: workui container_name: familytreeui
volumes: volumes:
- ./:/app - ./:/app
networks: networks:
@@ -54,8 +54,7 @@ services:
environment: environment:
- "Logging:Microsoft.AspNetCore.DataProtection:None" - "Logging:Microsoft.AspNetCore.DataProtection:None"
- "AppSettings:SQLConnectionString=host=postgresdb;database=FamilyTreeDB;username=postgres;password=Positive~1" - "AppSettings:SQLConnectionString=host=postgresdb;database=FamilyTreeDB;username=postgres;password=Positive~1"
volumes:
- myapikey:/home/app/.aspnet/DataProtection-Keys
ports: ports:
- "8080:8080" - "8080:8080"
build: build:
+32
View File
@@ -0,0 +1,32 @@
FROM node:24.0.0 AS build
RUN mkdir -p /app
WORKDIR /app
COPY ["./*.json", "./"]
RUN npm install -g @angular/cli
COPY . .
# Run command in Virtual directory
RUN npm cache clean --force
RUN npm install
#RUN ng build --configuration=production
RUN ng build -c=production
FROM nginx:latest
#### copy nginx conf
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
#COPY --from=build app/dist/Familytree/browser /usr/share/nginx/html
#### copy artifact build from the 'build environment' old is not in browser folder
COPY --from=build /app/dist/Familytree/browser /usr/share/nginx/html
#CMD ["nginx", "-g", "daemon off;"]
EXPOSE 80
#docker build -t my_angular_app:latest .
#docker run --name carval -d -p 4200:80 varlidate_ui
#npm error code ENOENT
+20
View File
@@ -0,0 +1,20 @@
server {
listen 80;
sendfile on;
default_type application/octet-stream;
gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 256;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 9;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html =404;
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
{ {
"baseUrl1": "http://192.168.8.188:5015", "baseUrl1": "http://192.168.8.188:5015",
"baseUrl": "http://localhost:5015", "baseUrl": "http://localhost:5016",
"baseUrl_docker": "http://localhost:8080",
"attachment": "http://localhost/document/family" "attachment": "http://localhost/document/family"
} }
+2
View File
@@ -4,12 +4,14 @@ import { StaffComponent, StaffEditComponent } from './staff';
import { AuthGuard } from './route-guard'; import { AuthGuard } from './route-guard';
import { FamilyTree, FamilyList} from './person'; import { FamilyTree, FamilyList} from './person';
import { ImportCom } from './import.com/import.com'; import { ImportCom } from './import.com/import.com';
import { ImageDisplayComponent } from './pickperson/image.display';
export const routes: Routes = [ export const routes: Routes = [
{ path: '', redirectTo: 'login', pathMatch: 'full' }, { path: '', redirectTo: 'login', pathMatch: 'full' },
// { path: 'approval', component: ApprovalComponent,canActivate: [AuthGuard], data: { roleAllowed: '1,2,3' }},}, // { path: 'approval', component: ApprovalComponent,canActivate: [AuthGuard], data: { roleAllowed: '1,2,3' }},},
{ path: 'login', component: Login}, { path: 'login', component: Login},
{ path: 'staff', component: StaffComponent}, { path: 'staff', component: StaffComponent},
{ path: 'person', component: FamilyList}, { path: 'person', component: FamilyList},
{ path: 'imagedisplay/:id', component: ImageDisplayComponent},
{ path: 'import', component: ImportCom}, { path: 'import', component: ImportCom},
{ path: 'familytree', component: FamilyTree}, { path: 'familytree', component: FamilyTree},
{ path: 'staff/:id', component: StaffEditComponent}, { path: 'staff/:id', component: StaffEditComponent},
+1 -1
View File
@@ -2,7 +2,7 @@
<label class="flex mb-2"> Import Excel File</label> <label class="flex mb-2"> Import Excel File</label>
<p-fileupload #fu mode="basic" chooseLabel="Choose" <p-fileupload #fu mode="basic" chooseLabel="Choose"
chooseIcon="pi pi-upload" name="file" chooseIcon="pi pi-upload" name="file"
url="http://localhost:5015/api/FileUpload/UploadFile" url='{{baseUrl}}'
maxFileSize="10000000000" (onUpload)="onUpload($event)" /> maxFileSize="10000000000" (onUpload)="onUpload($event)" />
<p-button styleClass="mt-4" label="Upload" (onClick)="fu.upload()" severity="primary" /> <p-button styleClass="mt-4" label="Upload" (onClick)="fu.upload()" severity="primary" />
+11 -2
View File
@@ -1,9 +1,10 @@
import { Component } from '@angular/core'; import { Component, inject, OnInit } from '@angular/core';
import { ButtonModule } from 'primeng/button'; import { ButtonModule } from 'primeng/button';
import { FileUploadEvent, FileUploadModule } from 'primeng/fileupload'; import { FileUploadEvent, FileUploadModule } from 'primeng/fileupload';
import { MessageService } from 'primeng/api'; import { MessageService } from 'primeng/api';
import { FileUpload } from 'primeng/fileupload'; import { FileUpload } from 'primeng/fileupload';
import { ToastModule } from 'primeng/toast'; import { ToastModule } from 'primeng/toast';
import { AppSettingService } from '../shares';
/* /*
interface UploadEvent { interface UploadEvent {
originalEvent: Event; originalEvent: Event;
@@ -16,9 +17,17 @@ interface UploadEvent {
templateUrl: './import.com.html', templateUrl: './import.com.html',
styleUrl: './import.com.css' styleUrl: './import.com.css'
}) })
export class ImportCom { export class ImportCom implements OnInit {
uploadedFiles: any[] = []; uploadedFiles: any[] = [];
baseUrl = "";
private appSetting = inject(AppSettingService);
constructor(private messageService: MessageService) {} constructor(private messageService: MessageService) {}
ngOnInit(): void
{
const cbaseUrl = this.appSetting.appSetting.baseUrl;
//http://localhost:5015/api/FileUpload/UploadFile"
this.baseUrl = cbaseUrl + "/api/FileUpload/UploadFile";
}
onUpload(event:FileUploadEvent) { onUpload(event:FileUploadEvent) {
for(let file of event.files) { for(let file of event.files) {
this.uploadedFiles.push(file); this.uploadedFiles.push(file);
+1
View File
@@ -12,5 +12,6 @@ export enum ConfigureUrl
logoutUrl ="api/Users/Logout", logoutUrl ="api/Users/Logout",
adminUserUrl = "api/Staff", adminUserUrl = "api/Staff",
lookupUrl = "api/Lookup", lookupUrl = "api/Lookup",
FileUploadUrl = "api/FileUpload",
} }
+4 -8
View File
@@ -5,9 +5,7 @@ import { OrganizationChartModule } from 'primeng/organizationchart';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { Router } from '@angular/router';
import { PersonService } from './person.service'; import { PersonService } from './person.service';
import { AuthenticationService } from '../user-services';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@@ -41,15 +39,13 @@ export class FamilyOrga implements OnInit, OnDestroy{
familyList:Person[] = []; familyList:Person[] = [];
msg ="[Person organise component]"; msg ="[Person organise component]";
private messageService = inject(MessageService); private messageService = inject(MessageService);
public ref = inject(DynamicDialogRef);
public config = inject(DynamicDialogConfig);
/* /*
private store: Store<appValidationState> private store: Store<appValidationState>
*/ */
constructor( private personService = inject(PersonService);
public dialogService: DialogService, public dialogService = inject(DialogService);
private personService: PersonService,
public ref: DynamicDialogRef, public config: DynamicDialogConfig,
) {}
ngOnInit(): void ngOnInit(): void
{ {
+11 -6
View File
@@ -52,10 +52,10 @@ export class FamilyList implements OnInit, OnDestroy{
public dialogService= inject( DialogService); public dialogService= inject( DialogService);
private personService= inject( PersonService); private personService= inject( PersonService);
private confirmationService = inject(ConfirmationService); private confirmationService = inject(ConfirmationService);
private cd = inject(ChangeDetectorRef); private cdr = inject(ChangeDetectorRef);
private authenticationService= inject( AuthenticationService); private authenticationService= inject( AuthenticationService);
private router= inject( Router); private router= inject( Router);
constructor() {}
getSearchCiteria(): StaffSearch { getSearchCiteria(): StaffSearch {
let criteria:StaffSearch = { let criteria:StaffSearch = {
email: this.email, email: this.email,
@@ -182,7 +182,7 @@ export class FamilyList implements OnInit, OnDestroy{
console.log("the person from load", this.familyList()); console.log("the person from load", this.familyList());
this.loading = false; this.loading = false;
this.cd.detectChanges(); this.cdr.detectChanges();
}, },
error: e => { error: e => {
const message = e || e.message; const message = e || e.message;
@@ -250,6 +250,7 @@ export class FamilyList implements OnInit, OnDestroy{
const nlist = this.familyList().filter(d => d.id !== id); const nlist = this.familyList().filter(d => d.id !== id);
this.familyList.set(nlist); this.familyList.set(nlist);
this.cdr.detectChanges();
}, },
error: e => console.error(e) error: e => console.error(e)
}); });
@@ -311,19 +312,21 @@ export class FamilyList implements OnInit, OnDestroy{
} }
updateList(item: Person) :void { updateList(item: Person) :void {
const idx = this.familyList().findIndex( x => x.id == item.id); const list = this.familyList();
const idx = list.findIndex( x => x.id === item.id);
if (item.fatherId && item.fatherId > 0) if (item.fatherId && item.fatherId > 0)
item.fatherName = this.getName(item.fatherId); item.fatherName = this.getName(item.fatherId);
if (item.motherId && item.motherId > 0) if (item.motherId && item.motherId > 0)
item.motherName = this.getName(item.motherId); item.motherName = this.getName(item.motherId);
if (idx < 0) if (idx < 0)
{ {
const olist = [... this.familyList(), item]; const olist = [... list, item];
this.familyList.set(olist); this.familyList.set(olist);
} }
else else
{ {
const oitem = this.familyList()[idx];
const oitem = list[idx];
oitem.firstName = item.firstName; oitem.firstName = item.firstName;
oitem.lastName = item.lastName; oitem.lastName = item.lastName;
oitem.address = item.address; oitem.address = item.address;
@@ -335,7 +338,9 @@ export class FamilyList implements OnInit, OnDestroy{
oitem.motherId = item.motherId; oitem.motherId = item.motherId;
oitem.fatherName = item.fatherName; oitem.fatherName = item.fatherName;
oitem.motherName = item.motherName; oitem.motherName = item.motherName;
this.familyList.set(list);
} }
this.cdr.markForCheck();
} }
+10 -5
View File
@@ -53,11 +53,15 @@
<div> <div>
<div class="field col-12 md:col-6 sm:col-8"> <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) @if (adminuserForm.value.image != "" && adminuserForm.value.image != null)
{ {
<div class="ml-6 file-upload"> <div class="ml-6 file-upload">
<a href="{{hostsite}}/{{adminuserForm.value.image}}" target="_blank" class="text-blue-400">View Attachment <!--a href="{{hostsite}}/{{adminuserForm.value.image}}" target="_blank" class="text-blue-400">View Attachment
</a> </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" <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" class="p-button-rounded p-button-text text-red-500 p-button-raised ml-2"
(click)="deleteFile()"></button> (click)="deleteFile()"></button>
@@ -65,7 +69,7 @@
} }
@else @else
{ {
<div class="ml-6"> <div class="ml-6 ">
<input type="file" class="file-input" (change)="onFileSelected($event)" #fileUpload> <input type="file" class="file-input" (change)="onFileSelected($event)" #fileUpload>
<div class="file-upload"> <div class="file-upload">
<label>{{ adminuserForm.value.image || "No attachment file uploaded yet."}}</label> <label>{{ adminuserForm.value.image || "No attachment file uploaded yet."}}</label>
@@ -77,9 +81,10 @@
} }
</div> </div>
</div> </div>
</div>
<div class="mt-2 w-full"> <div class="mt-2 w-full">
<p-button class="flex justify-end mr-2" icon="pi pi-user" label="Add Partner" <p-button class="flex justify-end mr-2" icon="pi pi-user" [raised]="true" severity="info" label="Add Partner"
severity="warn" (onClick)="addPartner()"/> (onClick)="addPartner()"/>
<div class="shadow rounded mt-2 mb-2"> <div class="shadow rounded mt-2 mb-2">
<p-table [value]="partners()"> <p-table [value]="partners()">
<ng-template #header> <ng-template #header>
+30 -6
View File
@@ -17,7 +17,8 @@ import moment from 'moment';
import { HttpEvent } from '@angular/common/http'; import { HttpEvent } from '@angular/common/http';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { Pickperson } from '../pickperson/pickperson'; import { Pickperson } from '../pickperson/pickperson';
import { ImageDisplayComponent } from '../pickperson/image.display';
import { TooltipModule } from 'primeng/tooltip';
export interface FileUploadEvent { export interface FileUploadEvent {
originalEvent: HttpEvent<any>; originalEvent: HttpEvent<any>;
@@ -30,7 +31,8 @@ export interface FileUploadHandlerEvent {
@Component({ @Component({
templateUrl: 'person.edit.html', templateUrl: 'person.edit.html',
selector: 'person-edit', selector: 'person-edit',
imports:[ButtonModule,TableModule,ReactiveFormsModule,SelectModule,CheckboxModule, InputTextModule,DatePickerModule], imports:[ButtonModule,TableModule,ReactiveFormsModule,TooltipModule,
SelectModule,CheckboxModule, InputTextModule,DatePickerModule],
styleUrls: ['person.edit.css'], styleUrls: ['person.edit.css'],
providers: [DialogService] providers: [DialogService]
@@ -233,8 +235,7 @@ populateSex(): void {
name:"Male", name:"Male",
status:'M' status:'M'
}; };
this.sexList.push(item); this.sexList.push(item);
} }
ngOnInit():void { ngOnInit():void {
@@ -275,9 +276,32 @@ ngOnInit():void {
// this for disable submit button // this for disable submit button
get isFieldsChange() { get isFieldsChange() {
const chan = this.isChange || !this.adminuserForm.valid; // this disable so need true valid = true not const chan = this.isChange || !this.adminuserForm.valid; // this disable so need true valid = true not
//console.log(this.msg + 'is fields change', chan); console.log(this.msg + 'is fields change', chan);
return chan; return chan;
}
doViewImage(imageName:string): void {
const ref = this.dialogService.open(ImageDisplayComponent, {
data: {
imageName,
},
header: 'View Image',
draggable: true,
width: '70%',
modal:true,
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
} }
});
}
assignValue(item:Person): void { assignValue(item:Person): void {
this._id = item.id; this._id = item.id;
@@ -537,7 +561,7 @@ showPickPerson(title:string, callback:(id: Person) => void) :void {
}, },
header: title, header: title,
width: '80%', width: '80%',
draggable: true,
maximizable: true maximizable: true
}); });
+7
View File
@@ -77,6 +77,13 @@ export class PersonService {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/UploadImage"; const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/UploadImage";
return this.http.post<ResultModel<string>>(baseUrl, data); return this.http.post<ResultModel<string>>(baseUrl, data);
} }
downloadFile(imageName: string): Observable<ResultModel<string>> {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DownloadFile";
const data = {
fileName: imageName
};
return this.http.post<ResultModel<string>>(baseUrl, data);
}
deleteUploadFile(data: any): Observable<ResultModel<number>> { deleteUploadFile(data: any): Observable<ResultModel<number>> {
//data ={filename}; //data ={filename};
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/DeleteUploadFile"; const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/DeleteUploadFile";
+6
View File
@@ -0,0 +1,6 @@
<img [src]="imageDataUrl" alt="Person Image" width="400" height="300"/>
<div class="flex justify-end">
<button pButton pRipple class="p-button-sm mr-2 p-button-secondary" type="button" icon="pi pi-sign-in" label="Close"
(click)="close()"></button>
</div>
+64
View File
@@ -0,0 +1,64 @@
import { Component, inject, OnDestroy, OnInit } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { AppSettingService } from '../shares';
import { PersonService } from '../person';
import { Subscription } from 'rxjs';
import { ActivatedRoute } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ButtonModule } from 'primeng/button';
import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
@Component({
selector: 'app-image-display',
imports:[CommonModule, ButtonModule],
templateUrl: './image.display.html',
styleUrls: ['./image.display.css']
})
export class ImageDisplayComponent implements OnInit, OnDestroy {
//base64ImageString: string = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='; // Example Base64 (a tiny red dot PNG)
//imageDataUrl: SafeResourceUrl ={};
imageDataUrl = "";
private personService = inject(PersonService);
private sanitizer = inject(DomSanitizer);
//private route = inject(ActivatedRoute);
public ref = inject(DynamicDialogRef);
public config = inject(DynamicDialogConfig);
private subscription:Subscription = new Subscription();
ngOnInit(): void {
const imageName = this.config.data.imageName;
this.loadImage(imageName);
}
loadImage(fileName: string| null): void {
const download = this.personService.downloadFile(fileName!);
this.subscription.add(download.subscribe({
next: x => {
if (x.statusCode == 1)
{
this.display(x.data);
console.log("this is show image" , this.imageDataUrl, x);
}
else
{
console.log("error in download in api ", x.message);
}
},
error: e => console.error("error in download image", e)
}));
}
display(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 = fullDataUri
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
close() :void {
this.ref.close(null);
}
}