Commit 7db38b63 by Nattana Chaiyamat

excel-report

parent 4f0b56ab
{
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -104,6 +104,7 @@ import { ExcelReportComponent } from './excel-report/excel-report.component'; ...@@ -104,6 +104,7 @@ import { ExcelReportComponent } from './excel-report/excel-report.component';
import { ExcelListComponent } from './excel-list/excel-list.component'; import { ExcelListComponent } from './excel-list/excel-list.component';
import { ExcelReportToggleComponent } from './excel-report-toggle/excel-report-toggle.component'; import { ExcelReportToggleComponent } from './excel-report-toggle/excel-report-toggle.component';
import { ExcelReportEmpviewComponent } from './excel-report-empview/excel-report-empview.component'; import { ExcelReportEmpviewComponent } from './excel-report-empview/excel-report-empview.component';
import { SafeUrlPipe } from 'src/pipe/safe-url.pipe';
@NgModule({ @NgModule({
imports: [ imports: [
...@@ -184,7 +185,8 @@ import { ExcelReportEmpviewComponent } from './excel-report-empview/excel-report ...@@ -184,7 +185,8 @@ import { ExcelReportEmpviewComponent } from './excel-report-empview/excel-report
ExcelReportComponent, ExcelReportComponent,
ExcelListComponent, ExcelListComponent,
ExcelReportToggleComponent, ExcelReportToggleComponent,
ExcelReportEmpviewComponent ExcelReportEmpviewComponent,
SafeUrlPipe
], ],
providers: [ providers: [
ContactService, ContactService,
......
...@@ -73,69 +73,135 @@ ...@@ -73,69 +73,135 @@
<tbody *ngIf="template.filter.length"> <tbody *ngIf="template.filter.length">
<ng-container <ng-container
*ngFor="let items of template.filter | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index"> *ngFor="let items of template.filter | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<tr style="background-color:#ebf2f6"> <tr (mouseenter)="tableHover.set(items.templateId,!tableHover.get(items.templateId))"
(mouseleave)="tableHover.clear()"
[ngStyle]="{'background-color':tableHover.get(items.templateId)?'rgb(201 223 235)':'#ebf2f6'}">
<td colspan="6" class="font-16 font-medium"> <td colspan="6" class="font-16 font-medium">
<span class="cursor-pointer" (click)="openAddGroupModal(addGroupModal,items)"> <span class="cursor-pointer text-info" style="text-decoration: underline;"
{{items.tname}}-{{items.ename}} (click)="openAddGroupModal(addGroupModal,items)">
{{items.tname}}
</span>
<span>
-{{items.ename}}
</span> </span>
</td> </td>
<td class="text-center"> <td class="text-center">
<button type="button" *ngIf="!openTemplate.get(items.tname+'-'+items.ename)" <ng-container *ngIf="items.templateFile.length">
class="btn" <ng-container *ngIf="!openTemplate.get(items.templateId)">
style="border:3px solid #2962ff;border-radius: 10%;background-color: white;" <button type="button" title="เปิด" class="btn"
(click)=" style="border:3px solid #2962ff;border-radius: 10%;" (click)="
openTemplate.set(items.tname+'-'+items.ename,true)"> openTemplate.set(items.templateId,true)"
<i class="fa fa-arrow-right text-info"></i> (mouseenter)="buttonHover.set(items.templateId+'open',!buttonHover.get(items.templateId))"
</button> (mouseleave)="buttonHover.clear()"
<button type="button" *ngIf="openTemplate.get(items.tname+'-'+items.ename)" [ngStyle]="{'background-color':buttonHover.get(items.templateId+'open')?'#dfdfdf':'#ffffff'}">
class="btn" <i class="fa fa-arrow-right text-info"></i>
style="border:3px solid #2962ff;border-radius: 10%;background-color: white;" </button>
(click)=" </ng-container>
openTemplate.set(items.tname+'-'+items.ename,false)"> <ng-container *ngIf="openTemplate.get(items.templateId)">
<i class="fa fa-arrow-down text-info"></i> <button type="button" title="ปิด" class="btn"
style="border:3px solid #2962ff;border-radius: 10%;" (click)="
openTemplate.set(items.templateId,false)"
(mouseenter)="buttonHover.set(items.templateId+'close',!buttonHover.get(items.templateId))"
(mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(items.templateId+'close')?'#dfdfdf':'#ffffff'}">
<i class="fa fa-arrow-down text-info"></i>
</button>
</ng-container>
&nbsp;
</ng-container>
<button type="button" title="เพิ่ม EXCCHILD" class="btn"
style="border:3px solid #2962ff;border-radius: 10%;"
(click)="openAddChildModal(addChildModal,items,'add')"
(mouseenter)="buttonHover.set(items.templateId+'add',!buttonHover.get(items.templateId))"
(mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(items.templateId+'add')?'#dfdfdf':'#ffffff'}">
<i class="fa fa-floppy-o text-info"></i>
</button> </button>
&nbsp; &nbsp;
<button type="button" class="btn" <button type="button" title="ลบ" class="btn"
style="border:3px solid #2962ff;border-radius: 10%;background-color: white;" style="border:3px solid #2962ff;border-radius: 10%;"
(click)="openAddChildModal(addChildModal)"> (mouseenter)="buttonHover.set(items.templateId+'delete',!buttonHover.get(items.templateId))"
<i class="fa fa-floppy-o text-info"></i> (mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(items.templateId+'delete')?'#dfdfdf':'#ffffff'}"
(click)="deleteTemplate(items)">
<i class="fa fa-trash text-danger"></i>
</button> </button>
</td> </td>
</tr> </tr>
<ng-container *ngIf="openTemplate.get(items.tname+'-'+items.ename)"> <ng-container *ngIf="openTemplate.get(items.templateId)">
<ng-container <ng-container
*ngFor="let item of items.templateFile | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index"> *ngFor="let item of items.templateFile | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<tr style="background-color:#ffffff"> <tr (mouseenter)="tableHover.set(item.fileName,!tableHover.get(item.fileName))"
<td style="white-space: normal !important;word-break: break-word;"> (mouseleave)="tableHover.clear()"
<i *ngIf="item.menuActive=='0'" class="fa fa-times text-danger"></i> [ngStyle]="{'background-color':tableHover.get(item.fileName)?'rgb(201 223 235)':'#ffffff'}">
<i *ngIf="item.menuActive=='1'" class="fa fa-check text-success"></i> <ng-container *ngIf="downloadTemplateFileLoading.get(item.fileName)">
{{item.tdesc}} <td colspan="7" class="text-center">
</td> <div *ngFor="let item of [1,2,3]" class="spinner-grow text-info mx-1"
<td style="white-space: normal !important;word-break: break-word;"> role="status">
{{item.edesc}}</td> <span class="sr-only">Loading...</span>
<td class="text-center" </div>
style="white-space: normal !important;word-break: break-word;"> </td>
{{item.createBy.thFullName}}</td> </ng-container>
<td class="text-center" <ng-container *ngIf="!downloadTemplateFileLoading.get(item.fileName)">
style="white-space: normal !important;word-break: break-word;"> <td style="white-space: normal !important;word-break: break-word;">
{{item.createDate}}</td> <i *ngIf="item.menuActive=='0'"
<td class="text-center" class="fa fa-times text-danger cursor-pointer"
style="white-space: normal !important;word-break: break-word;"> style="text-decoration: underline;"
{{item.createTime}}</td> (click)="menuActiveTemplateFile(item)"></i>
<td class="text-center" <i *ngIf="item.menuActive=='1'"
style="white-space: normal !important;word-break: break-word;"> class="fa fa-check text-success cursor-pointer"
{{item.module}}</td> style="text-decoration: underline;"
<td class="text-center" class="text-center"> (click)="menuActiveTemplateFile(item)"></i>
<button type="button" class="btn" &nbsp;
style="border:3px solid #2962ff;border-radius: 10%;background-color: white;"> <span class="cursor-pointer text-info"
<i class="fa fa-files-o text-info"></i> style="text-decoration: underline;"
</button> (click)="openAddChildModal(addChildModal,item,'edit')">
&nbsp; {{item.tdesc}}
<button type="button" class="btn" </span>
style="border:3px solid #2962ff;border-radius: 10%;background-color: white;"> </td>
<i class="fa fa-print text-info"></i> <td style="white-space: normal !important;word-break: break-word;">
</button> {{item.edesc}}</td>
</td> <td class="text-center"
style="white-space: normal !important;word-break: break-word;">
<!-- {{item.createBy.thFullName}}</td> -->
<td class="text-center"
style="white-space: normal !important;word-break: break-word;">
{{formatISOToLocal(item.createDate).date}}</td>
<td class="text-center"
style="white-space: normal !important;word-break: break-word;">
{{formatISOToLocal(item.createDate).time}}</td>
<td class="text-center"
style="white-space: normal !important;word-break: break-word;">
{{item.module}}</td>
<td class="text-center" class="text-center">
<button type="button" title="Download File" class="btn"
style="border:3px solid #2962ff;border-radius: 10%"
(mouseenter)="buttonHover.set(item.fileName+'copy',!buttonHover.get(item.fileName))"
(mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(item.fileName+'copy')?'#dfdfdf':'#ffffff'}"
(click)="downloadTemplateFile(item)">
<i class="fa fa-files-o text-info"></i>
</button>
&nbsp;
<button type="button" title="Print" class="btn"
style="border:3px solid #2962ff;border-radius: 10%"
(mouseenter)="buttonHover.set(item.fileName+'print',!buttonHover.get(item.fileName))"
(mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(item.fileName+'print')?'#dfdfdf':'#ffffff'}"
(click)="openPrintModal(printModal,item);">
<i class="fa fa-print text-info"></i>
</button>
&nbsp;
<button type="button" title="ลบ" class="btn"
style="border:3px solid #2962ff;border-radius: 10%;"
(mouseenter)="buttonHover.set(item.fileName+'delete',!buttonHover.get(item.fileName))"
(mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(item.fileName+'delete')?'#dfdfdf':'#ffffff'}"
(click)="deleteTemplateFile(item)">
<i class="fa fa-trash text-danger"></i>
</button>
</td>
</ng-container>
</tr> </tr>
</ng-container> </ng-container>
</ng-container> </ng-container>
...@@ -217,74 +283,500 @@ ...@@ -217,74 +283,500 @@
</select> </select>
</div> </div>
</div> </div>
<div class="modal-footer "> </div>
<button type="submit" class="btn btn-info" [disabled]="!bodyTemplate.data.tname||!bodyTemplate.data.module" <div class="modal-footer ">
(click)="modal.close()">บันทึก</button> <button type="submit" class="btn btn-info" [disabled]="!bodyTemplate.data.tname||!bodyTemplate.data.module"
<button type="button" class="btn btn-danger" (click)="modal.dismiss()">ปิด</button> (click)="modal.close()">บันทึก</button>
</div> <button type="button" class="btn btn-danger" (click)="modal.dismiss()">ปิด</button>
</div> </div>
</ng-template> </ng-template>
<ng-template #addChildModal let-modal> <ng-template #addChildModal let-modal>
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">EXCHEAD, Template header excel</h5> <h5 class="modal-title" id="edittemplateLabel">EXCCHILD, Template file excel</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close"> <button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group row"> <div class="form-group row ml-0">
<label for="nameth" class="col-sm-4 col-form-label"> <div class="custom-control custom-radio col-sm-4 d-flex align-items-center">
ชื่อเอ็กเซลล์ไฟล์</label> <input type="radio" class="custom-control-input cursor-pointer" name="excelFile" id="excelFilePortal"
<div class="col-sm-8"> [checked]="templateFileType=='portal'"
<input type="text" class="form-control"> (click)="templateFileType='portal';templateFile.fileData='';templateFile.fileType='';templateFileName=''">
<label class="custom-control-label cursor-pointer" for="excelFilePortal">เลือกเอ็กเซลล์ไฟล์จาก
Portal<span *ngIf="templateFileType=='portal'" style="color: red">*</span></label>
</div>
<div class="col-sm-8 d-flex align-items-center">
<ng-container *ngIf="templateFileType=='portal'">
<input *ngIf="templateFile.portalId" type="text" class="form-control col-10 bg-white"
[value]="templateFile.portalId" readonly>
<button type="button" class="btn btn-info mr-2 col-auto"
(click)="openExcelPortalModal(excel_portalModal)"><i
class="fa fa-search text-white"></i></button>
</ng-container>
</div>
</div>
<div class="form-group row ml-0">
<div class="custom-control custom-radio col-sm-4">
<input type="radio" class="custom-control-input cursor-pointer" name="excelFile" id="excelFileUpload"
[checked]="templateFileType=='upload'" (click)="templateFileType='upload';templateFile.portalId=''">
<label class="custom-control-label cursor-pointer" for="excelFileUpload">อัพโหลดเอ็กเซลล์ไฟล์<span
*ngIf="templateFileType=='upload'" style="color: red">*</span></label>
</div>
<div class="col-sm-8 d-flex align-items-center">
<ng-container *ngIf="templateFileType=='upload'">
<input #fileInput type="file" accept=".xlsx" (change)="onFileSelected($event)"
style="display:none;" />
<button (click)="fileInput.click()">เลือกไฟล์</button>
&nbsp;
<span *ngIf="templateFileName">{{ templateFileName }}</span>
</ng-container>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="nameth" class="col-sm-4 col-form-label">รายละเอียด<span <label for="nameth" class="col-sm-4 col-form-label">รายละเอียด (ภาษาไทย)<span
style="color: red">*</span></label> style="color: red">*</span></label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="text" class="form-control" [(ngModel)]="bodyTemplate.data.tname"> <input type="text" class="form-control" [(ngModel)]="templateFile.tdesc">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="nameeng" class="col-sm-4 col-form-label">ชื่อกลุ่มรายงาน (ภาษาอังกฤษ)</label> <label for="nameeng" class="col-sm-4 col-form-label">รายละเอียด (ภาษาอังกฤษ)</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="text" class="form-control" [(ngModel)]="bodyTemplate.data.ename"> <input type="text" class="form-control" [(ngModel)]="templateFile.edesc">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">รายละเอียด (ภาษาไทย)</label> <label for="position" class="col-sm-4 col-form-label">แบ่งปัน</label>
<div class="col-sm-8"> <div class="row col-sm-8">
<textarea class="form-control" [(ngModel)]="bodyTemplate.data.tdesc"></textarea> <div class="custom-control custom-radio m-2">
<input type="radio" class="custom-control-input cursor-pointer" name="share" id="shareNo"
[checked]="templateFile.isShare=='0'" (click)="templateFile.isShare='0'">
<label class="custom-control-label cursor-pointer" for="shareNo">ไม่ใช่</label>
</div>
<div class="custom-control custom-radio m-2">
<input type="radio" class="custom-control-input cursor-pointer" name="share" id="shareYes"
[checked]="templateFile.isShare=='1'" (click)="templateFile.isShare='1'">
<label class="custom-control-label cursor-pointer" for="shareYes">ใช่</label>
</div>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">รายละเอียด (ภาษาอังกฤษ)</label> <label for="position" class="col-sm-4 col-form-label">แสดงรูปแบบ pivot</label>
<div class="col-sm-8"> <div class="row col-sm-8">
<textarea class="form-control" [(ngModel)]="bodyTemplate.data.edesc"></textarea> <div class="custom-control custom-radio m-2">
<input type="radio" class="custom-control-input cursor-pointer" name="pivot" id="pivotNo"
[checked]="templateFile.isPivot=='0'" (click)="templateFile.isPivot='0'">
<label class="custom-control-label cursor-pointer" for="pivotNo">ไม่ใช่</label>
</div>
<div class="custom-control custom-radio m-2">
<input type="radio" class="custom-control-input cursor-pointer" name="pivot" id="pivotYes"
[checked]="templateFile.isPivot=='1'" (click)="templateFile.isPivot='1'">
<label class="custom-control-label cursor-pointer" for="pivotYes">ใช่</label>
</div>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">โมดูล<span style="color: red">*</span></label> <label for="position" class="col-sm-4 col-form-label">แสดงรูปแบบ datagrid</label>
<div class="col-sm-8"> <div class="row col-sm-8">
<select class=" custom-select" [disabled]="bodyTemplate.status=='edit'" <div class="custom-control custom-radio m-2">
[(ngModel)]="bodyTemplate.data.module"> <input type="radio" class="custom-control-input cursor-pointer" name="datagt" id="datagtNo"
<option style="color: red" [class.d-none]="bodyTemplate.data.module==''" [value]="''"> [checked]="templateFile.isDataGrid=='0'" (click)="templateFile.isDataGrid='0'">
{{bodyTemplate.data.module!=''?'ยกเลิก':''}}</option> <label class="custom-control-label cursor-pointer" for="datagtNo">ไม่ใช่</label>
<option *ngFor="let item of module.data" [ngValue]="item.code">{{item.tdesc}}</option> </div>
<div class="custom-control custom-radio m-2">
<input type="radio" class="custom-control-input cursor-pointer" name="datagt" id="datagtYes"
[checked]="templateFile.isDataGrid=='1'" (click)="templateFile.isDataGrid='1'">
<label class="custom-control-label cursor-pointer" for="datagtYes">ใช่</label>
</div>
</div>
</div>
<div class="row">
<div class="col-12 d-flex justify-content-center align-content-center">
<button type="button" class="btn btn-info" (click)="openGridModal(gridModal)">Datagrid</button>
&nbsp;
<button type="button" class="btn btn-info" (click)="openPivotModal(pivotModal)">Pivot</button>
</div>
</div>
</div>
<div class="modal-footer ">
<button type="submit" class="btn btn-info"
[disabled]="(!templateFile.portalId&&!templateFile.fileData)||!templateFile.tdesc"
(click)="postTemplateFile()">บันทึก</button>
<button type="button" class="btn btn-danger" (click)="modal.dismiss()">ปิด</button>
</div>
</ng-template>
<ng-template #excel_portalModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">EXCEL_PORTAL</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row align-items-center mb-2">
<div class="col-12 col-lg-3 mb-2">
<select class="custom-select" [(ngModel)]="excelPortalSearch.groupId">
<option value="" *ngIf="excelPortalSearch.groupId==''" disabled selected hidden>เลือกกลุ่ม
</option>
<option style="color: red" [class.d-none]="excelPortalSearch.groupId==''" [value]="''">
{{excelPortalSearch.groupId!=''?'ยกเลิก':''}}</option>
<option *ngFor="let item of excelPortalGroup.data; let i=index" [ngValue]="item.groupId">
{{item.thName}}
</option>
</select>
</div>
<div class="col-12 col-lg-3 mb-2">
<select class="custom-select" [(ngModel)]="excelPortalSearch.tags">
<option value="" *ngIf="excelPortalSearch.tags==''" disabled selected hidden>เลือกtags
</option>
<option style="color: red" [class.d-none]="excelPortalSearch.tags==''" [value]="''">
{{excelPortalSearch.tags!=''?'ยกเลิก':''}}</option>
<option *ngFor="let item of excelPortalTags.data; let i=index" [ngValue]="item.value">{{item.value}}
</option>
</select> </select>
</div> </div>
<div class="col-12 col-lg-6 d-flex justify-content-end mb-2">
<div class="col-12 col-lg-6 p-0">
<input type="text" class="form-control" placeholder="ค้นหา" [(ngModel)]="excelPortalSearch.search">
</div>
</div>
</div>
<div class="table-responsive">
<table class="table mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">Ex.</th>
<th class="text-center" scope="col">VDO</th>
<th class="text-center" scope="col" style="min-width: 200px">Name</th>
<th class="text-center" scope="col" style="min-width: 200px">Description</th>
<th class="text-center" scope="col">Database Support</th>
<th class="text-center" scope="col">Pivot</th>
<th class="text-center" scope="col">DataGrid</th>
<th class="text-center" scope="col">Download</th>
<th class="text-center" scope="col">Last Download</th>
<th class="text-center" scope="col">Upload Date</th>
</tr>
</thead>
<tbody *ngIf="!excelPortalFilter().length">
<tr style="background-color:#ebf2f6">
<td colspan="10" class="text-center">ไม่พบข้อมูล</td>
</tr>
</tbody>
<tbody *ngIf="excelPortalFilter().length">
<ng-container
*ngFor="let item of excelPortalFilter() | slice: (pageModal-1) * pageSizeModal : (pageModal-1) * pageSizeModal + pageSizeModal ; let i = index">
<tr (mouseenter)="tableHover.set(item.excelId,!tableHover.get(item.excelId))"
(mouseleave)="tableHover.clear()"
[ngStyle]="{'background-color':tableHover.get(item.excelId)?'rgb(201 223 235)':'#ebf2f6'}">
<td><img *ngIf="item.getImg()" class="border p-1" [src]="item.getImg()">
</td>
<td>
<button *ngIf="item.link1" type="button" class="btn btn-info"
(click)="openVideoModal(videoModal,item.link1)"><i
class="fa fa-search text-white"></i></button>
</td>
<td class="cursor-pointer" (click)="modal.close(item)"
style="white-space: normal !important;word-break: break-word;">
{{item.thName}}
</td>
<td class="cursor-pointer" (click)="modal.close(item)"
style="white-space: normal !important;word-break: break-word;">
{{item.thDesc}}
</td>
<td class="cursor-pointer" (click)="modal.close(item)"
style="white-space: normal !important;word-break: break-word;">
{{item.dbSupport}}
</td>
<td class="cursor-pointer" (click)="modal.close(item)"
style="white-space: normal !important;word-break: break-word;">
{{item.isPivot}}
</td>
<td class="cursor-pointer" (click)="modal.close(item)"
style="white-space: normal !important;word-break: break-word;">
{{item.isDataGrid}}
</td>
<td class="cursor-pointer" (click)="modal.close(item)"
style="white-space: normal !important;word-break: break-word;">
{{item.dwTime}}
</td>
<td class="cursor-pointer" (click)="modal.close(item)"
style="white-space: normal !important;word-break: break-word;">
{{item.downloadDate}} {{item.downloadTime}}
</td>
<td class="cursor-pointer" (click)="modal.close(item)"
style="white-space: normal !important;word-break: break-word;">
{{item.uploadDate}} {{item.uploadTime}}
</td>
</tr>
</ng-container>
</tbody>
</table>
</div>
<div class="d-flex justify-content-end py-2">
<select class="custom-select m-r-5" style="width: auto" [(ngModel)]="pageSizeModal"
(ngModelChange)="pageModal">
<option [ngValue]="10">รายการต่อหน้า: 10</option>
<option [ngValue]="50">รายการต่อหน้า: 50</option>
<option [ngValue]="100">รายการต่อหน้า: 100</option>
</select>
<ngb-pagination [(page)]="pageModal" [pageSize]="pageSizeModal"
[collectionSize]="excelPortalFilter().length" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div> </div>
</div>
<div class="modal-footer ">
<button type="button" class="btn btn-danger" (click)="modal.dismiss()">ปิด</button>
</div>
</ng-template>
<ng-template #videoModal let-modal>
<div style="width: 100%; height: 70vh;">
<iframe class="w-100 h-100" [src]="videoLink | safeUrl" frameborder="0" allow="autoplay; encrypted-media"
allowfullscreen>
</iframe>
</div>
</ng-template>
<div class="modal-footer ">
<button type="submit" class="btn btn-info" [disabled]="!bodyTemplate.data.tname||!bodyTemplate.data.module" <ng-template #printModal let-modal>
(click)="modal.close()">บันทึก</button> <div class="modal-header">
<button type="button" class="btn btn-danger" (click)="modal.dismiss()">ปิด</button> <h5 class="modal-title" id="edittemplateLabel">Excel Report</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="d-flex col-12 justify-content-center" *ngIf="loading||loadingExcel">
<div *ngFor="let item of [1,2,3]" class="spinner-grow text-info mx-1" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
<ng-container *ngIf="!loading&&!loadingExcel">
<ng-container *ngFor="let item of variableSheet; let i=index">
<div class="col-12 row">
<div class="col-3 form-group justify-content-center font-weight-bold control-label col-form-label font-14"
style="text-align: end;">
{{item.label}}
</div>
<div class="col-3 d-flex form-group align-items-center">
<ng-container *ngIf="item.type=='text'">
<input type="text" class="form-control" [(ngModel)]="item.value">
</ng-container>
<ng-container *ngIf="item.type=='list'">
<select class="custom-select" [(ngModel)]="item.value">
<option *ngFor="let list of item.option" [value]="list.value">
{{list.text}}
</option>
</select>
</ng-container>
<ng-container *ngIf="item.type=='radio'">
<div class="row m-0">
<ng-container *ngFor="let radioItem of item.option">
<div class="col-auto custom-control custom-radio">
<input type="radio" class="custom-control-input"
[name]="'group-' + item.label" [id]="radioItem.text+radioItem.value"
[value]="radioItem.value" [(ngModel)]="item.value">
<label class="custom-control-label"
[for]="radioItem.text+radioItem.value">{{radioItem.text}}</label>
</div>
</ng-container>
</div>
</ng-container>
<ng-container *ngIf="item.type=='help'">
<div class="input-group">
<input type="text" readonly class="form-control bg-white cursor-pointer"
[value]="item.value.tdesc" (click)="openModalData(item,modalData)">
<div class="input-group-append">
<button class="btn mr-0 btn-info" type="button"
(click)="openModalData(item,modalData)">
<i class="fa fa-search"></i>
</button>
</div>
</div>
</ng-container>
<ng-container *ngIf="item.type=='calendar'">
<div class="input-group">
<input class="form-control bg-white cursor-pointer"
placeholder="{{ 'dd.mm.yyyy' }}" name="dp1" ngbDatepicker #d1="ngbDatepicker"
[(ngModel)]="select[item.key]" readonly (click)="d1.toggle()"
(ngModelChange)="formatNgbDate(item.key,select[item.key])" #c1="ngModel"
(change)="validateDate(c1)">
<div class="input-group-append">
<button class="btn btn-outline-info no-shadow" (click)="d1.toggle()"
type="button">
<i class="far fa-calendar-alt"></i>
</button>
</div>
</div>
</ng-container>
</div>
<div class="col">
<ng-container *ngIf="item.type=='help'">
<button type="button" class="btn btn-danger btn-sm btn-circle"
(click)="item.value={id:'',tdesc:'',edesc:''}"><i class="fa fa-times"></i>
</button>
</ng-container>
<ng-container *ngIf="item.type=='calendar'">
<button type="button" class="btn btn-danger btn-sm btn-circle"
(click)="select[item.key]=null ;formatNgbDate(item.key)"><i class="fa fa-times"></i>
</button>
</ng-container>
<ng-container *ngIf="item.type=='list'">
<button type="button" class="btn btn-danger btn-sm btn-circle"
(click)="item.value=''"><i class="fa fa-times"></i>
</button>
</ng-container>
</div>
</div>
</ng-container>
<!-- <div *ngIf="variableSheet.length&&!loadingExcel"
class="col-12 justify-content-center align-content-center d-flex" style="margin-bottom: 1rem;">
<button type="submit" class="btn btn-info waves-effect waves-light btn-w-100"
(click)="dowloadExcelReport()">
{{"Print" }}
</button>
</div>
<div *ngIf="loadingExcel" class="col-12 justify-content-center align-content-center d-flex"
style="margin-bottom: 1rem;">
<div *ngFor="let item of [1,2,3]" class="spinner-grow text-info mx-1" role="status">
<span class="sr-only">Loading...</span>
</div>
</div> -->
<div *ngIf="!variableSheet.length" class="col-12 justify-content-center align-content-center d-flex"
style="margin-bottom: 1rem;margin-top: 1rem;">
<div
class="col-3 justify-content-center text-center font-weight-bold control-label col-form-label font-14">
{{'No Data Found' }}
</div>
</div>
</ng-container>
</div> </div>
</div> </div>
<div class="modal-footer ">
<ng-container *ngIf="variableSheet.length">
<button type="submit" class="btn btn-info waves-effect waves-light btn-w-100" [disabled]="loadingExcel"
(click)="dowloadExcelReport()">
{{"Print" }}
</button>
</ng-container>
<button type="button" class="btn btn-danger" (click)="modal.dismiss()">ปิด</button>
</div>
</ng-template>
<ng-template #modalData let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel"> {{modalDetail.text.cardHead }}</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="d-flex mb-1">
<input type="text" placeholder="{{'systemcode.search' }} {{modalDetail.text.search[0]}}"
class=" form-control w-75 border-color-gray-full-focus" [(ngModel)]='searchModal'>
</div>
<div class="table-responsive">
<table class="table table-hover table-striped-myhr table-sm mb-0 no-wrap v-middle ">
<thead class="bg-info ">
<tr class="text-white font-weight-normal">
<th class="font-weight-normal text-center" scope="col"
*ngFor="let item of modalDetail.text.tableHead">
{{item}}
</th>
</tr>
</thead>
<tbody *ngIf="!valueDetailFilter().length">
<tr>
<td colspan="9" class="font-weight-normal text-center">
{{"No Data Found" }}
</td>
</tr>
</tbody>
<tbody *ngIf="valueDetailFilter().length">
<tr class="cursor-pointer"
*ngFor="let item of valueDetailFilter() | slice: (pageModal-1) * pageSizeModal : (pageModal-1) * pageSizeModal + pageSizeModal; let i=index"
(click)="selectData(item);modal.dismiss()"
(mouseenter)="tableHover.set(item.id,!tableHover.get(item.id))"
(mouseleave)="tableHover.clear()"
[ngStyle]="{'background-color':tableHover.get(item.id)?'rgb(201 223 235)':'#ffffff'}">
<td class="align-middle text-center">
{{item.id}}
</td>
<td class="align-middle text-center">
{{item.tdesc}}
</td>
<td class="align-middle text-center">
{{item.edesc}}
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-end p-2">
<select class="custom-select m-r-5 border-color-gray-full-focus" style="width: auto"
[(ngModel)]="pageSizeModal" (ngModelChange)="pageModal=1">
<option *ngFor="let item of [10,50,100]" [ngValue]="item">
{{"Items per page"}}: {{item}}
</option>
</select>
<ngb-pagination [collectionSize]="valueDetailFilter().length" [(page)]="pageModal"
[pageSize]="pageSizeModal" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>{{"Prev"}}</ng-template>
<ng-template ngbPaginationNext>{{"Next"}}</ng-template>
</ngb-pagination>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="modal.close()">
{{"Close"}}
</button>
</div>
</ng-template>
<ng-template #gridModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">GridData</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<ejs-grid [dataSource]="gridData" [allowPaging]="true" [pageSettings]="{ pageSize: 5 }">
<e-columns>
<e-column field="id" headerText="ID" width="100"></e-column>
<e-column field="name" headerText="Name" width="150"></e-column>
<e-column field="age" headerText="Age" width="100"></e-column>
</e-columns>
</ejs-grid>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="modal.close()">
{{"Close"}}
</button>
</div>
</ng-template>
<ng-template #pivotModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">Pivot</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<ejs-pivotview [dataSourceSettings]="pivotDataSource" height="300"></ejs-pivotview>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="modal.close()">
{{"Close"}}
</button>
</div>
</ng-template> </ng-template>
\ No newline at end of file
import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { NgbDate, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbDate, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import * as FileSaver from 'file-saver'; import * as FileSaver from 'file-saver';
import { IDataOptions } from '@syncfusion/ej2-angular-pivotview'; import { IDataOptions } from '@syncfusion/ej2-angular-pivotview';
import { ExcelReportService } from 'src/app/service/excel-report.service'; import { ExcelReportService } from 'src/app/service/excel-report.service';
import { MyTemplateModel, TemplateModel } from 'src/app/model/template.model'; import { MyTemplateFileModel, MyTemplateModel, TemplateFileModel, TemplateModel } from 'src/app/model/template.model';
import { AlertModalComponent } from '../alert-modal/alert-modal.component'; import { AlertModalComponent } from '../alert-modal/alert-modal.component';
import { MyModuleModel, ModuleModel } from 'src/app/model/module.model'; import { MyModuleModel, ModuleModel } from 'src/app/model/module.model';
import { ConfirmModalComponent } from '../confirm-modal/confirm-modal.component'; import { ConfirmModalComponent } from '../confirm-modal/confirm-modal.component';
import { ExcelPortalModel, ExcelPortalGroupModel, MyExcelPortalModel, ExcelPortalTagsModel, MyExcelPortalGroupModel, MyExcelPortalTagsModel } from 'src/app/model/excel-portal.model';
import { Subscription } from 'rxjs';
export interface ModalDetail { export interface ModalDetail {
text: { cardHead: string, search: string[], tableHead: string[] } text: { cardHead: string, search: string[], tableHead: string[] }
...@@ -19,9 +21,12 @@ export interface ModalDetail { ...@@ -19,9 +21,12 @@ export interface ModalDetail {
}) })
export class ExcelListComponent implements OnInit { export class ExcelListComponent implements OnInit {
template: { data: TemplateModel[], filter: TemplateModel[], loading: boolean } = { data: [], filter: [], loading: false } template: { data: TemplateModel[], filter: TemplateModel[], loading: boolean } = { data: [], filter: [], loading: false }
templateFile: TemplateFileModel = new MyTemplateFileModel()
module: { data: ModuleModel[], loading: boolean } = { data: [], loading: false } module: { data: ModuleModel[], loading: boolean } = { data: [], loading: false }
page = 1 page = 1
pageSize = 10 pageSize = 10
pageModal = 1
pageSizeModal = 10
searchBy = '' searchBy = ''
condition = '' condition = ''
searchValue = '' searchValue = ''
...@@ -47,6 +52,47 @@ export class ExcelListComponent implements OnInit { ...@@ -47,6 +52,47 @@ export class ExcelListComponent implements OnInit {
module: '' module: ''
} }
} }
excelPortalSearch: {
groupId: string,
tags: string,
search: string
} = {
groupId: '',
tags: '',
search: ''
}
excelPortal: { data: ExcelPortalModel[], loading: boolean } = { data: [], loading: false }
excelPortalGroup: { data: ExcelPortalGroupModel[], loading: boolean } = { data: [], loading: false }
excelPortalTags: { data: ExcelPortalTagsModel[], loading: boolean } = { data: [], loading: false }
videoLink = ""
templateFileType: 'portal' | 'upload' = 'portal'
templateFileName = ''
tableHover: Map<string, boolean> = new Map<string, boolean>()
buttonHover: Map<string, boolean> = new Map<string, boolean>()
addChildModalRef?: NgbModalRef
@ViewChild('fileInput') fileInput!: ElementRef<HTMLInputElement>;
downloadTemplateFileLoading: Map<string, boolean> = new Map<string, boolean>()
changeDate = new Date();
select: any = {}
excelReport?: any
variableSheet: any = []
loading = false
loadingExcel = false
valueDetail = []
modalDetail: ModalDetail = {
text: {
cardHead: '',
search: [],
tableHead: []
}
}
keySelect = ""
searchModal = ""
getTemplateFileSubscription?: Subscription
constructor(private excelReportService: ExcelReportService, constructor(private excelReportService: ExcelReportService,
private modalService: NgbModal, private modalService: NgbModal,
private cdr: ChangeDetectorRef) { private cdr: ChangeDetectorRef) {
...@@ -55,6 +101,59 @@ export class ExcelListComponent implements OnInit { ...@@ -55,6 +101,59 @@ export class ExcelListComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
this.getExcelList() this.getExcelList()
this.getModuleList() this.getModuleList()
this.getExcelPortalList()
this.getExcelPortalgGroupList()
this.getExcelPortalTagsList()
}
getExcelPortalList() {
this.excelPortal.loading = true
this.excelReportService.getExcelPortalList().subscribe(response => {
this.excelPortal.data = response.map(e => new MyExcelPortalModel(e))
this.excelPortal.loading = false
}, error => {
this.excelPortal.loading = false
})
}
excelPortalFilter() {
const search = this.excelPortalSearch.search?.trim();
let result = this.excelPortal.data.filter(x =>
x.group?.groupId?.includes(this.excelPortalSearch.groupId) ||
x.tags?.some(e => e.value?.includes(this.excelPortalSearch.tags))
);
if (search) {
result = result.filter(x =>
(x.thName).includes(search) ||
(x.thDesc).includes(search) ||
(x.dbSupport).includes(search) ||
String(x.isPivot ?? 0).includes(search) ||
String(x.isDataGrid ?? 0).includes(search) ||
((x.downloadDate + x.downloadTime)).includes(search) ||
((x.uploadDate + x.uploadTime)).includes(search)
);
}
return result;
}
getExcelPortalgGroupList() {
this.excelPortalGroup.loading = true
this.excelReportService.getExcelPortalgGroupList().subscribe(response => {
this.excelPortalGroup.data = response.map(e => new MyExcelPortalGroupModel(e))
this.excelPortalGroup.loading = false
}, error => {
this.excelPortalGroup.loading = false
})
}
getExcelPortalTagsList() {
this.excelPortalTags.loading = true
this.excelReportService.getExcelPortalTagsList().subscribe(response => {
this.excelPortalTags.data = response.map(e => new MyExcelPortalTagsModel(e))
this.excelPortalTags.loading = false
}, error => {
this.excelPortalTags.loading = false
})
} }
getExcelList() { getExcelList() {
this.template.loading = true this.template.loading = true
...@@ -123,7 +222,6 @@ export class ExcelListComponent implements OnInit { ...@@ -123,7 +222,6 @@ export class ExcelListComponent implements OnInit {
}) })
modalConfirmRef.componentInstance.message = 'คุณต้องการบันทึกข้อมูลหรือไม่' modalConfirmRef.componentInstance.message = 'คุณต้องการบันทึกข้อมูลหรือไม่'
modalConfirmRef.result.then(result => { modalConfirmRef.result.then(result => {
console.log(" 🐒 this.bodyTemplate:", this.bodyTemplate)
this.excelReportService.postTemplate(this.bodyTemplate.data).subscribe((response: any) => { this.excelReportService.postTemplate(this.bodyTemplate.data).subscribe((response: any) => {
this.openAlertModal(response.message) this.openAlertModal(response.message)
if (response.success) { if (response.success) {
...@@ -137,24 +235,82 @@ export class ExcelListComponent implements OnInit { ...@@ -137,24 +235,82 @@ export class ExcelListComponent implements OnInit {
} }
openAddChildModal(targetModal: NgbModal) { deleteTemplate(template: TemplateModel) {
const modalRef = this.modalService.open(targetModal, { const modalConfirmRef = this.modalService.open(ConfirmModalComponent, {
centered: true,
backdrop: 'static',
})
modalConfirmRef.componentInstance.message = 'คุณต้องการลบข้อมูลหรือไม่'
modalConfirmRef.result.then(result => {
this.excelReportService.deleteTemplate(template).subscribe(response => {
if (response.success) {
this.openAlertModal(response.message)
this.getExcelList()
} else {
this.openAlertModal(response.message)
}
}, error => {
this.openAlertModal(error.message)
})
}, reject => { })
}
openAddChildModal(targetModal: NgbModal, data: TemplateModel | TemplateFileModel, status: 'add' | 'edit') {
if (status == 'add') {
this.templateFile = new MyTemplateFileModel({ templateId: data.templateId, module: data.module })
this.templateFileType = 'portal'
this.templateFileName = ''
} else if (status == 'edit') {
this.templateFile = new MyTemplateFileModel(data)
this.templateFileType = this.templateFile.portalId ? 'portal' : 'upload'
this.templateFileName = this.templateFile.portalId ? '' : this.templateFile.fileName
}
this.addChildModalRef = this.modalService.open(targetModal, {
centered: true, centered: true,
backdrop: 'static', backdrop: 'static',
size: 'lg' size: 'lg'
}) })
}
openExcelPortalModal(targetModal: NgbModal) {
this.pageModal = 1
this.pageSizeModal = 10
const modalRef = this.modalService.open(targetModal, {
centered: true,
backdrop: 'static',
size: 'xl'
})
modalRef.result.then(result => { modalRef.result.then(result => {
const modalConfirmRef = this.modalService.open(ConfirmModalComponent, { this.templateFile.portalId = result.excelId
centered: true,
backdrop: 'static',
})
modalConfirmRef.componentInstance.message = 'คุณต้องการบันทึกข้อมูลหรือไม่'
modalConfirmRef.result.then(result => {
console.log(" 🐒 this.bodyTemplate:", this.bodyTemplate)
}, reject => { })
}, reject => { }) }, reject => { })
} }
openVideoModal(targetModal: NgbModal, videoLink: string) {
this.videoLink = this.convertToEmbedUrl(videoLink)
this.modalService.open(targetModal, {
centered: true,
windowClass: 'my-dialog-video-preview'
})
}
convertToEmbedUrl(youtubeUrl: string): string {
try {
const url = new URL(youtubeUrl);
if (url.hostname.includes('youtube.com') && url.searchParams.has('v')) {
const videoId = url.searchParams.get('v');
return `https://www.youtube.com/embed/${videoId}`;
}
if (url.hostname === 'youtu.be') {
const videoId = url.pathname.slice(1); // เอา path หลัง youtu.be/
return `https://www.youtube.com/embed/${videoId}`;
}
} catch (e) {
// ถ้า url ผิดรูปแบบ
console.warn('Invalid YouTube URL:', youtubeUrl);
}
// ถ้าไม่เข้าเงื่อนไขใดเลย ให้คืนลิงก์เดิม
return youtubeUrl;
}
templateListSearch() { templateListSearch() {
if (!this.searchBy || !this.condition || !this.searchValue) { if (!this.searchBy || !this.condition || !this.searchValue) {
...@@ -181,4 +337,267 @@ export class ExcelListComponent implements OnInit { ...@@ -181,4 +337,267 @@ export class ExcelListComponent implements OnInit {
return compareFn(value, this.searchValue); return compareFn(value, this.searchValue);
}).map(e => new MyTemplateModel(e)); }).map(e => new MyTemplateModel(e));
} }
onFileSelected(event: any) {
const file: File = event.target.files[0];
if (!file) {
alert('กรุณาเลือกไฟล์');
return;
}
const allowedExtensions = ['xls', 'xlsx'];
const fileExtension = file.name.split('.').pop()?.toLowerCase();
if (!allowedExtensions.includes(fileExtension || '')) {
alert('รองรับเฉพาะไฟล์ Excel (.xls, .xlsx) เท่านั้น');
return;
}
const reader = new FileReader();
reader.onload = () => {
const base64String = (reader.result as string).split(',')[1]; // เอาเฉพาะส่วน base64
// ✅ สร้าง payload
const payload = {
filename: file.name,
filetype: file.type,
fileExtension: fileExtension,
data: base64String
};
this.templateFileName = payload.filename
this.templateFile.fileData = payload.data
this.templateFile.fileType = payload.fileExtension || ''
this.fileInput.nativeElement.value = '';
};
reader.readAsDataURL(file); // อ่านแบบ Base64
}
postTemplateFile() {
const modalConfirmRef = this.modalService.open(ConfirmModalComponent, {
centered: true,
backdrop: 'static',
})
modalConfirmRef.componentInstance.message = 'คุณต้องการบันทึกข้อมูลหรือไม่'
modalConfirmRef.result.then(result => {
this.addChildModalRef?.close()
this.templateFile.createDate = new Date().toISOString();
this.excelReportService.postTemplateFile(this.templateFile).subscribe(response => {
if (response.success) {
this.openAlertModal(response.message)
this.getExcelList()
} else {
this.openAlertModal(response.message)
}
}, error => {
this.openAlertModal(error.message)
})
}, reject => { })
}
menuActiveTemplateFile(templateFile: TemplateFileModel) {
const modalConfirmRef = this.modalService.open(ConfirmModalComponent, {
centered: true,
backdrop: 'static',
})
modalConfirmRef.componentInstance.message = 'คุณต้องการ' + (templateFile.menuActive == '1' ? 'ปิด' : 'เปิด') + 'การใช้งานหรือไม่'
modalConfirmRef.result.then(result => {
templateFile.menuActive = templateFile.menuActive == '1' ? '0' : '1'
this.excelReportService.postTemplateFile(templateFile).subscribe(response => {
if (response.success) {
this.openAlertModal(response.message)
this.getExcelList()
} else {
this.openAlertModal(response.message)
}
}, error => {
this.openAlertModal(error.message)
})
}, reject => { })
}
formatISOToLocal(isoString: string) {
const date = new Date(isoString);
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0'); // เดือนเริ่มที่ 0
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return { date: `${day}-${month}-${year}`, time: `${hours}:${minutes}` };
}
deleteTemplateFile(templateFile: TemplateFileModel) {
const modalConfirmRef = this.modalService.open(ConfirmModalComponent, {
centered: true,
backdrop: 'static',
})
modalConfirmRef.componentInstance.message = 'คุณต้องการลบข้อมูลหรือไม่'
modalConfirmRef.result.then(result => {
this.excelReportService.deleteTemplateFile(templateFile).subscribe(response => {
if (response.success) {
this.openAlertModal(response.message)
this.getExcelList()
} else {
this.openAlertModal(response.message)
}
}, error => {
this.openAlertModal(error.message)
})
}, reject => { })
}
downloadTemplateFile(templateFile: TemplateFileModel) {
this.downloadTemplateFileLoading.set(templateFile.fileName, true)
this.excelReportService.downloadTemplateFile(templateFile.fileName).subscribe((response: any) => {
const blob = new Blob([response], { type: 'application/octet-stream' });
FileSaver.saveAs(blob, templateFile.fileName);
this.downloadTemplateFileLoading.clear()
}, error => {
this.downloadTemplateFileLoading.clear()
this.openAlertModal(error.message)
})
}
openPrintModal(targetModal: NgbModal, templateFile: TemplateFileModel) {
this.getTemplateFile(templateFile)
this.modalService.open(targetModal, {
centered: true,
size: 'lg'
})
}
getTemplateFile(templateFile: TemplateFileModel) {
this.loading = true
this.excelReport = undefined
this.variableSheet = []
this.valueDetail = []
this.getTemplateFileSubscription = this.excelReportService.getTemplateFile(templateFile.templateId, templateFile.fileName).subscribe(response => {
this.excelReport = response
if (this.excelReport.param) {
Object.entries(this.excelReport.param.variableSheet).forEach(([key, value]) => {
const data = value as any
if (data.type == 'text') {
this.variableSheet.push({
...data, value: data.valueDefault || '', key: key
})
} else if (data.type == 'list') {
this.variableSheet.push({
...data, value: data.valueDefault || '', key: key, option: data.option.split('customize|')[1].split(',').map((x: any) => {
const [value, text] = x.split('#')
return { value: value || '', text: text || '' }
})
})
} else if (data.type == 'radio') {
this.variableSheet.push({
...data, value: data.valueDefault || '', key: key, option: data.option.split('customize|')[1].split(',').map((x: any) => {
const [value, text] = x.split('#')
return { value: value || '', text: text || '' }
})
})
} else if (data.type == 'help') {
this.variableSheet.push({ ...data, value: data.valueDefault ? { id: data.valueDefault, tdesc: data.valueDefault, edesc: data.valueDefault } : { id: "", tdesc: "", edesc: "" }, key: key })
} else if (data.type == 'calendar') {
this.variableSheet.push({ ...data, value: data.valueDefault || '', key: key })
const [d, m, y] = data.valueDefault ? data.valueDefault.split('-').map(Number) : [null, null, null]
this.select[key] = y ? new NgbDate(y, m, d) : null
}
})
}
this.loading = false
this.cdr.detectChanges()
}, (err) => {
this.loading = false
})
}
openModalData(data: any, modal: any) {
this.searchModal = ''
this.page = 1
this.pageSize = 10
this.valueDetail = data.valueDetail.map((x: any) => ({ id: x.id || '', tdesc: x.tdesc || '', edesc: x.edesc || '' }))
this.keySelect = data.key
this.modalDetail = {
text: {
cardHead: "Table " + data.table,
search: ["Table " + data.table],
tableHead: ['ID', 'detailTH', 'detailENG']
}
}
this.modalService.open(modal, { centered: true, size: 'lg' })
}
valueDetailFilter() {
return this.valueDetail.filter((item: any) =>
item.id.toLowerCase().includes(this.searchModal.toLowerCase()) ||
item.tdesc.toLowerCase().includes(this.searchModal.toLowerCase()) ||
item.edesc.toLowerCase().includes(this.searchModal.toLowerCase())
)
}
selectData(data: any) {
const item = this.variableSheet.find((i: any) => i.key === this.keySelect);
if (item) item.value = data;
}
formatNgbDate(key: string, date?: NgbDate) {
if (date) {
const day = String(date.day).padStart(2, '0');
const month = String(date.month).padStart(2, '0');
const year = date.year;
const item = this.variableSheet.find((i: any) => i.key === key);
if (item) item.value = `${day}-${month}-${year}`
} else {
const item = this.variableSheet.find((i: any) => i.key === key);
if (item) item.value = ''
}
}
dowloadExcelReport() {
this.loadingExcel = true
const fileName = this.excelReport.param.excelFile
const param = this.excelReport.param.variableName
const data = this.variableSheet.map((item: any) => {
if (item.type == 'help') {
return "__" + item.key + "=" + item.value.id
} else if (item.type == 'calendar' || item.type == 'list' || item.type == 'radio' || item.type == 'text') {
return "__" + item.key + "=" + item.value
}
return ""
}).join('|')
const body = {
fileName: fileName,
paramObj: data
}
this.excelReportService.printExcelReport(body).subscribe((res: any) => {
const blob = new Blob([res], { type: 'application/octet-stream' });
FileSaver.saveAs(blob, fileName);
this.loadingExcel = false
this.cdr.detectChanges()
}, (err) => {
this.loadingExcel = false
this.openAlertModal(err.message)
this.cdr.detectChanges()
})
}
openGridModal(targetModal: NgbModal) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static',
size: 'lg'
})
}
openPivotModal(targetModal: NgbModal) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static',
size: 'lg'
})
}
ngOnDestroy(): void {
this.getTemplateFileSubscription?.unsubscribe()
}
} }
\ No newline at end of file
<div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการเอกสาร</h4>
<div class="row align-items-center mb-2">
<div class="col-4 col-lg-3 text-right">
Search By
</div>
<div class="col-8 col-lg-3">
<select class="custom-select" [(ngModel)]="searchBy">
<option style="color: red" [class.d-none]="searchBy==''" [value]="''">
{{searchBy!=''?'ยกเลิก':''}}</option>
<option [value]="'templateId'">รหัสกลุ่มแม่แบบ</option>
<option [value]="'module'">โมดูล</option>
<option [value]="'tname'">ชื่อกลุ่มรายงาน (ภาษาไทย)</option>
<option [value]="'ename'">ชื่อกลุ่มรายงาน (ภาษาอังกฤษ)</option>
<option [value]="'tdesc'">รายละเอียด (ภาษาไทย)</option>
<option [value]="'edesc'">รายละเอียด (ภาษาอังกฤษ)</option>
</select>
</div>
</div>
<div class="row align-items-center mb-2">
<div class="col-4 col-lg-3 text-right">
Condition
</div>
<div class="col-8 col-lg-3">
<select class="custom-select" [(ngModel)]="condition">
<option style="color: red" [class.d-none]="condition==''" [value]="''">
{{condition!=''?'ยกเลิก':''}}</option>
<option value="includes">คำในประโยค</option>
<option value="lt">น้อยกว่า</option>
<option value="gt">มากกว่า</option>
<option value="eq">เท่ากับ</option>
<option value="lte">น้อยกว่าเท่ากับ</option>
<option value="gte">มากกว่าเท่ากับ</option>
<option value="neq">ไม่เท่ากับ</option>
</select>
</div>
</div>
<div class="row align-items-center mb-2">
<div class="col-4 col-lg-3 text-right">
Key Value
</div>
<div class="col-8 col-lg-3">
<input type="text" class="form-control" [(ngModel)]="searchValue">
</div>
</div>
<div class="row justify-content-center align-items-center mb-2">
<button type="button" class="btn btn-info"
(click)="openTemplate.clear();templateListSearch()">ค้นหา</button>
</div>
<div class="table-responsive">
<table class="table mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">ชื่อกลุ่มรายงาน(Thai)</th>
<th class="text-center" scope="col">ชื่อกลุ่มรายงาน (ภาษาอังกฤษ)</th>
<th class="text-center" scope="col" style="min-width: 200px">สร้างโดย</th>
<th class="text-center" scope="col" style="min-width:120px">วันที่สร้าง</th>
<th class="text-center" scope="col">สร้างเมื่อ</th>
<th class="text-center" scope="col" style="min-width: 120px;">โมดูล</th>
<th class="text-center" scope="col">Add file</th>
</tr>
</thead>
<tbody *ngIf="!template.filter.length">
<tr style="background-color:#ebf2f6">
<td colspan="7" class="text-center">ไม่พบข้อมูล</td>
</tr>
</tbody>
<tbody *ngIf="template.filter.length">
<ng-container
*ngFor="let items of template.filter | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<tr (mouseenter)="tableHover.set(items.templateId,!tableHover.get(items.templateId))"
(mouseleave)="tableHover.clear()"
[ngStyle]="{'background-color':tableHover.get(items.templateId)?'rgb(201 223 235)':'#ebf2f6'}">
<td colspan="6" class="font-16 font-medium">
{{items.tname}}-{{items.ename}}
</td>
<td class="text-center">
<ng-container *ngIf="items.templateFile.length">
<ng-container *ngIf="!openTemplate.get(items.templateId)">
<button type="button" title="เปิด" class="btn"
style="border:3px solid #2962ff;border-radius: 10%;" (click)="
openTemplate.set(items.templateId,true)"
(mouseenter)="buttonHover.set(items.templateId+'open',!buttonHover.get(items.templateId))"
(mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(items.templateId+'open')?'#dfdfdf':'#ffffff'}">
<i class="fa fa-arrow-right text-info"></i>
</button>
</ng-container>
<ng-container *ngIf="openTemplate.get(items.templateId)">
<button type="button" title="ปิด" class="btn"
style="border:3px solid #2962ff;border-radius: 10%;" (click)="
openTemplate.set(items.templateId,false)"
(mouseenter)="buttonHover.set(items.templateId+'close',!buttonHover.get(items.templateId))"
(mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(items.templateId+'close')?'#dfdfdf':'#ffffff'}">
<i class="fa fa-arrow-down text-info"></i>
</button>
</ng-container>
</ng-container>
</td>
</tr>
<ng-container *ngIf="openTemplate.get(items.templateId)">
<ng-container
*ngFor="let item of items.templateFile | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<tr (mouseenter)="tableHover.set(item.fileName,!tableHover.get(item.fileName))"
(mouseleave)="tableHover.clear()"
[ngStyle]="{'background-color':tableHover.get(item.fileName)?'rgb(201 223 235)':'#ffffff'}">
<td style="white-space: normal !important;word-break: break-word;">
{{item.tdesc}}
</td>
<td style="white-space: normal !important;word-break: break-word;">
{{item.edesc}}</td>
<td class="text-center"
style="white-space: normal !important;word-break: break-word;">
<!-- {{item.createBy.thFullName}}</td> -->
<td class="text-center"
style="white-space: normal !important;word-break: break-word;">
{{formatISOToLocal(item.createDate).date}}</td>
<td class="text-center"
style="white-space: normal !important;word-break: break-word;">
{{formatISOToLocal(item.createDate).time}}</td>
<td class="text-center"
style="white-space: normal !important;word-break: break-word;">
{{item.module}}</td>
<td class="text-center" class="text-center">
<i *ngIf="item.menuActive=='0'"
class="fa fa-times text-danger cursor-pointer"
style="text-decoration: underline;"
(click)="menuActiveTemplateFile(item)"></i>
<i *ngIf="item.menuActive=='1'"
class="fa fa-check text-success cursor-pointer"
style="text-decoration: underline;"
(click)="menuActiveTemplateFile(item)"></i>
&nbsp;
<button type="button" title="Print" class="btn"
style="border:3px solid #2962ff;border-radius: 10%"
(mouseenter)="buttonHover.set(item.fileName+'print',!buttonHover.get(item.fileName))"
(mouseleave)="buttonHover.clear()"
[ngStyle]="{'background-color':buttonHover.get(item.fileName+'print')?'#dfdfdf':'#ffffff'}"
(click)="openPrintModal(printModal,item);">
<i class="fa fa-print text-info"></i>
</button>
</td>
</tr>
</ng-container>
</ng-container>
</ng-container>
</tbody>
</table>
</div>
<div class="d-flex justify-content-end py-2">
<select class="custom-select m-r-5" style="width: auto" [(ngModel)]="pageSize" (ngModelChange)="page">
<option [ngValue]="10">รายการต่อหน้า: 10</option>
<option [ngValue]="50">รายการต่อหน้า: 50</option>
<option [ngValue]="100">รายการต่อหน้า: 100</option>
</select>
<ngb-pagination [(page)]="page" [pageSize]="pageSize" [collectionSize]="template.filter.length"
[maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
<div class="row justify-content-end align-items-center">
<i class="fa fa-times text-danger"></i>&nbsp;=&nbsp;used on menu&nbsp;&nbsp;&nbsp;
<i class="fa fa-check text-success"></i>&nbsp;=&nbsp;unused on menu&nbsp;&nbsp;&nbsp;
<i class="fa fa-files-o text-info"></i>&nbsp;=&nbsp;copy template&nbsp;&nbsp;&nbsp;
<i class="fa fa-print text-info"></i>&nbsp;=&nbsp;print report
</div>
</div>
</div>
</div>
<ng-template #printModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">Excel Report</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="d-flex col-12 justify-content-center" *ngIf="loading||loadingExcel">
<div *ngFor="let item of [1,2,3]" class="spinner-grow text-info mx-1" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
<ng-container *ngIf="!loading&&!loadingExcel">
<ng-container *ngFor="let item of variableSheet; let i=index">
<div class="col-12 row">
<div class="col-3 form-group justify-content-center font-weight-bold control-label col-form-label font-14"
style="text-align: end;">
{{item.label}}
</div>
<div class="col-3 d-flex form-group align-items-center">
<ng-container *ngIf="item.type=='text'">
<input type="text" class="form-control" [(ngModel)]="item.value">
</ng-container>
<ng-container *ngIf="item.type=='list'">
<select class="custom-select" [(ngModel)]="item.value">
<option *ngFor="let list of item.option" [value]="list.value">
{{list.text}}
</option>
</select>
</ng-container>
<ng-container *ngIf="item.type=='radio'">
<div class="row m-0">
<ng-container *ngFor="let radioItem of item.option">
<div class="col-auto custom-control custom-radio">
<input type="radio" class="custom-control-input"
[name]="'group-' + item.label" [id]="radioItem.text+radioItem.value"
[value]="radioItem.value" [(ngModel)]="item.value">
<label class="custom-control-label"
[for]="radioItem.text+radioItem.value">{{radioItem.text}}</label>
</div>
</ng-container>
</div>
</ng-container>
<ng-container *ngIf="item.type=='help'">
<div class="input-group">
<input type="text" readonly class="form-control bg-white cursor-pointer"
[value]="item.value.tdesc" (click)="openModalData(item,modalData)">
<div class="input-group-append">
<button class="btn mr-0 btn-info" type="button"
(click)="openModalData(item,modalData)">
<i class="fa fa-search"></i>
</button>
</div>
</div>
</ng-container>
<ng-container *ngIf="item.type=='calendar'">
<div class="input-group">
<input class="form-control bg-white cursor-pointer"
placeholder="{{ 'dd.mm.yyyy' }}" name="dp1" ngbDatepicker #d1="ngbDatepicker"
[(ngModel)]="select[item.key]" readonly (click)="d1.toggle()"
(ngModelChange)="formatNgbDate(item.key,select[item.key])" #c1="ngModel"
(change)="validateDate(c1)">
<div class="input-group-append">
<button class="btn btn-outline-info no-shadow" (click)="d1.toggle()"
type="button">
<i class="far fa-calendar-alt"></i>
</button>
</div>
</div>
</ng-container>
</div>
<div class="col">
<ng-container *ngIf="item.type=='help'">
<button type="button" class="btn btn-danger btn-sm btn-circle"
(click)="item.value={id:'',tdesc:'',edesc:''}"><i class="fa fa-times"></i>
</button>
</ng-container>
<ng-container *ngIf="item.type=='calendar'">
<button type="button" class="btn btn-danger btn-sm btn-circle"
(click)="select[item.key]=null ;formatNgbDate(item.key)"><i class="fa fa-times"></i>
</button>
</ng-container>
<ng-container *ngIf="item.type=='list'">
<button type="button" class="btn btn-danger btn-sm btn-circle"
(click)="item.value=''"><i class="fa fa-times"></i>
</button>
</ng-container>
</div>
</div>
</ng-container>
<!-- <div *ngIf="variableSheet.length&&!loadingExcel"
class="col-12 justify-content-center align-content-center d-flex" style="margin-bottom: 1rem;">
<button type="submit" class="btn btn-info waves-effect waves-light btn-w-100"
(click)="dowloadExcelReport()">
{{"Print" }}
</button>
</div>
<div *ngIf="loadingExcel" class="col-12 justify-content-center align-content-center d-flex"
style="margin-bottom: 1rem;">
<div *ngFor="let item of [1,2,3]" class="spinner-grow text-info mx-1" role="status">
<span class="sr-only">Loading...</span>
</div>
</div> -->
<div *ngIf="!variableSheet.length" class="col-12 justify-content-center align-content-center d-flex"
style="margin-bottom: 1rem;margin-top: 1rem;">
<div
class="col-3 justify-content-center text-center font-weight-bold control-label col-form-label font-14">
{{'No Data Found' }}
</div>
</div>
<div *ngIf="variableSheet.length" class="col-12 d-flex justify-content-center align-content-center">
<button type="button" class="btn btn-info" (click)="openGridModal(gridModal)">Datagrid</button>
&nbsp;
<button type="button" class="btn btn-info" (click)="openPivotModal(pivotModal)">Pivot</button>
</div>
</ng-container>
</div>
</div>
<div class="modal-footer ">
<ng-container *ngIf="variableSheet.length">
<button type="submit" class="btn btn-info waves-effect waves-light btn-w-100" [disabled]="loadingExcel"
(click)="dowloadExcelReport()">
{{"Print" }}
</button>
</ng-container>
<button type="button" class="btn btn-danger" (click)="modal.dismiss()">ปิด</button>
</div>
</ng-template>
<ng-template #modalData let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel"> {{modalDetail.text.cardHead }}</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="d-flex mb-1">
<input type="text" placeholder="{{'systemcode.search' }} {{modalDetail.text.search[0]}}"
class=" form-control w-75 border-color-gray-full-focus" [(ngModel)]='searchModal'>
</div>
<div class="table-responsive">
<table class="table table-hover table-striped-myhr table-sm mb-0 no-wrap v-middle ">
<thead class="bg-info ">
<tr class="text-white font-weight-normal">
<th class="font-weight-normal text-center" scope="col"
*ngFor="let item of modalDetail.text.tableHead">
{{item}}
</th>
</tr>
</thead>
<tbody *ngIf="!valueDetailFilter().length">
<tr>
<td colspan="9" class="font-weight-normal text-center">
{{"No Data Found" }}
</td>
</tr>
</tbody>
<tbody *ngIf="valueDetailFilter().length">
<tr class="cursor-pointer"
*ngFor="let item of valueDetailFilter() | slice: (pageModal-1) * pageSizeModal : (pageModal-1) * pageSizeModal + pageSizeModal; let i=index"
(click)="selectData(item);modal.dismiss()"
(mouseenter)="tableHover.set(item.id,!tableHover.get(item.id))"
(mouseleave)="tableHover.clear()"
[ngStyle]="{'background-color':tableHover.get(item.id)?'rgb(201 223 235)':'#ffffff'}">
<td class="align-middle text-center">
{{item.id}}
</td>
<td class="align-middle text-center">
{{item.tdesc}}
</td>
<td class="align-middle text-center">
{{item.edesc}}
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-end p-2">
<select class="custom-select m-r-5 border-color-gray-full-focus" style="width: auto"
[(ngModel)]="pageSizeModal" (ngModelChange)="pageModal=1">
<option *ngFor="let item of [10,50,100]" [ngValue]="item">
{{"Items per page"}}: {{item}}
</option>
</select>
<ngb-pagination [collectionSize]="valueDetailFilter().length" [(page)]="pageModal"
[pageSize]="pageSizeModal" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>{{"Prev"}}</ng-template>
<ng-template ngbPaginationNext>{{"Next"}}</ng-template>
</ngb-pagination>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="modal.close()">
{{"Close"}}
</button>
</div>
</ng-template>
<ng-template #gridModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">GridData</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<ejs-grid [dataSource]="gridData" [allowPaging]="true" [pageSettings]="{ pageSize: 5 }">
<e-columns>
<e-column field="id" headerText="ID" width="100"></e-column>
<e-column field="name" headerText="Name" width="150"></e-column>
<e-column field="age" headerText="Age" width="100"></e-column>
</e-columns>
</ejs-grid>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="modal.close()">
{{"Close"}}
</button>
</div>
</ng-template>
<ng-template #pivotModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">Pivot</h5>
<button type="button" class="close" (click)="modal.dismiss()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<ejs-pivotview [dataSourceSettings]="pivotDataSource" height="300"></ejs-pivotview>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="modal.close()">
{{"Close"}}
</button>
</div>
</ng-template>
\ No newline at end of file
...@@ -4,6 +4,11 @@ import { NgbDate, NgbModal } from '@ng-bootstrap/ng-bootstrap'; ...@@ -4,6 +4,11 @@ import { NgbDate, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ExcelReportService } from 'src/app/service/excel-report.service'; import { ExcelReportService } from 'src/app/service/excel-report.service';
import * as FileSaver from 'file-saver'; import * as FileSaver from 'file-saver';
import { IDataOptions } from '@syncfusion/ej2-angular-pivotview'; import { IDataOptions } from '@syncfusion/ej2-angular-pivotview';
import { ModuleModel } from 'src/app/model/module.model';
import { TemplateModel, TemplateFileModel, MyTemplateFileModel, MyTemplateModel } from 'src/app/model/template.model';
import { ConfirmModalComponent } from '../confirm-modal/confirm-modal.component';
import { AlertModalComponent } from '../alert-modal/alert-modal.component';
import { Subscription } from 'rxjs';
export interface ModalDetail { export interface ModalDetail {
text: { cardHead: string, search: string[], tableHead: string[] } text: { cardHead: string, search: string[], tableHead: string[] }
...@@ -14,7 +19,294 @@ export interface ModalDetail { ...@@ -14,7 +19,294 @@ export interface ModalDetail {
styleUrls: ['./excel-report-toggle.component.scss'] styleUrls: ['./excel-report-toggle.component.scss']
}) })
export class ExcelReportToggleComponent implements OnInit { export class ExcelReportToggleComponent implements OnInit {
ngOnInit(): void { template: { data: TemplateModel[], filter: TemplateModel[], loading: boolean } = { data: [], filter: [], loading: false }
templateFile: TemplateFileModel = new MyTemplateFileModel()
module: { data: ModuleModel[], loading: boolean } = { data: [], loading: false }
page = 1
pageSize = 10
pageModal = 1
pageSizeModal = 10
searchBy = ''
condition = ''
searchValue = ''
openTemplate: Map<string, boolean> = new Map<string, boolean>()
bodyTemplate: {
status: 'add' | 'edit',
data: {
templateId: string,
tname: string,
ename: string,
tdesc: string,
edesc: string,
module: string
}
} = {
status: 'add',
data: {
templateId: '',
tname: '',
ename: '',
tdesc: '',
edesc: '',
module: ''
}
}
excelPortalSearch: {
groupId: string,
tags: string,
search: string
} = {
groupId: '',
tags: '',
search: ''
}
tableHover: Map<string, boolean> = new Map<string, boolean>()
buttonHover: Map<string, boolean> = new Map<string, boolean>()
changeDate = new Date();
select: any = {}
excelReport?: any
variableSheet: any = []
loading = false
loadingExcel = false
valueDetail = []
modalDetail: ModalDetail = {
text: {
cardHead: '',
search: [],
tableHead: []
}
}
keySelect = ""
searchModal = ""
getTemplateFileSubscription?: Subscription
constructor(private excelReportService: ExcelReportService,
private modalService: NgbModal,
private cdr: ChangeDetectorRef) {
}
ngOnInit(): void {
this.getExcelList()
}
getExcelList() {
this.template.loading = true
this.excelReportService.getExcelList().subscribe(response => {
this.template.data = response.map(e => new MyTemplateModel(e))
this.template.filter = response.map(e => new MyTemplateModel(e))
this.template.loading = false
}, error => {
this.template.loading = false
})
}
templateListSearch() {
if (!this.searchBy || !this.condition || !this.searchValue) {
this.template.filter = this.template.data.map(e => new MyTemplateModel(e))
}
const conditionMap: { [key: string]: (a: any, b: any) => boolean } = {
includes: (a, b) => (a || '').toString().toLowerCase().includes((b || '').toString().toLowerCase()),
lt: (a, b) => parseFloat(a) < parseFloat(b),
gt: (a, b) => parseFloat(a) > parseFloat(b),
eq: (a, b) => a == b,
lte: (a, b) => parseFloat(a) <= parseFloat(b),
gte: (a, b) => parseFloat(a) >= parseFloat(b),
neq: (a, b) => a != b,
};
const compareFn = conditionMap[this.condition];
if (!compareFn) {
this.template.filter = this.template.data.map(e => new MyTemplateModel(e))
} }
this.template.filter = this.template.data.filter(item => {
const value = (item as any)[this.searchBy];
return compareFn(value, this.searchValue);
}).map(e => new MyTemplateModel(e));
}
menuActiveTemplateFile(templateFile: TemplateFileModel) {
const modalConfirmRef = this.modalService.open(ConfirmModalComponent, {
centered: true,
backdrop: 'static',
})
modalConfirmRef.componentInstance.message = 'คุณต้องการ' + (templateFile.menuActive == '1' ? 'ปิด' : 'เปิด') + 'การใช้งานหรือไม่'
modalConfirmRef.result.then(result => {
templateFile.menuActive = templateFile.menuActive == '1' ? '0' : '1'
this.excelReportService.postTemplateFile(templateFile).subscribe(response => {
if (response.success) {
this.openAlertModal(response.message)
this.getExcelList()
} else {
this.openAlertModal(response.message)
}
}, error => {
this.openAlertModal(error.message)
})
}, reject => { })
}
formatISOToLocal(isoString: string) {
const date = new Date(isoString);
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0'); // เดือนเริ่มที่ 0
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return { date: `${day}-${month}-${year}`, time: `${hours}:${minutes}` };
}
openAlertModal(message?: string) {
const modalRef = this.modalService.open(AlertModalComponent, {
centered: true,
backdrop: 'static'
})
modalRef.componentInstance.message = message ? message : ""
modalRef.result.then(result => {
}, reason => {
})
}
openPrintModal(targetModal: NgbModal, templateFile: TemplateFileModel) {
this.getTemplateFile(templateFile)
this.modalService.open(targetModal, {
centered: true,
size: 'lg'
})
}
getTemplateFile(templateFile: TemplateFileModel) {
this.loading = true
this.excelReport = undefined
this.variableSheet = []
this.valueDetail = []
this.getTemplateFileSubscription = this.excelReportService.getTemplateFile(templateFile.templateId, templateFile.fileName).subscribe(response => {
this.excelReport = response
if (this.excelReport.param) {
Object.entries(this.excelReport.param.variableSheet).forEach(([key, value]) => {
const data = value as any
if (data.type == 'text') {
this.variableSheet.push({
...data, value: data.valueDefault || '', key: key
})
} else if (data.type == 'list') {
this.variableSheet.push({
...data, value: data.valueDefault || '', key: key, option: data.option.split('customize|')[1].split(',').map((x: any) => {
const [value, text] = x.split('#')
return { value: value || '', text: text || '' }
})
})
} else if (data.type == 'radio') {
this.variableSheet.push({
...data, value: data.valueDefault || '', key: key, option: data.option.split('customize|')[1].split(',').map((x: any) => {
const [value, text] = x.split('#')
return { value: value || '', text: text || '' }
})
})
} else if (data.type == 'help') {
this.variableSheet.push({ ...data, value: data.valueDefault ? { id: data.valueDefault, tdesc: data.valueDefault, edesc: data.valueDefault } : { id: "", tdesc: "", edesc: "" }, key: key })
} else if (data.type == 'calendar') {
this.variableSheet.push({ ...data, value: data.valueDefault || '', key: key })
const [d, m, y] = data.valueDefault ? data.valueDefault.split('-').map(Number) : [null, null, null]
this.select[key] = y ? new NgbDate(y, m, d) : null
}
})
}
this.loading = false
this.cdr.detectChanges()
}, (err) => {
this.loading = false
})
}
openModalData(data: any, modal: any) {
this.searchModal = ''
this.page = 1
this.pageSize = 10
this.valueDetail = data.valueDetail.map((x: any) => ({ id: x.id || '', tdesc: x.tdesc || '', edesc: x.edesc || '' }))
this.keySelect = data.key
this.modalDetail = {
text: {
cardHead: "Table " + data.table,
search: ["Table " + data.table],
tableHead: ['ID', 'detailTH', 'detailENG']
}
}
this.modalService.open(modal, { centered: true, size: 'lg' })
}
valueDetailFilter() {
return this.valueDetail.filter((item: any) =>
item.id.toLowerCase().includes(this.searchModal.toLowerCase()) ||
item.tdesc.toLowerCase().includes(this.searchModal.toLowerCase()) ||
item.edesc.toLowerCase().includes(this.searchModal.toLowerCase())
)
}
selectData(data: any) {
const item = this.variableSheet.find((i: any) => i.key === this.keySelect);
if (item) item.value = data;
}
formatNgbDate(key: string, date?: NgbDate) {
if (date) {
const day = String(date.day).padStart(2, '0');
const month = String(date.month).padStart(2, '0');
const year = date.year;
const item = this.variableSheet.find((i: any) => i.key === key);
if (item) item.value = `${day}-${month}-${year}`
} else {
const item = this.variableSheet.find((i: any) => i.key === key);
if (item) item.value = ''
}
}
dowloadExcelReport() {
this.loadingExcel = true
const fileName = this.excelReport.param.excelFile
const param = this.excelReport.param.variableName
const data = this.variableSheet.map((item: any) => {
if (item.type == 'help') {
return "__" + item.key + "=" + item.value.id
} else if (item.type == 'calendar' || item.type == 'list' || item.type == 'radio' || item.type == 'text') {
return "__" + item.key + "=" + item.value
}
return ""
}).join('|')
const body = {
fileName: fileName,
paramObj: data
}
this.excelReportService.printExcelReport(body).subscribe((res: any) => {
const blob = new Blob([res], { type: 'application/octet-stream' });
FileSaver.saveAs(blob, fileName);
this.loadingExcel = false
this.cdr.detectChanges()
}, (err) => {
this.loadingExcel = false
this.openAlertModal(err.message)
this.cdr.detectChanges()
})
}
openGridModal(targetModal: NgbModal) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static',
size: 'lg'
})
}
openPivotModal(targetModal: NgbModal) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static',
size: 'lg'
})
}
ngOnDestroy(): void {
this.getTemplateFileSubscription?.unsubscribe()
}
} }
\ No newline at end of file
<h2>🔹 Syncfusion Grid</h2> <h2>🔹 Syncfusion Grid</h2>
<ejs-grid [dataSource]="gridData" [allowPaging]="true" [pageSettings]="{ pageSize: 5 }"> <ejs-grid [dataSource]="gridData" [allowPaging]="true" [pageSettings]="{ pageSize: 5 }">
<e-columns> <e-columns>
<e-column field="id" headerText="ID" width="100"></e-column> <e-column field="id" headerText="ID" width="100"></e-column>
<e-column field="name" headerText="Name" width="150"></e-column> <e-column field="name" headerText="Name" width="150"></e-column>
<e-column field="age" headerText="Age" width="100"></e-column> <e-column field="age" headerText="Age" width="100"></e-column>
</e-columns> </e-columns>
</ejs-grid> </ejs-grid>
<hr /> <hr />
...@@ -69,10 +69,10 @@ ...@@ -69,10 +69,10 @@
<ng-container *ngIf="item.type=='calendar'"> <ng-container *ngIf="item.type=='calendar'">
<div class="input-group"> <div class="input-group">
<input class="form-control bg-white cursor-pointer" <input class="form-control bg-white cursor-pointer"
placeholder="{{ 'dd.mm.yyyy' | translate }}" name="dp1" ngbDatepicker placeholder="{{ 'dd.mm.yyyy' }}" name="dp1" ngbDatepicker #d1="ngbDatepicker"
#d1="ngbDatepicker" [(ngModel)]="select[item.key]" readonly [(ngModel)]="select[item.key]" readonly (click)="d1.toggle()"
(click)="d1.toggle()" (ngModelChange)="formatNgbDate(item.key,select[item.key])" (ngModelChange)="formatNgbDate(item.key,select[item.key])" #c1="ngModel"
#c1="ngModel" (change)="validateDate(c1)"> (change)="validateDate(c1)">
<div class="input-group-append"> <div class="input-group-append">
<button class="btn btn-outline-info no-shadow" (click)="d1.toggle()" <button class="btn btn-outline-info no-shadow" (click)="d1.toggle()"
type="button"> type="button">
...@@ -104,7 +104,7 @@ ...@@ -104,7 +104,7 @@
class="col-12 justify-content-center align-content-center d-flex" style="margin-bottom: 1rem;"> class="col-12 justify-content-center align-content-center d-flex" style="margin-bottom: 1rem;">
<button type="submit" class="btn btn-info waves-effect waves-light btn-w-100" <button type="submit" class="btn btn-info waves-effect waves-light btn-w-100"
(click)="dowloadExcelReport()"> (click)="dowloadExcelReport()">
{{"Print" |translate }} {{"Print" }}
</button> </button>
</div> </div>
<div *ngIf="loadingExcel" class="col-12 justify-content-center align-content-center d-flex" <div *ngIf="loadingExcel" class="col-12 justify-content-center align-content-center d-flex"
...@@ -117,7 +117,7 @@ ...@@ -117,7 +117,7 @@
style="margin-bottom: 1rem;margin-top: 1rem;"> style="margin-bottom: 1rem;margin-top: 1rem;">
<div <div
class="col-3 justify-content-center text-center font-weight-bold control-label col-form-label font-14"> class="col-3 justify-content-center text-center font-weight-bold control-label col-form-label font-14">
{{'No Data Found' | translate}} {{'No Data Found' }}
</div> </div>
</div> </div>
</ng-container> </ng-container>
...@@ -131,12 +131,11 @@ ...@@ -131,12 +131,11 @@
<div class="card" style="margin-bottom:-15px"> <div class="card" style="margin-bottom:-15px">
<div class="card-header bg-myhr"> <div class="card-header bg-myhr">
<h5 class="card-title"> <h5 class="card-title">
{{modalDetail.text.cardHead | translate}}</h5> {{modalDetail.text.cardHead }}</h5>
</div> </div>
<div class="card-body pb-0 pt-1"> <div class="card-body pb-0 pt-1">
<div class="d-flex mb-1"> <div class="d-flex mb-1">
<input type="text" <input type="text" placeholder="{{'systemcode.search' }} {{modalDetail.text.search[0]}}"
placeholder="{{'systemcode.search' | translate}} {{modalDetail.text.search[0]| translate}}"
class=" form-control w-75 border-color-gray-full-focus" [(ngModel)]='searchModal'> class=" form-control w-75 border-color-gray-full-focus" [(ngModel)]='searchModal'>
</div> </div>
<div class="table-responsive"> <div class="table-responsive">
...@@ -145,14 +144,14 @@ ...@@ -145,14 +144,14 @@
<tr class="text-white font-weight-normal"> <tr class="text-white font-weight-normal">
<th class="font-weight-normal text-center" scope="col" <th class="font-weight-normal text-center" scope="col"
*ngFor="let item of modalDetail.text.tableHead"> *ngFor="let item of modalDetail.text.tableHead">
{{item| translate}} {{item}}
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody *ngIf="!valueDetailFilter().length"> <tbody *ngIf="!valueDetailFilter().length">
<tr> <tr>
<td colspan="9" class="font-weight-normal text-center"> <td colspan="9" class="font-weight-normal text-center">
{{"No Data Found" |translate}} {{"No Data Found" }}
</td> </td>
</tr> </tr>
</tbody> </tbody>
...@@ -177,13 +176,13 @@ ...@@ -177,13 +176,13 @@
<select class="custom-select m-r-5 border-color-gray-full-focus" style="width: auto" <select class="custom-select m-r-5 border-color-gray-full-focus" style="width: auto"
[(ngModel)]="pageSize" (ngModelChange)="page=1"> [(ngModel)]="pageSize" (ngModelChange)="page=1">
<option *ngFor="let item of [10,50,100]" [ngValue]="item"> <option *ngFor="let item of [10,50,100]" [ngValue]="item">
{{"Items per page"| translate}}: {{item}} {{"Items per page"}}: {{item}}
</option> </option>
</select> </select>
<ngb-pagination [collectionSize]="valueDetailFilter().length" [(page)]="page" <ngb-pagination [collectionSize]="valueDetailFilter().length" [(page)]="page"
[pageSize]="pageSize" [maxSize]="3" [rotate]="true"> [pageSize]="pageSize" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>{{"Prev"| translate}}</ng-template> <ng-template ngbPaginationPrevious>{{"Prev"}}</ng-template>
<ng-template ngbPaginationNext>{{"Next"| translate}}</ng-template> <ng-template ngbPaginationNext>{{"Next"}}</ng-template>
</ngb-pagination> </ngb-pagination>
</div> </div>
</div> </div>
...@@ -191,7 +190,7 @@ ...@@ -191,7 +190,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="modal.close()"> <button type="button" class="btn btn-danger" (click)="modal.close()">
{{"Close"| translate}} {{"Close"}}
</button> </button>
</div> </div>
</div> </div>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
export interface AlertModel {
actionStatus: string
fail: boolean
memberId: any
message: string
none: boolean
resultObject: any
state: string
statusCode: number
success: boolean
}
\ No newline at end of file
import { environment } from "src/environments/environment"
export interface ExcelPortalModel {
approveBy: string
approveDate: string
approveTime: string
dbSupport: string
downloadDate: string
downloadTime: string
dwTime: number
engDesc: string
engName: string
excelId: string
fileData: string
fileType: string
group: ExcelPortalGroupModel
isDataGrid: number
isPivot: number
link1: string
referId: string
remark: string
tags: ExcelPortalTagsModel[]
thDesc: string
thName: string
thumbnail: string
uploadBy: string
uploadDate: string
uploadTime: string
}
export class MyExcelPortalModel implements ExcelPortalModel {
approveBy: string
approveDate: string
approveTime: string
dbSupport: string
downloadDate: string
downloadTime: string
dwTime: number
engDesc: string
engName: string
excelId: string
fileData: string
fileType: string
group: ExcelPortalGroupModel
isDataGrid: number
isPivot: number
link1: string
referId: string
remark: string
tags: ExcelPortalTagsModel[]
thDesc: string
thName: string
thumbnail: string
uploadBy: string
uploadDate: string
uploadTime: string
constructor(data?: Partial<ExcelPortalModel>) {
this.approveBy = data?.approveBy || ''
this.approveDate = data?.approveDate || ''
this.approveTime = data?.approveTime || ''
this.dbSupport = data?.dbSupport || ''
this.downloadDate = data?.downloadDate || ''
this.downloadTime = data?.downloadTime || ''
this.dwTime = data?.dwTime ?? 0
this.engDesc = data?.engDesc || ''
this.engName = data?.engName || ''
this.excelId = data?.excelId || ''
this.fileData = data?.fileData || ''
this.fileType = data?.fileType || ''
this.group = new MyExcelPortalGroupModel(data?.group || {})
this.isDataGrid = data?.isDataGrid ?? 0
this.isPivot = data?.isPivot ?? 0
this.link1 = data?.link1 || ''
this.referId = data?.referId || ''
this.remark = data?.remark || ''
this.tags = data?.tags?.map(e => new MyExcelPortalTagsModel(e)) || []
this.thDesc = data?.thDesc || ''
this.thName = data?.thName || ''
this.thumbnail = data?.thumbnail || ''
this.uploadBy = data?.uploadBy || ''
this.uploadDate = data?.uploadDate || ''
this.uploadTime = data?.uploadTime || ''
}
getImg() {
return this.thumbnail ? environment.url + "files/image/" + this.thumbnail : ''
}
}
export interface ExcelPortalGroupModel {
engName: string
groupId: string
groupType: number
thName: string
}
export class MyExcelPortalGroupModel implements ExcelPortalGroupModel {
engName: string
groupId: string
groupType: number
thName: string
constructor(data?: Partial<ExcelPortalGroupModel>) {
this.engName = data?.engName || ''
this.groupId = data?.groupId || ''
this.groupType = data?.groupType ?? 0
this.thName = data?.thName || ''
}
}
export interface ExcelPortalTagsModel {
display: string
value: string
}
export class MyExcelPortalTagsModel implements ExcelPortalTagsModel {
display: string
value: string
constructor(data?: Partial<ExcelPortalTagsModel>) {
this.display = data?.display || ''
this.value = data?.value || ''
}
}
\ No newline at end of file
...@@ -55,63 +55,66 @@ export class MyCreateByModel implements CreateByModel { ...@@ -55,63 +55,66 @@ export class MyCreateByModel implements CreateByModel {
} }
export interface TemplateFileModel { export interface TemplateFileModel {
templateId: string createDate: string
portalId: string
itemId: string
fileName: string
realFileName: string
realFileNameOld: string
tdesc: string
edesc: string edesc: string
fileName: string
isDataGrid: string
isPivot: string
isShare: string
itemId: string
menuActive: string menuActive: string
uponMenu: string
module: string module: string
page: string page: string
isShare: string
isPivot: string
createDate: string
createTime: string
param: any | null param: any | null
createBy: CreateByModel
}
export class MyTemplateFileModel implements TemplateFileModel {
templateId: string
portalId: string portalId: string
itemId: string
fileName: string
realFileName: string realFileName: string
realFileNameOld: string realFileNameOld: string
tdesc: string tdesc: string
templateId: string
uponMenu: string
fileData: string
fileType: string
}
export class MyTemplateFileModel implements TemplateFileModel {
createDate: string
edesc: string edesc: string
fileName: string
isDataGrid: string
isPivot: string
isShare: string
itemId: string
menuActive: string menuActive: string
uponMenu: string
module: string module: string
page: string page: string
isShare: string
isPivot: string
createDate: string
createTime: string
param: any | null param: any | null
createBy: CreateByModel portalId: string
realFileName: string
realFileNameOld: string
tdesc: string
templateId: string
uponMenu: string
fileData: string
fileType: string
constructor(data?: Partial<TemplateFileModel>) { constructor(data?: Partial<TemplateFileModel>) {
this.templateId = data?.templateId || '' this.createDate = data?.createDate || ''
this.portalId = data?.portalId || '' this.edesc = data?.edesc || ''
this.itemId = data?.itemId || ''
this.fileName = data?.fileName || '' this.fileName = data?.fileName || ''
this.isDataGrid = data?.isDataGrid || '0'
this.isPivot = data?.isPivot || '0'
this.isShare = data?.isShare || '0'
this.itemId = data?.itemId || ''
this.menuActive = data?.menuActive || ''
this.module = data?.module || ''
this.page = data?.page || ''
this.param = data?.param
this.portalId = data?.portalId || ''
this.realFileName = data?.realFileName || '' this.realFileName = data?.realFileName || ''
this.realFileNameOld = data?.realFileNameOld || '' this.realFileNameOld = data?.realFileNameOld || ''
this.tdesc = data?.tdesc || '' this.tdesc = data?.tdesc || ''
this.edesc = data?.edesc || '' this.templateId = data?.templateId || ''
this.menuActive = data?.menuActive || ''
this.uponMenu = data?.uponMenu || '' this.uponMenu = data?.uponMenu || ''
this.module = data?.module || '' this.fileData = data?.fileData || ''
this.page = data?.page || '' this.fileType = data?.fileType || ''
this.isShare = data?.isShare || ''
this.isPivot = data?.isPivot || ''
this.createDate = data?.createDate || ''
this.createTime = data?.createTime || ''
this.param = data?.param || null
this.createBy = new MyCreateByModel(data?.createBy)
} }
} }
......
...@@ -3,8 +3,10 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; ...@@ -3,8 +3,10 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from '../../environments/environment'; import { environment } from '../../environments/environment';
import { TemplateModel } from '../model/template.model'; import { TemplateFileModel, TemplateModel } from '../model/template.model';
import { ModuleModel } from '../model/module.model'; import { ModuleModel } from '../model/module.model';
import { ExcelPortalModel, ExcelPortalGroupModel, ExcelPortalTagsModel } from '../model/excel-portal.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
...@@ -16,16 +18,25 @@ export class ExcelReportService { ...@@ -16,16 +18,25 @@ export class ExcelReportService {
) { } ) { }
getExcelReport(itemId: string): Observable<any> { getExcelReport(itemId: string): Observable<any> {
return this.http.get(environment.url + "/irapi/menuitem/" + itemId + '?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47') return this.http.get(environment.url + "irapi/menuitem/" + itemId + '?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47')
} }
dowloadExcelReport(fileName: string, varname: string, data: string): Observable<any> { dowloadExcelReport(fileName: string, varname: string, data: string): Observable<any> {
return this.http.get(environment.url + "/irapi/excel/export-to-excel?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47&fileName=" + fileName + "&param=__varname=" + varname + "|__screen=XLSOPTION|" + data, { responseType: 'blob' }) return this.http.get(environment.url + "irapi/excel/export-to-excel?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47&fileName=" + fileName + "&param=__varname=" + varname + "|__screen=XLSOPTION|" + data, { responseType: 'blob' })
} }
getExcelList(): Observable<TemplateModel[]> { getExcelList(): Observable<TemplateModel[]> {
return this.http.get<TemplateModel[]>("https://hrplus-std.myhr.co.th/plus/template/lists?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47") return this.http.get<TemplateModel[]>(environment.url + "template/lists?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47")
} }
getModuleList(): Observable<ModuleModel[]> { getModuleList(): Observable<ModuleModel[]> {
return this.http.get<ModuleModel[]>("https://hrplus-std.myhr.co.th/plus/template/lists/module?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47") return this.http.get<ModuleModel[]>(environment.url + "template/lists/module?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47")
}
getExcelPortalList(): Observable<ExcelPortalModel[]> {
return this.http.get<ExcelPortalModel[]>(environment.url + "excel-center/content/lists")
}
getExcelPortalgGroupList(): Observable<ExcelPortalGroupModel[]> {
return this.http.get<ExcelPortalGroupModel[]>(environment.url + "portal-group/lists")
}
getExcelPortalTagsList(): Observable<ExcelPortalTagsModel[]> {
return this.http.get<ExcelPortalTagsModel[]>(environment.url + "tag/lists")
} }
postTemplate(body: { postTemplate(body: {
...@@ -36,6 +47,39 @@ export class ExcelReportService { ...@@ -36,6 +47,39 @@ export class ExcelReportService {
edesc: string, edesc: string,
module: string module: string
}) { }) {
return this.http.post("https://hrplus-std.myhr.co.th/plus/template?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47", body) return this.http.post(environment.url + "template?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47", body)
}
deleteTemplate(body: TemplateModel): Observable<AlertModel> {
let option = {
headers: new HttpHeaders({
"Content-Type": "application/json",
}),
body: body
}
return this.http.delete<AlertModel>(environment.url + "template?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47", option)
}
postTemplateFile(body: TemplateFileModel): Observable<AlertModel> {
return this.http.post<AlertModel>(environment.url + "template-file?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47", body)
}
deleteTemplateFile(body: TemplateFileModel): Observable<AlertModel> {
let option = {
headers: new HttpHeaders({
"Content-Type": "application/json",
}),
body: body
}
return this.http.delete<AlertModel>(environment.url + "template-file?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47", option)
}
downloadTemplateFile(fileName: string) {
return this.http.get(environment.url + "template-file/download/excel/" + fileName + "?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47", { responseType: 'blob' })
}
printExcelReport(body: {
fileName: string,
paramObj: string
}) {
return this.http.post(environment.url + "template-file/export-to-excel?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47", body, { responseType: 'blob' })
}
getTemplateFile(templateid: string, filename: string): Observable<AlertModel> {
return this.http.get<AlertModel>(environment.url + "template-file/" + templateid + "/" + filename + "?companyid=eb2f4f30-edaf-11ee-a69a-c7680edc0e47",)
} }
} }
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http'; import { HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
@Injectable() @Injectable()
export class HttpRequestInterceptor { export class HttpRequestInterceptor {
// token= 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJBdXRoIiwidWlkIjoiOGFhNDUzMzAtMzE0Yy0xMWU3LWJhZjMtMmQ3ZDA5ODc3NzQ0Iiwicm9sZSI6InVzZXIiLCJpc3MiOiJDb21wdXRlciBTY2llbmNlIENvcnBvcmF0aW9uIExpbWl0ZWQiLCJmdWxsTmFtZSI6InRlZXJhZGFjaCBrdWhhdGFuYXNhdGllbiIsIm1lbWJlcklkIjoiOGFhNDUzMzAtMzE0Yy0xMWU3LWJhZjMtMmQ3ZDA5ODc3NzQ0In0.FO7u8g7KfzkmZFTuuniBCEQxduPjcvzMbH7iug3DT90' token = ''
token= 'eyJhbGciOiJIUzI1NiJ9.eyJzY2hlbWEiOiJkYm8iLCJlbmNvZGUiOiIyIiwic3ViIjoiQXV0aCIsImNvbXBhbnlOYW1lIjoi4Lia4Lij4Li04Lip4Lix4LiXIOC4oeC4suC4ouC5gOC4reC4iuC4reC4suC4o-C5jCDguIjguLPguIHguLHguJQiLCJkYk5hbWUiOiJNWUhSUExVUyIsInJvbGVzIjpbIlVTRVIiXSwid29ya2FyZWEiOiJUS1ciLCJpc3MiOiJDb21wdXRlciBTY2llbmNlIENvcnBvcmF0aW9uIExpbWl0ZWQiLCJ6bWxvZ2luIjoiZmFsc2UiLCJyb2xlX2xldmVsIjoiNiIsImVtcGxveWVlaWQiOiIxMDAwMDA4MiIsImJyYW5jaCI6Im15aHIiLCJlbXBfcG9zaXRpb24iOiIwOTciLCJ1c2VyX3JvbGUiOiJBbGwiLCJ1aWQiOiIxMDAwMDA4MiIsImNvbXBhbnlpZCI6IjEwMCIsImFjdG9yaWQiOiIxMDAwMDA4MiIsImFjY291bnRhY3RpdmUiOiJ0cnVlIiwibGFuZyI6InRoIiwiYWQiOiJmYWxzZSIsImZpcnN0bG9naW4iOiJmYWxzZSIsInVybF9teWhyIjoiaHR0cDovL2hycGx1cy1zdGQubXloci5jby50aC9ociIsImFwcF9uYW1lIjoibXlociIsInJlZ2lvbmFsbHR5IjoiRU5HIiwidG9rZW5femVlbWUiOiIiLCJ1c2VyX2xldmVsIjoiTVlIUiIsImZ1bGxuYW1lIjoi4LiZ4Liy4Lii4Lit4Lie4Li04Lij4Lix4LiV4LiZ4LmMICDguJfguJTguKrguK3guJoiLCJjb21pZCI6IiIsImpvYiI6IjA5Ny0yNDY5IiwidXNlciI6Im15aHIiLCJ6bV91c2VyIjoiIiwidXNlcm5hbWUiOiJteWhyIiwibWVtYmVyaWQiOiIifQ.z106M3tnpWYWmD7tzAf7hPv2CDSyw50FoUrfDqqHFjw'
constructor() { } constructor() { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let authHeader = localStorage.getItem('accessToken') ? localStorage.getItem('accessToken')! : "Bearer "+this.token if (req.url.includes('hrplus-std')) {
this.token = 'eyJhbGciOiJIUzI1NiJ9.eyJzY2hlbWEiOiJkYm8iLCJlbmNvZGUiOiIyIiwic3ViIjoiQXV0aCIsImNvbXBhbnlOYW1lIjoi4Lia4Lij4Li04Lip4Lix4LiXIOC4oeC4suC4ouC5gOC4reC4iuC4reC4suC4o-C5jCDguIjguLPguIHguLHguJQiLCJkYk5hbWUiOiJNWUhSUExVUyIsInJvbGVzIjpbIlVTRVIiXSwid29ya2FyZWEiOiJUS1ciLCJpc3MiOiJDb21wdXRlciBTY2llbmNlIENvcnBvcmF0aW9uIExpbWl0ZWQiLCJ6bWxvZ2luIjoiZmFsc2UiLCJyb2xlX2xldmVsIjoiNiIsImVtcGxveWVlaWQiOiIxMDAwMDA4MiIsImJyYW5jaCI6Im15aHIiLCJlbXBfcG9zaXRpb24iOiIwOTciLCJ1c2VyX3JvbGUiOiJBbGwiLCJ1aWQiOiIxMDAwMDA4MiIsImNvbXBhbnlpZCI6IjEwMCIsImFjdG9yaWQiOiIxMDAwMDA4MiIsImFjY291bnRhY3RpdmUiOiJ0cnVlIiwibGFuZyI6InRoIiwiYWQiOiJmYWxzZSIsImZpcnN0bG9naW4iOiJmYWxzZSIsInVybF9teWhyIjoiaHR0cDovL2hycGx1cy1zdGQubXloci5jby50aC9ociIsImFwcF9uYW1lIjoibXlociIsInJlZ2lvbmFsbHR5IjoiRU5HIiwidG9rZW5femVlbWUiOiIiLCJ1c2VyX2xldmVsIjoiTVlIUiIsImZ1bGxuYW1lIjoi4LiZ4Liy4Lii4Lit4Lie4Li04Lij4Lix4LiV4LiZ4LmMICDguJfguJTguKrguK3guJoiLCJjb21pZCI6IiIsImpvYiI6IjA5Ny0yNDY5IiwidXNlciI6Im15aHIiLCJ6bV91c2VyIjoiIiwidXNlcm5hbWUiOiJteWhyIiwibWVtYmVyaWQiOiIifQ.z106M3tnpWYWmD7tzAf7hPv2CDSyw50FoUrfDqqHFjw'
}
if (req.url.includes('portal.myhr')) {
this.token = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJBdXRoIiwidWlkIjoiOGFhNDUzMzAtMzE0Yy0xMWU3LWJhZjMtMmQ3ZDA5ODc3NzQ0Iiwicm9sZSI6InVzZXIiLCJpc3MiOiJDb21wdXRlciBTY2llbmNlIENvcnBvcmF0aW9uIExpbWl0ZWQiLCJmdWxsTmFtZSI6InRlZXJhZGFjaCBrdWhhdGFuYXNhdGllbiIsIm1lbWJlcklkIjoiOGFhNDUzMzAtMzE0Yy0xMWU3LWJhZjMtMmQ3ZDA5ODc3NzQ0In0.FO7u8g7KfzkmZFTuuniBCEQxduPjcvzMbH7iug3DT90'
}
let authHeader = localStorage.getItem('accessToken') ? localStorage.getItem('accessToken')! : "Bearer " + this.token
const overideReq = { const overideReq = {
headers: req.headers.set('Authorization', authHeader), headers: req.headers.set('Authorization', authHeader),
url: req.url url: req.url
......
...@@ -17,24 +17,31 @@ export class VerticalSidebarService { ...@@ -17,24 +17,31 @@ export class VerticalSidebarService {
items = new BehaviorSubject<RouteInfo[]>(this.MENUITEMS); items = new BehaviorSubject<RouteInfo[]>(this.MENUITEMS);
submenu = [ submenu: {
{ "itemId": string,
"itemId": "3459", "templateId": string,
"templateId": "3011", "fileName": string,
"fileName": "BFET6T4QJ.xlsx", "tdesc": string,
"tdesc": "FOR TEST OPTION ESS", "edesc": string,
"edesc": "FOR TEST OPTION ESS", "module": string,
"module": "EMPVIEW" }[] = [
}, // {
{ // "itemId": "3459",
"itemId": "3462", // "templateId": "3011",
"templateId": "3011", // "fileName": "BFET6T4QJ.xlsx",
"fileName": "F5QTI20MBJ.xls", // "tdesc": "FOR TEST OPTION ESS",
"tdesc": "REPORT WORKING HOURS_BU3", // "edesc": "FOR TEST OPTION ESS",
"edesc": "REPORT WORKING HOURS_BU3", // "module": "EMPVIEW"
"module": "EMPVIEW" // },
} // {
] // "itemId": "3462",
// "templateId": "3011",
// "fileName": "F5QTI20MBJ.xls",
// "tdesc": "REPORT WORKING HOURS_BU3",
// "edesc": "REPORT WORKING HOURS_BU3",
// "module": "EMPVIEW"
// }
]
constructor() { constructor() {
} }
} }
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
@Pipe({
name: 'safeUrl'
})
export class SafeUrlPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(url: string): SafeResourceUrl {
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
}
}
...@@ -15,120 +15,155 @@ ...@@ -15,120 +15,155 @@
@import '../node_modules/@syncfusion/ej2-angular-grids/styles/material.css'; @import '../node_modules/@syncfusion/ej2-angular-grids/styles/material.css';
body { body {
font-family: "Kanit", sans-serif !important; font-family: "Kanit", sans-serif !important;
} }
.msg-detail{
width: 100%; .msg-detail {
margin-top: 0.25rem; width: 100%;
font-size: 0.875em; margin-top: 0.25rem;
color: #f62d51; font-size: 0.875em;
color: #f62d51;
} }
.myhrcolor-1 .tooltip-inner { .myhrcolor-1 .tooltip-inner {
background-color: #fff; background-color: #fff;
color: #2962ff; color: #2962ff;
font-weight: 400; font-weight: 400;
border-style: solid; border-style: solid;
border-color: #2962ff; border-color: #2962ff;
border-width: 1px; border-width: 1px;
} }
.myhrcolor-1 .arrow::before {
border-top-color: #2962ff; .myhrcolor-1 .arrow::before {
} border-top-color: #2962ff;
.myhrcolor-2 .tooltip-inner { }
background-color: #fff;
color: #36bea6; .myhrcolor-2 .tooltip-inner {
font-weight: 400; background-color: #fff;
border-style: solid; color: #36bea6;
border-color: #36bea6; font-weight: 400;
border-width: 1px; border-style: solid;
} border-color: #36bea6;
.myhrcolor-2 .arrow::before { border-width: 1px;
border-top-color: #36bea6; }
}
.myhrcolor-3 .tooltip-inner { .myhrcolor-2 .arrow::before {
background-color: #fff; border-top-color: #36bea6;
color: #f62d51; }
font-weight: 400;
border-style: solid; .myhrcolor-3 .tooltip-inner {
border-color: #f62d51; background-color: #fff;
border-width: 1px; color: #f62d51;
} font-weight: 400;
.myhrcolor-3 .arrow::before { border-style: solid;
border-top-color: #f62d51; border-color: #f62d51;
} border-width: 1px;
.myhrcolor-4 .tooltip-inner { }
background-color: #fff;
color: #ffbc34; .myhrcolor-3 .arrow::before {
font-weight: 400; border-top-color: #f62d51;
border-style: solid; }
border-color: #ffbc34;
border-width: 1px; .myhrcolor-4 .tooltip-inner {
} background-color: #fff;
.myhrcolor-4 .arrow::before { color: #ffbc34;
border-top-color: #ffbc34; font-weight: 400;
} border-style: solid;
.myhrcolor-date .tooltip-inner { border-color: #ffbc34;
background-color: #fff; border-width: 1px;
color: #a1aab2; }
font-weight: 400;
border-style: solid; .myhrcolor-4 .arrow::before {
border-color: #a1aab2; border-top-color: #ffbc34;
border-width: 1px; }
}
.myhrcolor-date .arrow::before { .myhrcolor-date .tooltip-inner {
border-top-color: #a1aab2; background-color: #fff;
} color: #a1aab2;
.pointer{ font-weight: 400;
cursor: pointer; border-style: solid;
} border-color: #a1aab2;
.pointer:hover{ border-width: 1px;
font-weight: 700; }
color: #2962ff;
.myhrcolor-date .arrow::before {
border-top-color: #a1aab2;
}
.pointer {
cursor: pointer;
}
.pointer:hover {
font-weight: 700;
color: #2962ff;
}
.my-dialog-img-preview .modal-dialog {
display: flex !important;
justify-content: center !important;
.modal-content {
background-color: #fff0 !important;
border: none !important;
width: auto !important;
} }
.my-dialog-img-preview .modal-dialog {
display: flex !important;
justify-content: center !important;
.modal-content {
background-color: #fff0 !important;
border: none !important;
width: auto !important;
}
} }
.cover { .cover {
border-radius: 4%; border-radius: 4%;
border: 10px solid #ccc; border: 10px solid #ccc;
object-fit: cover; object-fit: cover;
height: 200px; height: 200px;
} }
.border-excel { .border-excel {
border:1px solid #21a366 !important; border: 1px solid #21a366 !important;
border-color: #21a366 !important; border-color: #21a366 !important;
} }
.border-doc { .border-doc {
border:1px solid #2091eb !important; border: 1px solid #2091eb !important;
border-color: #2091eb !important; border-color: #2091eb !important;
} }
.border-course { .border-course {
border:1px solid #7460ee !important; border: 1px solid #7460ee !important;
border-color: #7460ee !important; border-color: #7460ee !important;
} }
.border-widget { .border-widget {
border:1px solid #ccc !important; border: 1px solid #ccc !important;
border-color: #ccc !important; border-color: #ccc !important;
} }
.border-5{
.border-5 {
border-radius: 10px border-radius: 10px
} }
.no-bg{
.no-bg {
background-color: #fff0; background-color: #fff0;
} }
.view-detail{
.view-detail {
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 4; -webkit-line-clamp: 4;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
} }
.border-bottom-5{
.border-bottom-5 {
border-radius: 0 0 6px 6px !important; border-radius: 0 0 6px 6px !important;
}
.my-dialog-video-preview .modal-dialog {
display: flex !important;
justify-content: center !important;
.modal-content {
background-color: #fff0 !important;
border: none !important;
min-width: 70vw !important;
min-height: 70vh !important;
}
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment