Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
portal-apps-manage
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
angular
portal-apps-manage
Commits
73e72e5e
Commit
73e72e5e
authored
Aug 04, 2025
by
sawit
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ปรับ module myskill-x
parent
a76efb87
Hide whitespace changes
Inline
Side-by-side
Showing
98 changed files
with
13527 additions
and
42 deletions
+13527
-42
alert-modal.component.html
...myskill-x/myportal/alert-modal/alert-modal.component.html
+39
-0
alert-modal.component.scss
...myskill-x/myportal/alert-modal/alert-modal.component.scss
+0
-0
alert-modal.component.spec.ts
...kill-x/myportal/alert-modal/alert-modal.component.spec.ts
+25
-0
alert-modal.component.ts
...U/myskill-x/myportal/alert-modal/alert-modal.component.ts
+30
-0
confirm-modal.component.html
...ill-x/myportal/confirm-modal/confirm-modal.component.html
+18
-0
confirm-modal.component.scss
...ill-x/myportal/confirm-modal/confirm-modal.component.scss
+0
-0
confirm-modal.component.ts
...skill-x/myportal/confirm-modal/confirm-modal.component.ts
+16
-0
datasource-table.component.html
...myportal/datasource-table/datasource-table.component.html
+310
-0
datasource-table.component.scss
...myportal/datasource-table/datasource-table.component.scss
+5
-0
datasource-table.component.ts
...x/myportal/datasource-table/datasource-table.component.ts
+277
-0
excel-report.component.css
...yskill-x/myportal/excel-report/excel-report.component.css
+0
-0
excel-report.component.html
...skill-x/myportal/excel-report/excel-report.component.html
+228
-0
excel-report.component.spec.ts
...ll-x/myportal/excel-report/excel-report.component.spec.ts
+28
-0
excel-report.component.ts
...myskill-x/myportal/excel-report/excel-report.component.ts
+410
-0
home-common.component.css
.../myskill-x/myportal/home-common/home-common.component.css
+0
-0
home-common.component.html
...myskill-x/myportal/home-common/home-common.component.html
+402
-0
home-common.component.spec.ts
...kill-x/myportal/home-common/home-common.component.spec.ts
+28
-0
home-common.component.ts
...U/myskill-x/myportal/home-common/home-common.component.ts
+510
-0
list-course.component.html
...myskill-x/myportal/list-course/list-course.component.html
+340
-0
list-course.component.scss
...myskill-x/myportal/list-course/list-course.component.scss
+10
-0
list-course.component.ts
...U/myskill-x/myportal/list-course/list-course.component.ts
+407
-0
list-doc.component.html
...p/DPU/myskill-x/myportal/list-doc/list-doc.component.html
+519
-0
list-doc.component.scss
...p/DPU/myskill-x/myportal/list-doc/list-doc.component.scss
+10
-0
list-doc.component.ts
...app/DPU/myskill-x/myportal/list-doc/list-doc.component.ts
+442
-0
list-excell.component.html
...myskill-x/myportal/list-excell/list-excell.component.html
+387
-0
list-excell.component.scss
...myskill-x/myportal/list-excell/list-excell.component.scss
+10
-0
list-excell.component.ts
...U/myskill-x/myportal/list-excell/list-excell.component.ts
+488
-0
list-widgets.component.html
...skill-x/myportal/list-widgets/list-widgets.component.html
+344
-0
list-widgets.component.scss
...skill-x/myportal/list-widgets/list-widgets.component.scss
+10
-0
list-widgets.component.ts
...myskill-x/myportal/list-widgets/list-widgets.component.ts
+419
-0
approved-list.component.html
...tal/management/approved-list/approved-list.component.html
+69
-0
approved-list.component.scss
...tal/management/approved-list/approved-list.component.scss
+0
-0
approved-list.component.spec.ts
.../management/approved-list/approved-list.component.spec.ts
+25
-0
approved-list.component.ts
...ortal/management/approved-list/approved-list.component.ts
+94
-0
view-list-course.component.html
...ved-list/view-list-course/view-list-course.component.html
+207
-0
view-list-course.component.scss
...ved-list/view-list-course/view-list-course.component.scss
+0
-0
view-list-course.component.ts
...roved-list/view-list-course/view-list-course.component.ts
+146
-0
view-list-doc.component.html
.../approved-list/view-list-doc/view-list-doc.component.html
+209
-0
view-list-doc.component.scss
.../approved-list/view-list-doc/view-list-doc.component.scss
+0
-0
view-list-doc.component.ts
...nt/approved-list/view-list-doc/view-list-doc.component.ts
+146
-0
view-list-excel.component.html
...roved-list/view-list-excel/view-list-excel.component.html
+217
-0
view-list-excel.component.scss
...roved-list/view-list-excel/view-list-excel.component.scss
+0
-0
view-list-excel.component.ts
...pproved-list/view-list-excel/view-list-excel.component.ts
+158
-0
management.component.css
...PU/myskill-x/myportal/management/management.component.css
+0
-0
management.component.html
...U/myskill-x/myportal/management/management.component.html
+3
-0
management.component.spec.ts
...yskill-x/myportal/management/management.component.spec.ts
+28
-0
management.component.ts
...DPU/myskill-x/myportal/management/management.component.ts
+15
-0
approve-course.component.html
...list-approve/approve-course/approve-course.component.html
+227
-0
approve-course.component.scss
...list-approve/approve-course/approve-course.component.scss
+0
-0
approve-course.component.ts
...y-list-approve/approve-course/approve-course.component.ts
+180
-0
approve-doc.component.html
...egory-list-approve/approve-doc/approve-doc.component.html
+232
-0
approve-doc.component.scss
...egory-list-approve/approve-doc/approve-doc.component.scss
+0
-0
approve-doc.component.ts
...ategory-list-approve/approve-doc/approve-doc.component.ts
+179
-0
approve-excel.component.html
...y-list-approve/approve-excel/approve-excel.component.html
+231
-0
approve-excel.component.scss
...y-list-approve/approve-excel/approve-excel.component.scss
+0
-0
approve-excel.component.ts
...ory-list-approve/approve-excel/approve-excel.component.ts
+182
-0
portal-category-list-approve.component.html
...-list-approve/portal-category-list-approve.component.html
+69
-0
portal-category-list-approve.component.scss
...-list-approve/portal-category-list-approve.component.scss
+0
-0
portal-category-list-approve.component.ts
...ry-list-approve/portal-category-list-approve.component.ts
+113
-0
myportal.component.css
src/app/DPU/myskill-x/myportal/myportal.component.css
+0
-0
myportal.component.html
src/app/DPU/myskill-x/myportal/myportal.component.html
+3
-0
myportal.component.spec.ts
src/app/DPU/myskill-x/myportal/myportal.component.spec.ts
+28
-0
myportal.component.ts
src/app/DPU/myskill-x/myportal/myportal.component.ts
+15
-0
open-image.component.html
...U/myskill-x/myportal/open-image/open-image.component.html
+13
-0
open-image.component.scss
...U/myskill-x/myportal/open-image/open-image.component.scss
+0
-0
open-image.component.ts
...DPU/myskill-x/myportal/open-image/open-image.component.ts
+26
-0
portal-category-list.component.html
.../portal-category-list/portal-category-list.component.html
+67
-0
portal-category-list.component.scss
.../portal-category-list/portal-category-list.component.scss
+0
-0
portal-category-list.component.ts
...al/portal-category-list/portal-category-list.component.ts
+118
-0
portal-create-category.component.html
...tal-create-category/portal-create-category.component.html
+115
-0
portal-create-category.component.scss
...tal-create-category/portal-create-category.component.scss
+0
-0
portal-create-category.component.ts
...ortal-create-category/portal-create-category.component.ts
+130
-0
excel-list.component.html
...al/set-excel-reports/excel-list/excel-list.component.html
+1167
-0
excel-list.component.scss
...al/set-excel-reports/excel-list/excel-list.component.scss
+31
-0
excel-list.component.ts
...rtal/set-excel-reports/excel-list/excel-list.component.ts
+980
-0
excel-report-toggle.component.html
...ts/excel-report-toggle/excel-report-toggle.component.html
+603
-0
excel-report-toggle.component.scss
...ts/excel-report-toggle/excel-report-toggle.component.scss
+30
-0
excel-report-toggle.component.ts
...orts/excel-report-toggle/excel-report-toggle.component.ts
+584
-0
set-excel-reports.component.css
...yportal/set-excel-reports/set-excel-reports.component.css
+0
-0
set-excel-reports.component.html
...portal/set-excel-reports/set-excel-reports.component.html
+3
-0
set-excel-reports.component.spec.ts
...tal/set-excel-reports/set-excel-reports.component.spec.ts
+28
-0
set-excel-reports.component.ts
...myportal/set-excel-reports/set-excel-reports.component.ts
+15
-0
view-list-course.component.html
...myportal/view-list-course/view-list-course.component.html
+149
-0
view-list-course.component.scss
...myportal/view-list-course/view-list-course.component.scss
+0
-0
view-list-course.component.ts
...x/myportal/view-list-course/view-list-course.component.ts
+144
-0
view-list-doc.component.html
...ill-x/myportal/view-list-doc/view-list-doc.component.html
+170
-0
view-list-doc.component.scss
...ill-x/myportal/view-list-doc/view-list-doc.component.scss
+0
-0
view-list-doc.component.ts
...skill-x/myportal/view-list-doc/view-list-doc.component.ts
+126
-0
view-list-excel.component.html
...x/myportal/view-list-excel/view-list-excel.component.html
+150
-0
view-list-excel.component.scss
...x/myportal/view-list-excel/view-list-excel.component.scss
+0
-0
view-list-excel.component.ts
...l-x/myportal/view-list-excel/view-list-excel.component.ts
+160
-0
view-list-widgets.component.html
...portal/view-list-widgets/view-list-widgets.component.html
+81
-0
view-list-widgets.component.scss
...portal/view-list-widgets/view-list-widgets.component.scss
+0
-0
view-list-widgets.component.ts
...myportal/view-list-widgets/view-list-widgets.component.ts
+107
-0
myskill-x.module.ts
src/app/DPU/myskill-x/myskill-x.module.ts
+27
-27
header.component.html
src/app/shared/components/header/header.component.html
+1
-1
sidebar.component.ts
src/app/shared/components/sidebar/sidebar.component.ts
+4
-4
nav.service.ts
src/app/shared/services/nav.service.ts
+10
-10
No files found.
src/app/DPU/myskill-x/myportal/alert-modal/alert-modal.component.html
0 → 100644
View file @
73e72e5e
<!-- <div class="modal-header">
<h5 class="modal-title" id="editLabel">ข้อความแจ้งเตือน</h5>
<button type="button" class="close" (click)="activeModal.dismiss('dismiss')" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<ng-container *ngIf="innerHTML!=undefined then InnerHTML else Message"></ng-container>
<ng-template #Message>
<div class="modal-body">
{{message}}
</div>
</ng-template>
<ng-template #InnerHTML>
<div class="modal-body" [innerHTML]="innerHTML">
</div>
</ng-template> -->
<div
class=
"modal-header"
>
<h5
class=
"modal-title"
id=
"editLabel"
>
ข้อความแจ้งเตือน
</h5>
<button
type=
"button"
class=
"close"
(
click
)="
close
()"
aria-label=
"Close"
>
<span
aria-hidden=
"true"
>
×
</span>
</button>
</div>
<ng-container
*
ngIf=
"data.innerHTML != undefined then InnerHTML else Message"
></ng-container>
<ng-template
#
Message
>
<div
class=
"modal-body"
>
{{data.message}}
</div>
</ng-template>
<ng-template
#
InnerHTML
>
<div
class=
"modal-body"
[
innerHTML
]="
data
.
innerHTML
"
>
</div>
</ng-template>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/alert-modal/alert-modal.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/alert-modal/alert-modal.component.spec.ts
0 → 100644
View file @
73e72e5e
import
{
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
AlertModalComponent
}
from
'./alert-modal.component'
;
describe
(
'AlertModalComponent'
,
()
=>
{
let
component
:
AlertModalComponent
;
let
fixture
:
ComponentFixture
<
AlertModalComponent
>
;
beforeEach
(
async
()
=>
{
await
TestBed
.
configureTestingModule
({
declarations
:
[
AlertModalComponent
]
})
.
compileComponents
();
});
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
AlertModalComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/DPU/myskill-x/myportal/alert-modal/alert-modal.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
,
Inject
}
from
'@angular/core'
;
import
{
MatDialogRef
,
MAT_DIALOG_DATA
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
@
Component
({
selector
:
'app-alert-modal'
,
templateUrl
:
'./alert-modal.component.html'
,
styleUrls
:
[
'./alert-modal.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
MatDialogModule
]
})
export
class
AlertModalComponent
implements
OnInit
{
constructor
(
public
dialogRef
:
MatDialogRef
<
AlertModalComponent
>
,
@
Inject
(
MAT_DIALOG_DATA
)
public
data
:
{
message
:
string
;
innerHTML
?:
string
}
)
{
}
ngOnInit
():
void
{
}
close
():
void
{
this
.
dialogRef
.
close
();
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/confirm-modal/confirm-modal.component.html
0 → 100644
View file @
73e72e5e
<div
class=
"modal-header"
>
<h5
class=
"modal-title"
id=
"editLabel"
>
ข้อความแจ้งเตือน
</h5>
<button
type=
"button"
class=
"close"
(
click
)="
activeModal
.
dismiss
('
dismiss
')"
aria-label=
"Close"
>
<span
aria-hidden=
"true"
>
×
</span>
</button>
</div>
<div
class=
"modal-body"
>
{{message}}
</div>
<div
class=
"modal-footer"
>
<button
type=
"button"
class=
"btn btn-info"
(
click
)="
activeModal
.
close
('
close
')"
>
ยืนยัน
</button>
<button
type=
"button"
class=
"btn btn-danger"
(
click
)="
activeModal
.
dismiss
('
dismiss
')"
>
ยกเลิก
</button>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/confirm-modal/confirm-modal.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/confirm-modal/confirm-modal.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
Input
,
OnInit
}
from
'@angular/core'
;
import
{
NgbActiveModal
}
from
'@ng-bootstrap/ng-bootstrap'
;
@
Component
({
selector
:
'app-confirm-modal'
,
templateUrl
:
'./confirm-modal.component.html'
,
styleUrls
:
[
'./confirm-modal.component.scss'
]
})
export
class
ConfirmModalComponent
implements
OnInit
{
@
Input
()
message
:
string
=
""
;
constructor
(
public
activeModal
:
NgbActiveModal
)
{
}
ngOnInit
():
void
{
}
}
src/app/DPU/myskill-x/myportal/datasource-table/datasource-table.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'
Datasource
Table
'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'
Datasource
Table
'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
{{ 'All List' | translate}}
<span
class=
"badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle"
>
{{itemsList.length}}
</span>
</div>
<div
class=
"flex flex-wrap gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(
click
)="
new
()"
data-hs-overlay=
"#modal-detail"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'Create' |
translate}}
</a>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-danger-full me-2"
*
ngIf=
"someSelected"
(
click
)="
deleteSelect
()"
><i
class=
"ri-delete-bin-line font-semibold align-middle"
></i>
{{ 'Delete' | translate}}
</a>
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหา..."
aria-label=
".form-control-sm example"
[(
ngModel
)]='
searchTerm
'
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead>
<tr
class=
"border-b border-defaultborder"
>
<th
scope=
"col"
class=
"!text-start"
>
<input
class=
"form-check-input check-all"
type=
"checkbox"
id=
"all-products"
(
change
)="
toggleAll
($
event
)"
[
checked
]="
allSelected
"
aria-label=
"..."
>
</th>
<th
scope=
"col"
class=
"text-start"
>
{{'รหัสบริษัท' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Company Name' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Database Type' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Port Number' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Database Name' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Server Name' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Status' | translate}}
</th>
<!-- <th scope="col" class="text-start">{{ 'User Name' | translate}}</th> -->
<!-- <th scope="col" class="text-start">{{ 'Password' | translate}}</th> -->
<th
scope=
"col"
class=
"text-start"
>
{{ 'Action' | translate}}
</th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for (item of filterList; track item.companyId) {
<tr
class=
"border border-defaultborder dark:border-defaultborder/10"
>
<td
class=
"product-checkbox"
>
<input
class=
"form-check-input"
type=
"checkbox"
[
checked
]="
selectedItems
.
get
(
item
.
companyId
)
||
false
"
(
change
)="
onCheckboxChange
(
item
.
companyId
)"
aria-label=
"..."
>
</td>
<td>
<span
class=
"block mb-1"
>
{{item.companyId}}
</span>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{item.companyName}}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{item.dbType}}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{item.portNumber}}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{item.databaseName}}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{item.serverName}}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{item.status}}
</span>
</div>
</td>
<!-- <td>
<div>
<span class="block mb-1">
{{item.userName}}
</span>
</div>
</td> -->
<!-- <td class="text-center" style="white-space: normal !important;word-break: break-word;">
<span class="cursor-pointer" (click)="selectData(item)">
{{tableShowPassword.get(item.companyId)?item.password : '*'.repeat(item.password?.length || 0) }}</span>
<i class="cursor-pointer fa fa-eye" *ngIf="tableShowPassword.get(item.companyId)" (click)="tableShowPassword.set(item.companyId,false)"></i>
<i class="cursor-pointer fa fa-eye-slash" *ngIf="!tableShowPassword.get(item.companyId)" (click)="tableShowPassword.set(item.companyId,true)"></i>
</td> -->
<td>
<div
class=
"flex flex-row items-center !gap-2 "
>
<a
aria-label=
"anchor"
(
click
)="
view
(
item
)"
data-hs-overlay=
"#modal-detail"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
>
<i
class=
"ri-pencil-line"
></i>
</a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
(
click
)="
delete
(
item
)"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"
>
<i
class=
"ri-delete-bin-line"
></i>
</a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td
[
attr
.
colspan
]="
6
"
class=
"text-center py-4"
>
<ng-container
*
ngIf=
"itemsList.length === 0 && !searchTerm"
>
<p>
กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...
</p>
</ng-container>
<ng-container
*
ngIf=
"itemsList.length > 0 && filterList.length === 0 && searchTerm"
>
<p>
ไม่พบข้อมูลที่ค้นหา...
</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterList.length > 0"
>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"pageIndex>0"
class=
"page-item {{pageIndex==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
pageIndex =
pageIndex-1;updatePagedItems()"
>
{{'Previous' | translate}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageIndex-1>0"
(
click
)="
pageIndex =
pageIndex-2;updatePagedItems()"
>
{{pageIndex-1}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(
click
)="
pageIndex =
pageIndex-1;updatePagedItems()"
>
{{pageIndex}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{pageIndex +1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(
click
)="
pageIndex =
pageIndex+1;updatePagedItems()"
>
{{pageIndex +2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(
click
)="
pageIndex =
pageIndex+2;updatePagedItems()"
>
{{pageIndex +3}}
</a></li>
<li
*
ngIf=
"(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
pageIndex =
pageIndex+1;updatePagedItems()"
>
{{'Next' |
translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div
id=
"modal-detail"
class=
"hs-overlay hidden ti-modal [--overlay-backdrop:static]"
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header"
>
<h6
class=
"modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
<!-- {{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('Datasource Table Information' | translate) }} -->
{{('Datasource Table Information' | translate)}}
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay=
"#modal-detail"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4"
>
<div
class=
"grid grid-cols-12 gap-4"
>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"action == 'edit'"
>
<label
for=
"companyId"
class=
"form-label"
>
{{'รหัสบริษัท' | translate}}
</label>
<input
type=
"text"
class=
"form-control !bg-input-readonly"
id=
"companyId"
placeholder=
""
[(
ngModel
)]="
selectModel
.
companyId
"
[
disabled
]="
action =
==
'
edit
'"
>
<!-- <div class="text-danger" *ngIf="!selectModel.companyId && action === 'add'">
{{'Please fill in information' | translate}}
</div> -->
</div>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"modalStatus=='add'"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{ 'Company Name' | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
companyName
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.companyName"
>
{{'Please fill in information' | translate}}
</div>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"modalStatus=='add'"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{ 'Database Type' | translate}}
</label>
<!-- <input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.dbType"> -->
<select
class=
"form-control"
[(
ngModel
)]="
selectModel
.
dbType
"
>
<option
style=
"color: red"
[
class
.
d-none
]="
selectModel
.
dbType=
=''"
[
value
]="''"
>
{{selectModel.dbType!=''?'ยกเลิก':''}}
</option>
<option
value=
"MSSQL"
>
MSSQL
</option>
<option
value=
"PGSQL"
>
PGSQL
</option>
</select>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.dbType"
>
{{'Please fill in information' | translate}}
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"modalStatus=='add'"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{ 'Port Number' | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
portNumber
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.portNumber"
>
{{'Please fill in information' | translate}}
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"modalStatus=='add'"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{ 'Database Name' | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
databaseName
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.databaseName"
>
{{'Please fill in information' | translate}}
</div>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"modalStatus=='add'"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{ 'Server Name' | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
serverName
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.serverName"
>
{{'Please fill in information' | translate}}
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"modalStatus=='add'"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{ 'Status' | translate}}
</label>
<!-- <input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.status"> -->
<select
class=
"form-control"
[(
ngModel
)]="
selectModel
.
status
"
>
<option
style=
"color: red"
[
class
.
d-none
]="
selectModel
.
status=
=''"
[
value
]="''"
>
{{selectModel.status!=''?'ยกเลิก':''}}
</option>
<option
value=
"online"
>
online
</option>
<option
value=
"offline"
>
offline
</option>
</select>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.status"
>
{{'Please fill in information' | translate}}
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"modalStatus=='add'"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{ 'User Name' | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
userName
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.userName"
>
{{'Please fill in information' | translate}}
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12 my-2"
*
ngIf=
"modalStatus=='add'"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{ 'Password' | translate}}
</label><br>
<input
type=
"text"
class=
"form-control"
style=
"width: 95%"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
password
"
[
class
.
secure-input
]="!
showPassword
"
>
<i
class=
"fa fa-eye cursor-pointer"
*
ngIf=
"showPassword"
(
click
)="
showPassword=
false"
></i>
<i
class=
"fa fa-eye-slash cursor-pointer"
*
ngIf=
"!showPassword"
(
click
)="
showPassword=
true"
></i>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.password"
>
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div
class=
"ti-modal-footer"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay=
"#modal-detail"
>
{{'Cancel' | translate}}
</button>
<button
type=
"button"
(
click
)="
save
()"
class=
"ti-btn bg-primary text-white !font-medium"
[
class
.
ti-btn-disabled
]="!
selectModel
.
companyName
||!
selectModel
.
dbType
||!
selectModel
.
portNumber
||!
selectModel
.
databaseName
||!
selectModel
.
serverName
||!
selectModel
.
status
||!
selectModel
.
userName
||!
selectModel
.
password
"
[
disabled
]="!
selectModel
.
companyName
||!
selectModel
.
dbType
||!
selectModel
.
portNumber
||!
selectModel
.
databaseName
||!
selectModel
.
serverName
||!
selectModel
.
status
||!
selectModel
.
userName
||!
selectModel
.
password
"
>
{{'Save' | translate}}
</button>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/datasource-table/datasource-table.component.scss
0 → 100644
View file @
73e72e5e
.secure-input
{
-webkit-text-security
:
disc
;
text-security
:
disc
;
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/datasource-table/datasource-table.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
ElementRef
,
ViewChild
}
from
'@angular/core'
;
import
{
DomSanitizer
,
SafeHtml
}
from
'@angular/platform-browser'
;
import
{
Router
,
RouterModule
}
from
'@angular/router'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
TranslateModule
,
TranslateService
}
from
'@ngx-translate/core'
;
import
swal
from
'sweetalert'
;
import
{
MatPaginator
}
from
'@angular/material/paginator'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FileUploadModule
}
from
'ng2-file-upload'
;
import
{
FileItem
,
FileUploader
,
ParsedResponseHeaders
}
from
"ng2-file-upload"
;
import
{
environment
}
from
'../../../../../environments/environment'
;
import
{
TokenService
}
from
'../../../../shared/services/token.service'
import
{
QuillModule
}
from
'ngx-quill'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
DatasourseTableService
}
from
'../../../services/datasourse-table.service'
;
import
{
NgbPagination
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
DatasourceTableModel
,
MyDatasourceTableModel
}
from
'../../../models/datasource-table.model'
;
@
Component
({
selector
:
'app-datasource-table'
,
templateUrl
:
'./datasource-table.component.html'
,
styleUrls
:
[
'./datasource-table.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
]
})
export
class
DatasourceTableComponent
{
quillConfig
=
{
toolbar
:
[
[
'link'
],
// เพิ่มปุ่มลิงก์
[
'bold'
,
'italic'
,
'underline'
,
'strike'
],
// toggled buttons
[
'blockquote'
,
'code-block'
],
[{
'header'
:
1
},
{
'header'
:
2
}],
// custom button values
[{
'list'
:
'ordered'
},
{
'list'
:
'bullet'
}],
[{
'script'
:
'sub'
},
{
'script'
:
'super'
}],
// superscript/subscript
[{
'indent'
:
'-1'
},
{
'indent'
:
'+1'
}],
// outdent/indent
[{
'direction'
:
'rtl'
}],
// text direction
[{
'size'
:
[
'small'
,
false
,
'large'
,
'huge'
]
}],
// custom dropdown
[{
'header'
:
[
1
,
2
,
3
,
4
,
5
,
6
,
false
]
}],
[{
'color'
:
[]
},
{
'background'
:
[]
}],
// dropdown with defaults from theme
[{
'align'
:
[]
}],
[
'clean'
],
// remove formatting button
]
};
@
ViewChild
(
'closeModal'
)
public
childModal
?:
ElementRef
;
@
ViewChild
(
'modalDetail'
)
public
modalDetail
?:
ElementRef
;
@
ViewChild
(
"CareerClusterModel"
)
CareerClusterModel
:
any
;
@
ViewChild
(
'profileChangeInput'
)
profileChangeInputRef
!
:
ElementRef
;
dialogRef
:
any
currentContentTab
:
number
=
1
;
currentExcerptTab
:
number
=
1
;
action
=
"new"
;
allSelected
=
false
;
someSelected
=
false
;
itemsList
:
DatasourceTableModel
[]
=
[];
filterList
:
DatasourceTableModel
[]
=
[];
selectModel
:
DatasourceTableModel
=
new
MyDatasourceTableModel
();
selectedItems
=
new
Map
<
string
,
boolean
>
();
// empList: DatasourceTableModel[] = [];
// descName = 'engName';
pageIndex
=
0
;
uploaderProfile
:
FileUploader
|
undefined
;
uploadErrorMsg
:
string
=
""
;
modalStatus
:
"add"
|
"edit"
=
"add"
showPassword
=
false
tableShowPassword
:
Map
<
string
,
boolean
>
=
new
Map
<
string
,
boolean
>
()
get
searchTerm
():
string
{
return
this
.
_searchTerm
;
}
set
searchTerm
(
val
:
string
)
{
this
.
pageIndex
=
0
;
this
.
allSelected
=
false
;
this
.
_searchTerm
=
val
;
if
(
val
!=
''
)
{
this
.
filterList
=
this
.
filter
(
val
);
}
else
{
this
.
updatePagedItems
();
}
}
_searchTerm
=
""
;
constructor
(
private
datasourceTable
:
DatasourseTableService
,
public
translate
:
TranslateService
,
private
tokenService
:
TokenService
,
private
router
:
Router
,
private
dialog
:
MatDialog
,
)
{
}
getData
()
{
this
.
datasourceTable
.
getList
().
subscribe
({
next
:
(
response
:
DatasourceTableModel
[])
=>
{
this
.
itemsList
=
response
.
map
((
x
:
any
)
=>
new
MyDatasourceTableModel
(
x
));
console
.
log
(
'ข้อมูล (itemsList)'
,
this
.
itemsList
);
this
.
updatePagedItems
();
},
error
:
(
error
)
=>
{
console
.
error
(
'error cant get position'
,
error
);
swal
(
"ข้อผิดพลาด"
,
"ไม่สามารถดึงข้อมูลได้"
,
"error"
);
}
});
}
ngOnInit
():
void
{
this
.
getData
();
}
filter
(
v
:
string
)
{
return
this
.
itemsList
?.
filter
(
(
x
)
=>
x
.
companyId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
companyName
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
databaseName
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
dbType
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
password
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
portNumber
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
serverName
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
status
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
userName
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
// x.getStatus().toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete
(
item
:
DatasourceTableModel
)
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณจะไม่สามารถกู้คืนข้อมูลนี้ได้!"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"ยกเลิก"
,
"ใช่, ลบเลย!"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
const
newData
=
new
MyDatasourceTableModel
(
item
)
this
.
datasourceTable
.
delete
(
newData
).
subscribe
(
result
=>
{
swal
(
"ลบสำเร็จ!!"
,
"ลบข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnInit
();
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการลบ:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถลบข้อมูลได้"
,
"error"
);
});
}
});
}
new
()
{
this
.
action
=
'add'
;
this
.
selectModel
=
new
MyDatasourceTableModel
();
// this.selectModel.status = 1;
this
.
selectModel
.
companyId
=
""
;
this
.
selectModel
.
companyName
=
""
;
this
.
selectModel
.
databaseName
=
""
;
this
.
selectModel
.
dbType
=
""
;
this
.
selectModel
.
password
=
""
;
this
.
selectModel
.
portNumber
=
""
;
this
.
selectModel
.
serverName
=
""
;
this
.
selectModel
.
status
=
""
;
this
.
selectModel
.
userName
=
""
;
}
view
(
item
:
DatasourceTableModel
)
{
this
.
action
=
'edit'
;
this
.
selectModel
=
new
MyDatasourceTableModel
(
item
);
console
.
log
(
this
.
selectModel
);
}
save
()
{
console
.
log
(
'Before Save, selectModel is:'
,
this
.
selectModel
);
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
})
.
then
((
willSave
:
any
)
=>
{
if
(
willSave
)
{
this
.
datasourceTable
.
post
(
this
.
selectModel
).
subscribe
(
result
=>
{
console
.
log
(
result
);
swal
(
"บันทึกสำเร็จ!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
ngOnInit
();
this
.
childModal
?.
nativeElement
.
click
();
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
updatePagedItems
()
{
const
startIndex
=
this
.
pageIndex
*
10
;
const
endIndex
=
startIndex
+
10
;
this
.
filterList
=
this
.
itemsList
.
slice
(
startIndex
,
endIndex
);
}
toggleAll
(
event
:
any
)
{
this
.
allSelected
=
event
.
target
.
checked
;
this
.
selectedItems
.
clear
();
this
.
itemsList
.
forEach
(
item
=>
{
this
.
selectedItems
.
set
(
item
.
companyId
,
this
.
allSelected
);
});
this
.
someSelected
=
this
.
itemsList
.
some
(
item
=>
this
.
selectedItems
.
get
(
item
.
companyId
));
}
onCheckboxChange
(
companyId
:
string
)
{
const
isSelected
=
this
.
selectedItems
.
get
(
companyId
)
||
false
;
this
.
selectedItems
.
set
(
companyId
,
!
isSelected
);
this
.
allSelected
=
this
.
itemsList
.
every
(
item
=>
this
.
selectedItems
.
get
(
item
.
companyId
));
this
.
someSelected
=
this
.
itemsList
.
some
(
item
=>
this
.
selectedItems
.
get
(
item
.
companyId
));
}
deleteSelect
()
{
let
employeeInfo
=
''
;
this
.
selectedItems
.
forEach
((
isSelected
,
companyId
)
=>
{
if
(
isSelected
)
{
const
user
=
this
.
itemsList
.
find
(
user
=>
user
.
companyId
===
companyId
);
if
(
user
)
{
employeeInfo
+=
`
${
this
.
translate
.
instant
(
'companyName'
)}
:
${
user
.
companyName
}
\n`
;
}
}
});
swal
({
title
:
"Are you sure?"
,
text
:
employeeInfo
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"Cancel"
,
"Yes, Delete it!"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
this
.
selectedItems
.
forEach
((
isSelected
,
companyId
)
=>
{
if
(
isSelected
)
{
const
user
=
this
.
itemsList
.
find
(
user
=>
user
.
companyId
===
companyId
);
if
(
user
)
{
const
newData
=
new
MyDatasourceTableModel
(
user
)
this
.
datasourceTable
.
delete
(
newData
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnInit
();
});
}
}
});
}
});
}
selectData
(
data
:
DatasourceTableModel
)
{
this
.
selectModel
=
new
MyDatasourceTableModel
(
data
)
this
.
scrollTop
()
}
scrollTop
()
{
window
.
scrollTo
({
top
:
0
,
behavior
:
'smooth'
});
}
}
src/app/DPU/myskill-x/myportal/excel-report/excel-report.component.css
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/excel-report/excel-report.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายงาน
Excel
'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายงาน
Excel
'"
></app-page-header>
<div
class=
"box"
>
<div
class=
"relative w-full max-w-4xl mx-auto my-8 font-sans"
>
<button
(
click
)="
toggleDropdown
()"
class=
"w-full bg-white bg-gradient-to-r from-blue-600 to-blue-800 text-white font-semibold py-4 px-6 rounded-xl shadow-lg hover:from-blue-700 hover:to-blue-900 focus:outline-none focus:ring-4 focus:ring-blue-300 transition-all duration-300 ease-in-out flex items-center justify-between"
>
<span
class=
"text-xl sm:text-2xl text-primary"
>
{{ selectedTemplate ? selectedTemplate.tdesc + ' (' + selectedTemplate.fileName + ')' : 'รายงาน Excel' }}
</span>
<svg
class=
"w-6 h-6 transform transition-transform duration-300 text-primary"
[
class
.
rotate-180
]="
isDropdownOpen
"
fill=
"none"
stroke=
"currentColor"
viewBox=
"0 0 24 24"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
stroke-width=
"2"
d=
"M19 9l-7 7-7-7"
></path>
</svg>
</button>
<div
*
ngIf=
"isDropdownOpen"
class=
"absolute z-10 w-full mt-2 bg-white border border-gray-200 rounded-md shadow-lg overflow-hidden max-h-60 overflow-y-auto"
>
<ul
class=
"py-1"
>
<li
*
ngFor=
"let template of excelReportTemplates"
(
click
)="
selectTemplate
(
template
)"
class=
"px-4 py-2 hover:bg-gray-100 cursor-pointer text-gray-800 text-lg"
>
{{ template.tdesc }} ({{ template.fileName }})
</li>
<li
*
ngIf=
"excelReportTemplates.length === 0 && !loadingTemplates"
class=
"px-4 py-2 text-gray-500 text-lg"
>
ไม่พบรายการ Template
</li>
<li
*
ngIf=
"loadingTemplates"
class=
"px-4 py-2 text-gray-500 text-lg"
>
กำลังโหลด...
</li>
</ul>
</div>
</div>
<div
*
ngIf=
"selectedTemplate && excelReport"
class=
"p-6 bg-gray-100 rounded-b-xl shadow-inner transition-all duration-300 ease-in-out"
[
class
.
max-h-0
]="!
selectedTemplate
"
[
class
.
max-h-screen
]="
selectedTemplate
"
>
<div
class=
"pt-6 border-t border-gray-200 bg-white p-3 rounded-xl"
>
<h2
class=
"text-2xl font-bold text-gray-800 mb-4"
>
รายงาน Excel: {{ selectedTemplate.tdesc }}
</h2>
<p
class=
"mb-4 text-gray-700"
>
ชื่อไฟล์: {{ selectedTemplate.fileName }}
</p>
<!-- <p class="mb-4 text-gray-700">รหัส Template: {{ selectedTemplate.templateId }}</p> -->
<div
*
ngIf=
"variableSheet.length > 0"
class=
"grid grid-cols-1 md:grid-cols-2 gap-4 items-end mb-4 mt-4"
>
<ng-container
*
ngFor=
"let sheetVar of variableSheet"
>
<div
[
ngSwitch
]="
sheetVar
.
type
"
>
<label
[
for
]="
sheetVar
.
key
"
class=
"block text-gray-700 text-sm font-medium mb-1"
>
{{ sheetVar.label
}}
</label>
<ng-container
*
ngSwitchCase=
"'text'"
>
<input
type=
"text"
[
id
]="
sheetVar
.
key
"
[(
ngModel
)]="
sheetVar
.
value
"
[
placeholder
]="
sheetVar
.
tname
"
class=
"mt-1 block w-full pl-3 pr-10 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
/>
</ng-container>
<ng-container
*
ngSwitchCase=
"'calendar'"
>
<input
type=
"date"
[
id
]="
sheetVar
.
key
"
[(
ngModel
)]="
sheetVar
.
displayValue
"
(
ngModelChange
)="
formatNgbDate
(
sheetVar
.
key
,
$
event
)"
class=
"mt-1 block w-full pl-3 pr-10 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
/>
</ng-container>
<ng-container
*
ngSwitchCase=
"'list'"
>
<select
[
id
]="
sheetVar
.
key
"
[(
ngModel
)]="
sheetVar
.
value
"
class=
"mt-1 block w-full pl-3 pr-10 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
>
<option
*
ngFor=
"let opt of sheetVar.option"
[
value
]="
opt
.
value
"
>
{{ opt.text }}
</option>
</select>
</ng-container>
<ng-container
*
ngSwitchCase=
"'radio'"
>
<div
class=
"flex flex-wrap gap-4 mt-1"
>
<label
*
ngFor=
"let opt of sheetVar.option"
class=
"inline-flex items-center"
>
<input
type=
"radio"
[
name
]="
sheetVar
.
key
"
[
value
]="
opt
.
value
"
[(
ngModel
)]="
sheetVar
.
value
"
class=
"form-radio text-blue-600"
/>
<span
class=
"ml-2 text-gray-700"
>
{{ opt.text }}
</span>
</label>
</div>
</ng-container>
<ng-container
*
ngSwitchCase=
"'help'"
>
<div
class=
"relative"
>
<input
type=
"text"
[
id
]="
sheetVar
.
key
"
[(
ngModel
)]="
sheetVar
.
value
.
tdesc
"
class=
"mt-1 block w-full pl-3 pr-10 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
/>
<div
class=
"absolute inset-y-0 right-0 pr-3 flex items-center"
>
<button
type=
"button"
(
click
)="
selectData
(
sheetVar
.
key
)"
class=
"p-1 rounded-full bg-blue-500 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
<svg
class=
"h-5 w-5 text-black"
fill=
"none"
stroke=
"currentColor"
viewBox=
"0 0 24 24"
(
click
)="
openModal
(
sheetVar
,
detailModal
);
$
event
.
stopPropagation
();"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
stroke-width=
"2"
d=
"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
></path>
</svg>
</button>
</div>
</div>
</ng-container>
</div>
</ng-container>
</div>
<div
class=
"flex justify-end gap-3 mt-6"
>
<!-- <button (click)="dowloadExcelReport()"
class="bg-primary py-3 px-6 bg-green-600 text-white font-semibold rounded-lg shadow-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition duration-300 ease-in-out transform hover:scale-105">
Download Excel
</button> -->
<button
(
click
)="
printExcelReport
()"
class=
"bg-primary py-3 px-6 bg-blue-600 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-300 ease-in-out transform hover:scale-105"
>
Print Excel
</button>
</div>
</div>
</div>
</div>
<ng-template
#
detailModal
>
<h2
mat-dialog-title
clas
>
<div
class=
"text-primary"
>
รายชื่อพนักงาน
</div>
</h2>
<mat-dialog-content>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการทั้งหมด
</div>
<div
class=
"flex flex-wrap gap-2"
>
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"Search..."
aria-label=
".form-control-sm example"
[(
ngModel
)]="
searchModal
"
(
ngModelChange
)="
updateModalPagedItems
()"
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead>
<tr
class=
"border-b border-defaultborder bg-primary"
>
<th
scope=
"col"
*
ngFor=
"let head of modalDetail.text.tableHead"
class=
"text-start text-white"
>
{{ head }}
</th>
</tr>
</thead>
<tbody>
@if (modalFilterList.length > 0) {
@for (item of modalFilterList; track item.id) {
<tr
class=
"border border-defaultborder dark:border-defaultborder/10 cursor-pointer hover:bg-gray-100"
(
click
)="
selectData
(
item
)"
>
<td>
{{ item.id }}
</td>
<td>
{{ item.tdesc }}
</td>
<td>
{{ item.edesc }}
</td>
</tr>
}
} @else {
<tr>
<td
[
attr
.
colspan
]="
modalDetail
.
text
.
tableHead
.
length
"
class=
"text-center py-4 text-gray-500"
>
ไม่พบข้อมูล
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
<!-- <input type="text" [(ngModel)]="searchModal" placeholder="Search..."
(ngModelChange)="updateModalPagedItems()"
class="mt-1 block w-full pl-3 pr-10 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm mb-4" /> -->
<!-- <div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder bg-primary">
<th scope="col" *ngFor="let head of modalDetail.text.tableHead" class="text-start text-white">{{ head }}
</th>
</tr>
</thead>
<tbody>
@if (modalFilterList.length > 0) {
@for (item of modalFilterList; track item.id) {
<tr class="border border-defaultborder dark:border-defaultborder/10 cursor-pointer hover:bg-gray-100"
(click)="selectData(item)">
<td>{{ item.id }}</td>
<td>{{ item.tdesc }}</td>
<td>{{ item.edesc }}</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="modalDetail.text.tableHead.length" class="text-center py-4 text-gray-500">
ไม่พบข้อมูล
</td>
</tr>
}
</tbody>
</table>
</div>
</div> -->
<div
class=
"box-footer"
>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{ (modalPageIndex * modalPageSize) + 1 }} {{'to' | translate}} {{
Math.min((modalPageIndex + 1) * modalPageSize, totalModalItemsCount) }} {{'of' | translate}} {{
totalModalItemsCount }} {{'entries' | translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"flex items-center flex-wrap overflow-auto mt-3"
*
ngIf=
"totalModalItemsCount > 0"
>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
class=
"page-item"
[
class
.
disabled
]="
modalPageIndex =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
onModalPageChange
(
modalPageIndex
-
1
)"
>
{{'Previous' | translate}}
</a>
</li>
@for (pageNumber of totalPagesArrayInModal; track pageNumber) {
<li
class=
"page-item"
[
class
.
active
]="
modalPageIndex =
==
(
pageNumber
-
1
)"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
onModalPageChange
(
pageNumber
-
1
)"
>
{{ pageNumber }}
</a>
</li>
}
<li
class=
"page-item"
[
class
.
disabled
]="
modalPageIndex =
==
(
totalPagesArrayInModal
.
length
-
1
)"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
onModalPageChange
(
modalPageIndex
+
1
)"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions
style=
"justify-content: end; padding: 16px 20px;"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
mat-button
(
click
)="
closeDialog
()"
>
Close
</button>
</mat-dialog-actions>
</ng-template>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/excel-report/excel-report.component.spec.ts
0 → 100644
View file @
73e72e5e
/* tslint:disable:no-unused-variable */
import
{
async
,
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
By
}
from
'@angular/platform-browser'
;
import
{
DebugElement
}
from
'@angular/core'
;
import
{
ExcelReportComponent
}
from
'./excel-report.component'
;
describe
(
'ExcelReportComponent'
,
()
=>
{
let
component
:
ExcelReportComponent
;
let
fixture
:
ComponentFixture
<
ExcelReportComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
ExcelReportComponent
]
})
.
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
ExcelReportComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/DPU/myskill-x/myportal/excel-report/excel-report.component.ts
0 → 100644
View file @
73e72e5e
import
{
ChangeDetectorRef
,
Component
,
OnInit
}
from
'@angular/core'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
ActivatedRoute
,
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
ExcelReportService
}
from
'../../../services/excel-report.service'
;
import
{
NgbDate
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
FileSaver
from
'file-saver'
;
import
{
TemplateFileMiniModel
}
from
'../../../models/template-file-mini.model'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
,
TranslateService
}
from
'@ngx-translate/core'
;
export
interface
ValueDetailItem
{
id
:
string
;
tdesc
:
string
;
edesc
:
string
;
}
export
interface
ModalDetail
{
text
:
{
cardHead
:
string
,
search
:
string
[],
tableHead
:
string
[]
}
}
@
Component
({
selector
:
'app-excel-report'
,
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
],
templateUrl
:
'./excel-report.component.html'
,
styleUrls
:
[
'./excel-report.component.css'
]
})
export
class
ExcelReportComponent
implements
OnInit
{
isDropdownOpen
:
boolean
=
false
;
excelReportStartDate
:
string
=
'2025-07-09'
;
employeeId
:
string
=
''
;
// ลบ pageIndex และ _searchTerm ถ้าไม่ได้ใช้สำหรับส่วนอื่นนอก Modal
// pageIndex = 0;
// _searchTerm = "";
dialogRef
:
any
// ตัวแปรสำหรับ Pagination ของ Modal
modalPageIndex
=
0
;
// เริ่มที่ index 0 เหมือนต้นฉบับ
modalPageSize
=
10
;
// 10 รายการต่อหน้า
Math
=
Math
;
// เพื่อให้ template เข้าถึง Math ได้
readonly
maxPageButtons
=
15
;
changeDate
=
new
Date
();
select
:
any
=
{}
excelReport
?:
any
variableSheet
:
any
=
[]
loading
=
false
loadingExcel
=
false
valueDetail
:
ValueDetailItem
[]
=
[]
// ข้อมูลทั้งหมดที่ได้จาก API สำหรับ Modal
modalFilterList
:
ValueDetailItem
[]
=
[];
// <--- เพิ่มตัวแปรนี้: ข้อมูลที่ถูกแบ่งหน้าแล้วสำหรับแสดงในตาราง Modal
modalDetail
:
ModalDetail
=
{
text
:
{
cardHead
:
''
,
search
:
[],
tableHead
:
[]
}
}
keySelect
=
""
searchModal
=
""
// ใช้เป็น searchTerm สำหรับ Modal
// ลบ page และ pageSize ถ้าไม่ได้ใช้สำหรับส่วนอื่นนอก Modal
// page = 1
// pageSize = 10
// ** Updated properties for dropdown **
excelReportTemplates
:
TemplateFileMiniModel
[]
=
[];
loadingTemplates
:
boolean
=
false
;
selectedTemplate
:
TemplateFileMiniModel
|
null
=
null
;
constructor
(
private
route
:
ActivatedRoute
,
private
excelReportService
:
ExcelReportService
,
private
cdr
:
ChangeDetectorRef
,
private
dialog
:
MatDialog
,
public
translate
:
TranslateService
,
// ต้อง inject TranslateService เพื่อให้ translate pipe ทำงาน
)
{
}
ngOnInit
():
void
{
// Existing route parameter handling (if needed for direct links)
this
.
route
.
paramMap
.
subscribe
(
params
=>
{
const
rawId
=
params
.
get
(
'id'
);
if
(
rawId
)
{
const
[
id
,
queryString
]
=
rawId
.
split
(
'?'
);
const
searchParams
=
new
URLSearchParams
(
queryString
);
// Changed to searchParams for clarity
const
template
=
searchParams
.
get
(
'template'
);
const
name
=
searchParams
.
get
(
'name'
);
// If you want to pre-select a template based on URL params:
if
(
template
&&
name
)
{
// This assumes the list of templates is already loaded or will be loaded
// You might need to adjust this to wait for excelReportTemplates to be populated
this
.
excelReportService
.
getTemplateFileLists
().
subscribe
(
templates
=>
{
this
.
excelReportTemplates
=
templates
;
const
preselected
=
templates
.
find
(
t
=>
t
.
templateId
===
template
&&
t
.
fileName
===
name
);
if
(
preselected
)
{
this
.
selectedTemplate
=
preselected
;
this
.
getDataExcelReport
(
preselected
.
templateId
,
preselected
.
fileName
);
}
}
);
}
}
});
// Load templates for the dropdown when the component initializes
this
.
loadExcelReportTemplates
();
}
openModal
(
data
:
any
,
modal
:
any
)
{
this
.
searchModal
=
''
;
// รีเซ็ต search
this
.
modalPageIndex
=
0
;
// รีเซ็ต index หน้าเมื่อเปิด Modal
this
.
valueDetail
=
data
.
valueDetail
.
map
((
x
:
any
)
=>
({
id
:
x
.
id
||
''
,
tdesc
:
x
.
tdesc
||
''
,
edesc
:
x
.
edesc
||
''
}))
as
ValueDetailItem
[];
this
.
keySelect
=
data
.
key
;
this
.
modalDetail
=
{
text
:
{
cardHead
:
"Table "
+
data
.
table
,
search
:
[
"Table "
+
data
.
table
],
tableHead
:
[
'ID'
,
'detailTH'
,
'detailENG'
]
}
}
this
.
updateModalPagedItems
();
// <--- เรียก updateModalPagedItems() หลังจากโหลดข้อมูล Modal ครั้งแรก
this
.
dialogRef
=
this
.
dialog
.
open
(
modal
,{
width
:
'1100px'
,
height
:
'650px'
});
}
closeDialog
()
{
console
.
log
(
'closeDialog() called.'
);
if
(
this
.
dialogRef
)
{
this
.
dialogRef
.
close
();
this
.
dialogRef
=
undefined
;
console
.
log
(
'Modal closed and dialogRef cleared.'
);
}
else
{
console
.
log
(
'closeDialog() called, but dialogRef is undefined.'
);
}
}
// ลบ updatePagedItems() ออกไป ถ้าไม่ได้ใช้สำหรับส่วนอื่นนอก Modal
// updatePagedItems() {
// const startIndex = this.pageIndex * 10;
// const endIndex = startIndex + 10;
// this.filterList = this.itemsList.slice(startIndex, endIndex);
// }
loadExcelReportTemplates
():
void
{
this
.
loadingTemplates
=
true
;
this
.
excelReportService
.
getTemplateFileLists
().
subscribe
({
next
:
(
data
)
=>
{
this
.
excelReportTemplates
=
data
;
this
.
loadingTemplates
=
false
;
this
.
cdr
.
detectChanges
();
// ลบการเรียก updatePagedItems() ออกจากตรงนี้ด้วย ถ้าไม่ได้ใช้กับส่วนหลัก
// this.updatePagedItems();
},
error
:
(
err
)
=>
{
console
.
error
(
'Failed to load Excel report templates for dropdown'
,
err
);
this
.
loadingTemplates
=
false
;
this
.
excelReportTemplates
=
[];
this
.
cdr
.
detectChanges
();
}
});
}
toggleDropdown
():
void
{
this
.
isDropdownOpen
=
!
this
.
isDropdownOpen
;
}
selectTemplate
(
template
:
TemplateFileMiniModel
):
void
{
this
.
selectedTemplate
=
template
;
this
.
isDropdownOpen
=
false
;
this
.
cdr
.
detectChanges
();
this
.
getDataExcelReport
(
this
.
selectedTemplate
.
templateId
,
this
.
selectedTemplate
.
fileName
);
}
getDataExcelReport
(
templateId
:
string
,
fileName
:
string
)
{
this
.
loading
=
true
this
.
excelReport
=
undefined
this
.
variableSheet
=
[]
this
.
valueDetail
=
[]
this
.
excelReportService
.
getTemplateFile
(
templateId
,
fileName
).
subscribe
((
res
:
any
)
=>
{
console
.
log
(
'response'
,
res
);
this
.
excelReport
=
res
;
if
(
this
.
excelReport
&&
this
.
excelReport
.
param
&&
this
.
excelReport
.
param
.
variableSheet
)
{
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'
)
{
let
initialValueForInput
:
string
=
''
;
// ค่าสำหรับ input type="date" (YYYY-MM-DD)
let
initialValueForModel
:
string
=
''
;
// ค่าสำหรับ sheetVar.value (DD-MM-YYYY, ตามที่คุณต้องการส่งกลับไป)
let
initialNgbDate
:
NgbDate
|
null
=
null
;
if
(
data
.
valueDefault
)
{
// ถ้ามี valueDefault ให้ใช้ค่าจาก API
initialValueForModel
=
data
.
valueDefault
;
const
[
d
,
m
,
y
]
=
data
.
valueDefault
.
split
(
'-'
).
map
(
Number
);
initialNgbDate
=
new
NgbDate
(
y
,
m
,
d
);
initialValueForInput
=
`
${
y
}
-
${
String
(
m
).
padStart
(
2
,
'0'
)}
-
${
String
(
d
).
padStart
(
2
,
'0'
)}
`
;
}
else
{
// ถ้าไม่มี valueDefault ให้กำหนดเป็นวันที่ปัจจุบัน
const
today
=
new
Date
();
const
day
=
String
(
today
.
getDate
()).
padStart
(
2
,
'0'
);
const
month
=
String
(
today
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
);
const
year
=
today
.
getFullYear
();
initialValueForModel
=
`
${
day
}
-
${
month
}
-
${
year
}
`
;
initialValueForInput
=
`
${
year
}
-
${
month
}
-
${
day
}
`
;
initialNgbDate
=
new
NgbDate
(
year
,
today
.
getMonth
()
+
1
,
today
.
getDate
());
}
this
.
variableSheet
.
push
({
...
data
,
value
:
initialValueForModel
,
key
:
key
,
displayValue
:
initialValueForInput
});
this
.
select
[
key
]
=
initialNgbDate
;
}
})
}
this
.
loading
=
false
this
.
cdr
.
detectChanges
()
},
error
=>
{
console
.
error
(
"Error fetching detailed excel report:"
,
error
);
this
.
loading
=
false
// Handle error, maybe show a message to the user
this
.
cdr
.
detectChanges
()
})
}
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
=
''
}
}
valueDetailFilter
():
ValueDetailItem
[]
{
return
this
.
valueDetail
.
filter
((
item
:
ValueDetailItem
)
=>
item
.
id
.
toLowerCase
().
includes
(
this
.
searchModal
.
toLowerCase
())
||
item
.
tdesc
.
toLowerCase
().
includes
(
this
.
searchModal
.
toLowerCase
())
||
item
.
edesc
.
toLowerCase
().
includes
(
this
.
searchModal
.
toLowerCase
())
)
}
// >>>>>> เมธอดสำหรับแบ่งหน้าใน Modal (คล้าย updatePagedItems ของต้นฉบับ)
updateModalPagedItems
()
{
const
filteredData
=
this
.
valueDetailFilter
();
// ใช้ข้อมูลที่กรองแล้ว
const
startIndex
=
this
.
modalPageIndex
*
this
.
modalPageSize
;
const
endIndex
=
startIndex
+
this
.
modalPageSize
;
this
.
modalFilterList
=
filteredData
.
slice
(
startIndex
,
endIndex
);
}
// >>>>>> Getter สำหรับจำนวนรายการทั้งหมดหลังจาก filter (คล้าย itemsList.length / filterList.length)
get
totalModalItemsCount
():
number
{
return
this
.
valueDetailFilter
().
length
;
}
// >>>>>> Getter สำหรับ Array ของเลขหน้า (คล้าย Math.ceil(total / pageSize) ของต้นฉบับ)
get
totalPagesArrayInModal
():
number
[]
{
const
totalPages
=
Math
.
ceil
(
this
.
totalModalItemsCount
/
this
.
modalPageSize
);
const
pageButtons
:
number
[]
=
[];
// กำหนดขอบเขตของปุ่มที่จะแสดง
let
startPage
:
number
,
endPage
:
number
;
if
(
totalPages
<=
this
.
maxPageButtons
)
{
// ถ้าจำนวนหน้าน้อยกว่าหรือเท่ากับจำนวนปุ่มสูงสุดที่กำหนดไว้ ให้แสดงทั้งหมด
startPage
=
1
;
endPage
=
totalPages
;
}
else
{
// ถ้าจำนวนหน้ามากกว่าจำนวนปุ่มสูงสุด
const
halfButtons
=
Math
.
floor
(
this
.
maxPageButtons
/
2
);
if
(
this
.
modalPageIndex
<
halfButtons
)
{
// อยู่ใกล้จุดเริ่มต้น
startPage
=
1
;
endPage
=
this
.
maxPageButtons
;
}
else
if
(
this
.
modalPageIndex
>=
totalPages
-
halfButtons
)
{
// อยู่ใกล้จุดสิ้นสุด
startPage
=
totalPages
-
this
.
maxPageButtons
+
1
;
endPage
=
totalPages
;
}
else
{
// อยู่กลางๆ
startPage
=
this
.
modalPageIndex
-
halfButtons
+
1
;
endPage
=
this
.
modalPageIndex
+
halfButtons
;
}
}
// สร้าง Array ของเลขหน้าตามขอบเขตที่คำนวณได้
for
(
let
i
=
startPage
;
i
<=
endPage
;
i
++
)
{
pageButtons
.
push
(
i
);
}
return
pageButtons
;
}
// ... (เมธอดอื่นๆ ที่เหลือเหมือนเดิม)
selectData
(
data
:
any
)
{
const
item
=
this
.
variableSheet
.
find
((
i
:
any
)
=>
i
.
key
===
this
.
keySelect
);
if
(
item
)
item
.
value
=
data
;
this
.
closeDialog
();
}
dowloadExcelReport
()
{
this
.
loadingExcel
=
true
if
(
!
this
.
excelReport
||
!
this
.
excelReport
.
param
||
!
this
.
excelReport
.
param
.
excelFile
)
{
console
.
error
(
"No excel report selected or missing excelFile parameter."
);
this
.
loadingExcel
=
false
;
return
;
}
const
fileName
=
this
.
excelReport
.
param
.
excelFile
this
.
excelReportService
.
downloadTemplateFile
(
fileName
).
subscribe
((
res
:
any
)
=>
{
const
blob
=
new
Blob
([
res
],
{
type
:
'application/octet-stream'
});
FileSaver
.
saveAs
(
blob
,
fileName
);
this
.
loadingExcel
=
false
this
.
cdr
.
detectChanges
()
},
(
err
)
=>
{
console
.
error
(
"Error downloading excel report:"
,
err
);
this
.
loadingExcel
=
false
this
.
cdr
.
detectChanges
()
})
}
printExcelReport
():
void
{
if
(
!
this
.
selectedTemplate
||
!
this
.
excelReport
||
!
this
.
excelReport
.
param
)
{
alert
(
'Please select an Excel report template first.'
);
return
;
}
this
.
loadingExcel
=
true
;
// Use loadingExcel for print as well
const
fileName
=
this
.
excelReport
.
param
.
excelFile
;
const
paramObj
:
{
[
key
:
string
]:
string
}
=
{};
// Object to hold parameters
this
.
variableSheet
.
forEach
((
item
:
any
)
=>
{
if
(
item
.
type
===
'help'
)
{
paramObj
[
"__"
+
item
.
key
]
=
item
.
value
.
id
||
''
;
}
else
if
(
item
.
type
===
'calendar'
||
item
.
type
===
'list'
||
item
.
type
===
'radio'
||
item
.
type
===
'text'
)
{
paramObj
[
"__"
+
item
.
key
]
=
item
.
value
||
''
;
}
});
// Convert paramObj to string based on backend expectation, typically JSON.stringify
// Or if backend expects a pipe-separated string, adjust accordingly.
const
paramString
=
JSON
.
stringify
(
paramObj
);
// Common format
// const paramString = Object.entries(paramObj).map(([key, value]) => `${key}=${value}`).join('|'); // If backend expects old format
this
.
excelReportService
.
printExcelReport
({
fileName
:
fileName
,
paramObj
:
paramString
}).
subscribe
(
(
res
:
any
)
=>
{
const
blob
=
new
Blob
([
res
],
{
type
:
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
// Correct MIME type for .xlsx
FileSaver
.
saveAs
(
blob
,
fileName
);
this
.
loadingExcel
=
false
;
this
.
cdr
.
detectChanges
();
},
(
err
)
=>
{
console
.
error
(
'Error printing Excel report:'
,
err
);
this
.
loadingExcel
=
false
;
this
.
cdr
.
detectChanges
();
}
);
}
// >>>>>> เมธอดสำหรับเปลี่ยนหน้าใน Modal (คล้าย onCheckboxChange)
onModalPageChange
(
newPageIndex
:
number
):
void
{
this
.
modalPageIndex
=
newPageIndex
;
this
.
updateModalPagedItems
();
// เรียก updateModalPagedItems() เมื่อเปลี่ยนหน้า
}
}
src/app/DPU/myskill-x/myportal/home-common/home-common.component.css
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/home-common/home-common.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'
Analytics
'"
[
activeTitle
]="'
Dashboards
'"
[
title1
]="'
Analytics
'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-x-6"
>
<div
class=
"xl:col-span-7 col-span-12"
>
<div
class=
"grid grid-cols-12 gap-x-6"
>
<div
class=
"xl:col-span-4 lg:col-span-4 md:col-span-4 sm:col-span-6 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-body"
>
<div
class=
"flex flex-wrap items-center justify-between"
>
<div>
<h6
class=
"font-semibold mb-3 text-[1rem]"
>
Total Users
</h6>
<span
class=
"text-[1.5625rem] font-semibold"
>
9,789
</span>
<span
class=
"block text-success text-[0.75rem]"
>
+0.892
<i
class=
"ti ti-trending-up ms-1"
></i></span>
</div>
<div
id=
"analytics-users"
>
<apx-chart
[
series
]="
chartOptions1
.
series
"
[
chart
]="
chartOptions1
.
chart
"
[
xaxis
]="
chartOptions1
.
xaxis
"
[
dataLabels
]="
chartOptions1
.
dataLabels
"
[
colors
]="
chartOptions1
.
colors
"
[
fill
]="
chartOptions1
.
fill
"
[
markers
]="
chartOptions1
.
markers
"
[
stroke
]="
chartOptions1
.
stroke
"
></apx-chart>
</div>
</div>
</div>
</div>
</div>
<div
class=
"xl:col-span-4 lg:col-span-4 md:col-span-4 sm:col-span-6 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-body"
>
<div
class=
"flex items-center justify-between"
>
<div>
<h6
class=
"font-semibold mb-3 text-[1rem]"
>
Live Visitors
</h6>
<span
class=
"text-[1.5625rem] font-semibold"
>
12,240
</span>
<span
class=
"block text-danger text-[0.75rem]"
>
+0.59
<i
class=
"ti ti-trending-down ms-1 inline-flex"
></i></span>
</div>
<div>
<span
class=
"avatar avatar-md bg-secondary text-white"
>
<i
class=
"ri-user-3-line"
></i>
</span>
</div>
</div>
</div>
</div>
</div>
<div
class=
"xl:col-span-4 lg:col-span-4 md:col-span-4 sm:col-span-6 col-span-12"
>
<div
class=
"box overflow-hidden"
>
<div
class=
"box-body mb-3"
>
<div
class=
"flex items-center justify-between"
>
<div>
<h6
class=
"font-semibold text-primary mb-4 text-[1rem]"
>
Bounce Rate
</h6>
<span
class=
"text-[1.5625rem] flex items-center"
>
77.3%
<span
class=
" text-[0.75rem] text-warning opacity-[0.7] ms-2"
>
+0.59
<i
class=
"ti ti-arrow-big-up-line ms-1 inline-flex"
></i></span></span>
</div>
</div>
</div>
<div
id=
"analytics-bouncerate"
class=
"mt-1 w-full"
>
<apx-chart
[
series
]="
chartOptions2
.
series
"
[
chart
]="
chartOptions2
.
chart
"
[
xaxis
]="
chartOptions2
.
xaxis
"
[
dataLabels
]="
chartOptions2
.
dataLabels
"
[
colors
]="
chartOptions2
.
colors
"
[
fill
]="
chartOptions2
.
fill
"
[
markers
]="
chartOptions2
.
markers
"
[
stroke
]="
chartOptions2
.
stroke
"
></apx-chart>
</div>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
Audience Report
</div>
<div>
<button
type=
"button"
class=
"ti-btn ti-btn-primary ti-btn-wave !font-medium"
><i
class=
"ri-share-forward-line me-1 align-middle inline-block"
></i>
Export
</button>
</div>
</div>
<div
class=
"box-body"
>
<div
id=
"audienceReport"
>
<apx-chart
[
series
]="
chartOptions
.
series
"
[
chart
]="
chartOptions
.
chart
"
[
yaxis
]="
chartOptions
.
yaxis
"
[
xaxis
]="
chartOptions
.
xaxis
"
[
labels
]="
chartOptions
.
labels
"
[
stroke
]="
chartOptions
.
stroke
"
[
plotOptions
]="
chartOptions
.
plotOptions
"
[
markers
]="
chartOptions
.
markers
"
[
fill
]="
chartOptions
.
fill
"
[
tooltip
]="
chartOptions
.
tooltip
"
[
legend
]="
chartOptions
.
legend
"
[
colors
]="
chartOptions
.
colors
"
></apx-chart>
</div>
</div>
</div>
</div>
<div
class=
"xxl:col-span-6 xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
Top Countries Sessions vs Bounce Rate
</div>
<div
class=
"hs-dropdown ti-dropdown"
>
<a
href=
"javascript:void(0);"
class=
"px-2 font-normal text-[0.75rem] text-[#8c9097] dark:text-white/50"
aria-expanded=
"false"
>
View All
<i
class=
"ri-arrow-down-s-line align-middle ms-1 inline-block"
></i>
</a>
<ul
class=
"hs-dropdown-menu ti-dropdown-menu hidden"
role=
"menu"
>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
Today
</a></li>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
This Week
</a></li>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
Last Week
</a></li>
</ul>
</div>
</div>
<div
class=
"box-body"
>
<div
id=
"country-sessions"
>
<apx-chart
[
series
]="
chartOptions3
.
series
"
[
chart
]="
chartOptions3
.
chart
"
[
yaxis
]="
chartOptions3
.
yaxis
"
[
xaxis
]="
chartOptions3
.
xaxis
"
[
labels
]="
chartOptions3
.
labels
"
[
stroke
]="
chartOptions3
.
stroke
"
[
plotOptions
]="
chartOptions3
.
plotOptions
"
[
markers
]="
chartOptions3
.
markers
"
[
fill
]="
chartOptions3
.
fill
"
[
tooltip
]="
chartOptions3
.
tooltip
"
[
legend
]="
chartOptions3
.
legend
"
[
colors
]="
chartOptions3
.
colors
"
></apx-chart>
</div>
</div>
</div>
</div>
<div
class=
"xxl:col-span-6 xl:col-span-12 col-span-12"
>
<div
class=
"box overflow-hidden"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
Traffic Sources
</div>
<div
class=
"hs-dropdown ti-dropdown"
>
<a
href=
"javascript:void(0);"
class=
"px-2 font-normal text-[0.75rem] text-[#8c9097] dark:text-white/50"
aria-expanded=
"false"
>
View All
<i
class=
"ri-arrow-down-s-line align-middle ms-1 inline-block"
></i>
</a>
<ul
class=
"hs-dropdown-menu ti-dropdown-menu hidden"
role=
"menu"
>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
Today
</a></li>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
This Week
</a></li>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
Last Week
</a></li>
</ul>
</div>
</div>
<div
class=
"box-body !p-0"
>
<div
class=
"table-responsive"
>
<table
class=
"table table-hover whitespace-nowrap min-w-full"
>
<thead>
<tr>
<th
scope=
"col"
class=
"text-start"
>
Browser
</th>
<th
scope=
"col"
class=
"text-start"
>
Sessions
</th>
<th
scope=
"col"
class=
"text-start"
>
Traffic
</th>
</tr>
</thead>
<tbody>
<tr
class=
"border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10"
>
<td>
<div
class=
"flex items-center"
>
<span
class=
"avatar avatar-rounded avatar-sm p-2 bg-light me-2"
>
<i
class=
"ri-google-fill text-[1.125rem] text-primary"
></i>
</span>
<div
class=
"font-semibold"
>
Google
</div>
</div>
</td>
<td>
<span><i
class=
"ri-arrow-up-s-fill me-1 text-success align-middle text-[1.125rem]"
></i>
23,379
</span>
</td>
<td>
<div
class=
"progress progress-xs"
>
<div
class=
"progress-bar bg-primary w-[78%]"
aria-valuenow=
"78"
aria-valuemin=
"0"
aria-valuemax=
"100"
>
</div>
</div>
</td>
</tr>
<tr
class=
"border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10"
>
<td>
<div
class=
"flex items-center"
>
<span
class=
"avatar avatar-rounded avatar-sm p-2 bg-light me-2"
>
<i
class=
"ri-safari-line text-[1.125rem] text-secondary"
></i>
</span>
<div
class=
"font-semibold"
>
Safari
</div>
</div>
</td>
<td>
<span><i
class=
"ri-arrow-up-s-fill me-1 text-success align-middle text-[1.125rem]"
></i>
78,973
</span>
</td>
<td>
<div
class=
"progress progress-xs"
>
<div
class=
"progress-bar bg-primary w-[32%]"
aria-valuenow=
"32"
aria-valuemin=
"0"
aria-valuemax=
"100"
>
</div>
</div>
</td>
</tr>
<tr
class=
"border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10"
>
<td>
<div
class=
"flex items-center"
>
<span
class=
"avatar avatar-rounded avatar-sm p-2 bg-light me-2"
>
<i
class=
"ri-opera-fill text-[1.125rem] text-success"
></i>
</span>
<div
class=
"font-semibold"
>
Opera
</div>
</div>
</td>
<td>
<span><i
class=
"ri-arrow-down-s-fill me-1 text-danger align-middle text-[1.125rem]"
></i>
12,457
</span>
</td>
<td>
<div
class=
"progress progress-xs"
>
<div
class=
"progress-bar bg-primary w-[21%]"
aria-valuenow=
"21"
aria-valuemin=
"0"
aria-valuemax=
"100"
>
</div>
</div>
</td>
</tr>
<tr
class=
"border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10"
>
<td>
<div
class=
"flex items-center"
>
<span
class=
"avatar avatar-rounded avatar-sm p-2 bg-light me-2"
>
<i
class=
"ri-edge-fill text-[1.125rem] text-info"
></i>
</span>
<div
class=
"font-semibold"
>
Edge
</div>
</div>
</td>
<td>
<span><i
class=
"ri-arrow-up-s-fill me-1 text-success align-middle text-[1.125rem]"
></i>
8,570
</span>
</td>
<td>
<div
class=
"progress progress-xs"
>
<div
class=
"progress-bar bg-primary w-1/4"
aria-valuenow=
"25"
aria-valuemin=
"0"
aria-valuemax=
"100"
>
</div>
</div>
</td>
</tr>
<tr
class=
"border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10"
>
<td>
<div
class=
"flex items-center"
>
<span
class=
"avatar avatar-rounded avatar-sm p-2 bg-light me-2"
>
<i
class=
"ri-firefox-fill text-[1.125rem] text-warning"
></i>
</span>
<div
class=
"font-semibold"
>
Firefox
</div>
</div>
</td>
<td>
<span><i
class=
"ri-arrow-down-s-fill me-1 text-danger align-middle text-[1.125rem]"
></i>
6,135
</span>
</td>
<td>
<div
class=
"progress progress-xs"
>
<div
class=
"progress-bar bg-primary w-[35%]"
aria-valuenow=
"35"
aria-valuemin=
"0"
aria-valuemax=
"100"
>
</div>
</div>
</td>
</tr>
<tr
class=
"border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10"
>
<td
class=
"border-bottom-0"
>
<div
class=
"flex items-center"
>
<span
class=
"avatar avatar-rounded avatar-sm p-2 bg-light me-2"
>
<i
class=
"ri-ubuntu-fill text-[1.125rem] text-danger"
></i>
</span>
<div
class=
"font-semibold"
>
Ubuntu
</div>
</div>
</td>
<td
class=
"border-bottom-0"
>
<span><i
class=
"ri-arrow-up-s-fill me-1 text-success align-middle text-[1.125rem]"
></i>
4,789
</span>
</td>
<td
class=
"border-bottom-0"
>
<div
class=
"progress progress-xs"
>
<div
class=
"progress-bar bg-primary w-[12%]"
aria-valuenow=
"12"
aria-valuemin=
"0"
aria-valuemax=
"100"
>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"xl:col-span-5 col-span-12"
>
<div
class=
"grid grid-cols-12 gap-x-6"
>
<div
class=
"xxl:col-span-5 cxl:ol-span-12 col-span-12"
>
<div
class=
"box custom-card upgrade-card text-white"
>
<div
class=
"box-body text-white"
>
<span
class=
"avatar avatar-xxl !border-0"
>
<img
src=
"./assets/images/media/media-84.png"
alt=
""
>
</span>
<div
class=
"upgrade-card-content"
>
<span
class=
"opacity-[0.7] font-normal mb-1 !text-white"
>
Plan is expiring !
</span>
<span
class=
"text-[0.9375rem] font-semibold block mb-[3rem] upgrade-text !text-white"
>
Upgrade to premium
</span>
<button
type=
"button"
class=
"ti-btn !py-1 !px-2 bg-light text-defaulttextcolor !text-[0.75rem] font-medium ti-btn-wave"
>
Upgrade Now
</button>
</div>
</div>
</div>
<div
class=
"box"
>
<div
class=
"box-body !p-1"
>
<div
class=
"flex items-center flex-wrap"
>
<div
id=
"analytics-followers"
>
<apx-chart
[
series
]="
optionsCircle2
.
series
"
[
chart
]="
optionsCircle2
.
chart
"
[
xaxis
]="
optionsCircle2
.
xaxis
"
[
colors
]="
optionsCircle2
.
colors
"
[
labels
]="
optionsCircle2
.
labels
"
[
legend
]="
optionsCircle2
.
legend
"
[
stroke
]="
optionsCircle2
.
stroke
"
[
tooltip
]="
optionsCircle2
.
tooltip
"
[
plotOptions
]="
optionsCircle2
.
plotOptions
"
[
dataLabels
]="
optionsCircle2
.
dataLabels
"
></apx-chart>
</div>
<div
class=
"ms-1"
>
<p
class=
"mb-1 text-[#8c9097] dark:text-white/50"
>
Impressions
</p>
<h5
class=
"font-semibold mb-0 text-[1.25rem]"
>
9,903
</h5>
</div>
</div>
</div>
</div>
<div
class=
"box"
>
<div
class=
"box-body !p-1"
>
<div
class=
"flex items-center flex-wrap"
>
<div
id=
"analytics-views"
>
<apx-chart
[
series
]="
optionsCircle3
.
series
"
[
chart
]="
optionsCircle3
.
chart
"
[
xaxis
]="
optionsCircle3
.
xaxis
"
[
colors
]="
optionsCircle3
.
colors
"
[
labels
]="
optionsCircle3
.
labels
"
[
legend
]="
optionsCircle3
.
legend
"
[
stroke
]="
optionsCircle3
.
stroke
"
[
tooltip
]="
optionsCircle3
.
tooltip
"
[
plotOptions
]="
optionsCircle3
.
plotOptions
"
[
dataLabels
]="
optionsCircle3
.
dataLabels
"
></apx-chart>
</div>
<div
class=
"ms-1"
>
<p
class=
"mb-1 text-[#8c9097] dark:text-white/50"
>
Clicks
</p>
<h5
class=
"font-semibold mb-0 text-[1.25rem]"
>
16,789
</h5>
</div>
</div>
</div>
</div>
</div>
<div
class=
"xxl:col-span-7 xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
Sessions By Device
</div>
<div>
<button
type=
"button"
class=
"ti-btn ti-btn-primary 1 !text-[0.85rem] !m-0 !font-medium"
>
View All
</button>
</div>
</div>
<div
class=
"box-body !my-2 !py-6 !px-2"
>
<div
id=
"sessions"
>
<apx-chart
[
series
]="
optionsCircle1
.
series
"
[
chart
]="
optionsCircle1
.
chart
"
[
xaxis
]="
optionsCircle1
.
xaxis
"
[
labels
]="
optionsCircle1
.
labels
"
[
legend
]="
optionsCircle1
.
legend
"
[
stroke
]="
optionsCircle1
.
stroke
"
[
tooltip
]="
optionsCircle1
.
tooltip
"
[
plotOptions
]="
optionsCircle1
.
plotOptions
"
[
dataLabels
]="
optionsCircle1
.
dataLabels
"[
colors
]="
optionsCircle1
.
colors
"
></apx-chart>
</div>
</div>
<div
class=
"box-footer !p-0"
>
<div
class=
"grid grid-cols-12 justify-center"
>
<div
class=
"col-span-3 pe-0 text-center"
>
<div
class=
"sm:p-4 p-2 "
>
<span
class=
"text-[#8c9097] dark:text-white/50 text-[0.6875rem]"
>
Mobile
</span>
<span
class=
"block text-[1rem] font-semibold"
>
68.3%
</span>
</div>
</div>
<div
class=
"col-span-3 px-0 text-center"
>
<div
class=
"sm:p-4 p-2"
>
<span
class=
"text-[#8c9097] dark:text-white/50 text-[0.6875rem]"
>
Tablet
</span>
<span
class=
"block text-[1rem] font-semibold"
>
17.68%
</span>
</div>
</div>
<div
class=
"col-span-3 px-0 text-center"
>
<div
class=
"sm:p-4 p-2 "
>
<span
class=
"text-[#8c9097] dark:text-white/50 text-[0.6875rem]"
>
Desktop
</span>
<span
class=
"block text-[1rem] font-semibold"
>
10.5%
</span>
</div>
</div>
<div
class=
"col-span-3 px-0 text-center"
>
<div
class=
"sm:p-4 p-2"
>
<span
class=
"text-[#8c9097] dark:text-white/50 text-[0.6875rem]"
>
Others
</span>
<span
class=
"block text-[1rem] font-semibold"
>
5.16%
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
Sessions Duration By New Users
</div>
<div
class=
"hs-dropdown ti-dropdown"
>
<a
href=
"javascript:void(0);"
class=
"px-2 font-normal text-[0.75rem] text-[#8c9097] dark:text-white/50"
aria-expanded=
"false"
>
View All
<i
class=
"ri-arrow-down-s-line align-middle ms-1 inline-block"
></i>
</a>
<ul
class=
"hs-dropdown-menu ti-dropdown-menu hidden"
role=
"menu"
>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
Today
</a></li>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
This Week
</a></li>
<li><a
class=
"ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href=
"javascript:void(0);"
>
Last Week
</a></li>
</ul>
</div>
</div>
<div
class=
"box-body"
>
<div
id=
"session-users"
>
<apx-chart
[
series
]="
chartOptions4
.
series
"
[
chart
]="
chartOptions4
.
chart
"
[
yaxis
]="
chartOptions4
.
yaxis
"
[
xaxis
]="
chartOptions4
.
xaxis
"
[
labels
]="
chartOptions4
.
labels
"
[
stroke
]="
chartOptions4
.
stroke
"
[
plotOptions
]="
chartOptions4
.
plotOptions
"
[
markers
]="
chartOptions4
.
markers
"
[
fill
]="
chartOptions4
.
fill
"
[
tooltip
]="
chartOptions4
.
tooltip
"
[
colors
]="
chartOptions4
.
colors
"
[
legend
]="
chartOptions4
.
legend
"
></apx-chart>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
src/app/DPU/myskill-x/myportal/home-common/home-common.component.spec.ts
0 → 100644
View file @
73e72e5e
/* tslint:disable:no-unused-variable */
import
{
async
,
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
By
}
from
'@angular/platform-browser'
;
import
{
DebugElement
}
from
'@angular/core'
;
import
{
HomeCommonComponent
}
from
'./home-common.component'
;
describe
(
'HomeCommonComponent'
,
()
=>
{
let
component
:
HomeCommonComponent
;
let
fixture
:
ComponentFixture
<
HomeCommonComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
HomeCommonComponent
]
})
.
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
HomeCommonComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/DPU/myskill-x/myportal/home-common/home-common.component.ts
0 → 100644
View file @
73e72e5e
import
{
ChangeDetectorRef
,
Component
,
ElementRef
,
Renderer2
}
from
'@angular/core'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
ApexCharts
from
'apexcharts'
import
{
SharedModule
}
from
'../../../shared/shared.module'
;
import
{
NgApexchartsModule
}
from
'ng-apexcharts'
;
@
Component
({
selector
:
'app-home-common'
,
imports
:
[
RouterModule
,
SharedModule
,
NgApexchartsModule
],
standalone
:
true
,
templateUrl
:
'./home-common.component.html'
,
styleUrls
:
[
'./home-common.component.css'
]
})
export
class
HomeCommonComponent
{
chartOptions1
:
any
;
chartOptions2
:
any
;
chartOptions3
:
any
chartOptions
:
any
;
optionsCircle1
:
any
;
chartOptions4
:
any
;
optionsCircle2
:
any
;
optionsCircle3
:
any
constructor
(
private
el
:
ElementRef
,
private
renderer
:
Renderer2
,
private
cdr
:
ChangeDetectorRef
){
this
.
chartOptions1
=
{
chart
:
{
type
:
'line'
,
height
:
40
,
width
:
120
,
sparkline
:
{
enabled
:
true
},
dropShadow
:
{
enabled
:
true
,
top
:
0
,
left
:
0
,
blur
:
3
,
color
:
'#000'
,
opacity
:
0.1
},
},
grid
:
{
show
:
false
,
xaxis
:
{
lines
:
{
show
:
false
}
},
yaxis
:
{
lines
:
{
show
:
false
}
},
},
stroke
:
{
show
:
true
,
curve
:
'straight'
,
lineCap
:
'butt'
,
width
:
1.5
,
dashArray
:
0
,
},
fill
:
{
gradient
:
{
enabled
:
false
}
},
series
:
[{
name
:
'Value'
,
data
:
[
0
,
21
,
54
,
38
,
56
,
24
,
65
]
}],
yaxis
:
{
min
:
0
,
show
:
false
},
xaxis
:
{
show
:
false
,
axisTicks
:
{
show
:
false
,
axisBorder
:
{
show
:
false
},
},
axisBorder
:
{
show
:
false
}
},
colors
:
[
'#23b7e5'
],
}
this
.
chartOptions2
=
{
chart
:
{
type
:
'line'
,
height
:
45
,
sparkline
:
{
enabled
:
true
},
dropShadow
:
{
enabled
:
true
,
top
:
0
,
left
:
0
,
blur
:
1
,
color
:
'#fff'
,
opacity
:
0.05
}
},
stroke
:
{
show
:
true
,
curve
:
'smooth'
,
lineCap
:
'butt'
,
width
:
2
,
dashArray
:
0
,
},
fill
:
{
gradient
:
{
enabled
:
false
}
},
series
:
[{
name
:
'Value'
,
data
:
[
54
,
38
,
56
,
35
,
65
,
43
,
53
,
45
,
62
,
80
,
35
,
48
]
}],
yaxis
:
{
min
:
0
,
show
:
false
,
axisBorder
:
{
show
:
false
},
},
xaxis
:
{
axisBorder
:
{
show
:
false
},
},
colors
:
[
"rgba(132, 90, 223, 0.1)"
],
tooltip
:
{
enabled
:
false
,
}
}
this
.
optionsCircle1
=
{
series
:
[
1754
,
1234
,
878
,
270
],
labels
:
[
"Mobile"
,
"Tablet"
,
"Desktop"
,
"Others"
],
chart
:
{
height
:
250
,
type
:
'donut'
,
},
dataLabels
:
{
enabled
:
false
,
},
legend
:
{
show
:
false
,
},
stroke
:
{
show
:
true
,
curve
:
'smooth'
,
lineCap
:
'round'
,
colors
:
[
"#fff"
],
width
:
0
,
dashArray
:
0
,
},
plotOptions
:
{
pie
:
{
expandOnClick
:
false
,
donut
:
{
size
:
'80%'
,
background
:
'transparent'
,
labels
:
{
show
:
true
,
name
:
{
show
:
true
,
fontSize
:
'20px'
,
color
:
'#495057'
,
offsetY
:
-
4
},
value
:
{
show
:
true
,
fontSize
:
'18px'
,
offsetY
:
8
,
formatter
:
function
(
val
:
string
)
{
return
val
+
"%"
;
}
},
total
:
{
show
:
true
,
showAlways
:
true
,
label
:
'Total'
,
fontSize
:
'22px'
,
fontWeight
:
600
,
color
:
'#495057'
,
}
}
},
},
},
colors
:
[
"rgba(132, 90, 223, 1)"
,
"rgba(35, 183, 229, 1)"
,
"rgba(38, 191, 148, 1)"
,
"rgba(245, 184, 73, 1)"
,],
};
this
.
chartOptions
=
{
series
:
[
{
name
:
'Views'
,
type
:
'column'
,
data
:
[
23
,
11
,
22
,
27
,
13
,
22
,
37
,
21
,
44
,
22
,
45
,
35
],
},
{
name
:
'Followers'
,
type
:
'line'
,
data
:
[
44
,
55
,
41
,
67
,
22
,
43
,
21
,
41
,
56
,
27
,
43
,
27
],
},
],
chart
:
{
toolbar
:
{
show
:
false
,
},
type
:
'line'
,
height
:
250
,
},
grid
:
{
borderColor
:
'#f1f1f1'
,
strokeDashArray
:
3
,
},
labels
:
[
'Jan'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
,
'Jul'
,
'Aug'
,
'Sep'
,
'Oct'
,
'Nov'
,
'Dec'
,
],
dataLabels
:
{
enabled
:
false
,
},
stroke
:
{
width
:
[
1
,
1.1
],
curve
:
[
'straight'
,
'smooth'
],
},
legend
:
{
show
:
true
,
position
:
'top'
,
},
xaxis
:
{
axisBorder
:
{
color
:
'#e9e9e9'
,
},
},
plotOptions
:
{
bar
:
{
columnWidth
:
'20%'
,
borderRadius
:
2
,
},
},
colors
:
[
"rgba(132, 90, 223, 1)"
,
'#23b7e5'
],
};
this
.
chartOptions3
=
{
series
:
[
{
name
:
'Session'
,
data
:
[
24
,
23
,
20
,
25
,
27
,
26
,
24
,
23
,
23
,
25
,
23
,
23
],
type
:
'line'
,
},
{
name
:
'Bounce Rate'
,
data
:
[
20
,
23
,
26
,
22
,
20
,
26
,
28
,
26
,
22
,
27
,
25
,
26
],
type
:
'bar'
,
},
],
chart
:
{
height
:
328
,
zoom
:
{
enabled
:
false
},
},
dataLabels
:
{
enabled
:
false
,
},
grid
:
{
borderColor
:
'#f1f1f1'
,
strokeDashArray
:
3
},
legend
:
{
show
:
true
,
position
:
'top'
,
},
plotOptions
:
{
bar
:
{
borderRadius
:
5
,
columnWidth
:
"40%"
,
dataLabels
:
{
position
:
'top'
,
// top, center, bottom
},
}
},
colors
:
[
"rgb(132, 90, 223)"
,
"#ededed"
],
stroke
:
{
curve
:
[
'smooth'
,
'stepline'
],
width
:
[
2
,
0
],
},
xaxis
:
{
categories
:
[
'Jan'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
,
'Jul'
,
'Aug'
,
'Sep'
,
'Oct'
,
'Nov'
,
'Dec'
],
axisBorder
:
{
color
:
'#e9e9e9'
,
},
}
};
this
.
chartOptions4
=
{
series
:
[
{
name
:
'New Users'
,
data
:
[
32
,
15
,
63
,
51
,
36
,
62
,
99
,
42
,
78
,
76
,
32
,
120
],
},
{
name
:
'Sessions'
,
data
:
[
56
,
58
,
38
,
50
,
64
,
45
,
55
,
32
,
15
,
63
,
51
,
136
],
},
{
name
:
'Avg Session Duration'
,
data
:
[
48
,
29
,
50
,
69
,
20
,
59
,
52
,
12
,
48
,
28
,
17
,
98
],
},
],
chart
:
{
height
:
425
,
type
:
'line'
,
toolbar
:
{
show
:
false
,
},
background
:
'none'
,
fill
:
'#fff'
,
},
grid
:
{
borderColor
:
'#f2f6f7'
,
},
colors
:
[
'rgb(132, 90, 223)'
,
'#23b7e5'
,
'#f5b849'
],
background
:
'transparent'
,
dataLabels
:
{
enabled
:
false
,
},
stroke
:
{
curve
:
'straight'
,
width
:
3
,
},
legend
:
{
show
:
true
,
position
:
'top'
,
},
xaxis
:
{
categories
:
[
'Jan'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
,
'Jul'
,
'Aug'
,
'Sep'
,
'Oct'
,
'Nov'
,
'Dec'
,
],
show
:
false
,
axisBorder
:
{
show
:
false
,
color
:
'rgba(119, 119, 142, 0.05)'
,
offsetX
:
0
,
offsetY
:
0
,
},
axisTicks
:
{
show
:
false
,
borderType
:
'solid'
,
color
:
'rgba(119, 119, 142, 0.05)'
,
width
:
6
,
offsetX
:
0
,
offsetY
:
0
,
},
labels
:
{
rotate
:
-
90
,
},
},
yaxis
:
{
show
:
false
,
axisBorder
:
{
show
:
false
,
},
axisTicks
:
{
show
:
false
,
},
},
tooltip
:
{
x
:
{
format
:
'dd/MM/yy HH:mm'
,
},
},
};
this
.
optionsCircle2
=
{
chart
:
{
height
:
120
,
width
:
100
,
type
:
"radialBar"
,
},
series
:
[
48
],
colors
:
[
"#23b7e5"
],
plotOptions
:
{
radialBar
:
{
hollow
:
{
margin
:
0
,
size
:
"50%"
,
background
:
"#fff"
},
dataLabels
:
{
name
:
{
offsetY
:
-
10
,
color
:
"#4b9bfa"
,
fontSize
:
"10px"
,
show
:
false
},
value
:
{
offsetY
:
5
,
color
:
"#4b9bfa"
,
fontSize
:
"12px"
,
show
:
true
,
fontWeight
:
800
}
}
}
},
stroke
:
{
lineCap
:
"round"
},
labels
:
[
"Followers"
]
}
this
.
optionsCircle3
=
{
chart
:
{
height
:
120
,
width
:
100
,
type
:
"radialBar"
,
},
series
:
[
65
],
colors
:
[
"#ffc107"
],
plotOptions
:
{
radialBar
:
{
hollow
:
{
margin
:
0
,
size
:
"50%"
,
background
:
"#fff"
},
dataLabels
:
{
name
:
{
offsetY
:
-
10
,
color
:
"#4b9bfa"
,
fontSize
:
"10px"
,
show
:
false
},
value
:
{
offsetY
:
5
,
color
:
"#4b9bfa"
,
fontSize
:
"12px"
,
show
:
true
,
fontWeight
:
800
},
}
}
},
stroke
:
{
lineCap
:
"round"
},
labels
:
[
"Views"
]
}
}
// ngAfterViewInit(): void {
// this.setChartWidth();
// this.cdr.detectChanges();
// }
// private setChartWidth(): void {
// const chartContainer = this.el.nativeElement.querySelector('.chart-container');
// const chartContainer1 = this.el.nativeElement.querySelector('.chart-container1');
// const chartContainer2 = this.el.nativeElement.querySelector('.chart-container2');
// const chartContainer3 = this.el.nativeElement.querySelector('.chart-container3');
// const chart = new ApexCharts(chartContainer1, this.chartOptions);
// const chart1 = new ApexCharts(chartContainer, this.optionsCircle1);
// const chart2 = new ApexCharts(chartContainer2, this.chartOptions3);
// const chart3 = new ApexCharts(chartContainer3, this.chartOptions4);
// chart.render();
// chart2.render();
// chart1.render();
// chart3.render();
// }
}
src/app/DPU/myskill-x/myportal/list-course/list-course.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการหลักสูตร'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'อัพโหลดรายการหลักสูตร'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
{{ 'All List' | translate}}
</div>
<div
class=
"flex flex-wrap gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(
click
)="
openEditExcelDialog
()"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'Create' |
translate}}
</a>
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหาบริษัท"
aria-label=
".form-control-sm example"
[(
ngModel
)]="
search
"
(
ngModelChange
)="
onSearchChange
()"
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead>
<tr
class=
"border-b border-defaultborder text-white"
style=
"background-color: #49b6f5;"
>
<th
scope=
"col"
class=
"text-start"
>
#
</th>
<th
scope=
"col"
class=
"text-start"
>
รูปภาพ
</th>
<th
scope=
"col"
class=
"text-start"
>
ชื่อ
</th>
<th
scope=
"col"
class=
"text-start"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"text-start"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"text-start"
>
ไฟล์
</th>
<th
scope=
"col"
class=
"text-start"
>
สถานะ
</th>
<th
scope=
"col"
class=
"text-start"
>
การจัดการ
</th>
</tr>
</thead>
<tbody>
<tr
class=
"border border-defaultborder dark:border-defaultborder/10"
*
ngFor=
"let data of paginatedCourses; let i = index"
>
<td>
<div>
<span
class=
"block mb-1"
>
{{pageIndex * pageSize + i + 1}}
</span>
</div>
</td>
<td>
<div
class=
"flex items-center"
>
<span
class=
"p-3 me-1"
style=
"width: 200px;"
>
<img
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeDialog
(
data
.
getImage
())"
id=
"profile-img"
class=
"border-radius-1 cursor-pointer"
style=
"width: 180px; height: 120px; object-fit: cover;"
>
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{ data.thName }}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{ data.thDesc }}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0 cursor-pointer active: hover:text-danger"
(
click
)="
openLink
(
data
.
link1
)"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0 cursor-pointer active hover:text-success"
(
click
)="
downloadFile
(
data
.
logId
)"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td>
<div>
<ng-container
*
ngIf=
"data.status === 0"
>
<span
class=
"badge bg-amber-300 text-white"
>
รออนุมัติ
</span>
</ng-container>
<ng-container
*
ngIf=
"data.status === 1"
>
<span
class=
"badge bg-success text-white"
>
เปิดใช้งาน
</span>
</ng-container>
<ng-container
*
ngIf=
"data.status === 2"
>
<span
class=
"badge bg-gray-500 text-white"
>
ไม่อนุมัติ
</span>
</ng-container>
</div>
</td>
<td>
<div
class=
"flex flex-row items-center !gap-2 "
>
<a
aria-label=
"anchor"
(
click
)="
openEditExcelDialog
(
data
)"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
>
<i
class=
"ri-pencil-line"
></i>
</a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
(
click
)="
deleteFile
(
data
)"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"
>
<i
class=
"ri-delete-bin-line"
></i>
</a>
</div>
</td>
</tr>
<tr
*
ngIf=
"paginatedCourses.length === 0"
>
<td
colspan=
"9"
class=
"text-center py-4"
>
ไม่พบข้อมูล
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
>
<div
class=
"mb-2 sm:mb-0"
>
<select
class=
"custom-select m-r-5"
style=
"width: auto"
[(
ngModel
)]="
pageSize
"
(
ngModelChange
)="
goToPage
(
0
)"
>
<option
[
ngValue
]="
10
"
>
รายการต่อหน้า: 10
</option>
<option
[
ngValue
]="
50
"
>
รายการต่อหน้า: 50
</option>
<option
[
ngValue
]="
100
"
>
รายการต่อหน้า: 100
</option>
</select>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0 flex"
>
<li
class=
"page-item"
[
class
.
disabled
]="
pageIndex =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
goToPage
(
pageIndex
-
1
)"
>
{{ 'Previous' | translate }}
</a>
</li>
<ng-container
*
ngFor=
"let p of pages"
>
<li
class=
"page-item"
[
class
.
active
]="
p =
==
pageIndex
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
[
class
.
active
]="
p =
==
pageIndex
"
(
click
)="
goToPage
(
p
)"
>
{{ p + 1 }}
</a>
</li>
</ng-container>
<li
class=
"page-item"
[
class
.
disabled
]="
pageIndex =
==
totalPages
-
1
||
totalPages =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
goToPage
(
pageIndex
+
1
)"
>
{{ 'Next' | translate }}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template
#
editTemplateModal
let-modal
>
<div
class=
"modal-headtitle ti-modal-header flex justify-between items-center p-4"
style=
"background-color: #fefbfb;"
>
<h3
class=
"modal-title text-sm font-semibold text-defaulttextcolor"
id=
"edittemplateLabel"
>
{{ checkEdit ? ('แก้ไขไฟล์หลักสูตร' | translate) : ('เพิ่มไฟล์หลักสูตร' | translate) }}
</h3>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeDialog
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{ 'Close' | translate }}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"w-full flex justify-end"
>
<div
class=
"absolute flex"
>
<div
class=
"px-1"
>
</div>
</div>
</div>
<mat-dialog-content
style=
"padding: 0px; padding-left: 20px; padding-right: 20px;"
>
<div
class=
"box p-9 top-4"
>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"nameth"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อ (ไทย)' | translate }}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"nameth"
[(
ngModel
)]="
modelCourse
.
thName
"
name=
"thName"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"nameeng"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อ (อังกฤษ)' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"nameeng"
[(
ngModel
)]="
modelCourse
.
engName
"
name=
"engName"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"thDesc"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รายละเอียด (ไทย)' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"thDesc"
[(
ngModel
)]="
modelCourse
.
thDesc
"
rows=
"3"
name=
"thDesc"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"engDesc"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รายละเอียด (อังกฤษ)' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"engDesc"
[(
ngModel
)]="
modelCourse
.
engDesc
"
rows=
"3"
name=
"engDesc"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"objective"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'วัตถุประสงค์' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"objective"
[(
ngModel
)]="
modelCourse
.
objective
"
rows=
"2"
name=
"objective"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"courseOutline"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ตัวอย่างบทเรียน' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"courseOutline"
[(
ngModel
)]="
modelCourse
.
courseOutline
"
rows=
"2"
name=
"courseOutline"
></textarea>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"courseType"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ประเภทหลักสูตร' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"courseType"
[(
ngModel
)]="
modelCourse
.
courseType
"
name=
"courseType"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"courseLevel"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ระดับผู้เรียน' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"courseLevel"
[(
ngModel
)]="
modelCourse
.
courseLevel
"
name=
"courseLevel"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"courseTime"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ระยะเวลาในการเรียนรู้' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"courseTime"
[(
ngModel
)]="
modelCourse
.
courseTime
"
name=
"courseTime"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"courseTrainer"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อผู้สอน' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"courseTrainer"
[(
ngModel
)]="
modelCourse
.
courseTrainer
"
name=
"courseTrainer"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"courseTrainerDetail"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ประวัติผู้สอน' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"courseTrainerDetail"
[(
ngModel
)]="
modelCourse
.
courseTrainerDetail
"
rows=
"3"
name=
"courseTrainerDetail"
></textarea>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"linkExample"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'Link ตัวอย่าง' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"linkExample"
[(
ngModel
)]="
modelCourse
.
link1
"
name=
"link1"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"fileUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ไฟล์อัพโหลด' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"fileUpload"
(
change
)="
onSelectFile
($
event
)"
>
<button
*
ngIf=
"modelCourse.courseObj && checkEdit"
(
click
)="
downloadFile
(
modelCourse
.
logId
)"
class=
"ti-btn ti-btn-primary flex-shrink-0 px-4 py-2 rounded-md transition-all duration-200"
>
<i
class=
"fas fa-download mr-1"
></i>
{{ 'ดาวน์โหลด' | translate }}
</button>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.xlsx *.xlsm
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"imageUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รูปภาพตัวอย่าง' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"imageUpload"
(
change
)="
onUploadImage
($
event
)"
>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.jpeg, *.jpg, *.png
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"tags"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'แท็ก' | translate }}
</label>
<tag-input
[
theme
]="'
bootstrap
'"
[(
ngModel
)]='
modelCourse
.
tags
'
placeholder=
"{{ '+แท็ก' | translate }}"
[
onlyFromAutocomplete
]="
true
"
secondaryPlaceholder=
"{{ 'กดปุ่ม Enter เพื่อเพิ่มแท็กใหม่' | translate }}"
[
addOnBlur
]="
true
"
[
clearOnBlur
]="
true
"
class=
"w-full"
name=
"tags"
>
<tag-input-dropdown
[
autocompleteItems
]="
listTag
"
[
showDropdownIfEmpty
]="
true
"
>
</tag-input-dropdown>
</tag-input>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"group"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'กลุ่ม' | translate }}
</label>
<select
class=
"custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"group"
[(
ngModel
)]="
modelCourse
.
group
.
groupId
"
(
change
)="
selectGroup
()"
name=
"group"
>
<option
*
ngFor=
"let item of listGroup"
[
ngValue
]="
item
.
groupId
"
>
{{item.thName}}
</option>
</select>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"remark"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'หมายเหตุ' | translate }}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"remark"
[(
ngModel
)]="
modelCourse
.
remark
"
rows=
"4"
name=
"remark"
></textarea>
</div>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions
style=
"justify-content: end;"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
(
click
)="
closeDialog
()"
>
{{ 'Cancel' | translate }}
</button>
<button
type=
"submit"
class=
"ti-btn bg-primary text-white !font-medium"
[
class
.
ti-btn-disabled
]="!
modelCourse
.
thName
||!
modelCourse
.
engName
"
[
disabled
]="!
modelCourse
.
thName
||!
modelCourse
.
engName
"
(
click
)="
onSumit
()"
>
{{ 'Save' | translate }}
</button>
</mat-dialog-actions>
</ng-template>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-course/list-course.component.scss
0 → 100644
View file @
73e72e5e
::ng-deep
ng2-dropdown-menu
{
z-index
:
9999
!
important
;
.ng2-dropdown-menu
{
z-index
:
9999
!
important
;
ng2-menu-item
{
z-index
:
9999
!
important
;
}
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-course/list-course.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
,
TemplateRef
,
ViewChild
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
ConfirmModalComponent
}
from
'../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../alert-modal/alert-modal.component'
;
import
{
OpenImageComponent
}
from
'../open-image/open-image.component'
;
import
{
UploadService
}
from
'../../../services/upload.service'
;
import
{
TagService
}
from
'../../../services/tag.service'
;
import
{
TagModel
}
from
'../../../models/tag.mmodel'
;
import
{
GroupModel
}
from
'../../../models/group.mmodel'
;
import
{
GroupService
}
from
'../../../services/group.service'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
CourseService
}
from
'../../../services/course.service'
;
import
{
CourseModel
}
from
'../../../models/course.model'
;
// Corrected model import
import
saveAs
from
'file-saver'
;
import
{
TagInputModule
}
from
'ngx-chips'
;
import
swal
from
'sweetalert'
;
@
Component
({
selector
:
'app-list-course'
,
templateUrl
:
'./list-course.component.html'
,
styleUrls
:
[
'./list-course.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
TagInputModule
,
],
})
export
class
ListCourseComponent
implements
OnInit
{
@
ViewChild
(
"editTemplateModal"
)
editTemplateModalRef
!
:
TemplateRef
<
any
>
;
dialogRef
:
any
;
page
=
1
;
// This 'page' property is not directly used for slicing anymore, but can remain if other parts of your code rely on it.
pageSize
=
10
;
pageIndex
:
number
=
0
;
maxPagesToShow
:
number
=
3
;
originalListCourse
:
CourseModel
[]
=
[];
// Stores the complete, unfiltered list from the backend
listCourse
:
CourseModel
[]
=
[];
// Stores the list after applying search filter
paginatedCourses
:
CourseModel
[]
=
[];
// Stores the subset of courses for the current page
modelCourse
:
CourseModel
=
new
CourseModel
({});
checkEdit
:
boolean
=
false
;
search
:
string
=
''
;
listTag
:
TagModel
[]
=
[];
listGroup
:
GroupModel
[]
=
[];
constructor
(
private
modalService
:
NgbModal
,
private
courseService
:
CourseService
,
private
uploadService
:
UploadService
,
private
tagService
:
TagService
,
private
groupService
:
GroupService
,
private
dialog
:
MatDialog
,
)
{
}
async
onUploadImage
(
event
:
any
)
{
try
{
if
(
event
.
target
.
files
.
length
>
0
)
{
let
fileData
=
event
.
target
.
files
[
0
];
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
fileData
);
const
allowedTypes
=
[
'image/png'
,
'image/jpeg'
,
'image/jpg'
];
if
(
!
allowedTypes
.
includes
(
fileData
.
type
))
{
this
.
openAlertModalWithMatDialog
(
'อัพโหลดได้เฉพาะไฟล์ *.jpeg, *.jpg, *.png เท่านั้น'
);
}
else
{
const
data
=
await
this
.
uploadService
.
uploadImage
(
formData
).
toPromise
();
if
(
data
)
{
this
.
modelCourse
.
thumbnail
=
data
.
body
.
fileId
;
}
}
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'เกิดข้อผิดพลาดในการอัปโหลดรูปภาพ'
);
}
}
onSelectFile
(
event
:
any
)
{
if
(
event
.
target
.
files
&&
event
.
target
.
files
[
0
])
{
const
reader
=
new
FileReader
();
const
file
:
File
=
event
.
target
.
files
[
0
];
reader
.
readAsDataURL
(
event
.
target
.
files
[
0
]);
// read file as data url
reader
.
onload
=
(
event
)
=>
{
// called once readAsDataURL is completed
if
(
event
)
{
// Changed allowed types from 'application/json' to Excel types based on your HTML comment
// Please double check the exact MIME types for .xlsx and .xlsm
const
allowedTypes
=
[
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
// .xlsx
'application/vnd.ms-excel.addin.macroEnabled.12'
,
// .xlsm (sometimes used, check if correct)
'application/vnd.ms-excel'
// Older .xls
];
if
(
!
allowedTypes
.
includes
(
file
.
type
))
{
this
.
openAlertModalWithMatDialog
(
'อัพโหลดได้เฉพาะไฟล์ *.xlsx, *.xlsm เท่านั้น'
);
}
else
{
let
base64
=
event
.
target
!
.
result
as
string
;
this
.
modelCourse
.
courseObj
=
base64
.
split
(
','
)[
1
];
}
}
};
}
}
applyFilterAndPagination
()
{
this
.
listCourse
=
this
.
originalListCourse
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
);
const
totalPagesAfterFilter
=
Math
.
ceil
(
this
.
listCourse
.
length
/
this
.
pageSize
);
if
(
this
.
pageIndex
>=
totalPagesAfterFilter
&&
totalPagesAfterFilter
>
0
)
{
this
.
pageIndex
=
totalPagesAfterFilter
-
1
;
}
else
if
(
totalPagesAfterFilter
===
0
)
{
this
.
pageIndex
=
0
;
}
const
startIndex
=
this
.
pageIndex
*
this
.
pageSize
;
const
endIndex
=
startIndex
+
this
.
pageSize
;
this
.
paginatedCourses
=
this
.
listCourse
.
slice
(
startIndex
,
endIndex
);
}
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
courseService
.
downloadFile
(
logId
).
toPromise
();
if
(
data
)
{
saveAs
(
new
Blob
([
data
]),
"file_download.json"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถดาวน์โหลดไฟล์ได้'
);
}
}
deleteFile
(
item
:
CourseModel
)
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการลบข้อมูลนี้หรือไม่"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willDelete
:
boolean
)
=>
{
if
(
willDelete
)
{
this
.
courseService
.
deleteCourse
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
swal
(
"ลบสำเร็จ!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getListCourse
();
}
else
{
swal
(
"สำเร็จบางส่วน/ข้อผิดพลาด!!"
,
"มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด"
,
"warning"
);
}
},
error
=>
{
this
.
openAlertModalWithMatDialog
(
error
.
message
);
});
}
});
}
openAlertModalWithMatDialog
(
message
?:
string
)
{
this
.
dialog
.
open
(
AlertModalComponent
,
{
data
:
{
message
:
message
?
message
:
""
},
width
:
'400px'
,
disableClose
:
true
,
});
}
onUpdate
()
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการอัพเดทข้อมูลหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willUpdate
:
boolean
)
=>
{
if
(
willUpdate
)
{
console
.
log
(
this
.
modelCourse
);
this
.
courseService
.
createCourse
(
this
.
modelCourse
).
subscribe
(
res
=>
{
if
(
res
)
{
swal
(
"บันทึกสำเร็จ!!"
,
"อัพเดทข้อมูลสำเร็จ"
,
"success"
);
this
.
closeDialog
();
this
.
getListCourse
();
}
else
{
swal
(
'ไม่สามารถอัพเดทข้อมูลได้'
);
}
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
onCreate
()
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willSave
:
boolean
)
=>
{
if
(
willSave
)
{
this
.
courseService
.
createCourse
(
this
.
modelCourse
).
subscribe
(
res
=>
{
if
(
res
)
{
swal
(
"บันทึกสำเร็จ!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
closeDialog
();
this
.
getListCourse
();
}
else
{
swal
(
'ไม่สามารถสร้างเอกสารได้'
);
}
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
onSumit
()
{
if
(
this
.
checkEdit
)
{
this
.
onUpdate
();
}
else
{
this
.
onCreate
();
}
}
async
getCourseById
(
targetModal
:
NgbModal
,
id
:
string
)
{
try
{
const
data
=
await
this
.
courseService
.
getCourseById
(
id
).
toPromise
();
this
.
modelCourse
=
new
CourseModel
(
data
!
);
if
(
data
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
'static'
,
size
:
'lg'
});
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
async
getListCourse
()
{
try
{
const
data
=
await
this
.
courseService
.
getListCourse
().
toPromise
();
this
.
originalListCourse
=
data
!
.
map
(
x
=>
new
CourseModel
(
x
));
this
.
applyFilterAndPagination
();
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการหลักสูตรได้'
);
}
}
get
totalFilteredItems
():
number
{
return
this
.
listCourse
.
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalFilteredItems
/
this
.
pageSize
);
}
get
startItemIndex
():
number
{
if
(
this
.
totalFilteredItems
===
0
)
return
0
;
return
this
.
pageIndex
*
this
.
pageSize
+
1
;
}
get
endItemIndex
():
number
{
const
end
=
Math
.
min
((
this
.
pageIndex
+
1
)
*
this
.
pageSize
,
this
.
totalFilteredItems
);
return
end
;
}
goToPage
(
page
:
number
)
{
if
(
page
>=
0
&&
page
<
this
.
totalPages
)
{
this
.
pageIndex
=
page
;
this
.
applyFilterAndPagination
();
}
else
if
(
this
.
totalPages
===
0
&&
page
===
0
)
{
this
.
pageIndex
=
0
;
this
.
applyFilterAndPagination
();
}
}
onSearchChange
()
{
this
.
pageIndex
=
0
;
this
.
applyFilterAndPagination
();
}
get
pages
():
number
[]
{
const
pages
:
number
[]
=
[];
const
startPage
=
Math
.
max
(
0
,
this
.
pageIndex
-
Math
.
floor
(
this
.
maxPagesToShow
/
2
));
const
endPage
=
Math
.
min
(
this
.
totalPages
-
1
,
startPage
+
this
.
maxPagesToShow
-
1
);
for
(
let
i
=
startPage
;
i
<=
endPage
;
i
++
)
{
pages
.
push
(
i
);
}
return
pages
;
}
ngOnInit
()
{
this
.
getListCourse
();
this
.
getListTag
();
this
.
getListGroup
();
}
async
getListGroup
()
{
try
{
const
data
=
await
this
.
groupService
.
getList
().
toPromise
();
this
.
listGroup
=
data
!
.
map
(
x
=>
new
GroupModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading groups:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการกลุ่มได้'
);
}
}
selectGroup
()
{
let
findData
=
this
.
listGroup
.
find
(
x
=>
x
.
groupId
===
this
.
modelCourse
.
group
.
groupId
);
this
.
modelCourse
.
group
=
findData
?
new
GroupModel
(
findData
)
:
new
GroupModel
({});
}
closeBtnClick
()
{
this
.
modalService
.
dismissAll
();
}
async
getListTag
()
{
try
{
const
data
=
await
this
.
tagService
.
getList
().
toPromise
();
this
.
listTag
=
data
!
.
map
(
x
=>
new
TagModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading tags:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการแท็กได้'
);
}
}
openEmployeeDialog
(
image
:
string
)
{
const
dialogConfig
=
{
width
:
'750px'
,
disableClose
:
false
,
data
:
{
linkImage
:
image
},
panelClass
:
'my-dialog-img-preview'
,
};
this
.
dialogRef
=
this
.
dialog
.
open
(
OpenImageComponent
,
dialogConfig
);
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
any
)
=>
{
console
.
log
(
'The dialog was closed'
,
result
);
},
(
reason
:
any
)
=>
{
});
}
openEditExcelDialog
(
item
?:
CourseModel
)
{
if
(
item
)
{
this
.
courseService
.
getCourseById
(
item
.
logId
).
toPromise
().
then
(
data
=>
{
if
(
data
)
{
this
.
modelCourse
=
new
CourseModel
(
data
!
);
this
.
checkEdit
=
true
;
}
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'1100px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Edit Course dialog closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListCourse
();
}
});
}).
catch
(
error
=>
{
console
.
error
(
'Error loading data for edit:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดข้อมูลเพื่อแก้ไขได้'
);
});
}
else
{
this
.
modelCourse
=
new
CourseModel
({});
this
.
checkEdit
=
false
;
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'800px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Edit Course dialog closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListCourse
();
}
});
}
}
closeDialog
()
{
if
(
this
.
dialogRef
)
{
this
.
dialogRef
.
close
();
}
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-doc/list-doc.component.html
0 → 100644
View file @
73e72e5e
<!-- <div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการเอกสาร</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search" >
<button class="btn btn-primary ml-auto" (click)="openModal(editTemplateModal)">เพิ่มไฟล์เอกสาร</button>
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col" class="text-center">ลิงค์</th>
<th scope="col" class="text-center">ไฟล์ (ไทย)</th>
<th scope="col" class="text-center">ไฟล์ (อังกฤษ)</th>
<th scope="col" class="text-center">สถานะ</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of filterListDoc() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}" (click)="openEmployeeModal(data.getImage())"></td>
<td>{{ data.thName }}</td>
<td>{{ data.thDesc }}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)" ></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.logId,'tha')"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.logId,'eng')"></i></td>
<td class="text-center">
<span class="fa-stack rt_anim" *ngIf="data.status == '0'" ngbTooltip="รออนุมัติ" container="body" tooltipClass="myhrcolor-1">
<i class="fa fa-circle fa-stack-2x text-info"></i>
<i class=" fas fa-hourglass-half fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack rt_anim" *ngIf="data.status == '1'" ngbTooltip="เปิดใช้งาน" container="body" tooltipClass="myhrcolor-2">
<i class="fa fa-circle fa-stack-2x text-success"></i>
<i class=" fas fa-check fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack rt_anim" *ngIf="data.status == '2'" ngbTooltip="ไม่อนุมัติ" container="body" tooltipClass="myhrcolor-3">
<i class="fa fa-circle fa-stack-2x text-danger"></i>
<i class="fas fa-times fa-stack-1x fa-inverse" style="font-size: 1.25em;"></i>
</span>
</td>
<td>
<button type="button" [disabled]="data.status != 0" class="btn btn-circle btn-primary rounded-circle btn-sm mr-2" (click)="openModal(editTemplateModal,data)" placement="top" ngbTooltip="แก้ไข">
<i class="fas fa-edit"></i>
</button>
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2" (click)="deleteFile(data)" placement="top" ngbTooltip="ลบ">
<i class="fas fa-trash-alt"></i>
</button>
</td>
</tr>
</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]="listDoc.length" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div> -->
<app-page-header
[
title
]="'รายการเอกสาร'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'อัพโหลดรายการเอกสาร'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
{{ 'All List' | translate}}
</div>
<div
class=
"flex flex-wrap gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(
click
)="
openEditExcelDialog
()"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'Create' |
translate}}
</a>
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหาบริษัท"
aria-label=
".form-control-sm example"
[(
ngModel
)]="
search
"
(
ngModelChange
)="
onSearchChange
()"
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead>
<tr
class=
"border-b border-defaultborder text-white"
style=
"background-color: #49b6f5;"
>
<th
scope=
"col"
class=
"text-start"
>
#
</th>
<th
scope=
"col"
class=
"text-start"
>
รูปภาพ
</th>
<th
scope=
"col"
class=
"text-start"
>
ชื่อ
</th>
<th
scope=
"col"
class=
"text-start"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"text-start"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"text-start"
>
ไฟล์(ไทย)
</th>
<th
scope=
"col"
class=
"text-start"
>
ไฟล์(อังกฤษ)
</th>
<th
scope=
"col"
class=
"text-start"
>
สถานะ
</th>
<th
scope=
"col"
class=
"text-start"
>
การจัดการ
</th>
</tr>
</thead>
<tbody>
<tr
class=
"border border-defaultborder dark:border-defaultborder/10"
*
ngFor=
"let data of paginatedDocs; let i = index"
>
<td>
<div>
<span
class=
"block mb-1"
>
{{pageIndex * pageSize + i + 1}}
</span>
</div>
</td>
<td>
<div
class=
"flex items-center"
>
<span
class=
"p-3 me-1"
style=
"width: 200px;"
>
<img
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeDialog
(
data
.
getImage
())"
id=
"profile-img"
class=
"border-radius-1 cursor-pointer"
style=
"width: 180px; height: 120px; object-fit: cover;"
>
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{ data.thName }}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{ data.thDesc }}
</span>
</div>
</td>
<td
style=
"justify-items: center;"
>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0 cursor-pointer active: hover:text-danger"
(
click
)="
openLink
(
data
.
link1
)"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td
style=
"justify-items: center;"
>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0 cursor-pointer active hover:text-success"
(
click
)="
downloadFile
(
data
.
logId
,'
tha
')"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td
style=
"justify-items: center;"
>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0 cursor-pointer active hover:text-success"
(
click
)="
downloadFile
(
data
.
logId
,'
eng
')"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td>
<div>
<ng-container
*
ngIf=
"data.status === 0"
>
<span
class=
"badge bg-amber-300 text-white"
>
รออนุมัติ
</span>
</ng-container>
<ng-container
*
ngIf=
"data.status === 1"
>
<span
class=
"badge bg-success text-white"
>
เปิดใช้งาน
</span>
</ng-container>
<ng-container
*
ngIf=
"data.status === 2"
>
<span
class=
"badge bg-gray-500 text-white"
>
ไม่อนุมัติ
</span>
</ng-container>
</div>
</td>
<td>
<div
class=
"flex flex-row items-center !gap-2 "
>
<a
aria-label=
"anchor"
(
click
)="
openEditExcelDialog
(
data
)"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
>
<i
class=
"ri-pencil-line"
></i>
</a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
(
click
)="
deleteFile
(
data
)"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"
>
<i
class=
"ri-delete-bin-line"
></i>
</a>
</div>
</td>
</tr>
<tr
*
ngIf=
"paginatedDocs.length === 0"
>
<td
colspan=
"9"
class=
"text-center py-4"
>
ไม่พบข้อมูล
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
>
<div
class=
"mb-2 sm:mb-0"
>
<select
class=
"custom-select m-r-5"
style=
"width: auto"
[(
ngModel
)]="
pageSize
"
(
ngModelChange
)="
goToPage
(
0
)"
>
<option
[
ngValue
]="
10
"
>
รายการต่อหน้า: 10
</option>
<option
[
ngValue
]="
50
"
>
รายการต่อหน้า: 50
</option>
<option
[
ngValue
]="
100
"
>
รายการต่อหน้า: 100
</option>
</select>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0 flex"
>
<li
class=
"page-item"
[
class
.
disabled
]="
pageIndex =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
goToPage
(
pageIndex
-
1
)"
>
{{ 'Previous' | translate }}
</a>
</li>
<ng-container
*
ngFor=
"let p of pages"
>
<li
class=
"page-item"
[
class
.
active
]="
p =
==
pageIndex
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
[
class
.
active
]="
p =
==
pageIndex
"
(
click
)="
goToPage
(
p
)"
>
{{ p + 1 }}
</a>
</li>
</ng-container>
<li
class=
"page-item"
[
class
.
disabled
]="
pageIndex =
==
totalPages
-
1
||
totalPages =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
goToPage
(
pageIndex
+
1
)"
>
{{ 'Next' | translate }}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template
#
editTemplateModal
let-modal
>
<div
class=
"modal-headtitle ti-modal-header flex justify-between items-center p-4"
style=
"background-color: #fefbfb;"
>
<h3
class=
"modal-title text-sm font-semibold text-defaulttextcolor"
id=
"edittemplateLabel"
>
{{ checkEdit ? ('แก้ไขไฟล์เอกสาร' | translate) : ('เพิ่มไฟล์เอกสาร' | translate) }}
</h3>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeDialog
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{ 'Close' | translate }}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"w-full flex justify-end"
>
<div
class=
"absolute flex"
>
<div
class=
"px-1"
>
</div>
</div>
</div>
<mat-dialog-content
style=
"padding: 0px; padding-left: 20px; padding-right: 20px;"
>
<div
class=
"box p-9 top-4"
>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"nameth"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อ (ไทย)' | translate }}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"nameth"
[(
ngModel
)]="
modelDoc
.
thName
"
name=
"thName"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"nameeng"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อ (อังกฤษ)' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"nameeng"
[(
ngModel
)]="
modelDoc
.
engName
"
name=
"engName"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"thDesc"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รายละเอียด (ไทย)' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"thDesc"
[(
ngModel
)]="
modelDoc
.
thDesc
"
rows=
"3"
name=
"thDesc"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"engDesc"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รายละเอียด (อังกฤษ)' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"engDesc"
[(
ngModel
)]="
modelDoc
.
engDesc
"
rows=
"3"
name=
"engDesc"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"group"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ภาษาที่รองรับ' | translate }}
</label>
<select
class=
"custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"langSupport"
[(
ngModel
)]="
modelDoc
.
langSupport
"
name=
"langSupport"
>
<option
value=
"THA"
>
ไทย
</option>
<option
value=
"ENG"
>
English
</option>
</select>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"fileUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ไฟล์อัพโหลด' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"fileUpload"
(
change
)="
onSelectFile
($
event
,'
th
')"
>
<button
*
ngIf=
"modelDoc.thDocObj && checkEdit"
(
click
)="
downloadFile
(
modelDoc
.
logId
,'
tha
')"
class=
"ti-btn ti-btn-primary flex-shrink-0 px-4 py-2 rounded-md transition-all duration-200"
>
<i
class=
"fas fa-download mr-1"
></i>
{{ 'ดาวน์โหลด' | translate }}
</button>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.xlsx *.xlsm
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"fileUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ไฟล์อัพโหลด' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"fileUpload"
(
change
)="
onSelectFile
($
event
,'
eng
')"
>
<button
*
ngIf=
"modelDoc.engDocObj && checkEdit"
(
click
)="
downloadFile
(
modelDoc
.
logId
,'
eng
')"
class=
"ti-btn ti-btn-primary flex-shrink-0 px-4 py-2 rounded-md transition-all duration-200"
>
<i
class=
"fas fa-download mr-1"
></i>
{{ 'ดาวน์โหลด' | translate }}
</button>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.xlsx *.xlsm
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"imageUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รูปภาพตัวอย่าง' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"imageUpload"
(
change
)="
onUploadImage
($
event
)"
>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.jpeg, *.jpg, *.png
</div>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"linkExample"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'Link ตัวอย่าง' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"linkExample"
[(
ngModel
)]="
modelDoc
.
link1
"
name=
"link1"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"tags"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'แท็ก' | translate }}
</label>
<tag-input
[
theme
]="'
bootstrap
'"
[(
ngModel
)]='
modelDoc
.
tags
'
placeholder=
"{{ '+แท็ก' | translate }}"
[
onlyFromAutocomplete
]="
true
"
secondaryPlaceholder=
"{{ 'กดปุ่ม Enter เพื่อเพิ่มแท็กใหม่' | translate }}"
[
addOnBlur
]="
true
"
[
clearOnBlur
]="
true
"
class=
"w-full"
name=
"tags"
>
<tag-input-dropdown
[
autocompleteItems
]="
listTag
"
[
showDropdownIfEmpty
]="
true
"
>
</tag-input-dropdown>
</tag-input>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"group"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'กลุ่ม' | translate }}
</label>
<select
class=
"custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"group"
[(
ngModel
)]="
modelDoc
.
group
.
groupId
"
(
change
)="
selectGroup
()"
name=
"group"
>
<option
*
ngFor=
"let item of listGroup"
[
ngValue
]="
item
.
groupId
"
>
{{item.thName}}
</option>
</select>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"remark"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'หมายเหตุ' | translate }}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"remark"
[(
ngModel
)]="
modelDoc
.
remark
"
rows=
"4"
name=
"remark"
></textarea>
</div>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions
style=
"justify-content: end;"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
(
click
)="
closeDialog
()"
>
{{ 'Cancel' | translate }}
</button>
<button
type=
"submit"
class=
"ti-btn bg-primary text-white !font-medium"
[
class
.
ti-btn-disabled
]="!
modelDoc
.
thName
||!
modelDoc
.
engName
"
[
disabled
]="!
modelDoc
.
thName
||!
modelDoc
.
engName
"
(
click
)="
onSumit
()"
>
{{ 'Save' | translate }}
</button>
</mat-dialog-actions>
</ng-template>
<!-- <ng-template #editTemplateModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">{{checkEdit?"แก้ไขไฟล์เอกสาร":"เพิ่มไฟล์เอกสาร"}}</h5>
<button type="button" class="close" (click)="closeBtnClick()" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group row">
<label for="nameth" class="col-sm-4 col-form-label">ชื่อ (ไทย)</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="nameth" [(ngModel)]="modelDoc.thName">
</div>
</div>
<div class="form-group row">
<label for="nameeng" class="col-sm-4 col-form-label">ชื่อ (อังกฤษ)</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="nameeng" [(ngModel)]="modelDoc.engName">
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">รายละเอียด (ไทย)</label>
<div class="col-sm-8">
<textarea class="form-control" [(ngModel)]="modelDoc.thDesc"></textarea>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">รายละเอียด (อังกฤษ)</label>
<div class="col-sm-8">
<textarea class="form-control" [(ngModel)]="modelDoc.engDesc"></textarea>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">ภาษาที่รองรับ</label>
<div class="col-sm-8">
<select class="custom-select" [(ngModel)]="modelDoc.langSupport">
<option value="THA">ไทย</option>
<option value="ENG">English</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">ไฟล์อัพโหลด (ไทย)</label>
<div class="{{!modelDoc.thDocObj||!checkEdit ? 'col-sm-8' : 'col-sm-6'}}">
<input type="file" class="form-control" (change)="onSelectFile($event,'th')">
<div class="msg-detail">ไฟล์ที่อนุญาต:*.doc</div>
</div>
<div class="col-auto" *ngIf="modelDoc.thDocObj&&checkEdit">
<button class="btn btn-primary" (click)="downloadFile(modelDoc.logId,'tha')"><i class="fas fa-download" ></i></button>
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">ไฟล์อัพโหลด (อังกฤษ)</label>
<div class="{{!modelDoc.engDocObj||!checkEdit ? 'col-sm-8' : 'col-sm-6'}}">
<input type="file" class="form-control" (change)="onSelectFile($event,'eng')">
<div class="msg-detail">ไฟล์ที่อนุญาต:*.doc</div>
</div>
<div class="col-auto" *ngIf="modelDoc.engDocObj&&checkEdit">
<button class="btn btn-primary" (click)="downloadFile(modelDoc.logId,'eng')"><i class="fas fa-download" ></i></button>
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">รูปภาพตัวอย่าง</label>
<div class="col-sm-8">
<input type="file" class="form-control" (change)="onUploadImage($event)">
<div class="msg-detail">ไฟล์ที่อนุญาต:*.jpeg, *.jpg, *.png</div>
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">Link ตัวอย่าง</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="nameeng" [(ngModel)]="modelDoc.link1">
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">แท็ก</label>
<div class="col-sm-8">
<tag-input [theme]="'bootstrap'" [(ngModel)]='modelDoc.tags' placeholder="+แท็ก" [onlyFromAutocomplete]="true"
secondaryPlaceholder="กดปุ่ม Enter เพื่อเพิ่มแท็กใหม่" [addOnBlur]="true" [clearOnBlur]="true">
<tag-input-dropdown [autocompleteItems]="listTag" [showDropdownIfEmpty]="true">
</tag-input-dropdown>
</tag-input>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">กลุ่ม</label>
<div class="col-sm-8">
<select class="custom-select" [(ngModel)]="modelDoc.group.groupId" (change)="selectGroup()">
<option *ngFor="let item of listGroup" [ngValue]="item.groupId">{{item.thName}}</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">หมายเหตุ</label>
<div class="col-sm-8">
<textarea class="form-control"[(ngModel)]="modelDoc.remark"></textarea>
</div>
</div>
<div class="modal-footer ">
<button type="submit" class="btn btn-info" (click)="onSumit()" [disabled]="!modelDoc.thName||!modelDoc.engName">บันทึก</button>
<button type="button" class="btn btn-danger" (click)="closeBtnClick()">ปิด</button>
</div>
</div>
</ng-template> -->
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-doc/list-doc.component.scss
0 → 100644
View file @
73e72e5e
::ng-deep
ng2-dropdown-menu
{
z-index
:
9999
!
important
;
.ng2-dropdown-menu
{
z-index
:
9999
!
important
;
ng2-menu-item
{
z-index
:
9999
!
important
;
}
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-doc/list-doc.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
,
TemplateRef
,
ViewChild
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
ConfirmModalComponent
}
from
'../confirm-modal/confirm-modal.component'
;
// ตรวจสอบว่ามี ConfirmModalComponent นี้อยู่จริง
import
{
AlertModalComponent
}
from
'../alert-modal/alert-modal.component'
;
import
{
OpenImageComponent
}
from
'../open-image/open-image.component'
;
// ตรวจสอบว่ามี OpenImageComponent นี้อยู่จริง
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
TagInputModule
}
from
'ngx-chips'
;
import
{
UploadService
}
from
'../../../services/upload.service'
;
import
{
TagService
}
from
'../../../services/tag.service'
;
import
{
TagModel
}
from
'../../../models/tag.mmodel'
;
import
{
GroupModel
}
from
'../../../models/group.mmodel'
;
import
{
GroupService
}
from
'../../../services/group.service'
;
import
{
DocumentModel
}
from
'../../../models/document.model'
;
import
{
DocumentService
}
from
'../../../services/document.service'
;
import
saveAs
from
'file-saver'
;
import
swal
from
'sweetalert'
;
@
Component
({
selector
:
'app-list-doc'
,
templateUrl
:
'./list-doc.component.html'
,
styleUrls
:
[
'./list-doc.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
TagInputModule
,
],
})
export
class
ListDocComponent
implements
OnInit
{
@
ViewChild
(
"editTemplateModal"
)
editTemplateModalRef
!
:
TemplateRef
<
any
>
;
dialogRef
:
any
;
page
=
1
;
// อาจจะไม่จำเป็นต้องใช้โดยตรงแล้ว แต่ยังคงไว้หากมีส่วนอื่นใช้
pageSize
=
10
;
pageIndex
:
number
=
0
;
maxPagesToShow
:
number
=
3
;
originalListDoc
:
DocumentModel
[]
=
[];
// เก็บข้อมูลเอกสารทั้งหมดที่โหลดมาจาก API
listDoc
:
DocumentModel
[]
=
[];
// เก็บข้อมูลเอกสารที่ถูกกรองด้วย search term แล้ว
paginatedDocs
:
DocumentModel
[]
=
[];
// เก็บข้อมูลเอกสารสำหรับหน้าปัจจุบันที่แสดงในตาราง
modelDoc
:
DocumentModel
=
new
DocumentModel
({});
checkEdit
:
boolean
=
false
;
search
:
string
=
''
;
listTag
:
TagModel
[]
=
[];
listGroup
:
GroupModel
[]
=
[];
constructor
(
private
modalService
:
NgbModal
,
// ยังคง NgbModal ไว้เผื่อมีการใช้งานอื่น ๆ ที่ไม่ได้เปลี่ยน
private
documentService
:
DocumentService
,
private
uploadService
:
UploadService
,
private
tagService
:
TagService
,
private
groupService
:
GroupService
,
private
dialog
:
MatDialog
,
// MatDialog สำหรับ Material Dialogs
)
{}
async
onUploadImage
(
event
:
any
)
{
try
{
if
(
event
.
target
.
files
.
length
>
0
)
{
let
fileData
=
event
.
target
.
files
[
0
];
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
fileData
);
const
allowedTypes
=
[
'image/png'
,
'image/jpeg'
,
'image/jpg'
];
if
(
!
allowedTypes
.
includes
(
fileData
.
type
))
{
this
.
openAlertModalWithMatDialog
(
'อัพโหลดได้เฉพาะไฟล์ *.jpeg, *.jpg, *.png เท่านั้น'
);
}
else
{
const
data
=
await
this
.
uploadService
.
uploadImage
(
formData
).
toPromise
();
if
(
data
)
{
this
.
modelDoc
.
thumbnail
=
data
.
body
.
fileId
;
}
}
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
onSelectFile
(
event
:
any
,
lang
:
string
)
{
if
(
event
.
target
.
files
&&
event
.
target
.
files
[
0
])
{
const
reader
=
new
FileReader
();
const
file
:
File
=
event
.
target
.
files
[
0
];
reader
.
readAsDataURL
(
event
.
target
.
files
[
0
]);
// read file as data url
reader
.
onload
=
(
event
)
=>
{
// called once readAsDataURL is completed
if
(
event
)
{
const
allowedTypes
=
[
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'application/msword'
];
if
(
!
allowedTypes
.
includes
(
file
.
type
))
{
this
.
openAlertModalWithMatDialog
(
'อัพโหลดได้เฉพาะไฟล์ *.doc เท่านั้น'
);
}
else
{
let
base64
=
event
.
target
!
.
result
as
string
;
if
(
lang
===
'th'
)
{
this
.
modelDoc
.
thDocObj
=
base64
.
split
(
','
)[
1
];
}
else
{
this
.
modelDoc
.
engDocObj
=
base64
.
split
(
','
)[
1
];
}
}
}
};
}
}
// เมธอดหลักสำหรับกรองข้อมูลและแบ่งหน้า
applyFilterAndPagination
()
{
// 1. กรองข้อมูลจาก originalListDoc ด้วย search term
this
.
listDoc
=
this
.
originalListDoc
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
);
// 2. ปรับ pageIndex หากหน้าปัจจุบันอยู่นอกช่วงข้อมูลที่ถูกกรองแล้ว
const
totalPagesAfterFilter
=
Math
.
ceil
(
this
.
listDoc
.
length
/
this
.
pageSize
);
if
(
this
.
pageIndex
>=
totalPagesAfterFilter
&&
totalPagesAfterFilter
>
0
)
{
this
.
pageIndex
=
totalPagesAfterFilter
-
1
;
// ไปยังหน้าสุดท้ายที่มีข้อมูล
}
else
if
(
totalPagesAfterFilter
===
0
)
{
// ถ้าไม่มีข้อมูลเลย ให้เป็นหน้าแรก
this
.
pageIndex
=
0
;
}
// 3. แบ่งข้อมูลตาม pageIndex และ pageSize เพื่อแสดงบนหน้าปัจจุบัน
const
startIndex
=
this
.
pageIndex
*
this
.
pageSize
;
const
endIndex
=
startIndex
+
this
.
pageSize
;
this
.
paginatedDocs
=
this
.
listDoc
.
slice
(
startIndex
,
endIndex
);
}
async
downloadFile
(
logId
:
string
,
lang
:
string
)
{
try
{
const
data
=
await
this
.
documentService
.
downloadFile
(
logId
,
lang
).
toPromise
();
if
(
data
)
{
saveAs
(
new
Blob
([
data
]),
"file_download.doc"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถดาวน์โหลดไฟล์ได้'
);
}
}
deleteFile
(
item
:
DocumentModel
)
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการลบข้อมูลนี้หรือไม่"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willDelete
:
boolean
)
=>
{
if
(
willDelete
)
{
this
.
documentService
.
deleteExcel
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
swal
(
"ลบสำเร็จ!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getListDoc
();
// โหลดข้อมูลใหม่ทั้งหมดและใช้ applyFilterAndPagination
}
else
{
swal
(
"สำเร็จบางส่วน/ข้อผิดพลาด!!"
,
"มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด"
,
"warning"
);
}
},
error
=>
{
this
.
openAlertModalWithMatDialog
(
error
.
message
);
});
}
});
}
openAlertModalWithMatDialog
(
message
?:
string
)
{
this
.
dialog
.
open
(
AlertModalComponent
,
{
data
:
{
message
:
message
?
message
:
""
},
width
:
'400px'
,
disableClose
:
true
,
});
}
onUpdate
()
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการอัพเดทข้อมูลหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willUpdate
:
boolean
)
=>
{
if
(
willUpdate
)
{
console
.
log
(
this
.
modelDoc
);
this
.
documentService
.
createDoc
(
this
.
modelDoc
).
subscribe
(
res
=>
{
if
(
res
)
{
swal
(
"บันทึกสำเร็จ!!"
,
"อัพเดทข้อมูลสำเร็จ"
,
"success"
);
this
.
closeDialog
();
// ปิด MatDialog
this
.
getListDoc
();
// โหลดข้อมูลใหม่ทั้งหมดและใช้ applyFilterAndPagination
}
else
{
swal
(
'ไม่สามารถอัพเดทข้อมูลได้'
);
}
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
onCreate
()
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willSave
:
boolean
)
=>
{
if
(
willSave
)
{
this
.
documentService
.
createDoc
(
this
.
modelDoc
).
subscribe
(
res
=>
{
if
(
res
)
{
swal
(
"บันทึกสำเร็จ!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
closeDialog
();
// ปิด MatDialog
this
.
getListDoc
();
// โหลดข้อมูลใหม่ทั้งหมดและใช้ applyFilterAndPagination
}
else
{
swal
(
'ไม่สามารถสร้างเอกสารได้'
);
}
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
onSumit
()
{
if
(
this
.
checkEdit
)
{
this
.
onUpdate
();
}
else
{
this
.
onCreate
();
}
}
// Method นี้ไม่ได้ถูกใช้โดยตรงใน openEditExcelDialog แล้ว แต่ยังคงไว้เผื่อการใช้งานอื่น
async
getExcelById
(
targetModal
:
NgbModal
,
id
:
string
)
{
try
{
const
data
=
await
this
.
documentService
.
getDocById
(
id
).
toPromise
();
this
.
modelDoc
=
new
DocumentModel
(
data
!
);
if
(
data
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
'static'
,
size
:
'lg'
});
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
// openModal นี้เป็นการใช้ NgbModal ซึ่งอาจจะไม่ได้ใช้แล้วหากเปลี่ยนไปใช้ MatDialog ทั้งหมด
openModal
(
targetModal
:
NgbModal
,
item
?:
DocumentModel
)
{
if
(
item
)
{
this
.
getExcelById
(
targetModal
,
item
.
logId
);
// อันนี้ยังเรียก NgbModal อยู่
this
.
checkEdit
=
true
;
}
else
{
this
.
modelDoc
=
new
DocumentModel
({});
this
.
checkEdit
=
false
;
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
'static'
,
size
:
'lg'
});
}
}
getStatus
(
status
:
string
):
string
{
if
(
status
===
'0'
)
{
return
'รออนุมัติ'
;
}
else
if
(
status
===
'1'
)
{
return
'เปิดใช้งาน'
;
}
else
if
(
status
===
'2'
)
{
return
'ไม่อนุมัติ'
;
}
else
{
return
'ไม่ทราบสถานะ'
;
// ควรมีค่า default หรือจัดการ error ที่นี่
}
}
async
getListDoc
()
{
try
{
const
data
=
await
this
.
documentService
.
getListDoc
().
toPromise
();
this
.
originalListDoc
=
data
!
.
map
(
x
=>
new
DocumentModel
(
x
));
// เก็บข้อมูลทั้งหมดที่นี่
this
.
applyFilterAndPagination
();
// หลังจากได้ข้อมูลแล้ว ค่อยนำมา filter และ pagination
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดข้อมูลเอกสารได้'
);
}
}
// Getters สำหรับ Pagination (ใช้ this.listDoc.length ซึ่งเป็นข้อมูลที่ถูกกรองแล้ว)
get
totalFilteredItems
():
number
{
return
this
.
listDoc
.
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalFilteredItems
/
this
.
pageSize
);
}
get
startItemIndex
():
number
{
if
(
this
.
totalFilteredItems
===
0
)
return
0
;
return
this
.
pageIndex
*
this
.
pageSize
+
1
;
}
get
endItemIndex
():
number
{
const
end
=
Math
.
min
((
this
.
pageIndex
+
1
)
*
this
.
pageSize
,
this
.
totalFilteredItems
);
return
end
;
}
// เมธอดสำหรับเปลี่ยนหน้า
goToPage
(
page
:
number
)
{
if
(
page
>=
0
&&
page
<
this
.
totalPages
)
{
this
.
pageIndex
=
page
;
this
.
applyFilterAndPagination
();
// เมื่อเปลี่ยนหน้า ให้เรียกกรองและแบ่งหน้าใหม่
}
else
if
(
this
.
totalPages
===
0
&&
page
===
0
)
{
// กรณีไม่มีข้อมูลเลย ให้ pageIndex เป็น 0 และเรียก applyFilterAndPagination()
this
.
pageIndex
=
0
;
this
.
applyFilterAndPagination
();
}
}
// เมธอดที่เรียกเมื่อค่า search เปลี่ยน
onSearchChange
()
{
this
.
pageIndex
=
0
;
// รีเซ็ตไปหน้าแรกเมื่อค้นหาใหม่
this
.
applyFilterAndPagination
();
// เรียกกรองและแบ่งหน้าใหม่
}
// สำหรับแสดงเลขหน้าใน pagination
get
pages
():
number
[]
{
const
pages
:
number
[]
=
[];
const
startPage
=
Math
.
max
(
0
,
this
.
pageIndex
-
Math
.
floor
(
this
.
maxPagesToShow
/
2
));
const
endPage
=
Math
.
min
(
this
.
totalPages
-
1
,
startPage
+
this
.
maxPagesToShow
-
1
);
for
(
let
i
=
startPage
;
i
<=
endPage
;
i
++
)
{
pages
.
push
(
i
);
}
return
pages
;
}
ngOnInit
()
{
this
.
getListDoc
();
// โหลดข้อมูลเอกสารครั้งแรก
this
.
getListTag
();
this
.
getListGroup
();
}
async
getListGroup
()
{
try
{
const
data
=
await
this
.
groupService
.
getList
().
toPromise
();
this
.
listGroup
=
data
!
.
map
(
x
=>
new
GroupModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading groups:'
,
error
);
}
}
selectGroup
()
{
let
findData
=
this
.
listGroup
.
find
(
x
=>
x
.
groupId
===
this
.
modelDoc
.
group
.
groupId
);
this
.
modelDoc
.
group
=
findData
?
new
GroupModel
(
findData
)
:
new
GroupModel
({});
}
async
getListTag
()
{
try
{
const
data
=
await
this
.
tagService
.
getList
().
toPromise
();
this
.
listTag
=
data
!
.
map
(
x
=>
new
TagModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading tags:'
,
error
);
}
}
openEmployeeDialog
(
image
:
string
)
{
const
dialogConfig
=
{
width
:
'750px'
,
disableClose
:
false
,
data
:
{
linkImage
:
image
},
panelClass
:
'my-dialog-img-preview'
,
};
this
.
dialogRef
=
this
.
dialog
.
open
(
OpenImageComponent
,
dialogConfig
);
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
any
)
=>
{
console
.
log
(
'The dialog was closed'
,
result
);
},
(
reason
:
any
)
=>
{
});
}
openEditExcelDialog
(
item
?:
DocumentModel
)
{
if
(
item
)
{
this
.
documentService
.
getDocById
(
item
.
logId
).
toPromise
().
then
(
data
=>
{
if
(
data
)
{
this
.
modelDoc
=
new
DocumentModel
(
data
!
);
this
.
checkEdit
=
true
;
}
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'1100px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Edit Excel dialog closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListDoc
();
// รีเฟรชรายการเฉพาะเมื่อสำเร็จ
}
});
}).
catch
(
error
=>
{
console
.
error
(
'Error loading data for edit:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดข้อมูลเพื่อแก้ไขได้'
);
});
}
else
{
this
.
modelDoc
=
new
DocumentModel
({});
this
.
checkEdit
=
false
;
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'800px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Edit Excel dialog closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListDoc
();
// รีเฟรชรายการเฉพาะเมื่อสำเร็จ
}
});
}
}
closeDialog
()
{
if
(
this
.
dialogRef
)
{
this
.
dialogRef
.
close
();
}
}
// closeBtnClick นี้เป็นการใช้ NgbModal.dismissAll() ซึ่งอาจจะไม่ได้ใช้แล้วหากเปลี่ยนไปใช้ MatDialog ทั้งหมด
closeBtnClick
()
{
this
.
modalService
.
dismissAll
();
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-excell/list-excell.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการเอกสาร
Excel
'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการอัพโหลดเอกสาร
Excel
'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
{{ 'All List' | translate}}
</div>
<div
class=
"flex flex-wrap gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2 hover:scale-105 transition duration-300"
(
click
)="
openEditExcelDialog
()"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'Create' |
translate}}
</a>
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหาบริษัท"
aria-label=
".form-control-sm example"
[(
ngModel
)]="
search
"
(
ngModelChange
)="
onSearchChange
()"
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
*
ngIf=
"checkType !== '1'"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead>
<tr
class=
"border-b border-defaultborder text-white"
style=
"background-color: #49b6f5;"
>
<th
scope=
"col"
class=
"text-start"
>
#
</th>
<th
scope=
"col"
class=
"text-start"
>
รูปภาพ
</th>
<th
scope=
"col"
class=
"text-start"
>
ชื่อ
</th>
<th
scope=
"col"
class=
"text-start"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"text-start"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"text-start"
>
ไฟล์
</th>
<th
scope=
"col"
class=
"text-start"
>
สถานะ
</th>
<th
scope=
"col"
class=
"text-start"
>
การจัดการ
</th>
</tr>
</thead>
<tbody>
<tr
class=
"border border-defaultborder dark:border-defaultborder/10"
*
ngFor=
"let data of paginatedExcels; let i = index"
>
<td>
<div>
<span
class=
"block mb-1"
>
{{pageIndex * pageSize + i + 1}}
</span>
</div>
</td>
<td>
<div
class=
"flex items-center"
>
<span
class=
"p-3 me-1"
style=
"width: 200px;"
>
<img
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeDialog
(
data
.
getImage
())"
id=
"profile-img"
class=
"border-radius-1 cursor-pointer"
style=
"width: 180px; height: 120px; object-fit: cover;"
>
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{ data.thName }}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{ data.thDesc }}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0 cursor-pointer active: hover:text-danger hover:scale-125 transition duration-300"
(
click
)="
openLink
(
data
.
link1
)"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0 cursor-pointer active hover:text-success hover:scale-125 transition duration-300"
(
click
)="
downloadFile
(
data
.
logId
)"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td>
<div>
<ng-container
*
ngIf=
"data.status === 0"
>
<span
class=
"badge bg-amber-300 text-white"
>
รออนุมัติ
</span>
</ng-container>
<ng-container
*
ngIf=
"data.status === 1"
>
<span
class=
"badge bg-success text-white"
>
เปิดใช้งาน
</span>
</ng-container>
<ng-container
*
ngIf=
"data.status === 2"
>
<span
class=
"badge bg-gray-500 text-white"
>
ไม่อนุมัติ
</span>
</ng-container>
</div>
</td>
<td>
<div
class=
"flex flex-row items-center !gap-2 "
>
<a
aria-label=
"anchor"
(
click
)="
openEditExcelDialog
(
data
)"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
>
<i
class=
"ri-pencil-line"
></i>
</a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
(
click
)="
deleteFile
(
data
)"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"
>
<i
class=
"ri-delete-bin-line"
></i>
</a>
</div>
</td>
</tr>
<tr
*
ngIf=
"paginatedExcels.length === 0"
>
<td
colspan=
"9"
class=
"text-center py-4"
>
ไม่พบข้อมูล
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
>
<div
class=
"mb-2 sm:mb-0"
>
<select
class=
"custom-select m-r-5"
style=
"width: auto"
[(
ngModel
)]="
pageSize
"
(
ngModelChange
)="
goToPage
(
0
)"
>
<option
[
ngValue
]="
10
"
>
รายการต่อหน้า: 10
</option>
<option
[
ngValue
]="
50
"
>
รายการต่อหน้า: 50
</option>
<option
[
ngValue
]="
100
"
>
รายการต่อหน้า: 100
</option>
</select>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0 flex"
>
<li
class=
"page-item"
[
class
.
disabled
]="
pageIndex =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
goToPage
(
pageIndex
-
1
)"
>
{{ 'Previous' | translate }}
</a>
</li>
<ng-container
*
ngFor=
"let p of pages"
>
<li
class=
"page-item"
[
class
.
active
]="
p =
==
pageIndex
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
[
class
.
active
]="
p =
==
pageIndex
"
(
click
)="
goToPage
(
p
)"
>
{{ p + 1 }}
</a>
</li>
</ng-container>
<li
class=
"page-item"
[
class
.
disabled
]="
pageIndex =
==
totalPages
-
1
||
totalPages =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
goToPage
(
pageIndex
+
1
)"
>
{{ 'Next' | translate }}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"box p-4"
*
ngIf=
"checkType === '1'"
>
<div
class=
"flex flex-wrap -mx-2"
>
<div
class=
"w-full"
>
<div
class=
"py-3 px-2"
>
<input
type=
"text"
class=
"block w-full md:w-1/4 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 shadow-sm"
placeholder=
"ค้นหา"
[(
ngModel
)]="
search
"
(
ngModelChange
)="
onSearchChange
()"
/>
</div>
</div>
<div
class=
"w-full sm:w-1/2 lg:w-1/3 xl:w-1/3 px-2 mb-4"
*
ngFor=
"let data of paginatedExcels; let i = index"
>
<div
class=
"group bg-white rounded-lg overflow-hidden shadow-lg border-4 border-blue-600 h-full flex flex-col transform transition-all duration-300 ease-in-out hover:scale-[1.02] hover:shadow-xl"
>
<div
class=
"p-4 flex justify-center items-center flex-shrink-0"
>
<img
class=
"w-full h-full object-cover rounded-md shadow-md transform transition-transform duration-300 group-hover:scale-105 cursor-pointer"
style=
"width: 400px; height: 200px; max-width: 100%;"
src=
"{{ data.getImage() }}"
alt=
"{{ data.thName }}"
(
click
)="
openEmployeeDialog
(
data
.
getImage
())"
/>
</div>
<div
class=
"p-4 flex-grow"
>
<span
class=
"text-xl font-semibold text-gray-800 mb-2"
style=
"font-size: 18px;"
>
{{ data.thName }}
</span>
<p
class=
"text-gray-700 text-sm mb-3"
>
{{ data.thDesc }}
</p>
<div
class=
"mb-0 flex items-center justify-center sm:justify-start gap-2 w-1/2 mt-5"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ตัวอย่างวิธีใช้งาน'"
(
click
)="
openLink
(
data
.
link1
)"
style=
"background-color: rgb(76, 117, 207, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
</div>
<div
class=
"mb-2 flex items-center justify-center sm:justify-start gap-2 w-1/2"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ดาวน์โหลด'"
(
click
)="
downloadFile
(
data
.
logId
)"
style=
"background-color: rgb(34, 197, 94, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
</div>
</div>
<div
class=
"px-4 py-3 border-t border-gray-200 text-right flex-shrink-0"
>
<small
class=
"text-gray-500 text-xs"
>
วันที่อัพโหลด {{ coverDate(data.uploadDate) }}
{{ data.uploadTime }}
</small>
</div>
</div>
</div>
<div
class=
"w-full text-center py-4"
*
ngIf=
"paginatedExcels.length === 0"
>
ไม่พบข้อมูล
</div>
</div>
</div>
<ng-template
#
editTemplateModal
let-modal
>
<div
class=
"modal-headtitle ti-modal-header flex justify-between items-center p-4"
style=
"background-color: #fefbfb;"
>
<h3
class=
"modal-title text-sm font-semibold text-defaulttextcolor"
id=
"edittemplateLabel"
>
{{ checkEdit ? ('แก้ไขไฟล์ Excel' | translate) : ('เพิ่มไฟล์ Excel' | translate) }}
</h3>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeDialog
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{ 'Close' | translate }}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"w-full flex justify-end"
>
<div
class=
"absolute flex"
>
<div
class=
"px-1"
>
</div>
</div>
</div>
<mat-dialog-content
style=
"padding: 0px; padding-left: 20px; padding-right: 20px;"
>
<div
class=
"box p-9 top-4"
>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"nameth"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อ (ไทย)' | translate }}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"nameth"
[(
ngModel
)]="
modelExcel
.
thName
"
name=
"thName"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"nameeng"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อ (อังกฤษ)' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"nameeng"
[(
ngModel
)]="
modelExcel
.
engName
"
name=
"engName"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"thDesc"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รายละเอียด (ไทย)' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"thDesc"
[(
ngModel
)]="
modelExcel
.
thDesc
"
rows=
"3"
name=
"thDesc"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"engDesc"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รายละเอียด (อังกฤษ)' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"engDesc"
[(
ngModel
)]="
modelExcel
.
engDesc
"
rows=
"3"
name=
"engDesc"
></textarea>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"dbSupport"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ดาต้าเบสที่รองรับ' | translate
}}
</label>
<select
class=
"custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"dbSupport"
[(
ngModel
)]="
modelExcel
.
dbSupport
"
name=
"dbSupport"
>
<option
value=
"SQLServer"
>
SQLServer
</option>
<option
value=
"PostgreSQL"
>
PostgreSQL
</option>
<option
value=
"Oracle"
>
Oracle
</option>
</select>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"linkExample"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'Link ตัวอย่าง' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"linkExample"
[(
ngModel
)]="
modelExcel
.
link1
"
name=
"link1"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"fileUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ไฟล์อัพโหลด' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"fileUpload"
(
change
)="
onSelectFile
($
event
)"
>
<button
*
ngIf=
"modelExcel.excelObj && checkEdit"
(
click
)="
downloadFile
(
modelExcel
.
logId
)"
class=
"ti-btn ti-btn-primary flex-shrink-0 px-4 py-2 rounded-md transition-all duration-200"
>
<i
class=
"fas fa-download mr-1"
></i>
{{ 'ดาวน์โหลด' | translate }}
</button>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.xlsx *.xlsm
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"imageUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รูปภาพตัวอย่าง' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"imageUpload"
(
change
)="
onUploadImage
($
event
)"
>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.jpeg, *.jpg, *.png
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"tags"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'แท็ก' | translate }}
</label>
<tag-input
[
theme
]="'
bootstrap
'"
[(
ngModel
)]='
modelExcel
.
tags
'
placeholder=
"{{ '+แท็ก' | translate }}"
[
onlyFromAutocomplete
]="
true
"
secondaryPlaceholder=
"{{ 'กดปุ่ม Enter เพื่อเพิ่มแท็กใหม่' | translate }}"
[
addOnBlur
]="
true
"
[
clearOnBlur
]="
true
"
class=
"w-full"
name=
"tags"
>
<tag-input-dropdown
[
autocompleteItems
]="
listTag
"
[
showDropdownIfEmpty
]="
true
"
>
</tag-input-dropdown>
</tag-input>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"group"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'กลุ่ม' | translate }}
</label>
<select
class=
"custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"group"
[(
ngModel
)]="
modelExcel
.
group
.
groupId
"
(
change
)="
selectGroup
()"
name=
"group"
>
<option
*
ngFor=
"let item of listGroup"
[
ngValue
]="
item
.
groupId
"
>
{{item.thName}}
</option>
</select>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'แสดงรูปแบบ Pivot' | translate }}
</label>
<div
class=
"flex items-center gap-4 mt-2"
>
<div
class=
"flex items-center"
>
<input
type=
"radio"
class=
"form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id=
"pivot0"
name=
"radio-pivot"
[
value
]="
0
"
[(
ngModel
)]="
modelExcel
.
isPivot
"
>
<label
class=
"ml-2 text-gray-700"
for=
"pivot0"
>
{{ 'ใช่' | translate }}
</label>
</div>
<div
class=
"flex items-center"
>
<input
type=
"radio"
class=
"form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id=
"pivot1"
name=
"radio-pivot"
[
value
]="
1
"
[(
ngModel
)]="
modelExcel
.
isPivot
"
>
<label
class=
"ml-2 text-gray-700"
for=
"pivot1"
>
{{ 'ไม่ใช่' | translate }}
</label>
</div>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'แสดงรูปแบบ DataGrid' | translate }}
</label>
<div
class=
"flex items-center gap-4 mt-2"
>
<div
class=
"flex items-center"
>
<input
type=
"radio"
class=
"form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id=
"datagrid0"
name=
"datagridCheck"
[
value
]="
0
"
[(
ngModel
)]="
modelExcel
.
isDataGrid
"
>
<label
class=
"ml-2 text-gray-700"
for=
"datagrid0"
>
{{ 'ใช่' | translate }}
</label>
</div>
<div
class=
"flex items-center"
>
<input
type=
"radio"
class=
"form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id=
"datagrid1"
name=
"datagridCheck"
[
value
]="
1
"
[(
ngModel
)]="
modelExcel
.
isDataGrid
"
>
<label
class=
"ml-2 text-gray-700"
for=
"datagrid1"
>
{{ 'ไม่ใช่' | translate }}
</label>
</div>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"remark"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'หมายเหตุ' | translate }}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"remark"
[(
ngModel
)]="
modelExcel
.
remark
"
rows=
"4"
name=
"remark"
></textarea>
</div>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions
style=
"justify-content: end;"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
(
click
)="
closeDialog
()"
>
{{ 'Cancel' | translate }}
</button>
<button
type=
"submit"
class=
"ti-btn bg-primary text-white !font-medium"
[
class
.
ti-btn-disabled
]="!
modelExcel
.
thName
||!
modelExcel
.
engName
"
[
disabled
]="!
modelExcel
.
thName
||!
modelExcel
.
engName
"
(
click
)="
onSumit
()"
>
{{ 'Save' | translate }}
</button>
</mat-dialog-actions>
</ng-template>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-excell/list-excell.component.scss
0 → 100644
View file @
73e72e5e
::ng-deep
ng2-dropdown-menu
{
z-index
:
9999
!
important
;
.ng2-dropdown-menu
{
z-index
:
9999
!
important
;
ng2-menu-item
{
z-index
:
9999
!
important
;
}
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-excell/list-excell.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
,
TemplateRef
,
ViewChild
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
ExcelModel
}
from
'../../../models/excel.model'
;
import
{
ExcelService
}
from
'../../../services/excel.service'
;
import
{
AlertModalComponent
}
from
'../alert-modal/alert-modal.component'
;
import
{
UploadService
}
from
'../../../services/upload.service'
;
import
{
TagService
}
from
'../../../services/tag.service'
;
import
{
TagModel
}
from
'../../../models/tag.mmodel'
;
import
{
GroupModel
}
from
'../../../models/group.mmodel'
;
import
{
OpenImageComponent
}
from
'../open-image/open-image.component'
;
import
{
GroupService
}
from
'../../../services/group.service'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
saveAs
from
'file-saver'
;
import
{
TagInputModule
}
from
'ngx-chips'
;
import
swal
from
'sweetalert'
;
@
Component
({
selector
:
'app-list-excel'
,
templateUrl
:
'./list-excell.component.html'
,
// Note: original was list-excell.component.html
styleUrls
:
[
'./list-excell.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
TagInputModule
,
],
})
export
class
ListExcelComponent
implements
OnInit
{
@
ViewChild
(
"editTemplateModal"
)
editTemplateModalRef
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
"listexcel"
)
listexcel
:
any
;
page
=
1
;
pageSize
=
10
;
pageIndex
:
number
=
0
;
maxPagesToShow
:
number
=
3
;
originalListExcel
:
ExcelModel
[]
=
[];
listExcel
:
ExcelModel
[]
=
[];
paginatedExcels
:
ExcelModel
[]
=
[];
modelExcel
:
ExcelModel
=
new
ExcelModel
({});
checkEdit
:
boolean
=
false
;
search
:
string
=
''
;
checkType
:
string
=
''
;
dialogRef
:
any
;
listTag
:
TagModel
[]
=
[];
listGroup
:
GroupModel
[]
=
[];
constructor
(
private
excelService
:
ExcelService
,
private
uploadService
:
UploadService
,
private
tagService
:
TagService
,
private
groupService
:
GroupService
,
private
dialog
:
MatDialog
,
)
{
}
applyFilterAndPagination
()
{
this
.
listExcel
=
this
.
originalListExcel
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
);
const
totalPagesAfterFilter
=
Math
.
ceil
(
this
.
listExcel
.
length
/
this
.
pageSize
);
if
(
this
.
pageIndex
>=
totalPagesAfterFilter
&&
totalPagesAfterFilter
>
0
)
{
this
.
pageIndex
=
totalPagesAfterFilter
-
1
;
}
else
if
(
totalPagesAfterFilter
===
0
)
{
this
.
pageIndex
=
0
;
}
const
startIndex
=
this
.
pageIndex
*
this
.
pageSize
;
const
endIndex
=
startIndex
+
this
.
pageSize
;
this
.
paginatedExcels
=
this
.
listExcel
.
slice
(
startIndex
,
endIndex
);
}
async
onUploadImage
(
event
:
any
)
{
try
{
if
(
event
.
target
.
files
.
length
>
0
)
{
let
fileData
=
event
.
target
.
files
[
0
];
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
fileData
);
const
allowedTypes
=
[
'image/png'
,
'image/jpeg'
,
'image/jpg'
];
if
(
!
allowedTypes
.
includes
(
fileData
.
type
))
{
this
.
openAlertModalWithMatDialog
(
'อัพโหลดได้เฉพาะไฟล์ *.jpeg, *.jpg, *.png เท่านั้น'
);
// Using MatDialog alert
}
else
{
const
data
=
await
this
.
uploadService
.
uploadImage
(
formData
).
toPromise
();
if
(
data
)
{
this
.
modelExcel
.
thumbnail
=
data
.
body
.
fileId
;
}
}
}
}
catch
(
error
)
{
console
.
error
(
'Error uploading image:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'เกิดข้อผิดพลาดในการอัปโหลดรูปภาพ'
);
}
}
async
getListTag
()
{
try
{
const
data
=
await
this
.
tagService
.
getList
().
toPromise
();
this
.
listTag
=
data
!
.
map
(
x
=>
new
TagModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading tags:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการแท็กได้'
);
}
}
async
getListGroup
()
{
try
{
const
data
=
await
this
.
groupService
.
getList
().
toPromise
();
this
.
listGroup
=
data
!
.
map
(
x
=>
new
GroupModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading groups:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการกลุ่มได้'
);
}
}
selectGroup
()
{
let
findData
=
this
.
listGroup
.
find
(
x
=>
x
.
groupId
==
this
.
modelExcel
.
group
.
groupId
);
this
.
modelExcel
.
group
=
findData
?
new
GroupModel
(
findData
)
:
new
GroupModel
({});
}
onSelectFile
(
event
:
any
)
{
if
(
event
.
target
.
files
&&
event
.
target
.
files
[
0
])
{
const
reader
=
new
FileReader
();
const
file
:
File
=
event
.
target
.
files
[
0
];
console
.
log
(
"🚀 ~ ListExcelComponent ~ onSelectFile ~ file:"
,
file
);
reader
.
readAsDataURL
(
event
.
target
.
files
[
0
]);
reader
.
onload
=
(
event
)
=>
{
if
(
event
)
{
const
allowedTypes
=
[
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'application/vnd.ms-excel.sheet.macroEnabled.12'
];
if
(
!
allowedTypes
.
includes
(
file
.
type
))
{
this
.
openAlertModalWithMatDialog
(
'อัพโหลดได้เฉพาะไฟล์ *.xlsx *.xlsm เท่านั้น'
);
}
else
{
let
base64
=
event
.
target
!
.
result
as
string
;
this
.
modelExcel
.
excelObj
=
base64
.
split
(
','
)[
1
];
this
.
modelExcel
.
fileType
=
file
.
name
.
split
(
'.'
)[
file
.
name
.
split
(
'.'
).
length
-
1
];
}
}
};
}
}
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
excelService
.
downloadFile
(
logId
).
toPromise
();
if
(
data
)
{
const
fileName
=
`
${
logId
}
.
${
this
.
modelExcel
.
fileType
||
'xlsx'
}
`
;
saveAs
(
new
Blob
([
data
]),
fileName
);
}
}
catch
(
error
)
{
console
.
error
(
'Error downloading file:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถดาวน์โหลดไฟล์ได้'
);
}
}
deleteFile
(
item
:
ExcelModel
)
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการลบข้อมูลนี้หรือไม่"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willDelete
:
boolean
)
=>
{
if
(
willDelete
)
{
this
.
excelService
.
deleteExcel
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
swal
(
"ลบสำเร็จ!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getListExcel
();
}
else
{
swal
(
"สำเร็จบางส่วน/ข้อผิดพลาด!!"
,
"มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด"
,
"warning"
);
}
},
error
=>
{
this
.
openAlertModalWithMatDialog
(
error
.
message
);
});
}
});
}
openAlertModalWithMatDialog
(
message
?:
string
)
{
this
.
dialog
.
open
(
AlertModalComponent
,
{
data
:
{
message
:
message
?
message
:
""
},
width
:
'400px'
,
disableClose
:
true
,
});
}
onUpdate
()
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการอัพเดทข้อมูลหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willUpdate
:
boolean
)
=>
{
if
(
willUpdate
)
{
console
.
log
(
this
.
modelExcel
);
this
.
excelService
.
createExcel
(
this
.
modelExcel
).
subscribe
(
res
=>
{
if
(
res
)
{
swal
(
"บันทึกสำเร็จ!!"
,
"อัพเดทข้อมูลสำเร็จ"
,
"success"
);
this
.
closeDialog
();
this
.
getListExcel
();
}
else
{
swal
(
'ไม่สามารถอัพเดทข้อมูลได้'
);
}
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
onCreate
()
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willSave
:
boolean
)
=>
{
if
(
willSave
)
{
this
.
excelService
.
createExcel
(
this
.
modelExcel
).
subscribe
(
res
=>
{
if
(
res
)
{
swal
(
"บันทึกสำเร็จ!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
closeDialog
();
this
.
getListExcel
();
}
else
{
swal
(
'ไม่สามารถสร้างเอกสารได้'
);
}
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
// onUpdate() {
// swal({
// title: "คุณแน่ใจหรือไม่?",
// text: "คุณต้องการอัพเดทข้อมูลหรือไม่",
// icon: "warning",
// dangerMode: false,
// buttons: ["ยกเลิก", "ยืนยัน"],
// }).then((willUpdate: boolean) => {
// if (willUpdate) {
// this.excelService.createExcel(this.modelExcel).subscribe({
// next: (res) => {
// console.log('Excel update response:', res);
// if (res) {
// // this.openAlertModalWithMatDialog('อัพเดทข้อมูลสำเร็จ');
// } else {
// this.openAlertModalWithMatDialog('ไม่สามารถอัพเดทข้อมูลได้ (res is false/null)');
// }
// this.closeDialog();
// this.getListExcel();
// },
// error: (error) => {
// this.openAlertModalWithMatDialog(error.message || 'เกิดข้อผิดพลาดในการอัปเดทข้อมูล');
// this.closeDialog();
// },
// });
// } else {
// this.closeDialog();
// }
// });
// }
// onCreate() {
// swal({
// title: "คุณแน่ใจหรือไม่?",
// text: "คุณต้องการบันทึกหรือไม่",
// icon: "warning",
// dangerMode: false,
// buttons: ["ยกเลิก", "ยืนยัน"],
// }).then((willSave: boolean) => {
// if (willSave) {
// this.excelService.createExcel(this.modelExcel).subscribe({
// next: (res) => {
// if (res) {
// // this.openAlertModalWithMatDialog('บันทึกข้อมูลสำเร็จ'); // <--- ลบบรรทัดนี้ออก
// } else {
// this.openAlertModalWithMatDialog('ไม่สามารถสร้างเอกสารได้ (res is false/null)');
// }
// this.closeDialog();
// this.getListExcel();
// },
// error: (error) => {
// this.openAlertModalWithMatDialog(error.message || 'เกิดข้อผิดพลาดในการสร้างเอกสาร');
// this.closeDialog();
// },
// });
// } else {
// this.closeDialog();
// }
// });
// }
onSumit
()
{
if
(
this
.
checkEdit
)
{
this
.
onUpdate
();
}
else
{
this
.
onCreate
();
}
}
async
getExcelById
(
id
:
string
)
{
// <--- แก้ไขตรงนี้
try
{
const
data
=
await
this
.
excelService
.
getExcelById
(
id
).
toPromise
();
this
.
modelExcel
=
new
ExcelModel
(
data
!
);
console
.
log
(
"🚀 ~ ListExcelComponent ~ getExcelById ~ this.modelExcel:"
,
this
.
modelExcel
);
if
(
data
)
{
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'1100px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Excel dialog opened by getExcelById closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListExcel
();
}
});
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดข้อมูลได้'
);
// เพิ่มการแจ้งเตือน
}
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
getStatus
(
status
:
string
):
string
{
if
(
status
===
'0'
)
{
return
'รออนุมัติ'
;
}
else
if
(
status
===
'1'
)
{
return
'เปิดใช้งาน'
;
}
else
if
(
status
===
'2'
)
{
return
'ไม่อนุมัติ'
;
}
else
{
return
'ไม่ทราบสถานะ'
;
}
}
async
getListExcel
()
{
try
{
const
data
=
await
this
.
excelService
.
getListExcel
().
toPromise
();
this
.
originalListExcel
=
data
!
.
map
(
x
=>
new
ExcelModel
(
x
));
this
.
applyFilterAndPagination
();
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการ Excel ได้'
);
}
}
get
totalFilteredItems
():
number
{
return
this
.
listExcel
.
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalFilteredItems
/
this
.
pageSize
);
}
get
startItemIndex
():
number
{
if
(
this
.
totalFilteredItems
===
0
)
return
0
;
return
this
.
pageIndex
*
this
.
pageSize
+
1
;
}
get
endItemIndex
():
number
{
const
end
=
Math
.
min
((
this
.
pageIndex
+
1
)
*
this
.
pageSize
,
this
.
totalFilteredItems
);
return
end
;
}
goToPage
(
page
:
number
)
{
if
(
page
>=
0
&&
page
<
this
.
totalPages
)
{
this
.
pageIndex
=
page
;
this
.
applyFilterAndPagination
();
}
else
if
(
this
.
totalPages
===
0
&&
page
===
0
)
{
this
.
pageIndex
=
0
;
this
.
applyFilterAndPagination
();
}
}
onSearchChange
()
{
this
.
pageIndex
=
0
;
this
.
applyFilterAndPagination
();
}
get
pages
():
number
[]
{
const
pages
=
[];
const
startPage
=
Math
.
max
(
0
,
this
.
pageIndex
-
Math
.
floor
(
this
.
maxPagesToShow
/
2
));
const
endPage
=
Math
.
min
(
this
.
totalPages
-
1
,
startPage
+
this
.
maxPagesToShow
-
1
);
for
(
let
i
=
startPage
;
i
<=
endPage
;
i
++
)
{
pages
.
push
(
i
);
}
return
pages
;
}
ngOnInit
()
{
this
.
getListExcel
();
this
.
getListTag
();
this
.
getListGroup
();
}
openEmployeeDialog
(
image
:
string
)
{
const
dialogConfig
=
{
width
:
'750px'
,
disableClose
:
false
,
data
:
{
linkImage
:
image
},
panelClass
:
'my-dialog-img-preview'
,
};
this
.
dialogRef
=
this
.
dialog
.
open
(
OpenImageComponent
,
dialogConfig
);
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
any
)
=>
{
console
.
log
(
'The dialog was closed'
,
result
);
},
(
reason
:
any
)
=>
{
});
}
coverDate
(
date
:
string
)
{
return
date
.
split
(
'-'
).
reverse
().
join
(
'/'
);
}
openEditExcelDialog
(
item
?:
ExcelModel
)
{
if
(
item
)
{
this
.
excelService
.
getExcelById
(
item
.
logId
).
toPromise
().
then
(
data
=>
{
if
(
data
)
{
this
.
modelExcel
=
new
ExcelModel
(
data
!
);
this
.
checkEdit
=
true
;
}
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'1100px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Edit Excel dialog closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListExcel
();
}
});
}).
catch
(
error
=>
{
console
.
error
(
'Error loading data for edit:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดข้อมูลเพื่อแก้ไขได้'
);
});
}
else
{
this
.
modelExcel
=
new
ExcelModel
({});
this
.
checkEdit
=
false
;
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'800px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Edit Excel dialog closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListExcel
();
}
});
}
}
closeDialog
()
{
if
(
this
.
dialogRef
)
{
this
.
dialogRef
.
close
();
}
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-widgets/list-widgets.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการวิทเจ็ด'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการอัพโหลดเอกสาร
Widget
'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
{{ 'All List' | translate}}
</div>
<div
class=
"flex flex-wrap gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(
click
)="
openEditExcelDialog
()"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'Create' |
translate}}
</a>
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหาบริษัท"
aria-label=
".form-control-sm example"
[(
ngModel
)]="
search
"
(
ngModelChange
)="
onSearchChange
()"
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
*
ngIf=
"checkType !== '1'"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead>
<tr
class=
"border-b border-defaultborder text-white"
style=
"background-color: #49b6f5;"
>
<th
scope=
"col"
class=
"text-start"
>
#
</th>
<th
scope=
"col"
class=
"text-start"
>
รูปภาพ
</th>
<th
scope=
"col"
class=
"text-start"
>
ชื่อ
</th>
<th
scope=
"col"
class=
"text-start"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"text-start"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"text-start"
>
ไฟล์
</th>
<th
scope=
"col"
class=
"text-start"
>
สถานะ
</th>
<th
scope=
"col"
class=
"text-start"
>
การจัดการ
</th>
</tr>
</thead>
<tbody>
<tr
class=
"border border-defaultborder dark:border-defaultborder/10"
*
ngFor=
"let data of paginatedWidgets; let i = index"
>
<td>
<div>
<span
class=
"block mb-1"
>
{{pageIndex * pageSize + i + 1}}
</span>
</div>
</td>
<td>
<div
class=
"flex items-center"
>
<span
class=
"p-3 me-1"
style=
"width: 200px;"
>
<img
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeDialog
(
data
.
getImage
())"
id=
"profile-img"
class=
"border-radius-1 cursor-pointer"
style=
"width: 180px; height: 120px; object-fit: cover;"
>
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{ data.widgetTname }}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
{{ data.thDesc }}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0 cursor-pointer active: hover:text-danger hover:scale-125 transition duration-300"
(
click
)="
openLink
(
data
.
link1
)"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td>
<div>
<span
class=
"block mb-1"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0 cursor-pointer active hover:text-success hover:scale-125 transition duration-300"
(
click
)="
downloadFile
(
data
.
widgetId
)"
style=
"font-size: 20px;"
></i>
</span>
</div>
</td>
<td>
<div>
<ng-container
*
ngIf=
"data.status === 0"
>
<span
class=
"badge bg-amber-300 text-white"
>
รออนุมัติ
</span>
</ng-container>
<ng-container
*
ngIf=
"data.status === 1"
>
<span
class=
"badge bg-success text-white"
>
เปิดใช้งาน
</span>
</ng-container>
<ng-container
*
ngIf=
"data.status === 2"
>
<span
class=
"badge bg-gray-500 text-white"
>
ไม่อนุมัติ
</span>
</ng-container>
</div>
</td>
<td>
<div
class=
"flex flex-row items-center !gap-2 "
>
<a
aria-label=
"anchor"
(
click
)="
openEditExcelDialog
(
data
)"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
>
<i
class=
"ri-pencil-line"
></i>
</a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
(
click
)="
deleteFile
(
data
)"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"
>
<i
class=
"ri-delete-bin-line"
></i>
</a>
</div>
</td>
</tr>
<tr
*
ngIf=
"paginatedWidgets.length === 0"
>
<td
colspan=
"9"
class=
"text-center py-4"
>
ไม่พบข้อมูล
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
>
<div
class=
"mb-2 sm:mb-0"
>
<select
class=
"custom-select m-r-5"
style=
"width: auto"
[(
ngModel
)]="
pageSize
"
(
ngModelChange
)="
goToPage
(
0
)"
>
<option
[
ngValue
]="
10
"
>
รายการต่อหน้า: 10
</option>
<option
[
ngValue
]="
50
"
>
รายการต่อหน้า: 50
</option>
<option
[
ngValue
]="
100
"
>
รายการต่อหน้า: 100
</option>
</select>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0 flex"
>
<li
class=
"page-item"
[
class
.
disabled
]="
pageIndex =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
goToPage
(
pageIndex
-
1
)"
>
{{ 'Previous' | translate }}
</a>
</li>
<ng-container
*
ngFor=
"let p of pages"
>
<li
class=
"page-item"
[
class
.
active
]="
p =
==
pageIndex
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
[
class
.
active
]="
p =
==
pageIndex
"
(
click
)="
goToPage
(
p
)"
>
{{ p + 1 }}
</a>
</li>
</ng-container>
<li
class=
"page-item"
[
class
.
disabled
]="
pageIndex =
==
totalPages
-
1
||
totalPages =
==
0
"
>
<a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
goToPage
(
pageIndex
+
1
)"
>
{{ 'Next' | translate }}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template
#
editTemplateModal
let-modal
>
<div
class=
"modal-headtitle ti-modal-header flex justify-between items-center p-4"
style=
"background-color: #fefbfb;"
>
<h3
class=
"modal-title text-sm font-semibold text-defaulttextcolor"
id=
"edittemplateLabel"
>
{{ checkEdit ? ('แก้ไขไฟล์ Widget' | translate) : ('เพิ่มไฟล์ Widget' | translate) }}
</h3>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeDialog
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{ 'Close' | translate }}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"w-full flex justify-end"
>
<div
class=
"absolute flex"
>
<div
class=
"px-1"
>
</div>
</div>
</div>
<mat-dialog-content
style=
"padding: 0px; padding-left: 20px; padding-right: 20px;"
>
<div
class=
"box p-9 top-4"
>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"nameth"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อวิทเจ็ด (ไทย)' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"nameth"
[(
ngModel
)]="
modelWidget
.
widgetTname
"
name=
"widgetTname"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"nameeng"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ชื่อวิทเจ็ด (อังกฤษ)' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"nameeng"
[(
ngModel
)]="
modelWidget
.
widgetEname
"
name=
"widgetEname"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"thDesc"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รายละเอียด (ไทย)' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"thDesc"
[(
ngModel
)]="
modelWidget
.
thDesc
"
rows=
"3"
name=
"thDesc"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"engDesc"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รายละเอียด (อังกฤษ)' | translate
}}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"engDesc"
[(
ngModel
)]="
modelWidget
.
engDesc
"
rows=
"3"
name=
"engDesc"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"group"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ภาษาที่รองรับ' | translate }}
</label>
<select
class=
"custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"status"
[(
ngModel
)]="
modelWidget
.
status
"
name=
"status"
>
<option
[
value
]="
0
"
>
Private
</option>
<option
[
value
]="
1
"
>
Public
</option>
</select>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"dbSupport"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ดาต้าเบสที่รองรับ' | translate
}}
</label>
<select
class=
"custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"dbSupport"
[(
ngModel
)]="
modelWidget
.
dbSupport
"
name=
"dbSupport"
>
<option
value=
"SQLServer"
>
SQLServer
</option>
<option
value=
"PostgreSQL"
>
PostgreSQL
</option>
<option
value=
"Oracle"
>
Oracle
</option>
</select>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"fileUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'ไฟล์อัพโหลด' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"fileUpload"
(
change
)="
onSelectFile
($
event
)"
>
<button
*
ngIf=
"modelWidget.widgetObj && checkEdit"
(
click
)="
downloadFile
(
modelWidget
.
widgetId
)"
class=
"ti-btn ti-btn-primary flex-shrink-0 px-4 py-2 rounded-md transition-all duration-200"
>
<i
class=
"fas fa-download mr-1"
></i>
{{ 'ดาวน์โหลด' | translate }}
</button>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.xlsx *.xlsm
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"imageUpload"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'รูปภาพตัวอย่าง' | translate
}}
</label>
<div
class=
"flex items-center gap-2"
>
<input
type=
"file"
class=
"form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"imageUpload"
(
change
)="
onUploadImage
($
event
)"
>
</div>
<div
class=
"msg-detail text-sm text-red mt-1"
>
ไฟล์ที่อนุญาต:*.jpeg, *.jpg, *.png
</div>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"linkExample"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'Link ตัวอย่าง' | translate
}}
</label>
<input
type=
"text"
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"linkExample"
[(
ngModel
)]="
modelWidget
.
link1
"
name=
"link1"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"tags"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'แท็ก' | translate }}
</label>
<tag-input
[
theme
]="'
bootstrap
'"
[(
ngModel
)]='
modelWidget
.
tags
'
placeholder=
"{{ '+แท็ก' | translate }}"
[
onlyFromAutocomplete
]="
true
"
secondaryPlaceholder=
"{{ 'กดปุ่ม Enter เพื่อเพิ่มแท็กใหม่' | translate }}"
[
addOnBlur
]="
true
"
[
clearOnBlur
]="
true
"
class=
"w-full"
name=
"tags"
>
<tag-input-dropdown
[
autocompleteItems
]="
listTag
"
[
showDropdownIfEmpty
]="
true
"
>
</tag-input-dropdown>
</tag-input>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"group"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'กลุ่ม' | translate }}
</label>
<select
class=
"custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"group"
[(
ngModel
)]="
modelWidget
.
group
.
groupId
"
(
change
)="
selectGroup
()"
name=
"group"
>
<option
*
ngFor=
"let item of listGroup"
[
ngValue
]="
item
.
groupId
"
>
{{item.thName}}
</option>
</select>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'แสดงรูปแบบ Pivot' | translate }}
</label>
<div
class=
"flex items-center gap-4 mt-2"
>
<div
class=
"flex items-center"
>
<input
type=
"radio"
class=
"form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id=
"pivot0"
name=
"radio-pivot"
[
value
]="
0
"
[(
ngModel
)]="
modelWidget
.
isPivot
"
>
<label
class=
"ml-2 text-gray-700"
for=
"pivot0"
>
{{ 'ใช่' | translate }}
</label>
</div>
<div
class=
"flex items-center"
>
<input
type=
"radio"
class=
"form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id=
"pivot1"
name=
"radio-pivot"
[
value
]="
1
"
[(
ngModel
)]="
modelWidget
.
isPivot
"
>
<label
class=
"ml-2 text-gray-700"
for=
"pivot1"
>
{{ 'ไม่ใช่' | translate }}
</label>
</div>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'แสดงรูปแบบ DataGrid' | translate }}
</label>
<div
class=
"flex items-center gap-4 mt-2"
>
<div
class=
"flex items-center"
>
<input
type=
"radio"
class=
"form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id=
"datagrid0"
name=
"datagridCheck"
[
value
]="
0
"
[(
ngModel
)]="
modelWidget
.
isDataGrid
"
>
<label
class=
"ml-2 text-gray-700"
for=
"datagrid0"
>
{{ 'ใช่' | translate }}
</label>
</div>
<div
class=
"flex items-center"
>
<input
type=
"radio"
class=
"form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id=
"datagrid1"
name=
"datagridCheck"
[
value
]="
1
"
[(
ngModel
)]="
modelWidget
.
isDataGrid
"
>
<label
class=
"ml-2 text-gray-700"
for=
"datagrid1"
>
{{ 'ไม่ใช่' | translate }}
</label>
</div>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"remark"
class=
"block text-primary mb-2 font-bold font-14"
>
{{ 'หมายเหตุ' | translate }}
</label>
<textarea
class=
"form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id=
"remark"
[(
ngModel
)]="
modelWidget
.
remark
"
rows=
"4"
name=
"remark"
></textarea>
</div>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions
style=
"justify-content: end;"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
(
click
)="
closeDialog
()"
>
{{ 'Cancel' | translate }}
</button>
<button
type=
"submit"
class=
"ti-btn bg-primary text-white !font-medium"
[
class
.
ti-btn-disabled
]="!
modelWidget
.
widgetTname
||!
modelWidget
.
widgetEname
"
[
disabled
]="!
modelWidget
.
widgetTname
||!
modelWidget
.
widgetEname
"
(
click
)="
onSumit
()"
>
{{ 'Save' | translate }}
</button>
</mat-dialog-actions>
</ng-template>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-widgets/list-widgets.component.scss
0 → 100644
View file @
73e72e5e
::ng-deep
ng2-dropdown-menu
{
z-index
:
9999
!
important
;
.ng2-dropdown-menu
{
z-index
:
9999
!
important
;
ng2-menu-item
{
z-index
:
9999
!
important
;
}
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/list-widgets/list-widgets.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
,
TemplateRef
,
ViewChild
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
AlertModalComponent
}
from
'../alert-modal/alert-modal.component'
;
import
{
UploadService
}
from
'../../../services/upload.service'
;
import
{
TagService
}
from
'../../../services/tag.service'
;
import
{
TagModel
}
from
'../../../models/tag.mmodel'
;
import
{
GroupModel
}
from
'../../../models/group.mmodel'
;
import
{
OpenImageComponent
}
from
'../open-image/open-image.component'
;
import
{
GroupService
}
from
'../../../services/group.service'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
saveAs
from
'file-saver'
;
import
{
TagInputModule
}
from
'ngx-chips'
;
import
swal
from
'sweetalert'
;
import
{
WidgetModel
}
from
'../../../models/widgets.model'
;
import
{
WidgetService
}
from
'../../../services/widgets.service'
;
@
Component
({
selector
:
'app-list-widgets'
,
templateUrl
:
'./list-widgets.component.html'
,
styleUrls
:
[
'./list-widgets.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
TagInputModule
,
],
})
export
class
ListWidgetsComponent
implements
OnInit
{
@
ViewChild
(
"editTemplateModal"
)
editTemplateModalRef
!
:
TemplateRef
<
any
>
;
checkType
:
string
=
''
;
page
=
1
;
pageSize
=
10
;
pageIndex
:
number
=
0
;
maxPagesToShow
:
number
=
3
;
// Initialize with empty arrays to prevent undefined errors before data loads
listWidgets
:
WidgetModel
[]
=
[];
// This will now store the filtered list
originallistWidgets
:
WidgetModel
[]
=
[];
// This will store the raw data from API
paginatedWidgets
:
WidgetModel
[]
=
[];
// This will store the sliced data for the current page
dialogRef
:
any
;
modelWidget
:
WidgetModel
=
new
WidgetModel
({});
checkEdit
:
boolean
=
false
;
search
:
string
=
''
;
listTag
:
TagModel
[]
=
[];
listGroup
:
GroupModel
[]
=
[];
constructor
(
private
modalService
:
NgbModal
,
private
widgetService
:
WidgetService
,
private
uploadService
:
UploadService
,
private
tagService
:
TagService
,
private
groupService
:
GroupService
,
private
dialog
:
MatDialog
,)
{
}
// Central method for filtering and pagination
applyFilterAndPagination
()
{
// Ensure `originallistWidgets` is the source for filtering
this
.
listWidgets
=
this
.
originallistWidgets
.
filter
(
x
=>
x
.
widgetTname
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
widgetEname
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
);
const
totalPagesAfterFilter
=
Math
.
ceil
(
this
.
listWidgets
.
length
/
this
.
pageSize
);
if
(
this
.
pageIndex
>=
totalPagesAfterFilter
&&
totalPagesAfterFilter
>
0
)
{
this
.
pageIndex
=
totalPagesAfterFilter
-
1
;
}
else
if
(
totalPagesAfterFilter
===
0
)
{
this
.
pageIndex
=
0
;
}
const
startIndex
=
this
.
pageIndex
*
this
.
pageSize
;
const
endIndex
=
startIndex
+
this
.
pageSize
;
this
.
paginatedWidgets
=
this
.
listWidgets
.
slice
(
startIndex
,
endIndex
);
}
onSelectFile
(
event
:
any
)
{
if
(
event
.
target
.
files
&&
event
.
target
.
files
[
0
])
{
const
reader
=
new
FileReader
();
const
file
:
File
=
event
.
target
.
files
[
0
];
console
.
log
(
"🚀 ~ listWidgetsComponent ~ onSelectFile ~ file:"
,
file
)
reader
.
readAsDataURL
(
event
.
target
.
files
[
0
]);
// read file as data url
reader
.
onload
=
(
event
)
=>
{
// called once readAsDataURL is completed
if
(
event
)
{
const
allowedTypes
=
[
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
,
'application/vnd.ms-excel.sheet.macroEnabled.12'
];
if
(
!
allowedTypes
.
includes
(
file
.
type
))
{
this
.
openAlertModalWithMatDialog
(
'อัพโหลดได้เฉพาะไฟล์ *.xlsx *.xlsm เท่านั้น'
);
}
else
{
let
base64
=
event
.
target
!
.
result
as
string
;
this
.
modelWidget
.
widgetObj
=
base64
.
split
(
','
)[
1
];
this
.
modelWidget
.
fileType
=
file
.
name
.
split
(
'.'
)[
file
.
name
.
split
(
'.'
).
length
-
1
];
}
}
};
}
}
async
downloadFile
(
logId
:
string
)
{
try
{
// Assuming modelWidget.fileType is available and correct after a file has been selected/uploaded
// If not, you might need to get the file type from the service or infer it.
const
data
=
await
this
.
widgetService
.
downloadFile
(
logId
).
toPromise
();
if
(
data
)
{
const
fileName
=
`
${
logId
}
.
${
this
.
modelWidget
.
fileType
||
'xlsx'
}
`
;
// Fallback to 'xlsx'
saveAs
(
new
Blob
([
data
]),
fileName
);
}
}
catch
(
error
)
{
console
.
error
(
'Error downloading file:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถดาวน์โหลดไฟล์ได้'
);
}
}
async
getListGroup
()
{
try
{
const
data
=
await
this
.
groupService
.
getList
().
toPromise
();
this
.
listGroup
=
data
!
.
map
(
x
=>
new
GroupModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading groups:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการกลุ่มได้'
);
}
}
selectGroup
()
{
let
findData
=
this
.
listGroup
.
find
(
x
=>
x
.
groupId
===
this
.
modelWidget
.
group
.
groupId
);
this
.
modelWidget
.
group
=
findData
?
new
GroupModel
(
findData
)
:
new
GroupModel
({});
}
async
onUploadImage
(
event
:
any
)
{
try
{
if
(
event
.
target
.
files
.
length
>
0
)
{
let
fileData
=
event
.
target
.
files
[
0
];
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
fileData
);
const
allowedTypes
=
[
'image/png'
,
'image/jpeg'
,
'image/jpg'
];
if
(
!
allowedTypes
.
includes
(
fileData
.
type
))
{
this
.
openAlertModalWithMatDialog
(
'อัพโหลดได้เฉพาะไฟล์ *.jpeg, *.jpg, *.png เท่านั้น'
);
}
else
{
const
data
=
await
this
.
uploadService
.
uploadImage
(
formData
).
toPromise
();
if
(
data
)
{
this
.
modelWidget
.
picture
=
data
.
body
.
fileId
;
}
}
}
}
catch
(
error
)
{
console
.
error
(
'Error uploading image:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'เกิดข้อผิดพลาดในการอัปโหลดรูปภาพ'
);
}
}
deleteFile
(
item
:
WidgetModel
)
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการลบข้อมูลนี้หรือไม่"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willDelete
:
boolean
)
=>
{
if
(
willDelete
)
{
this
.
widgetService
.
deleteWidget
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
swal
(
"ลบสำเร็จ!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getListWidgets
();
// Re-fetch and re-apply filter/pagination
}
else
{
swal
(
"สำเร็จบางส่วน/ข้อผิดพลาด!!"
,
"มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด"
,
"warning"
);
}
},
error
=>
{
this
.
openAlertModalWithMatDialog
(
error
.
message
);
});
}
});
}
openAlertModalWithMatDialog
(
message
?:
string
)
{
this
.
dialog
.
open
(
AlertModalComponent
,
{
data
:
{
message
:
message
?
message
:
""
},
width
:
'400px'
,
disableClose
:
true
,
});
}
onUpdate
()
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการอัพเดทข้อมูลหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willUpdate
:
boolean
)
=>
{
if
(
willUpdate
)
{
console
.
log
(
this
.
modelWidget
);
this
.
widgetService
.
createWidget
(
this
.
modelWidget
).
subscribe
(
res
=>
{
if
(
res
)
{
swal
(
"บันทึกสำเร็จ!!"
,
"อัพเดทข้อมูลสำเร็จ"
,
"success"
);
this
.
closeDialog
();
this
.
getListWidgets
();
// Re-fetch and re-apply filter/pagination
}
else
{
swal
(
'ไม่สามารถอัพเดทข้อมูลได้'
);
}
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
onCreate
()
{
swal
({
title
:
"คุณแน่ใจหรือไม่?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"ยกเลิก"
,
"ยืนยัน"
],
}).
then
((
willSave
:
boolean
)
=>
{
if
(
willSave
)
{
this
.
widgetService
.
createWidget
(
this
.
modelWidget
).
subscribe
(
res
=>
{
if
(
res
)
{
swal
(
"บันทึกสำเร็จ!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
closeDialog
();
this
.
getListWidgets
();
// Re-fetch and re-apply filter/pagination
}
else
{
swal
(
'ไม่สามารถสร้างเอกสารได้'
);
}
},
error
=>
{
console
.
error
(
"เกิดข้อผิดพลาดในการบันทึก/อัปเดต:"
,
error
);
swal
(
"ข้อผิดพลาด!!"
,
"ไม่สามารถบันทึก/อัปเดตข้อมูลได้"
,
"error"
);
});
}
});
}
onSumit
()
{
if
(
this
.
checkEdit
)
{
this
.
onUpdate
();
}
else
{
this
.
onCreate
();
}
}
// This method openModal with NgbModal is currently unused as MatDialog is used for edit template.
// If not explicitly needed for other NgbModal usage, it can be removed.
async
getWidgetById
(
targetModal
:
NgbModal
,
id
:
string
)
{
try
{
const
data
=
await
this
.
widgetService
.
getWidgetById
(
id
).
toPromise
();
this
.
modelWidget
=
new
WidgetModel
(
data
!
);
if
(
data
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
'static'
,
size
:
'lg'
});
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
getStatus
(
status
:
string
):
string
{
if
(
status
===
'0'
)
{
return
'Private'
;
}
else
if
(
status
===
'1'
)
{
return
'Public'
;
}
else
{
return
'ไม่ทราบสถานะ'
;
}
}
async
getListWidgets
()
{
try
{
const
data
=
await
this
.
widgetService
.
getListWidgets
().
toPromise
();
this
.
originallistWidgets
=
data
!
.
map
(
x
=>
new
WidgetModel
(
x
));
// Populate original list
this
.
applyFilterAndPagination
();
// Apply filter and pagination after fetching
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการ Widget ได้'
);
}
}
get
totalFilteredItems
():
number
{
return
this
.
listWidgets
.
length
;
// `listWidgets` now holds the filtered count
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalFilteredItems
/
this
.
pageSize
);
}
get
startItemIndex
():
number
{
if
(
this
.
totalFilteredItems
===
0
)
return
0
;
return
this
.
pageIndex
*
this
.
pageSize
+
1
;
}
get
endItemIndex
():
number
{
const
end
=
Math
.
min
((
this
.
pageIndex
+
1
)
*
this
.
pageSize
,
this
.
totalFilteredItems
);
return
end
;
}
goToPage
(
page
:
number
)
{
if
(
page
>=
0
&&
page
<
this
.
totalPages
)
{
this
.
pageIndex
=
page
;
this
.
applyFilterAndPagination
();
// Re-apply filter and pagination
}
else
if
(
this
.
totalPages
===
0
&&
page
===
0
)
{
this
.
pageIndex
=
0
;
this
.
applyFilterAndPagination
();
}
}
onSearchChange
()
{
this
.
pageIndex
=
0
;
// Reset to the first page when search changes
this
.
applyFilterAndPagination
();
// Re-apply filter and pagination
}
get
pages
():
number
[]
{
const
pages
:
number
[]
=
[];
const
startPage
=
Math
.
max
(
0
,
this
.
pageIndex
-
Math
.
floor
(
this
.
maxPagesToShow
/
2
));
const
endPage
=
Math
.
min
(
this
.
totalPages
-
1
,
startPage
+
this
.
maxPagesToShow
-
1
);
for
(
let
i
=
startPage
;
i
<=
endPage
;
i
++
)
{
pages
.
push
(
i
);
}
return
pages
;
}
ngOnInit
()
{
this
.
getListWidgets
();
// Initial data fetch and display
this
.
getListTag
();
this
.
getListGroup
();
}
async
getListTag
()
{
try
{
// Assuming tagService.getListWidgets() is the correct method for tags
const
data
=
await
this
.
tagService
.
getList
().
toPromise
();
// Assuming general getList
this
.
listTag
=
data
!
.
map
(
x
=>
new
TagModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading tags:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดรายการแท็กได้'
);
}
}
openEmployeeDialog
(
image
:
string
)
{
const
dialogConfig
=
{
width
:
'750px'
,
disableClose
:
false
,
data
:
{
linkImage
:
image
},
panelClass
:
'my-dialog-img-preview'
,
};
this
.
dialogRef
=
this
.
dialog
.
open
(
OpenImageComponent
,
dialogConfig
);
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
any
)
=>
{
console
.
log
(
'The dialog was closed'
,
result
);
},
(
reason
:
any
)
=>
{
});
}
openEditExcelDialog
(
item
?:
WidgetModel
)
{
if
(
item
)
{
this
.
widgetService
.
getWidgetById
(
item
.
widgetId
).
toPromise
().
then
(
data
=>
{
if
(
data
)
{
this
.
modelWidget
=
new
WidgetModel
(
data
!
);
this
.
checkEdit
=
true
;
}
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'1100px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Edit Widget dialog closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListWidgets
();
// Refresh list on success
}
});
}).
catch
(
error
=>
{
console
.
error
(
'Error loading data for edit:'
,
error
);
this
.
openAlertModalWithMatDialog
(
'ไม่สามารถโหลดข้อมูลเพื่อแก้ไขได้'
);
});
}
else
{
this
.
modelWidget
=
new
WidgetModel
({});
this
.
checkEdit
=
false
;
this
.
dialogRef
=
this
.
dialog
.
open
(
this
.
editTemplateModalRef
,
{
width
:
'800px'
,
disableClose
:
true
,
});
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
boolean
)
=>
{
console
.
log
(
'Edit Widget dialog closed with result:'
,
result
);
if
(
result
===
true
)
{
this
.
getListWidgets
();
// Refresh list on success
}
});
}
}
closeDialog
()
{
if
(
this
.
dialogRef
)
{
this
.
dialogRef
.
close
();
}
}
closeBtnClick
()
{
this
.
modalService
.
dismissAll
();
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/approved-list/approved-list.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการเอกสารผ่านการอนุมัติ'"
[
activeTitle
]="'รายการเอกสารผ่านการอนุมัติ'"
[
title1
]="'อนุมัติหลักสูตร'"
></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการเอกสาร</h4>
<div class="row justify-content-center">
<div class="col-md-4 " *ngFor="let c of testdata|slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<div class="card border border-2">
<div class="card-body text-center">
<img src="{{ c.img }}" class="rounded-circle border p-1" width="100">
<h3 class="card-title mt-3 mb-0">{{c.name}}</h3>
</div>
<div class="d-flex justify-content-between bg-light border-top p-3">
<div>
<span class="align-middle">จำนวนเอกสาร {{ c.document }} ฉบับ</span>
</div>
<div >
<button class="btn btn-info btn-sm text-nowrap" (click)="openView(c.id)">รายละเอียด</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
<div
class=
"max-w-7xl mx-auto"
>
<div
class=
"box p-4"
>
<h4
class=
"text-xl font-semibold text-gray-800 mb-6"
>
รายการเอกสาร
</h4>
<!-- Flex แทน Grid -->
<div
class=
"flex flex-wrap justify-center gap-6"
>
<div
class=
" bg-white rounded-xl shadow-lg overflow-hidden transform hover:scale-105 transition duration-300 ease-in-out flex flex-col"
style=
"width: 30%;"
*
ngFor=
"let c of testdata | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize"
>
<div
class=
"p-8 text-center"
>
<div
class=
"w-24 h-24 mx-auto rounded-full bg-green-100 flex items-center justify-center shadow-inner"
>
<img
src=
"{{ c.img }}"
class=
""
alt=
""
/>
</div>
<h3
class=
"text-2xl font-bold text-gray-800 mt-6 mb-2"
>
{{ c.name }}
</h3>
</div>
<!-- Footer -->
<div
class=
"mt-auto"
>
<div
class=
"flex justify-between items-center bg-gray-50 border-t border-gray-200 p-4"
>
<div>
<span
class=
"text-sm text-gray-700"
>
จำนวนเอกสาร {{ c.document }} ฉบับ
</span>
</div>
<div>
<button
class=
"bg-primary inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md shadow-md
active hover:bg-success hover:scale-110 transition duration-300 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50"
(
click
)="
openView
(
c
.
id
)"
>
รายละเอียด
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/approved-list/approved-list.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/approved-list/approved-list.component.spec.ts
0 → 100644
View file @
73e72e5e
import
{
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
ApprovedListComponent
}
from
'./approved-list.component'
;
describe
(
'ApprovedListComponent'
,
()
=>
{
let
component
:
ApprovedListComponent
;
let
fixture
:
ComponentFixture
<
ApprovedListComponent
>
;
beforeEach
(
async
()
=>
{
await
TestBed
.
configureTestingModule
({
declarations
:
[
ApprovedListComponent
]
})
.
compileComponents
();
});
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
ApprovedListComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/DPU/myskill-x/myportal/management/approved-list/approved-list.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
Router
,
RouterModule
}
from
'@angular/router'
;
import
{
DocumentService
}
from
'../../../../services/document.service'
;
import
{
CourseService
}
from
'../../../../services/course.service'
;
import
{
ExcelService
}
from
'../../../../services/excel.service'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
SharedModule
}
from
'../../../../../shared/shared.module'
;
@
Component
({
selector
:
'app-approved-list'
,
templateUrl
:
'./approved-list.component.html'
,
styleUrls
:
[
'./approved-list.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
TranslateModule
,
SharedModule
,
],
})
export
class
ApprovedListComponent
implements
OnInit
{
constructor
(
private
routes
:
Router
,
private
excelService
:
ExcelService
,
private
documentService
:
DocumentService
,
private
courseService
:
CourseService
)
{}
page
=
1
;
pageSize
=
10
;
testdata
:
{
id
:
string
;
img
:
String
;
name
:
String
;
details
:
String
;
document
:
String
;
}[]
=
[];
ngOnInit
()
{
this
.
testdata
=
[
{
id
:
'1'
,
img
:
"assets/images/icons/excel.png"
,
name
:
"Excel"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'2'
,
img
:
"assets/images/icons/document.png"
,
name
:
"Document"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'3'
,
img
:
"assets/images/icons/course.png"
,
name
:
"Course"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
];
this
.
getListCount
();
}
async
getListCount
(){
try
{
const
countExcel
=
await
this
.
excelService
.
getCountContent
().
toPromise
();
const
countDoc
=
await
this
.
documentService
.
getCountContent
().
toPromise
();
const
countCourse
=
await
this
.
courseService
.
getCountContent
().
toPromise
();
this
.
testdata
.
forEach
((
x
,
i
)
=>
{
if
(
i
==
0
){
x
.
document
=
(
countExcel
??
0
).
toString
()
}
else
if
(
i
==
1
){
x
.
document
=
(
countDoc
??
0
).
toString
()
}
else
if
(
i
==
2
){
x
.
document
=
(
countCourse
??
0
).
toString
()
}
})
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
openView
(
id
:
string
){
if
(
id
==
'1'
){
this
.
routes
.
navigate
([
'/admin/view-list-excel/1'
]);
}
else
if
(
id
==
'2'
){
this
.
routes
.
navigate
([
'/admin/view-list-doc/1'
]);
}
else
if
(
id
==
'3'
){
this
.
routes
.
navigate
([
'/admin/view-list-course/1'
]);
}
}
}
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-course/view-list-course.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการหลักสูตร'"
[
activeTitle
]="'รายการเอกสาร'"
[
title1
]="'รายการหลักสูตร'"
></app-page-header>
<!-- <div class="row" *ngIf="checkType == '1'">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการหลักสูตร</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search" >
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col">ประเภทหลักสูตร</th>
<th scope="col">ลิงค์</th>
<th scope="col">สถานะ</th>
<th scope="col" class="text-center">วันที่อัพโหลด</th>
<th scope="col" class="text-center">วันล่าสุดดาวน์โหลด</th>
<th scope="col" class="text-center">จำนวนดาวน์โหลด</th>
<th scope="col" *ngIf="checkType == '1'"></th>
</tr>
</thead>
<tbody>
<tr *ngIf="listCourse.length == 0">
<td colspan="{{checkType == '1' ? '9' : '8'}}" class="text-center">ไม่พบข้อมูล</td>
</tr>
<tr *ngFor="let data of filterListCourse() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}" (click)="openEmployeeModal(data.getImage())"></td>
<td>{{ data.thName }}</td>
<td class="text-wrap">{{ data.thDesc }}</td>
<td>{{data.courseType}}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.courseId)"></i></td>
<td class="text-center">{{data.uploadDate}} {{data.uploadTime}}</td>
<td class="text-center">{{data.downloadDate}} {{data.downloadTime}}</td>
<td class="text-center">{{data.dwTime}} ครั้ง</td>
<td *ngIf="checkType == '1'">
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2" (click)="deleteFile(data)" placement="top" ngbTooltip="ลบ"><i class="fas fa-trash-alt"></i></button>
</td>
</tr>
</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]="listCourse.length" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="checkType != '1'">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search" >
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListCourse()">
<div class="card border-5 border border-course h-100 shadow" >
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}" (click)="openEmployeeModal(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.thName }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.courseId)"><i class="fas fa-download mr-1"></i> ดาวน์โหลด <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}} {{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i> ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5" >
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการหลักสูตร
</div>
<div
class=
"flex flex-wrap gap-4"
>
<!-- Buttons -->
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหา"
aria-label=
".form-control-sm example"
[(
ngModel
)]='
search
'
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover "
>
<thead
class=
"bg-info text-white"
>
<tr>
<th
class=
"!text-center"
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
รูปภาพ
</th>
<th
scope=
"col"
>
ชื่อ
</th>
<th
scope=
"col"
>
รายละเอียด
</th>
<th
scope=
"col"
>
ประเภทหลักสูตร
</th>
<th
scope=
"col"
>
ลิงค์
</th>
<th
scope=
"col"
>
สถานะ
</th>
<th
scope=
"col"
class=
"!text-center"
>
วันที่อัพโหลด
</th>
<th
scope=
"col"
class=
"!text-center"
>
วันล่าสุดดาวน์โหลด
</th>
<th
scope=
"col"
class=
"!text-center"
>
จำนวนดาวน์โหลด
</th>
<th
scope=
"col"
*
ngIf=
"checkType == '1'"
></th>
</tr>
</thead>
<tbody>
<tr
*
ngIf=
"listCourse.length == 0"
>
<td
[
attr
.
colspan
]="
checkType =
=
'
1
'
?
8
:
7
"
class=
"!text-center"
>
ไม่พบข้อมูล
</td>
</tr>
<tr
*
ngFor=
"let data of filterListCourse() | slice: page * pageSize : (page+1) * pageSize ; let i = index"
>
<td
class=
"!text-center"
>
{{i+1}}
</td>
<td><img
width=
"100"
class=
"border p-1"
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeModal
(
data
.
getImage
())"
style=
"width: 250px; max-width: none;"
></td>
<td>
{{ data.thName }}
</td>
<td
class=
"text-wrap"
>
{{ data.thDesc }}
</td>
<td>
{{data.courseType}}
</td>
<td
class=
"!text-center"
><i
class=
"ri-links-line text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
openLink
(
data
.
link1
)"
></i></td>
<td
class=
"!text-center"
>
<i
class=
"fa fa-download text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
downloadFile
(
data
.
courseId
)"
></i></td>
<td
class=
"!text-center"
>
{{data.uploadDate}} {{data.uploadTime}}
</td>
<td
class=
"!text-center"
>
{{data.downloadDate}} {{data.downloadTime}}
</td>
<td
class=
"!text-center"
>
{{data.dwTime}} ครั้ง
</td>
<td
*
ngIf=
"checkType == '1'"
>
<button
type=
"button"
class=
"btn btn-circle btn-danger rounded-circle btn-sm mr-2"
(
click
)="
deleteFile
(
data
)"
placement=
"top"
ngbTooltip=
"ลบ"
><i
class=
"fas fa-trash-alt"
></i></button>
</td>
</tr>
<tr
*
ngIf=
"filterListCourse().length === 0"
>
<td
[
attr
.
colspan
]="
checkType =
=
'
1
'
?
10
:
9
"
class=
"!text-center py-4"
>
<ng-container
*
ngIf=
"search"
>
<p>
ไม่พบข้อมูลที่ค้นหา...
</p>
</ng-container>
<ng-container
*
ngIf=
"!search"
>
<p>
กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...
</p>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterListCourse().length > 0"
>
<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
)]="
pageSize
"
(
ngModelChange
)="
page
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterListCourse().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"page > 0"
class=
"page-item {{page==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{'Previous' | translate}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"page > 0"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{page}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{page +
1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 1) * pageSize < filterListCourse().length"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{page + 2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 2) * pageSize < filterListCourse().length"
(
click
)="
page =
page
+
2
;
updatePagedItems
()"
>
{{page + 3}}
</a></li>
<li
*
ngIf=
"(page + 1) * pageSize < filterListCourse().length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-course/view-list-course.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-course/view-list-course.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
ActivatedRoute
}
from
'@angular/router'
;
import
{
OpenImageComponent
}
from
'../../../open-image/open-image.component'
;
import
{
ConfirmModalComponent
}
from
'../../../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../../../alert-modal/alert-modal.component'
;
import
{
firstValueFrom
}
from
'rxjs'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../../../shared/shared.module'
;
import
{
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
CourseContentModel
}
from
'../../../../../models/course-content.model'
;
import
{
CourseService
}
from
'../../../../../services/course.service'
;
declare
var
require
:
any
import
FileSaver
from
'file-saver'
;
@
Component
({
selector
:
'app-view-list-course'
,
templateUrl
:
'./view-list-course.component.html'
,
styleUrls
:
[
'./view-list-course.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
],
})
export
class
ViewListCourseComponent
implements
OnInit
{
page
=
0
;
pageSize
=
10
;
listCourse
:
CourseContentModel
[]
=
[]
search
:
string
=
''
checkType
:
string
=
'0'
pagedItems
:
CourseContentModel
[];
constructor
(
private
modalService
:
NgbModal
,
private
courseService
:
CourseService
,
private
activatedRoute
:
ActivatedRoute
)
{
this
.
activatedRoute
.
paramMap
.
subscribe
(
result
=>
{
this
.
checkType
=
result
.
get
(
"type"
)
!
;
});
}
get
totalItems
():
number
{
return
this
.
search
==
''
?
this
.
listCourse
.
length
:
this
.
filterListCourse
().
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalItems
/
this
.
pageSize
);
}
get
totalPagesArray
():
number
[]
{
return
Array
(
this
.
totalPages
).
fill
(
0
);
}
goToPage
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
totalPages
)
return
;
this
.
page
=
index
;
this
.
updatePagedItems
();
}
updatePagedItems
()
{
const
data
:
CourseContentModel
[]
=
this
.
search
===
''
?
this
.
listCourse
:
this
.
filterListCourse
();
const
start
=
this
.
page
*
this
.
pageSize
;
const
end
=
start
+
this
.
pageSize
;
this
.
pagedItems
=
data
.
slice
(
start
,
end
);
}
openEmployeeModal
(
image
:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
OpenImageComponent
,
{
centered
:
true
,
windowClass
:
'my-dialog-img-preview'
})
modalRef
.
componentInstance
.
linkImage
=
image
modalRef
.
result
.
then
(
result
=>
{
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
courseService
.
downloadFileContent
(
logId
).
toPromise
();
if
(
data
)
{
FileSaver
.
saveAs
(
new
Blob
([
data
]),
"file_download.json"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
filterListCourse
()
{
return
this
.
listCourse
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListCourse
()
{
try
{
const
data
=
await
firstValueFrom
(
this
.
courseService
.
getListCourseContent
(
'0'
));
this
.
listCourse
=
data
.
map
(
x
=>
new
CourseContentModel
(
x
))
console
.
log
(
"🚀 ~ ViewListCourseComponent ~ getListCourse ~ this.listCourse :"
,
this
.
listCourse
)
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
deleteFile
(
item
:
CourseContentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
this
.
courseService
.
deleteCourseContent
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
)
this
.
getListCourse
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
ngOnInit
()
{
this
.
getListCourse
();
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
this
.
modalService
.
dismissAll
()
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
coverDate
(
date
:
string
)
{
return
date
.
split
(
'-'
).
reverse
().
join
(
'/'
)
}
}
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-doc/view-list-doc.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการเอกสาร'"
[
activeTitle
]="'รายการเอกสาร'"
[
title1
]="'รายการเอกสาร'"
></app-page-header>
<!-- <div class="row" *ngIf="checkType == '1'">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการเอกสาร</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search" >
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col" class="text-center">ลิงค์</th>
<th scope="col" class="text-center">ไฟล์ (ไทย)</th>
<th scope="col" class="text-center">ไฟล์ (อังกฤษ)</th>
<th scope="col" class="text-center">วันที่อัพโหลด</th>
<th scope="col" class="text-center">วันล่าสุดดาวน์โหลด</th>
<th scope="col" class="text-center">จำนวนดาวน์โหลด</th>
<th scope="col" *ngIf="checkType == '1'"></th>
</tr>
</thead>
<tbody>
<tr *ngIf="listDoc.length == 0">
<td colspan="{{checkType == '1' ? '9' : '10'}}" class="text-center">ไม่พบข้อมูล</td>
</tr>
<tr *ngFor="let data of filterListDoc() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}" (click)="openEmployeeModal(data.getImage())"></td>
<td>{{ data.thName }}</td>
<td>{{ data.thDesc }}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.docId,'tha')"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.docId,'eng')"></i></td>
<td class="text-center">{{data.uploadDate}} {{data.uploadTime}}</td>
<td class="text-center">{{data.downloadDate}} {{data.downloadTime}}</td>
<td class="text-center">{{data.dwTime}} ครั้ง</td>
<td *ngIf="checkType == '1'">
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2" (click)="deleteFile(data)" placement="top" ngbTooltip="ลบ"><i class="fas fa-trash-alt"></i></button>
</td>
</tr>
</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]="listDoc.length" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="checkType != '1'">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search" >
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListDoc()">
<div class="card border-5 border border-doc h-100 shadow" >
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}" (click)="openEmployeeModal(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.thName }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.docId,'tha')"><i class="fas fa-download mr-1"></i> ดาวน์โหลด (ไทย) <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}} {{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.docId,'eng')"><i class="fas fa-download mr-1"></i> ดาวน์โหลด (อังกฤษ) <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}} {{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i> ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5" >
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการเอกสาร
</div>
<div
class=
"flex flex-wrap gap-4"
>
<!-- Buttons -->
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหา"
aria-label=
".form-control-sm example"
[(
ngModel
)]='
search
'
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover "
>
<thead
class=
"bg-info text-white"
>
<tr>
<th
class=
"!text-center"
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
รูปภาพ
</th>
<th
scope=
"col"
>
ชื่อ
</th>
<th
scope=
"col"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"!text-center"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"!text-center"
>
ไฟล์ (ไทย)
</th>
<th
scope=
"col"
class=
"!text-center"
>
ไฟล์ (อังกฤษ)
</th>
<th
scope=
"col"
class=
"!text-center"
>
วันที่อัพโหลด
</th>
<th
scope=
"col"
class=
"!text-center"
>
วันล่าสุดดาวน์โหลด
</th>
<th
scope=
"col"
class=
"!text-center"
>
จำนวนดาวน์โหลด
</th>
<th
scope=
"col"
*
ngIf=
"checkType == '1'"
></th>
</tr>
</thead>
<tbody>
<tr
*
ngIf=
"listDoc.length == 0"
>
<td
[
attr
.
colspan
]="
checkType =
=
'
1
'
?
8
:
7
"
class=
"!text-center"
>
ไม่พบข้อมูล
</td>
</tr>
<tr
*
ngFor=
"let data of filterListDoc() | slice: page * pageSize : (page+1) * pageSize ; let i = index"
>
<td
class=
"!text-center"
>
{{i+1}}
</td>
<td><img
class=
"border p-1"
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeModal
(
data
.
getImage
())"
style=
"width: 250px; max-width: none;"
></td>
<td>
{{ data.thName }}
</td>
<td>
{{ data.thDesc }}
</td>
<td
class=
"!text-center"
><i
class=
"ri-links-line text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
openLink
(
data
.
link1
)"
></i></td>
<td
class=
"!text-center"
>
<i
class=
"fa fa-download text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
downloadFile
(
data
.
docId
,'
tha
')"
></i></td>
<td
class=
"!text-center"
>
<i
class=
"fa fa-download text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
downloadFile
(
data
.
docId
,'
eng
')"
></i></td>
<td
class=
"!text-center"
>
{{data.uploadDate}} {{data.uploadTime}}
</td>
<td
class=
"!text-center"
>
{{data.downloadDate}} {{data.downloadTime}}
</td>
<td
class=
"!text-center"
>
{{data.dwTime}} ครั้ง
</td>
<td
*
ngIf=
"checkType == '1'"
>
<button
type=
"button"
class=
"bg-danger hover:bg-danger text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
deleteFile
(
data
)"
placement=
"top"
ngbTooltip=
"ลบ"
><i
class=
"fa fa-trash"
></i></button>
</td>
</tr>
<tr
*
ngIf=
"filterListDoc().length === 0"
>
<td
[
attr
.
colspan
]="
checkType =
=
'
1
'
?
10
:
9
"
class=
"!text-center py-4"
>
<ng-container
*
ngIf=
"search"
>
<p>
ไม่พบข้อมูลที่ค้นหา...
</p>
</ng-container>
<ng-container
*
ngIf=
"!search"
>
<p>
กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...
</p>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterListDoc().length > 0"
>
<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
)]="
pageSize
"
(
ngModelChange
)="
page
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterListDoc().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"page > 0"
class=
"page-item {{page==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{'Previous' | translate}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"page > 0"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{page}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{page +
1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 1) * pageSize < filterListDoc().length"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{page + 2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 2) * pageSize < filterListDoc().length"
(
click
)="
page =
page
+
2
;
updatePagedItems
()"
>
{{page + 3}}
</a></li>
<li
*
ngIf=
"(page + 1) * pageSize < filterListDoc().length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-doc/view-list-doc.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-doc/view-list-doc.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
ActivatedRoute
}
from
'@angular/router'
;
import
{
OpenImageComponent
}
from
'../../../open-image/open-image.component'
;
import
{
ConfirmModalComponent
}
from
'../../../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../../../alert-modal/alert-modal.component'
;
import
{
firstValueFrom
}
from
'rxjs'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../../../shared/shared.module'
;
import
{
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
DocumentContentModel
}
from
'../../../../../models/document-content.model'
;
import
{
DocumentService
}
from
'../../../../../services/document.service'
;
declare
var
require
:
any
import
FileSaver
from
'file-saver'
;
@
Component
({
selector
:
'app-view-list-doc'
,
templateUrl
:
'./view-list-doc.component.html'
,
styleUrls
:
[
'./view-list-doc.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
],
})
export
class
ViewListDocComponent
implements
OnInit
{
page
=
0
;
pageSize
=
10
;
listDoc
:
DocumentContentModel
[]
=
[]
search
:
string
=
''
checkType
:
string
=
'0'
pagedItems
:
DocumentContentModel
[]
=
[];
constructor
(
private
modalService
:
NgbModal
,
private
documentService
:
DocumentService
,
private
activatedRoute
:
ActivatedRoute
)
{
this
.
activatedRoute
.
paramMap
.
subscribe
(
result
=>
{
this
.
checkType
=
result
.
get
(
"type"
)
!
;
});
}
get
totalItems
():
number
{
return
this
.
search
==
''
?
this
.
listDoc
.
length
:
this
.
filterListDoc
().
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalItems
/
this
.
pageSize
);
}
get
totalPagesArray
():
number
[]
{
return
Array
(
this
.
totalPages
).
fill
(
0
);
}
goToPage
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
totalPages
)
return
;
this
.
page
=
index
;
this
.
updatePagedItems
();
}
updatePagedItems
()
{
const
data
:
DocumentContentModel
[]
=
this
.
search
===
''
?
this
.
listDoc
:
this
.
filterListDoc
();
const
start
=
this
.
page
*
this
.
pageSize
;
const
end
=
start
+
this
.
pageSize
;
this
.
pagedItems
=
data
.
slice
(
start
,
end
);
}
openEmployeeModal
(
image
:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
OpenImageComponent
,
{
centered
:
true
,
windowClass
:
'my-dialog-img-preview'
})
modalRef
.
componentInstance
.
linkImage
=
image
modalRef
.
result
.
then
(
result
=>
{
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
deleteFile
(
item
:
DocumentContentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
this
.
documentService
.
deleteExcelContent
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
)
this
.
getListDoc
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
async
downloadFile
(
logId
:
string
,
lang
:
string
)
{
try
{
const
data
=
await
this
.
documentService
.
downloadFileContent
(
logId
,
lang
).
toPromise
();
if
(
data
)
{
FileSaver
.
saveAs
(
new
Blob
([
data
]),
"file_download.doc"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
filterListDoc
()
{
return
this
.
listDoc
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListDoc
()
{
try
{
const
data
=
await
firstValueFrom
(
this
.
documentService
.
getListExcelContent
(
'0'
));
this
.
listDoc
=
data
.
map
(
x
=>
new
DocumentContentModel
(
x
))
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
ngOnInit
()
{
this
.
getListDoc
();
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
this
.
modalService
.
dismissAll
()
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
coverDate
(
date
:
string
)
{
return
date
.
split
(
'-'
).
reverse
().
join
(
'/'
)
}
}
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-excel/view-list-excel.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการ
Excel
'"
[
activeTitle
]="'รายการเอกสาร'"
[
title1
]="'รายการ
Excel
'"
></app-page-header>
<!-- <div class="row" *ngIf="checkType == '1'">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการ Excel</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col" class="text-center">ลิงค์</th>
<th scope="col" class="text-center">ไฟล์</th>
<th scope="col" class="text-center">วันที่อัพโหลด</th>
<th scope="col" class="text-center">วันล่าสุดดาวน์โหลด</th>
<th scope="col" class="text-center">จำนวนดาวน์โหลด</th>
<th scope="col" *ngIf="checkType == '1'"></th>
</tr>
</thead>
<tbody>
<tr *ngIf="listExcel.length == 0">
<td [attr.colspan]="checkType == '1' ? 8 : 7" class="text-center">ไม่พบข้อมูล</td>
</tr>
<tr
*ngFor="let data of filterListExcel() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}"
(click)="openEmployeeModal(data.getImage())"></td>
<td>{{ data.thName }}</td>
<td>{{ data.thDesc }}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.excelId)"></i></td>
<td class="text-center">{{data.uploadDate}} {{data.uploadTime}}</td>
<td class="text-center">{{data.downloadDate}} {{data.downloadTime}}</td>
<td class="text-center">{{data.dwTime}} ครั้ง</td>
<td *ngIf="checkType == '1'">
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2"
(click)="deleteFile(data)" placement="top" ngbTooltip="ลบ"><i class="fas fa-trash-alt"></i></button>
</td>
</tr>
</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]="listExcel.length" [maxSize]="3"
[rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="checkType != '1'">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListExcel()">
<div class="card border-5 border border-excel h-100 shadow">
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}"
(click)="openEmployeeModal(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.thName }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.excelId)"><i class="fas fa-download mr-1"></i>
ดาวน์โหลด <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}}
{{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i>
ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5">
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการ Excel
</div>
<div
class=
"flex flex-wrap gap-4"
>
<!-- Buttons -->
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหา"
aria-label=
".form-control-sm example"
[(
ngModel
)]='
search
'
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover "
>
<thead
class=
"bg-info text-white"
>
<tr>
<th
class=
"!text-center"
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
รูปภาพ
</th>
<th
scope=
"col"
>
ชื่อ
</th>
<th
scope=
"col"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"!text-center"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"!text-center"
>
ไฟล์
</th>
<th
scope=
"col"
class=
"!text-center"
>
วันที่อัพโหลด
</th>
<th
scope=
"col"
class=
"!text-center"
>
วันล่าสุดดาวน์โหลด
</th>
<th
scope=
"col"
class=
"!text-center"
>
จำนวนดาวน์โหลด
</th>
<th
scope=
"col"
*
ngIf=
"checkType == '1'"
></th>
</tr>
</thead>
<tbody>
<tr
*
ngIf=
"listExcel.length == 0"
>
<td
[
attr
.
colspan
]="
checkType =
=
'
1
'
?
8
:
7
"
class=
"!text-center"
>
ไม่พบข้อมูล
</td>
</tr>
<tr
*
ngFor=
"let data of filterListExcel() | slice: page * pageSize : (page+1) * pageSize ; let i = index"
>
<td
class=
"!text-center"
>
{{i+1}}
</td>
<td><img
class=
"border p-1"
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeModal
(
data
.
getImage
())"
style=
"width: 250px; max-width: none;"
></td>
<td>
{{ data.thName }}
</td>
<td>
{{ data.thDesc }}
</td>
<td
class=
"!text-center"
><i
class=
"ri-links-line text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
openLink
(
data
.
link1
)"
></i></td>
<td
class=
"!text-center"
>
<i
class=
"fa fa-download text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
downloadFile
(
data
.
excelId
)"
></i>
</td>
<td
class=
"!text-center"
>
{{data.uploadDate}} {{data.uploadTime}}
</td>
<td
class=
"!text-center"
>
{{data.downloadDate}} {{data.downloadTime}}
</td>
<td
class=
"!text-center"
>
{{data.dwTime}} ครั้ง
</td>
<td
*
ngIf=
"checkType == '1'"
>
<button
type=
"button"
class=
"bg-danger hover:bg-danger text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
deleteFile
(
data
)"
placement=
"top"
ngbTooltip=
"ลบ"
><i
class=
"fa fa-trash"
></i></button>
</td>
</tr>
<tr
*
ngIf=
"filterListExcel().length === 0"
>
<td
[
attr
.
colspan
]="
checkType =
=
'
1
'
?
10
:
9
"
class=
"!text-center py-4"
>
<ng-container
*
ngIf=
"search"
>
<p>
ไม่พบข้อมูลที่ค้นหา...
</p>
</ng-container>
<ng-container
*
ngIf=
"!search"
>
<p>
กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...
</p>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterListExcel().length > 0"
>
<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
)]="
pageSize
"
(
ngModelChange
)="
page
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterListExcel().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"page > 0"
class=
"page-item {{page==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{'Previous' | translate}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"page > 0"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{page}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{page +
1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 1) * pageSize < filterListExcel().length"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{page + 2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 2) * pageSize < filterListExcel().length"
(
click
)="
page =
page
+
2
;
updatePagedItems
()"
>
{{page + 3}}
</a></li>
<li
*
ngIf=
"(page + 1) * pageSize < filterListExcel().length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-excel/view-list-excel.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/approved-list/view-list-excel/view-list-excel.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
ActivatedRoute
}
from
'@angular/router'
;
import
{
ExcelContentModel
}
from
'../../../../../models/excel-content.model'
;
import
{
ExcelService
}
from
'../../../../../services/excel.service'
;
import
{
OpenImageComponent
}
from
'../../../open-image/open-image.component'
;
import
{
ConfirmModalComponent
}
from
'../../../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../../../alert-modal/alert-modal.component'
;
import
{
firstValueFrom
}
from
'rxjs'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../../../shared/shared.module'
;
import
{
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
declare
var
require
:
any
import
FileSaver
from
'file-saver'
;
@
Component
({
selector
:
'app-view-list-excel'
,
templateUrl
:
'./view-list-excel.component.html'
,
styleUrls
:
[
'./view-list-excel.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
],
})
export
class
ViewListExcelComponent
implements
OnInit
{
page
=
0
;
pageSize
=
10
;
listExcel
:
ExcelContentModel
[]
=
[]
search
:
string
=
''
checkType
:
string
=
'0'
pagedItems
:
ExcelContentModel
[]
=
[];
constructor
(
private
modalService
:
NgbModal
,
private
excelService
:
ExcelService
,
private
activatedRoute
:
ActivatedRoute
,)
{
this
.
activatedRoute
.
paramMap
.
subscribe
(
result
=>
{
this
.
checkType
=
result
.
get
(
"type"
)
!
;
});
}
get
totalItems
():
number
{
return
this
.
search
==
''
?
this
.
listExcel
.
length
:
this
.
filterListExcel
().
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalItems
/
this
.
pageSize
);
}
get
totalPagesArray
():
number
[]
{
return
Array
(
this
.
totalPages
).
fill
(
0
);
}
goToPage
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
totalPages
)
return
;
this
.
page
=
index
;
this
.
updatePagedItems
();
}
updatePagedItems
()
{
const
data
:
ExcelContentModel
[]
=
this
.
search
===
''
?
this
.
listExcel
:
this
.
filterListExcel
();
const
start
=
this
.
page
*
this
.
pageSize
;
const
end
=
start
+
this
.
pageSize
;
this
.
pagedItems
=
data
.
slice
(
start
,
end
);
}
openEmployeeModal
(
image
:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
OpenImageComponent
,
{
centered
:
true
,
windowClass
:
'my-dialog-img-preview'
})
modalRef
.
componentInstance
.
linkImage
=
image
modalRef
.
result
.
then
(
result
=>
{
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
deleteFile
(
item
:
ExcelContentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
this
.
excelService
.
deleteExcelContent
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
)
this
.
getListExcel
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
excelService
.
downloadFileContent
(
logId
).
toPromise
();
if
(
data
)
{
FileSaver
.
saveAs
(
new
Blob
([
data
]),
"file_download.xlsx"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
getStatus
(
status
:
string
):
string
{
if
(
status
===
'0'
)
{
return
'รออนุมัติ'
;
}
else
if
(
status
===
'1'
)
{
return
'เปิดใช้งาน'
;
}
else
if
(
status
===
'2'
)
{
return
'ไม่อนุมัติ'
;
}
else
{
return
'ไม่ทราบสถานะ'
;
// สำหรับกรณีที่ไม่ตรงกับเงื่อนไขใดเลย
}
}
filterListExcel
()
{
return
this
.
listExcel
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListExcel
()
{
try
{
const
data
=
await
firstValueFrom
(
this
.
excelService
.
getListExcelContent
(
'0'
));
this
.
listExcel
=
data
.
map
(
x
=>
new
ExcelContentModel
(
x
))
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
ngOnInit
()
{
this
.
getListExcel
();
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
this
.
modalService
.
dismissAll
()
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
coverDate
(
date
:
string
)
{
return
date
.
split
(
'-'
).
reverse
().
join
(
'/'
)
}
}
src/app/DPU/myskill-x/myportal/management/management.component.css
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/management.component.html
0 → 100644
View file @
73e72e5e
<p>
management works!
</p>
src/app/DPU/myskill-x/myportal/management/management.component.spec.ts
0 → 100644
View file @
73e72e5e
/* tslint:disable:no-unused-variable */
import
{
async
,
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
By
}
from
'@angular/platform-browser'
;
import
{
DebugElement
}
from
'@angular/core'
;
import
{
ManagementComponent
}
from
'./management.component'
;
describe
(
'ManagementComponent'
,
()
=>
{
let
component
:
ManagementComponent
;
let
fixture
:
ComponentFixture
<
ManagementComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
ManagementComponent
]
})
.
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
ManagementComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/DPU/myskill-x/myportal/management/management.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
@
Component
({
selector
:
'app-management'
,
templateUrl
:
'./management.component.html'
,
styleUrls
:
[
'./management.component.css'
]
})
export
class
ManagementComponent
implements
OnInit
{
constructor
()
{
}
ngOnInit
()
{
}
}
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-course/approve-course.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'อนุมัติหลักสูตร'"
[
activeTitle
]="'รายการเอกสารรอการอนุมัติ'"
[
title1
]="'อนุมัติหลักสูตร'"
></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการหลักสูตร</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search" >
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col">ประเภทหลักสูตร</th>
<th scope="col" class="text-center">ลิงค์</th>
<th scope="col" class="text-center">ไฟล์</th>
<th scope="col" class="text-center">สถานะ</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr *ngIf="listCourse.length == 0">
<td colspan="9" class="text-center">ไม่พบข้อมูล</td>
</tr>
<tr *ngFor="let data of filterListCourse() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}" (click)="openEmployeeModal(data.getImage())"></td>
<td>{{ data.thName }}</td>
<td class="text-wrap">{{ data.thDesc }}</td>
<td>{{data.courseType}}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.logId)"></i></td>
<td class="text-center">
<span class="fa-stack rt_anim" *ngIf="data.status == 0" ngbTooltip="รออนุมัติ" container="body" tooltipClass="myhrcolor-1">
<i class="fa fa-circle fa-stack-2x text-info"></i>
<i class=" fas fa-hourglass-half fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack rt_anim" *ngIf="data.status == 1" ngbTooltip="เปิดใช้งาน" container="body" tooltipClass="myhrcolor-2">
<i class="fa fa-circle fa-stack-2x text-success"></i>
<i class=" fas fa-check fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack rt_anim" *ngIf="data.status == 2" ngbTooltip="ไม่อนุมัติ" container="body" tooltipClass="myhrcolor-3">
<i class="fa fa-circle fa-stack-2x text-danger"></i>
<i class="fas fa-times fa-stack-1x fa-inverse" style="font-size: 1.25em;"></i>
</span>
</td>
<td>
<button type="button" class="btn btn-circle btn-success rounded-circle btn-sm mr-2" (click)="onApprove(data)"><i class="fa fa-check"></i></button>
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2" (click)="onCancelApprove(data)"><i class="fas fa-times"></i></button>
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2" (click)="deleteFile(data)" placement="top" ngbTooltip="ลบ">
<i class="fas fa-trash-alt"></i>
</button>
</td>
</tr>
</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]="listCourse.length" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div> -->
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการหลักสูตร
</div>
<div
class=
"flex flex-wrap gap-4"
>
<!-- Buttons -->
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหา"
aria-label=
".form-control-sm example"
[(
ngModel
)]='
search
'
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover "
>
<thead
class=
"bg-info text-white"
>
<tr>
<th
class=
"!text-center"
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
รูปภาพ
</th>
<th
scope=
"col"
>
ชื่อ
</th>
<th
scope=
"col"
>
รายละเอียด
</th>
<th
scope=
"col"
>
ประเภทหลักสูตร
</th>
<th
scope=
"col"
class=
"!text-center"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"!text-center"
>
ไฟล์
</th>
<th
scope=
"col"
class=
"!text-center"
>
สถานะ
</th>
<th
scope=
"col"
></th>
</tr>
</thead>
<tbody>
<tr
*
ngFor=
"let data of filterListCourse() | slice: page * pageSize : (page+1) * pageSize ; let i = index"
>
<td
class=
"!text-center"
>
{{i+1}}
</td>
<td><img
width=
"100"
class=
"border p-1"
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeModal
(
data
.
getImage
())"
></td>
<td>
{{ data.thName }}
</td>
<td
class=
"text-wrap"
>
{{ data.thDesc }}
</td>
<td>
{{data.courseType}}
</td>
<td
class=
"!text-center"
><i
class=
"ri-links-line text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
openLink
(
data
.
link1
)"
></i></td>
<td
class=
"!text-center"
>
<i
class=
"fa fa-download text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
downloadFile
(
data
.
logId
)"
></i></td>
<td
class=
"!text-center"
>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 0"
ngbTooltip=
"รออนุมัติ"
container=
"body"
tooltipClass=
"myhrcolor-1"
>
<i
class=
"fa fa-circle fa-stack-2x text-info"
></i>
<i
class=
" fa fa-hourglass-half fa-stack-1x fa-inverse"
></i>
</span>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 1"
ngbTooltip=
"เปิดใช้งาน"
container=
"body"
tooltipClass=
"myhrcolor-2"
>
<i
class=
"fa fa-circle fa-stack-2x text-success"
></i>
<i
class=
"fa fa-check fa-stack-1x fa-inverse"
></i>
</span>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 2"
ngbTooltip=
"ไม่อนุมัติ"
container=
"body"
tooltipClass=
"myhrcolor-3"
>
<i
class=
"fa fa-circle fa-stack-2x text-danger"
></i>
<i
class=
"fa fa-times fa-stack-1x fa-inverse"
style=
"font-size: 1.25em;"
></i>
</span>
</td>
<td>
<div
class=
"flex space-x-2 justify-center"
>
<button
type=
"button"
class=
"bg-success hover:bg-success text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
onApprove
(
data
)"
><i
class=
"fa fa-check"
></i></button>
<button
type=
"button"
class=
"bg-danger hover:bg-danger text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
onCancelApprove
(
data
)"
><i
class=
"fas fa-times"
></i></button>
<button
type=
"button"
class=
"bg-danger hover:bg-danger text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
deleteFile
(
data
)"
placement=
"top"
ngbTooltip=
"ลบ"
>
<i
class=
"fas fa-trash-alt"
></i>
</button>
</div>
</td>
</tr>
<tr
*
ngIf=
"filterListCourse().length === 0"
>
<td
[
attr
.
colspan
]="
9
"
class=
"!text-center py-4"
>
<ng-container
*
ngIf=
"listCourse.length === 0"
>
<p>
ไม่พบข้อมูล
</p>
</ng-container>
<ng-container
*
ngIf=
"listCourse.length > 0 && search"
>
<p>
ไม่พบข้อมูลที่ค้นหา...
</p>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterListCourse().length > 0"
>
<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
)]="
pageSize
"
(
ngModelChange
)="
page
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterListCourse().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"page > 0"
class=
"page-item {{page==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{'Previous' | translate}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"page > 0"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{page}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{page +
1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 1) * pageSize < filterListCourse().length"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{page + 2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 2) * pageSize < filterListCourse().length"
(
click
)="
page =
page
+
2
;
updatePagedItems
()"
>
{{page + 3}}
</a></li>
<li
*
ngIf=
"(page + 1) * pageSize < filterListCourse().length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-course/approve-course.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-course/approve-course.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
CourseModel
}
from
'../../../../../models/course.model'
;
import
{
CourseService
}
from
'../../../../../services/course.service'
;
import
{
OpenImageComponent
}
from
'../../../open-image/open-image.component'
;
import
{
ConfirmModalComponent
}
from
'../../../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../../../alert-modal/alert-modal.component'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../../../shared/shared.module'
;
import
{
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
firstValueFrom
}
from
'rxjs'
;
declare
var
require
:
any
import
FileSaver
from
'file-saver'
;
@
Component
({
selector
:
'app-approve-course'
,
templateUrl
:
'./approve-course.component.html'
,
styleUrls
:
[
'./approve-course.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
],
})
export
class
ApproveCourseComponent
implements
OnInit
{
page
=
0
;
pageSize
=
10
;
listCourse
:
CourseModel
[]
=
[]
search
:
string
=
''
pagedItems
:
CourseModel
[]
=
[];
constructor
(
private
modalService
:
NgbModal
,
private
courseService
:
CourseService
)
{
}
get
totalItems
():
number
{
return
this
.
search
==
''
?
this
.
listCourse
.
length
:
this
.
filterListCourse
().
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalItems
/
this
.
pageSize
);
}
get
totalPagesArray
():
number
[]
{
return
Array
(
this
.
totalPages
).
fill
(
0
);
}
goToPage
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
totalPages
)
return
;
this
.
page
=
index
;
this
.
updatePagedItems
();
}
updatePagedItems
()
{
const
data
:
CourseModel
[]
=
this
.
search
===
''
?
this
.
listCourse
:
this
.
filterListCourse
();
const
start
=
this
.
page
*
this
.
pageSize
;
const
end
=
start
+
this
.
pageSize
;
this
.
pagedItems
=
data
.
slice
(
start
,
end
);
}
openEmployeeModal
(
image
:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
OpenImageComponent
,
{
centered
:
true
,
windowClass
:
'my-dialog-img-preview'
})
modalRef
.
componentInstance
.
linkImage
=
image
modalRef
.
result
.
then
(
result
=>
{
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
courseService
.
downloadFile
(
logId
).
toPromise
();
if
(
data
)
{
FileSaver
.
saveAs
(
new
Blob
([
data
]),
"file_download.json"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
filterListCourse
()
{
return
this
.
listCourse
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListCourse
()
{
try
{
const
data
=
await
firstValueFrom
(
this
.
courseService
.
getListCourse
(
'0'
));
this
.
listCourse
=
data
.
map
(
x
=>
new
CourseModel
(
x
))
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
onApprove
(
item
:
CourseModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการอนุมัติข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
item
.
status
=
1
this
.
courseService
.
approve
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
modalService
.
dismissAll
()
this
.
openAlertModal
(
'บันทึกข้อมูลสำเร็จ'
)
this
.
getListCourse
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถบันทึกข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
onCancelApprove
(
item
:
CourseModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการไม่อนุมัติข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
item
.
status
=
2
this
.
courseService
.
approve
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'บันทึกข้อมูลสำเร็จ'
)
this
.
getListCourse
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถบันทึกข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
ngOnInit
()
{
this
.
getListCourse
();
}
deleteFile
(
item
:
CourseModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
this
.
courseService
.
deleteCourse
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
)
this
.
getListCourse
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
// this.modalService.dismissAll()
},
reason
=>
{
// this.modalService.dismissAll()
})
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
}
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-doc/approve-doc.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'อนุมัติเอกสาร'"
[
activeTitle
]="'รายการเอกสารรอการอนุมัติ'"
[
title1
]="'อนุมัติเอกสาร'"
></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการเอกสาร</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search" >
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">รหัสเอกสาร</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col" class="text-center">ลิงค์</th>
<th scope="col" class="text-center">ไฟล์ (ไทย)</th>
<th scope="col" class="text-center">ไฟล์ (อังกฤษ)</th>
<th scope="col" class="text-center">สถานะ</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr *ngIf="listDoc.length == 0">
<td colspan="9" class="text-center">ไม่พบข้อมูล</td>
</tr>
<tr *ngFor="let data of filterListDoc() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}" (click)="openEmployeeModal(data.getImage())"></td>
<td >{{data.id}}</td>
<td>{{ data.thName }}</td>
<td>{{ data.thDesc }}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.logId,'tha')"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.logId,'eng')"></i></td>
<td class="text-center">
<span class="fa-stack rt_anim" *ngIf="data.status == 0" ngbTooltip="รออนุมัติ" container="body" tooltipClass="myhrcolor-1">
<i class="fa fa-circle fa-stack-2x text-info"></i>
<i class=" fas fa-hourglass-half fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack rt_anim" *ngIf="data.status == 1" ngbTooltip="เปิดใช้งาน" container="body" tooltipClass="myhrcolor-2">
<i class="fa fa-circle fa-stack-2x text-success"></i>
<i class=" fas fa-check fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack rt_anim" *ngIf="data.status == 2" ngbTooltip="ไม่อนุมัติ" container="body" tooltipClass="myhrcolor-3">
<i class="fa fa-circle fa-stack-2x text-danger"></i>
<i class="fas fa-times fa-stack-1x fa-inverse" style="font-size: 1.25em;"></i>
</span>
</td>
<td>
<button type="button" class="btn btn-circle btn-success rounded-circle btn-sm mr-2" (click)="onApprove(data)"><i class="fa fa-check"></i></button>
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2" (click)="onCancelApprove(data)"><i class="fas fa-times"></i></button>
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2" (click)="deleteFile(data)" placement="top" ngbTooltip="ลบ">
<i class="fas fa-trash-alt"></i>
</button>
</td>
</tr>
</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]="listDoc.length" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div> -->
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการเอกสาร
</div>
<div
class=
"flex flex-wrap gap-4"
>
<!-- Buttons -->
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหา"
aria-label=
".form-control-sm example"
[(
ngModel
)]='
search
'
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead
class=
"bg-info text-white"
>
<tr>
<th
class=
"!text-center"
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
รูปภาพ
</th>
<!-- <th scope="col">รหัสเอกสาร</th> -->
<th
scope=
"col"
>
ชื่อ
</th>
<th
scope=
"col"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"!text-center"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"!text-center"
>
ไฟล์ (ไทย)
</th>
<th
scope=
"col"
class=
"!text-center"
>
ไฟล์ (อังกฤษ)
</th>
<th
scope=
"col"
class=
"!text-center"
>
สถานะ
</th>
<th
scope=
"col"
></th>
</tr>
</thead>
<tbody>
<tr
*
ngFor=
"let data of filterListDoc() | slice: page * pageSize : (page+1) * pageSize ; let i = index"
>
<td
class=
"!text-center"
>
{{i+1}}
</td>
<td><img
width=
"100"
class=
"border p-1"
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeModal
(
data
.
getImage
())"
></td>
<!-- <td >{{data.id}}</td> -->
<td>
{{ data.thName }}
</td>
<td>
{{ data.thDesc }}
</td>
<td
class=
"!text-center"
><i
class=
"ri-links-line text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
openLink
(
data
.
link1
)"
></i></td>
<td
class=
"!text-center"
>
<i
class=
"fa fa-download text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
downloadFile
(
data
.
logId
,'
tha
')"
></i></td>
<td
class=
"!text-center"
>
<i
class=
"fa fa-download text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
downloadFile
(
data
.
logId
,'
eng
')"
></i></td>
<td
class=
"!text-center"
>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 0"
ngbTooltip=
"รออนุมัติ"
container=
"body"
tooltipClass=
"myhrcolor-1"
>
<i
class=
"fa fa-circle fa-stack-2x text-info"
></i>
<i
class=
" fa fa-hourglass-half fa-stack-1x fa-inverse"
></i>
</span>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 1"
ngbTooltip=
"เปิดใช้งาน"
container=
"body"
tooltipClass=
"myhrcolor-2"
>
<i
class=
"fa fa-circle fa-stack-2x text-success"
></i>
<i
class=
" fa fa-check fa-stack-1x fa-inverse"
></i>
</span>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 2"
ngbTooltip=
"ไม่อนุมัติ"
container=
"body"
tooltipClass=
"myhrcolor-3"
>
<i
class=
"fa fa-circle fa-stack-2x text-danger"
></i>
<i
class=
"fa fa-times fa-stack-1x fa-inverse"
style=
"font-size: 1.25em;"
></i>
</span>
</td>
<td>
<div
class=
"flex space-x-2 justify-center"
>
<button
type=
"button"
class=
"bg-success hover:bg-success text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
onApprove
(
data
)"
><i
class=
"fa fa-check"
></i></button>
<button
type=
"button"
class=
"bg-danger hover:bg-danger text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
onCancelApprove
(
data
)"
><i
class=
"fa fa-times"
></i></button>
<button
type=
"button"
class=
"bg-danger hover:bg-danger text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
deleteFile
(
data
)"
placement=
"top"
ngbTooltip=
"ลบ"
>
<i
class=
"fa fa-trash"
></i>
</button>
</div>
</td>
</tr>
<tr
*
ngIf=
"filterListDoc().length === 0"
>
<td
[
attr
.
colspan
]="
9
"
class=
"!text-center py-4"
>
<ng-container
*
ngIf=
"listDoc.length === 0"
>
<p>
ไม่พบข้อมูล
</p>
</ng-container>
<ng-container
*
ngIf=
"listDoc.length > 0 && search"
>
<p>
ไม่พบข้อมูลที่ค้นหา...
</p>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterListDoc().length > 0"
>
<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
)]="
pageSize
"
(
ngModelChange
)="
page
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterListDoc().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"page > 0"
class=
"page-item {{page==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{'Previous' | translate}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"page > 0"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{page}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{page +
1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 1) * pageSize < filterListDoc().length"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{page + 2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 2) * pageSize < filterListDoc().length"
(
click
)="
page =
page
+
2
;
updatePagedItems
()"
>
{{page + 3}}
</a></li>
<li
*
ngIf=
"(page + 1) * pageSize < filterListDoc().length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-doc/approve-doc.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-doc/approve-doc.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
OpenImageComponent
}
from
'../../../open-image/open-image.component'
;
import
{
ConfirmModalComponent
}
from
'../../../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../../../alert-modal/alert-modal.component'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../../../shared/shared.module'
;
import
{
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
DocumentModel
}
from
'../../../../../models/document.model'
;
import
{
DocumentService
}
from
'../../../../../services/document.service'
;
import
{
firstValueFrom
}
from
'rxjs'
;
declare
var
require
:
any
import
FileSaver
from
'file-saver'
;
@
Component
({
selector
:
'app-approve-doc'
,
templateUrl
:
'./approve-doc.component.html'
,
styleUrls
:
[
'./approve-doc.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
],
})
export
class
ApproveDocComponent
implements
OnInit
{
page
=
0
;
pageSize
=
10
;
listDoc
:
DocumentModel
[]
=
[]
search
:
string
=
''
pagedItems
:
DocumentModel
[]
=
[];
constructor
(
private
modalService
:
NgbModal
,
private
documentService
:
DocumentService
)
{
}
get
totalItems
():
number
{
return
this
.
search
==
''
?
this
.
listDoc
.
length
:
this
.
filterListDoc
().
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalItems
/
this
.
pageSize
);
}
get
totalPagesArray
():
number
[]
{
return
Array
(
this
.
totalPages
).
fill
(
0
);
}
goToPage
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
totalPages
)
return
;
this
.
page
=
index
;
this
.
updatePagedItems
();
}
updatePagedItems
()
{
const
data
:
DocumentModel
[]
=
this
.
search
===
''
?
this
.
listDoc
:
this
.
filterListDoc
();
const
start
=
this
.
page
*
this
.
pageSize
;
const
end
=
start
+
this
.
pageSize
;
this
.
pagedItems
=
data
.
slice
(
start
,
end
);
}
openEmployeeModal
(
image
:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
OpenImageComponent
,
{
centered
:
true
,
windowClass
:
'my-dialog-img-preview'
})
modalRef
.
componentInstance
.
linkImage
=
image
modalRef
.
result
.
then
(
result
=>
{
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
async
downloadFile
(
logId
:
string
,
lang
:
string
)
{
try
{
const
data
=
await
this
.
documentService
.
downloadFile
(
logId
,
lang
).
toPromise
();
if
(
data
)
{
FileSaver
.
saveAs
(
new
Blob
([
data
]),
"file_download.doc"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
filterListDoc
()
{
return
this
.
listDoc
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListDoc
()
{
try
{
const
data
=
await
firstValueFrom
(
this
.
documentService
.
getListDoc
(
'0'
));
this
.
listDoc
=
data
.
map
(
x
=>
new
DocumentModel
(
x
))
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
onApprove
(
item
:
DocumentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการอนุมัติข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
item
.
status
=
1
this
.
documentService
.
approve
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
modalService
.
dismissAll
()
this
.
openAlertModal
(
'บันทึกข้อมูลสำเร็จ'
)
this
.
getListDoc
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถบันทึกข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
onCancelApprove
(
item
:
DocumentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการไม่อนุมัติข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
item
.
status
=
2
this
.
documentService
.
approve
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'บันทึกข้อมูลสำเร็จ'
)
this
.
getListDoc
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถบันทึกข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
ngOnInit
()
{
this
.
getListDoc
();
}
deleteFile
(
item
:
DocumentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
this
.
documentService
.
deleteExcel
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
)
this
.
getListDoc
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
// this.modalService.dismissAll()
},
reason
=>
{
// this.modalService.dismissAll()
})
}
}
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-excel/approve-excel.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'อนุมัติ
Excel
'"
[
activeTitle
]="'รายการเอกสารรอการอนุมัติ'"
[
title1
]="'อนุมัติ
Excel
'"
></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการ Excel</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">รหัสเอกสาร</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col" class="text-center">ลิงค์</th>
<th scope="col" class="text-center">ไฟล์</th>
<th scope="col" class="text-center">สถานะ</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr *ngIf="listExcel.length == 0">
<td colspan="8" class="text-center">ไม่พบข้อมูล</td>
</tr>
<tr
*ngFor="let data of filterListExcel() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}"
(click)="openEmployeeModal(data.getImage())"></td>
<td >{{data.id}}</td>
<td>{{ data.thName }}</td>
<td>{{ data.thDesc }}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.logId)"></i></td>
<td class="text-center">
<span class="fa-stack rt_anim" *ngIf="data.status == 0" ngbTooltip="รออนุมัติ" container="body"
tooltipClass="myhrcolor-1">
<i class="fa fa-circle fa-stack-2x text-info"></i>
<i class=" fas fa-hourglass-half fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack rt_anim" *ngIf="data.status == 1" ngbTooltip="เปิดใช้งาน" container="body"
tooltipClass="myhrcolor-2">
<i class="fa fa-circle fa-stack-2x text-success"></i>
<i class=" fas fa-check fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack rt_anim" *ngIf="data.status == 2" ngbTooltip="ไม่อนุมัติ" container="body"
tooltipClass="myhrcolor-3">
<i class="fa fa-circle fa-stack-2x text-danger"></i>
<i class="fas fa-times fa-stack-1x fa-inverse" style="font-size: 1.25em;"></i>
</span>
</td>
<td>
<button type="button" class="btn btn-circle btn-success rounded-circle btn-sm mr-2"
(click)="onApprove(data)"><i class="fa fa-check"></i></button>
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2"
(click)="onCancelApprove(data)"><i class="fas fa-times"></i></button>
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2"
(click)="deleteFile(data)" placement="top" ngbTooltip="ลบ"><i class="fas fa-trash-alt"></i></button>
</td>
</tr>
</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]="listExcel.length" [maxSize]="3"
[rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div> -->
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการ Excel
</div>
<div
class=
"flex flex-wrap gap-4"
>
<!-- Buttons -->
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหา"
aria-label=
".form-control-sm example"
[(
ngModel
)]='
search
'
>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover "
>
<thead
class=
"bg-info text-white"
>
<tr>
<th
class=
"text-center"
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
รูปภาพ
</th>
<!-- <th scope="col">รหัสเอกสาร</th> -->
<th
scope=
"col"
>
ชื่อ
</th>
<th
scope=
"col"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"text-center"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"text-center"
>
ไฟล์
</th>
<th
scope=
"col"
class=
"text-center"
>
สถานะ
</th>
<th
scope=
"col"
></th>
</tr>
</thead>
<tbody>
<tr
*
ngFor=
"let data of filterListExcel() | slice: page * pageSize : (page+1) * pageSize ; let i = index"
>
<td
class=
"text-center"
>
{{i+1}}
</td>
<td><img
width=
"100"
class=
"border p-1"
src=
"{{data.getImage()}}"
(
click
)="
openEmployeeModal
(
data
.
getImage
())"
></td>
<!-- <td >{{data.id}}</td> -->
<td>
{{ data.thName }}
</td>
<td>
{{ data.thDesc }}
</td>
<td
class=
"text-center"
><i
class=
"ri-links-line text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
openLink
(
data
.
link1
)"
></i></td>
<td
class=
"text-center"
>
<i
class=
"fa fa-download text-base font-bold cursor-pointer hover:text-primary"
(
click
)="
downloadFile
(
data
.
logId
)"
></i></td>
<td
class=
"text-center"
>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 0"
ngbTooltip=
"รออนุมัติ"
container=
"body"
tooltipClass=
"myhrcolor-1"
>
<i
class=
"fa fa-circle fa-stack-2x text-info"
></i>
<i
class=
" fa fa-hourglass-half fa-stack-1x fa-inverse"
></i>
</span>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 1"
ngbTooltip=
"เปิดใช้งาน"
container=
"body"
tooltipClass=
"myhrcolor-2"
>
<i
class=
"fa fa-circle fa-stack-2x text-success"
></i>
<i
class=
" fa fa-check fa-stack-1x fa-inverse"
></i>
</span>
<span
class=
"fa-stack rt_anim"
*
ngIf=
"data.status == 2"
ngbTooltip=
"ไม่อนุมัติ"
container=
"body"
tooltipClass=
"myhrcolor-3"
>
<i
class=
"fa fa-circle fa-stack-2x text-danger"
></i>
<i
class=
"fa fa-times fa-stack-1x fa-inverse"
style=
"font-size: 1.25em;"
></i>
</span>
</td>
<td>
<div
class=
"flex space-x-2 justify-center"
>
<button
type=
"button"
class=
"bg-success hover:bg-success text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
onApprove
(
data
)"
><i
class=
"fa fa-check"
></i></button>
<button
type=
"button"
class=
"bg-danger hover:bg-danger text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
onCancelApprove
(
data
)"
><i
class=
"fa fa-times"
></i></button>
<button
type=
"button"
class=
"bg-danger hover:bg-danger text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
deleteFile
(
data
)"
placement=
"top"
ngbTooltip=
"ลบ"
><i
class=
"fa fa-trash"
></i></button>
</div>
</td>
</tr>
<tr
*
ngIf=
"filterListExcel().length === 0"
>
<td
[
attr
.
colspan
]="
9
"
class=
"!text-center py-4"
>
<ng-container
*
ngIf=
"listExcel.length === 0"
>
<p>
ไม่พบข้อมูล
</p>
</ng-container>
<ng-container
*
ngIf=
"listExcel.length > 0 && search"
>
<p>
ไม่พบข้อมูลที่ค้นหา...
</p>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterListExcel().length > 0"
>
<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
)]="
pageSize
"
(
ngModelChange
)="
page
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterListExcel().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"page > 0"
class=
"page-item {{page==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{'Previous' | translate}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"page > 0"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{page}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{page +
1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 1) * pageSize < filterListExcel().length"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{page + 2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 2) * pageSize < filterListExcel().length"
(
click
)="
page =
page
+
2
;
updatePagedItems
()"
>
{{page + 3}}
</a></li>
<li
*
ngIf=
"(page + 1) * pageSize < filterListExcel().length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-excel/approve-excel.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/approve-excel/approve-excel.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
OpenImageComponent
}
from
'../../../open-image/open-image.component'
;
import
{
ConfirmModalComponent
}
from
'../../../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../../../alert-modal/alert-modal.component'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../../../shared/shared.module'
;
import
{
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
ExcelModel
}
from
'../../../../../models/excel.model'
;
import
{
ExcelService
}
from
'../../../../../services/excel.service'
;
import
{
firstValueFrom
}
from
'rxjs'
;
declare
var
require
:
any
import
FileSaver
from
'file-saver'
;
import
{
TemplateModel
}
from
'../../../../../models/template.model'
;
@
Component
({
selector
:
'app-approve-excel'
,
templateUrl
:
'./approve-excel.component.html'
,
styleUrls
:
[
'./approve-excel.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
],
})
export
class
ApproveExcelComponent
implements
OnInit
{
page
=
0
;
pageSize
=
10
;
listExcel
:
ExcelModel
[]
=
[]
search
:
string
=
''
pagedItems
:
ExcelModel
[]
=
[];
constructor
(
private
modalService
:
NgbModal
,
private
excelService
:
ExcelService
)
{
}
get
totalItems
():
number
{
return
this
.
search
==
''
?
this
.
listExcel
.
length
:
this
.
filterListExcel
().
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalItems
/
this
.
pageSize
);
}
get
totalPagesArray
():
number
[]
{
return
Array
(
this
.
totalPages
).
fill
(
0
);
}
goToPage
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
totalPages
)
return
;
this
.
page
=
index
;
this
.
updatePagedItems
();
}
updatePagedItems
()
{
const
data
:
ExcelModel
[]
=
this
.
search
===
''
?
this
.
listExcel
:
this
.
filterListExcel
();
const
start
=
this
.
page
*
this
.
pageSize
;
const
end
=
start
+
this
.
pageSize
;
this
.
pagedItems
=
data
.
slice
(
start
,
end
);
}
openEmployeeModal
(
image
:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
OpenImageComponent
,
{
centered
:
true
,
windowClass
:
'my-dialog-img-preview'
})
modalRef
.
componentInstance
.
linkImage
=
image
modalRef
.
result
.
then
(
result
=>
{
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
excelService
.
downloadFile
(
logId
).
toPromise
();
if
(
data
)
{
FileSaver
.
saveAs
(
new
Blob
([
data
]),
"file_download.xlsx"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
filterListExcel
()
{
return
this
.
listExcel
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListExcel
()
{
try
{
const
data
=
await
firstValueFrom
(
this
.
excelService
.
getListExcel
(
'0'
));
this
.
listExcel
=
data
.
map
(
x
=>
new
ExcelModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
this
.
listExcel
=
[];
}
}
onApprove
(
item
:
ExcelModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการอนุมัติข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
item
.
status
=
1
this
.
excelService
.
approve
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'บันทึกข้อมูลสำเร็จ'
)
this
.
getListExcel
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถบันทึกข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
onCancelApprove
(
item
:
ExcelModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการไม่อนุมัติข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
item
.
status
=
2
this
.
excelService
.
approve
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
modalService
.
dismissAll
()
this
.
openAlertModal
(
'บันทึกข้อมูลสำเร็จ'
)
this
.
getListExcel
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถบันทึกข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
ngOnInit
()
{
this
.
getListExcel
();
console
.
log
(
'search:'
,
this
.
search
,
'length:'
,
this
.
search
?.
length
)
}
deleteFile
(
item
:
ExcelModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
this
.
excelService
.
deleteExcel
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
)
this
.
getListExcel
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
// this.modalService.dismissAll()
},
reason
=>
{
// this.modalService.dismissAll()
})
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
}
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/portal-category-list-approve.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการเอกสารรอการอนุมัติ'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการเอกสารรอการอนุมัติ'"
></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการเอกสารรอการอนุมัติ</h4>
<div class="row justify-content-center">
<div class="col-md-4 " *ngFor="let c of testdata|slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<div class="card border border-2">
<div class="card-body text-center">
<img src="{{ c.img }}" class="rounded-circle border p-1" width="100">
<h3 class="card-title mt-3 mb-0">{{c.name}}</h3>
</div>
<div class="d-flex justify-content-between bg-light border-top p-3">
<div>
<span class="align-middle">จำนวนเอกสาร {{ c.document }} ฉบับ</span>
</div>
<div >
<button class="btn btn-info btn-sm text-nowrap" (click)="openView(c.id)">รายละเอียด</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
<div
class=
"max-w-7xl mx-auto"
>
<div
class=
"box p-4"
>
<h4
class=
"text-xl font-semibold text-gray-800 mb-6"
>
รายการเอกสารรอการอนุมัติ
</h4>
<!-- Flex แทน Grid -->
<div
class=
"flex flex-wrap justify-center gap-6"
>
<div
class=
" bg-white rounded-xl shadow-lg overflow-hidden transform hover:scale-105 transition duration-300 ease-in-out flex flex-col"
style=
"width: 30%;"
*
ngFor=
"let c of testdata | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize"
>
<div
class=
"p-8 text-center"
>
<div
class=
"w-24 h-24 mx-auto rounded-full bg-green-100 flex items-center justify-center shadow-inner"
>
<img
src=
"{{ c.img }}"
class=
""
alt=
""
/>
</div>
<h3
class=
"text-2xl font-bold text-gray-800 mt-6 mb-2"
>
{{ c.name }}
</h3>
</div>
<!-- Footer -->
<div
class=
"mt-auto"
>
<div
class=
"flex justify-between items-center bg-gray-50 border-t border-gray-200 p-4"
>
<div>
<span
class=
"text-sm text-gray-700"
>
จำนวนเอกสาร {{ c.document }} ฉบับ
</span>
</div>
<div>
<button
class=
"bg-primary inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md shadow-md
active hover:bg-success hover:scale-110 transition duration-300 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50"
(
click
)="
openView
(
c
.
id
)"
>
รายละเอียด
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/portal-category-list-approve.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/management/portal-category-list-approve/portal-category-list-approve.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
"@angular/core"
;
import
{
NgbModal
}
from
"@ng-bootstrap/ng-bootstrap"
;
import
{
FormBuilder
,
FormGroup
,
FormsModule
,
Validators
}
from
"@angular/forms"
;
import
{
Router
,
RouterModule
}
from
"@angular/router"
;
import
{
ExcelService
}
from
"../../../../services/excel.service"
;
import
{
DocumentService
}
from
"../../../../services/document.service"
;
import
{
CourseService
}
from
"../../../../services/course.service"
;
import
{
CommonModule
}
from
"@angular/common"
;
import
{
TranslateModule
}
from
"@ngx-translate/core"
;
import
{
SharedModule
}
from
"../../../../../shared/shared.module"
;
@
Component
({
selector
:
"app-portal-category-list-approve"
,
templateUrl
:
"./portal-category-list-approve.component.html"
,
styleUrls
:
[
"./portal-category-list-approve.component.scss"
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
TranslateModule
,
SharedModule
,
],
})
export
class
PortalCategoryListApproveComponent
implements
OnInit
{
constructor
(
private
modalService
:
NgbModal
,
private
router
:
Router
,
private
excelService
:
ExcelService
,
private
documentService
:
DocumentService
,
private
courseService
:
CourseService
)
{
}
page
=
1
;
pageSize
=
7
;
testdata
:
{
id
:
string
img
:
String
;
name
:
String
;
details
:
String
;
document
:
String
;
}[]
=
[];
ngOnInit
()
{
this
.
testdata
=
[
{
id
:
'1'
,
img
:
"assets/images/icons/excel.png"
,
name
:
"Excel"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'2'
,
img
:
"assets/images/icons/document.png"
,
name
:
"Document"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'3'
,
img
:
"assets/images/icons/course.png"
,
name
:
"Course"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
];
this
.
getListCount
();
}
openView
(
id
:
string
)
{
if
(
id
==
'1'
)
{
this
.
router
.
navigate
([
'/admin/approve-excel'
]);
}
else
if
(
id
==
'2'
)
{
this
.
router
.
navigate
([
'/admin/approve-doc'
]);
}
else
if
(
id
==
'3'
)
{
this
.
router
.
navigate
([
'/admin/approve-course'
]);
}
}
async
getListCount
()
{
try
{
const
countExcel
=
await
this
.
excelService
.
getCount
().
toPromise
();
const
countDoc
=
await
this
.
documentService
.
getCount
().
toPromise
();
const
countCourse
=
await
this
.
courseService
.
getCount
().
toPromise
();
this
.
testdata
.
forEach
((
x
,
i
)
=>
{
if
(
i
==
0
)
{
x
.
document
=
(
countExcel
??
0
).
toString
();
}
else
if
(
i
==
1
)
{
x
.
document
=
(
countDoc
??
0
).
toString
();
}
else
if
(
i
==
2
)
{
x
.
document
=
(
countCourse
??
0
).
toString
();
}
});
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
openModal
(
targetModal
:
NgbModal
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
"static"
,
});
}
closeBtnClick
()
{
this
.
modalService
.
dismissAll
();
}
routerLink
(
path
:
String
,
type
:
String
)
{
this
.
router
.
navigate
([
path
,
{
type
:
type
}])
}
}
src/app/DPU/myskill-x/myportal/myportal.component.css
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/myportal.component.html
0 → 100644
View file @
73e72e5e
<p>
myportal works!
</p>
src/app/DPU/myskill-x/myportal/myportal.component.spec.ts
0 → 100644
View file @
73e72e5e
/* tslint:disable:no-unused-variable */
import
{
async
,
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
By
}
from
'@angular/platform-browser'
;
import
{
DebugElement
}
from
'@angular/core'
;
import
{
MyportalComponent
}
from
'./myportal.component'
;
describe
(
'MyportalComponent'
,
()
=>
{
let
component
:
MyportalComponent
;
let
fixture
:
ComponentFixture
<
MyportalComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
MyportalComponent
]
})
.
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
MyportalComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/DPU/myskill-x/myportal/myportal.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
@
Component
({
selector
:
'app-myportal'
,
templateUrl
:
'./myportal.component.html'
,
styleUrls
:
[
'./myportal.component.css'
]
})
export
class
MyportalComponent
implements
OnInit
{
constructor
()
{
}
ngOnInit
()
{
}
}
src/app/DPU/myskill-x/myportal/open-image/open-image.component.html
0 → 100644
View file @
73e72e5e
<div
class=
"p-4"
>
<img
[
src
]="
linkImage
"
alt=
"Image Preview"
class=
"w-full h-auto max-w-full block mx-auto"
/>
<div
class=
"mt-4 text-right"
>
<button
(
click
)="
onClose
()"
class=
"px-4 py-2 bg-gray-200 text-gray-800 rounded-md hover:bg-gray-300 transition-colors duration-200"
>
ปิด
</button>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/open-image/open-image.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/open-image/open-image.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
,
Inject
}
from
'@angular/core'
;
import
{
MAT_DIALOG_DATA
,
MatDialogRef
}
from
'@angular/material/dialog'
;
// นำเข้า MAT_DIALOG_DATA และ MatDialogRef
@
Component
({
selector
:
'app-open-image'
,
templateUrl
:
'./open-image.component.html'
,
styleUrls
:
[
'./open-image.component.scss'
]
})
export
class
OpenImageComponent
implements
OnInit
{
linkImage
:
string
=
''
;
constructor
(
@
Inject
(
MAT_DIALOG_DATA
)
public
data
:
{
linkImage
:
string
},
public
dialogRef
:
MatDialogRef
<
OpenImageComponent
>
)
{
}
ngOnInit
():
void
{
if
(
this
.
data
&&
this
.
data
.
linkImage
)
{
this
.
linkImage
=
this
.
data
.
linkImage
;
}
}
onClose
():
void
{
this
.
dialogRef
.
close
();
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/portal-category-list/portal-category-list.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการเอกสาร'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการเอกสาร'"
></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการเอกสาร</h4>
<div class="row justify-content-center">
<div class="col-lg-4 col-md-6 col-sm-6 col-12" *ngFor="let c of testdata|slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<div class="card border-border-2">
<div class="card-body text-center">
<img src="{{ c.img }}" class="rounded-circle border p-1" width="100">
<h3 class="card-title mt-3 mb-0">{{c.name}}</h3>
</div>
<div class="d-flex justify-content-between bg-light border-top p-3">
<div>
<span class="align-middle">จำนวนเอกสาร {{ c.document }} ฉบับ</span>
</div>
<div >
<button class="btn btn-info btn-sm text-nowrap" (click)="openView(c.id)">รายละเอียด</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
<div
class=
"max-w-7xl mx-auto"
>
<div
class=
"box p-4"
>
<h4
class=
"text-xl font-semibold text-gray-800 mb-6"
>
รายการเอกสาร
</h4>
<!-- Flex แทน Grid -->
<div
class=
"flex flex-wrap justify-center gap-6"
>
<div
class=
" bg-white rounded-xl shadow-lg overflow-hidden transform hover:scale-105 transition duration-300 ease-in-out flex flex-col"
style=
"width: 30%;"
*
ngFor=
"let c of testdata | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize"
>
<div
class=
"p-8 text-center"
>
<div
class=
"w-24 h-24 mx-auto rounded-full bg-green-100 flex items-center justify-center shadow-inner"
>
<img
src=
"{{ c.img }}"
class=
""
alt=
""
/>
</div>
<h3
class=
"text-2xl font-bold text-gray-800 mt-6 mb-2"
>
{{ c.name }}
</h3>
</div>
<!-- Footer -->
<div
class=
"mt-auto"
>
<div
class=
"flex justify-between items-center bg-gray-50 border-t border-gray-200 p-4"
>
<div>
<span
class=
"text-sm text-gray-700"
>
จำนวนเอกสาร {{ c.document }} ฉบับ
</span>
</div>
<div>
<button
class=
"bg-primary inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700
text-white text-sm font-medium rounded-md shadow-md ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50
active hover:bg-success hover:scale-110 transition duration-300"
(
click
)="
openView
(
c
.
id
)"
>
รายละเอียด
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
src/app/DPU/myskill-x/myportal/portal-category-list/portal-category-list.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/portal-category-list/portal-category-list.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
Router
,
RouterModule
}
from
'@angular/router'
;
import
{
ExcelService
}
from
'../../../services/excel.service'
;
import
{
DocumentService
}
from
'../../../services/document.service'
;
import
{
CourseService
}
from
'../../../services/course.service'
;
import
{
WidgetService
}
from
'../../../services/widgets.service'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
@
Component
({
selector
:
'app-portal-category-list'
,
templateUrl
:
'./portal-category-list.component.html'
,
styleUrls
:
[
'./portal-category-list.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
TranslateModule
,
SharedModule
,
],
})
export
class
PortalCategoryListComponent
implements
OnInit
{
constructor
(
private
routes
:
Router
,
private
excelService
:
ExcelService
,
private
documentService
:
DocumentService
,
private
courseService
:
CourseService
,
private
widgetService
:
WidgetService
)
{
}
page
=
1
;
pageSize
=
10
;
testdata
:
{
id
:
string
;
img
:
String
;
name
:
String
;
details
:
String
;
document
:
String
;
}[]
=
[];
ngOnInit
()
{
this
.
testdata
=
[
{
id
:
'1'
,
img
:
"assets/images/icons/excel.png"
,
name
:
"Excel"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'2'
,
img
:
"assets/images/icons/document.png"
,
name
:
"Document"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'3'
,
img
:
"assets/images/icons/course.png"
,
name
:
"Course"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'4'
,
img
:
"assets/images/icons/widget.png"
,
name
:
"Widgets"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'5'
,
img
:
"assets/images/faces/1.jpg"
,
name
:
"BI"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
];
this
.
getListCount
();
}
async
getListCount
()
{
try
{
const
countExcel
=
await
this
.
excelService
.
getCountContent
().
toPromise
();
const
countDoc
=
await
this
.
documentService
.
getCountContent
().
toPromise
();
const
countCourse
=
await
this
.
courseService
.
getCountContent
().
toPromise
();
const
countWidgets
=
await
this
.
widgetService
.
getCount
().
toPromise
();
this
.
testdata
.
forEach
((
x
,
i
)
=>
{
if
(
i
==
0
)
{
x
.
document
=
countExcel
!
.
toString
()
}
else
if
(
i
==
1
)
{
x
.
document
=
countDoc
!
.
toString
()
}
else
if
(
i
==
2
)
{
x
.
document
=
countCourse
!
.
toString
()
}
else
if
(
i
==
3
)
{
x
.
document
=
countWidgets
!
.
toString
()
}
})
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
openView
(
id
:
string
)
{
if
(
id
==
'1'
)
{
this
.
routes
.
navigate
([
'/admin/view-list-excel'
]);
}
else
if
(
id
==
'2'
)
{
this
.
routes
.
navigate
([
'/admin/view-list-doc'
]);
}
else
if
(
id
==
'3'
)
{
this
.
routes
.
navigate
([
'/admin/view-list-course'
]);
}
else
if
(
id
==
'4'
)
{
this
.
routes
.
navigate
([
'/admin/view-list-widgets'
]);
}
}
}
src/app/DPU/myskill-x/myportal/portal-create-category/portal-create-category.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการอัพโหลดเอกสาร'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการอัพโหลดเอกสาร'"
></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการอัพโหลดเอกสาร</h4>
<div class="row justify-content-center">
<div class="col-md-4 " *ngFor="let c of testdata|slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<div class="card border border-2">
<div class="card-body text-center">
<img src="{{ c.img }}" class="rounded-circle border p-1" width="100">
<h3 class="card-title mt-3 mb-0">{{c.name}}</h3>
</div>
<div class="d-flex justify-content-between bg-light border-top p-3">
<div>
<span class="align-middle">จำนวนเอกสาร {{ c.document }} ฉบับ</span>
</div>
<div >
<button class="btn btn-info btn-sm text-nowrap" (click)="openView(c.id)">รายละเอียด</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
<div
class=
"max-w-7xl mx-auto"
>
<div
class=
"box p-4"
>
<h4
class=
"text-xl font-semibold text-gray-800 mb-6"
>
รายการเอกสาร
</h4>
<!-- Flex แทน Grid -->
<div
class=
"flex flex-wrap justify-center gap-6"
>
<div
class=
" bg-white rounded-xl shadow-lg overflow-hidden transform hover:scale-105 transition duration-300 ease-in-out flex flex-col"
style=
"width: 30%;"
*
ngFor=
"let c of testdata | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize"
>
<div
class=
"p-8 text-center"
>
<div
class=
"w-24 h-24 mx-auto rounded-full bg-green-100 flex items-center justify-center shadow-inner"
>
<img
src=
"{{ c.img }}"
class=
""
alt=
""
/>
</div>
<h3
class=
"text-2xl font-bold text-gray-800 mt-6 mb-2"
>
{{ c.name }}
</h3>
</div>
<!-- Footer -->
<div
class=
"mt-auto"
>
<div
class=
"flex justify-between items-center bg-gray-50 border-t border-gray-200 p-4"
>
<div>
<span
class=
"text-sm text-gray-700"
>
จำนวนเอกสาร {{ c.document }} ฉบับ
</span>
</div>
<div>
<button
class=
"bg-primary inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md shadow-md
active hover:bg-success hover:scale-110 transition duration-300 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50"
(
click
)="
openView
(
c
.
id
)"
>
รายละเอียด
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Add File -->
<!-- <ng-template #editTemplateModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">Add File Type Category</h5>
<button type="button" class="close" (click)="closeBtnClick()" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="edittemplate" (ngSubmit)="onSubmit()">
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">ชื่อประเภทไฟล์</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Name" id="name" (blur)=logValidationErrors(edittemplate)>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">รายละเอียด</label>
<div class="col-sm-8">
<textarea class="form-control"></textarea>
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">รูปประเภทไฟล์</label>
<div class="col-sm-8">
<input type="file" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="closeBtnClick()">Close</button>
<button type="submit" class="btn btn-primary" >Save</button>
</div>
</form>
</div>
</ng-template> -->
\ No newline at end of file
src/app/DPU/myskill-x/myportal/portal-create-category/portal-create-category.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/portal-create-category/portal-create-category.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
NgbModal
}
from
"@ng-bootstrap/ng-bootstrap"
;
import
{
Router
,
RouterModule
}
from
'@angular/router'
;
import
{
ExcelService
}
from
'../../../services/excel.service'
;
import
{
DocumentService
}
from
'../../../services/document.service'
;
import
{
CourseService
}
from
'../../../services/course.service'
;
import
{
WidgetService
}
from
'../../../services/widgets.service'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
@
Component
({
selector
:
'app-portal-create-category'
,
templateUrl
:
'./portal-create-category.component.html'
,
styleUrls
:
[
'./portal-create-category.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
TranslateModule
,
SharedModule
,
],
})
export
class
PortalCreateCategoryComponent
implements
OnInit
{
constructor
(
private
modalService
:
NgbModal
,
private
routes
:
Router
,
private
excelService
:
ExcelService
,
private
documentService
:
DocumentService
,
private
courseService
:
CourseService
,
private
widgetService
:
WidgetService
)
{}
page
=
1
;
pageSize
=
10
;
testdata
:
{
id
:
string
;
img
:
String
;
name
:
String
;
details
:
String
;
document
:
String
;
}[]
=
[];
ngOnInit
()
{
this
.
testdata
=
[
{
id
:
'1'
,
img
:
"assets/images/icons/excel.png"
,
name
:
"Excel"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'2'
,
img
:
"assets/images/icons/document.png"
,
name
:
"Document"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'3'
,
img
:
"assets/images/icons/course.png"
,
name
:
"Course"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'4'
,
img
:
"assets/images/icons/widget.png"
,
name
:
"Widgets"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
},
{
id
:
'5'
,
img
:
"assets/images/faces/1.jpg"
,
name
:
"BI"
,
details
:
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
,
document
:
"0"
}
];
this
.
getListCount
();
}
async
getListCount
(){
try
{
const
countExcel
=
await
this
.
excelService
.
getCount
().
toPromise
();
const
countDoc
=
await
this
.
documentService
.
getCount
().
toPromise
();
const
countCourse
=
await
this
.
courseService
.
getCount
().
toPromise
();
const
countWidgets
=
await
this
.
widgetService
.
getCount
().
toPromise
();
this
.
testdata
.
forEach
((
x
,
i
)
=>
{
if
(
i
==
0
){
x
.
document
=
countExcel
!
.
toString
()
}
else
if
(
i
==
1
){
x
.
document
=
countDoc
!
.
toString
()
}
else
if
(
i
==
2
){
x
.
document
=
countCourse
!
.
toString
()
}
else
if
(
i
==
3
){
x
.
document
=
countWidgets
!
.
toString
()
}
})
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
openView
(
id
:
string
){
if
(
id
==
'1'
){
this
.
routes
.
navigate
([
'/admin/list-excell'
]);
}
else
if
(
id
==
'2'
){
this
.
routes
.
navigate
([
'/admin/list-doc'
]);
}
else
if
(
id
==
'3'
){
this
.
routes
.
navigate
([
'/admin/list-course'
]);
}
else
if
(
id
==
'4'
){
this
.
routes
.
navigate
([
'/admin/list-widgets'
]);
}
}
openModal
(
targetModal
:
NgbModal
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
"static"
,
});
}
closeBtnClick
()
{
this
.
modalService
.
dismissAll
();
}
}
src/app/DPU/myskill-x/myportal/set-excel-reports/excel-list/excel-list.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'เพิ่มรายงาน
Excel
'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'เพิ่มรายงาน
Excel
'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการเอกสาร
</div>
<div
class=
"flex flex-wrap gap-4"
>
<!-- Search By -->
<div
class=
"d-flex flex-column"
style=
"min-width: 200px;"
>
<label
class=
"mb-1 font-medium text-sm"
>
Search By
</label>
<select
class=
"form-control h-100"
[(
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>
<!-- Condition -->
<div
class=
"d-flex flex-column"
style=
"min-width: 200px;"
>
<label
class=
"mb-1 font-medium text-sm"
>
Condition
</label>
<select
class=
"form-control h-100"
[(
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>
<!-- Key Value -->
<div
class=
"d-flex flex-column"
style=
"min-width: 200px;"
>
<label
class=
"mb-1 font-medium text-sm"
>
Key Value
</label>
<input
class=
"form-control h-100"
type=
"text"
placeholder=
"ค้นหา"
aria-label=
".form-control-sm example"
[(
ngModel
)]="
searchValue
"
>
</div>
<!-- Buttons -->
<div
class=
"flex items-end gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full"
style=
"margin-bottom: unset;"
(
click
)="
openTemplate
.
clear
();
templateListSearch
()"
>
<i
class=
"ri-search-line font-semibold align-middle"
></i>
ค้นหา
</a>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-success-full"
style=
"margin-bottom: unset;"
(
click
)="
openAddGroupModal
()"
>
<i
class=
"ri-add-line font-semibold align-middle"
></i>
Add Group
</a>
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead>
<tr>
<th
class=
"text-center"
scope=
"col"
>
ชื่อกลุ่มรายงาน (ภาษาไทย)
</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
id=
"tableBody"
*
ngIf=
"isSearching || template.filter.length"
>
<tr
*
ngIf=
"isSearching"
>
<td
colspan=
"7"
class=
"loading"
>
<div
class=
"spinner"
></div>
<div
class=
"spinner"
></div>
<div
class=
"spinner"
></div>
<span>
กำลังค้นหา...
</span>
</td>
</tr>
<ng-container
*
ngIf=
"!isSearching"
>
<ng-container
*
ngFor=
"let items of template.filter | slice: page * pageSize : (page + 1) * 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"
>
<span
class=
"cursor-pointer text-info"
style=
"text-decoration: underline;"
(
click
)="
openAddGroupModal
(
items
)"
>
{{items.tname}}
</span>
<span
*
ngIf=
"items.tdesc"
>
-{{items.tdesc}}
</span>
</td>
<td
class=
"text-center"
>
<ng-container
*
ngIf=
"items.templateFile.length"
>
<ng-container
*
ngIf=
"!openTemplate.get(items.templateId)"
>
<a
aria-label=
"anchor"
title=
"เปิด"
(
click
)="
openTemplate
.
set
(
items
.
templateId
,
true
)"
(
mouseenter
)="
buttonHover
.
set
(
items
.
templateId
,
true
)"
(
mouseleave
)="
buttonHover
.
set
(
items
.
templateId
,
false
)"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
><i
class=
"ri-arrow-right-line"
></i></a>
</ng-container>
<ng-container
*
ngIf=
"openTemplate.get(items.templateId)"
>
<a
aria-label=
"anchor"
title=
"ปิด"
(
click
)="
openTemplate
.
set
(
items
.
templateId
,
false
)"
(
mouseenter
)="
buttonHover
.
set
(
items
.
templateId
+'
close
',!
buttonHover
.
get
(
items
.
templateId
))"
(
mouseleave
)="
buttonHover
.
clear
()"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
><i
class=
"ri-arrow-down-line"
></i></a>
</ng-container>
</ng-container>
<a
aria-label=
"anchor"
title=
"เพิ่ม EXCCHILD"
(
click
)="
openAddChildModal
(
items
,'
add
')"
(
mouseenter
)="
buttonHover
.
set
(
items
.
templateId
+'
add
',!
buttonHover
.
get
(
items
.
templateId
))"
(
mouseleave
)="
buttonHover
.
clear
()"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-success/10 text-success hover:bg-success hover:text-white hover:border-success"
><i
class=
"ri-save-2-line"
></i></a>
<a
aria-label=
"anchor"
title=
"ลบ"
(
click
)="
deleteTemplate
(
items
)"
(
mouseenter
)="
buttonHover
.
set
(
items
.
templateId
+'
delete
',!
buttonHover
.
get
(
items
.
templateId
))"
(
mouseleave
)="
buttonHover
.
clear
()"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"
><i
class=
"ri-delete-bin-line"
></i></a>
</td>
</tr>
<ng-container
*
ngIf=
"openTemplate.get(items.templateId)"
>
<ng-container
*
ngFor=
"let item of items.templateFile | slice: page * pageSize : (page+1) * 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
'}"
>
<ng-container
*
ngIf=
"downloadTemplateFileLoading.get(item.fileName)"
>
<td
colspan=
"7"
class=
"text-center"
>
<div
*
ngFor=
"let item of [1,2,3]"
class=
"spinner-grow text-info mx-1"
role=
"status"
>
<span
class=
"sr-only"
>
Loading...
</span>
</div>
</td>
</ng-container>
<ng-container
*
ngIf=
"!downloadTemplateFileLoading.get(item.fileName)"
>
<td
style=
"white-space: normal !important;word-break: break-word;"
>
<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>
<span
class=
"cursor-pointer text-info"
style=
"text-decoration: underline;"
(
click
)="
openAddChildModal
(
item
,'
edit
')"
>
{{item.tdesc}}
</span>
</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"
>
<a
aria-label=
"anchor"
title=
"Download File"
(
mouseenter
)="
buttonHover
.
set
(
item
.
fileName
+'
copy
',!
buttonHover
.
get
(
item
.
fileName
))"
(
mouseleave
)="
buttonHover
.
clear
()"
(
click
)="
downloadTemplateFile
(
item
)"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
><i
class=
"ri-file-download-line"
></i></a>
<a
aria-label=
"anchor"
title=
"Print"
(
mouseenter
)="
buttonHover
.
set
(
item
.
fileName
+'
print
',!
buttonHover
.
get
(
item
.
fileName
))"
(
mouseleave
)="
buttonHover
.
clear
()"
(
click
)="
openPrintModal
(
item
);"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-warning/10 text-warning hover:bg-warning hover:text-white hover:border-warning"
><i
class=
"ri-printer-line"
></i></a>
<a
aria-label=
"anchor"
title=
"ลบ"
(
mouseenter
)="
buttonHover
.
set
(
item
.
fileName
+'
delete
',!
buttonHover
.
get
(
item
.
fileName
))"
(
mouseleave
)="
buttonHover
.
clear
()"
(
click
)="
deleteTemplateFile
(
item
)"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"
><i
class=
"ri-delete-bin-line"
></i></a>
</td>
</ng-container>
</tr>
</ng-container>
</ng-container>
</ng-container>
</ng-container>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"template.filter.length > 0"
>
<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
)]="
pageSize
"
(
ngModelChange
)="
page
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{template.filter.length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"page > 0"
class=
"page-item {{page==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{'Previous' | translate}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"page > 0"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{page}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{page + 1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 1) * pageSize < template.filter.length"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{page + 2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 2) * pageSize < template.filter.length"
(
click
)="
page =
page
+
2
;
updatePagedItems
()"
>
{{page + 3}}
</a></li>
<li
*
ngIf=
"(page + 1) * pageSize < template.filter.length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
<div
class=
"flex justify-end items-center flex-wrap gap-4 mt-3"
>
<div><i
class=
"fa fa-times text-danger"
></i>
= used on menu
</div>
<div><i
class=
"fa fa-check text-success"
></i>
= unused on menu
</div>
<div><i
class=
"ri-file-download-line text-info"
></i>
= download files
</div>
<div><i
class=
"ri-printer-line text-warning"
></i>
= print report
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template
#
addGroupModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
EXCHEAD, Template header excel
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalAddGroup
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<div
class=
"grid grid-cols-12 gap-4"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
รหัสกลุ่มแม่แบบ
</label>
<input
type=
"text"
class=
"form-control !bg-input-readonly"
id=
"deal-title"
placeholder=
""
value=
"AUTO-001"
disabled
[
value
]="
bodyTemplate
.
data
.
templateId
"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
ชื่อกลุ่มรายงาน (ภาษาไทย)
<span
class=
"required text-danger"
>
*
</span>
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
bodyTemplate
.
data
.
tname
"
>
<div
class=
"text-danger"
*
ngIf=
"!bodyTemplate.data.tname"
>
กรอกชื่อกลุ่มรายงานภาษาไทย
</div>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
ชื่อกลุ่มรายงาน (ภาษาอังกฤษ)
<span
class=
"required text-danger"
>
*
</span>
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
bodyTemplate
.
data
.
ename
"
>
<div
class=
"text-danger"
*
ngIf=
"!bodyTemplate.data.ename"
>
Enter report group name in English
</div>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
รายละเอียด (ภาษาไทย)
</label>
<textarea
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
"กรอกรายละเอียดภาษาไทย..."
[(
ngModel
)]="
bodyTemplate
.
data
.
tdesc
"
></textarea>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
รายละเอียด (ภาษาอังกฤษ)
</label>
<textarea
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
"Enter description in English..."
[(
ngModel
)]="
bodyTemplate
.
data
.
edesc
"
></textarea>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"form-label"
>
โมดูล
<span
class=
"required text-danger"
>
*
</span>
</label>
<select
class=
"form-select"
required
[
disabled
]="
bodyTemplate
.
status=
='edit'"
[(
ngModel
)]="
bodyTemplate
.
data
.
module
"
>
<option
style=
"color: red"
[
class
.
d-none
]="
bodyTemplate
.
data
.
module=
=''"
[
value
]="''"
>
{{bodyTemplate.data.module!=''?'ยกเลิก':''}}
</option>
<option
*
ngFor=
"let item of module.data"
[
ngValue
]="
item
.
code
"
>
{{item.tdesc}}
</option>
</select>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"form-label"
>
ชื่อบริษัท
<span
class=
"required text-danger"
>
*
</span>
</label>
<select
class=
"form-select"
required
[
disabled
]="
bodyTemplate
.
status=
='edit'"
[(
ngModel
)]="
bodyTemplate
.
data
.
companyId
"
>
<option
style=
"color: red"
[
class
.
d-none
]="
bodyTemplate
.
data
.
companyId=
=''"
[
value
]="''"
>
{{bodyTemplate.data.companyId!=''?'ยกเลิก':''}}
</option>
<option
*
ngFor=
"let item of itemsList"
[
ngValue
]="
item
.
companyId
"
>
{{item.companyName}}
</option>
</select>
</div>
</div>
</div>
<div
class=
"border-t"
>
<div
class=
"ti-modal-footer flex justify-center gap-3 mb-3 mt-3"
>
<button
type=
"button"
class=
"ti-btn bg-danger text-white !font-medium"
(
click
)="
closeModalAddGroup
()"
>
{{'Cancel' | translate}}
</button>
<button
type=
"button"
[
class
.
ti-btn-disabled
]="!
bodyTemplate
.
data
.
tname
||
!
bodyTemplate
.
data
.
ename
||!
bodyTemplate
.
data
.
module
"
[
disabled
]="!
bodyTemplate
.
data
.
tname
||
!
bodyTemplate
.
data
.
ename
||!
bodyTemplate
.
data
.
module
"
(
click
)="
postTemplate
()"
class=
"ti-btn bg-primary text-white !font-medium"
>
{{'Save' |
translate}}
</button>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template
#
addChildModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
EXCCHILD, Template file excel
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModaladdChild
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<div
class=
"flex flex-col space-y-4"
>
<!-- ตัวเลือกไฟล์จาก Portal -->
<div
class=
"sm:grid grid-cols-3 gap-x-6 space-y-4 lg:space-y-0 mt-5"
>
<div
class=
"flex items-center gap-2 mb-2"
>
<input
type=
"radio"
class=
"custom-control-input cursor-pointer"
name=
"excelFile"
id=
"excelFilePortal"
[
checked
]="
templateFileType=
='portal'"
(
click
)="
templateFileTypeChange
()"
>
<label
class=
"custom-control-label cursor-pointer font-bold"
for=
"excelFilePortal"
>
เลือกเอ็กเซลล์ไฟล์จาก Portal
<span
*
ngIf=
"templateFileType=='portal'"
class=
"text-red"
>
*
</span>
</label>
</div>
<div
*
ngIf=
"templateFileType=='portal'"
class=
"flex items-center w-full col-span-2"
>
<input
*
ngIf=
"templateFile.portalId"
type=
"text"
class=
"form-control bg-white w-full flex-grow"
style=
"border-radius: 0px;"
[
value
]="
templateFile
.
portalId
"
readonly
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full flex-shrink-0 !mb-0"
style=
"border-radius: 0.1rem;"
(
click
)="
openExcelPortalModal
()"
>
<i
class=
"ri-search-line font-semibold align-middle"
></i>
</button>
</div>
</div>
<!-- อัปโหลดไฟล์ -->
<div
class=
"sm:grid grid-cols-3 gap-x-6 space-y-4 lg:space-y-0 mt-5"
>
<div
class=
"flex items-center gap-2 mb-2"
>
<input
type=
"radio"
class=
"custom-control-input cursor-pointer"
name=
"excelFile"
id=
"excelFileUpload"
[
checked
]="
templateFileType=
='upload'"
(
click
)="
templateFileTypeChange
()"
>
<label
class=
"custom-control-label cursor-pointer font-bold"
for=
"excelFileUpload"
>
อัพโหลดเอ็กเซลล์ไฟล์
<span
*
ngIf=
"templateFileType=='upload'"
style=
"color: red"
>
*
</span>
</label>
</div>
<div
*
ngIf=
"templateFileType=='upload'"
class=
"flex items-center gap-2 truncate"
>
<input
#
fileInput
type=
"file"
accept=
".xlsx"
(
change
)="
onFileSelected
($
event
)"
style=
"display: none;"
/>
<button
(
click
)="
fileInput
.
click
()"
class=
"px-2 py-1 border border-black rounded bg-white hover:bg-gray-100 shadow-sm font-bold whitespace-nowrap"
>
เลือกไฟล์
</button>
<span
*
ngIf=
"templateFileName"
class=
"truncate block max-w-[200px] overflow-hidden whitespace-nowrap text-ellipsis"
>
{{ templateFileName }}
</span>
</div>
</div>
<div
class=
"sm:grid grid-cols-3 gap-x-6 space-y-4 lg:space-y-0 mt-5"
>
<div
class=
"col-span-3 lg:col-span-5 sm:inline-flex sm:items-center space-y-2 sm:space-y-0 sm:space-x-3 w-full rtl:space-x-reverse"
>
<label
class=
"ti-form-label block mb-1 font-bold"
style=
"width: 50%;"
>
รายละเอียด (ภาษาไทย)
</label>
<input
type=
"text"
id=
"input-label"
class=
"ti-form-input w-full "
[(
ngModel
)]="
templateFile
.
tdesc
"
>
</div>
</div>
<div
class=
"sm:grid grid-cols-3 gap-x-6 space-y-4 lg:space-y-0 mt-5"
>
<div
class=
"col-span-3 lg:col-span-5 sm:inline-flex sm:items-center space-y-2 sm:space-y-0 sm:space-x-3 w-full rtl:space-x-reverse"
>
<label
class=
"ti-form-label block mb-1 font-bold"
style=
"width: 50%;"
>
รายละเอียด
(ภาษาอังกฤษ)
</label>
<input
type=
"text"
id=
"input-label"
class=
"ti-form-input w-full "
[(
ngModel
)]="
templateFile
.
edesc
"
>
</div>
</div>
<!-- แบ่งปัน -->
<div
class=
"sm:grid grid-cols-3 gap-x-6 space-y-4 lg:space-y-0 mt-5"
>
<label
class=
"ti-form-label block mb-1 font-bold"
>
แบ่งปัน
</label>
<div
class=
"flex gap-4"
>
<div
class=
"flex items-center gap-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=
"flex items-center gap-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>
<!-- แสดง Pivot -->
<div
class=
"sm:grid grid-cols-3 gap-x-6 space-y-4 lg:space-y-0 mt-5"
>
<label
class=
"ti-form-label block mb-1 font-bold"
>
แสดงรูปแบบ pivot
</label>
<div
class=
"flex gap-4"
>
<div
class=
"flex items-center gap-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=
"flex items-center gap-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>
<!-- แสดง DataGrid -->
<div
class=
"sm:grid grid-cols-3 gap-x-6 space-y-4 lg:space-y-0 mt-5"
>
<label
class=
"ti-form-label block mb-1 font-bold"
>
แสดงรูปแบบ datagrid
</label>
<div
class=
"flex gap-4"
>
<div
class=
"flex items-center gap-2"
>
<input
type=
"radio"
class=
"custom-control-input cursor-pointer"
name=
"datagt"
id=
"datagtNo"
[
checked
]="
templateFile
.
isDataGrid=
='0'"
(
click
)="
templateFile
.
isDataGrid=
'0'
"
>
<label
class=
"custom-control-label cursor-pointer"
for=
"datagtNo"
>
ไม่ใช่
</label>
</div>
<div
class=
"flex items-center gap-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>
</div>
<div
class=
"border-t mt-3"
>
<div
class=
"ti-modal-footer flex justify-end gap-3 mb-3 mt-3 mr-3"
>
<button
type=
"button"
class=
"ti-btn bg-danger text-white !font-medium"
(
click
)="
closeModaladdChild
()"
>
{{'Cancel' | translate}}
</button>
<button
type=
"submit"
[
class
.
ti-btn-disabled
]="(!
templateFile
.
portalId
&&!
templateFileName
)||!
templateFile
.
tdesc
"
[
disabled
]="(!
templateFile
.
portalId
&&!
templateFileName
)||!
templateFile
.
tdesc
"
(
click
)="
postTemplateFile
()"
class=
"ti-btn bg-primary text-white !font-medium"
>
{{'Save' |
translate}}
</button>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template
#
excel_portalModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
EXCEL_PORTAL
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalexcel_portal
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<div
class=
"flex flex-col space-y-4"
>
<div
class=
"flex flex-wrap items-start justify-between gap-4"
>
<div
class=
"flex flex-wrap gap-4"
>
<div
class=
"flex flex-col min-w-[200px]"
>
<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"
[
ngValue
]="
item
.
groupId
"
>
{{item.thName}}
</option>
</select>
</div>
<div
class=
"flex flex-col min-w-[200px]"
>
<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"
[
ngValue
]="
item
.
value
"
>
{{item.value}}
</option>
</select>
</div>
</div>
<div
class=
"flex flex-col min-w-[200px]"
>
<input
type=
"text"
class=
"form-control"
placeholder=
"ค้นหา"
[(
ngModel
)]="
excelPortalSearch
.
search
"
>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table mb-0 no-wrap v-middle "
style=
"width: 100%;"
>
<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 align-middle"
>
ไม่พบข้อมูล
</td>
</tr>
</tbody>
<tbody
*
ngIf=
"excelPortalFilter().length"
>
<ng-container
*
ngFor=
"let item of excelPortalFilter() | slice: pageModal * pageSizeModal : (pageModal+1) * 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"
style=
"width: auto;"
[
src
]="
item
.
getImg
()"
>
</td>
<td>
<button
*
ngIf=
"item.link1"
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full"
(
click
)="
openVideoModal
(
item
.
link1
)"
><i
class=
"ri-search-line font-semibold align-middle"
></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>
</div>
</div>
<div
class=
"box-footer !border-t-0"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"excelPortalFilter().length > 0"
>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{excelPortalFilter().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"pageModal > 0"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
pageModal =
pageModal
-
1
;
updatePagedItems
()"
>
{{'Previous' |
translate}}
</a>
</li>
<li
class=
"page-item"
*
ngIf=
"pageModal - 1 >= 0"
>
<a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
(
click
)="
pageModal =
pageModal
-
1
;
updatePagedItems
()"
>
{{pageModal}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{pageModal + 1}}
</a>
</li>
<li
class=
"page-item"
*
ngIf=
"(pageModal + 1) * pageSizeModal < excelPortalFilter().length"
>
<a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
(
click
)="
pageModal =
pageModal
+
1
;
updatePagedItems
()"
>
{{pageModal + 2}}
</a>
</li>
<li
class=
"page-item"
*
ngIf=
"(pageModal + 2) * pageSizeModal < excelPortalFilter().length"
>
<a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
(
click
)="
pageModal =
pageModal
+
2
;
updatePagedItems
()"
>
{{pageModal + 3}}
</a>
</li>
<li
*
ngIf=
"(pageModal + 1) * pageSizeModal < excelPortalFilter().length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
pageModal =
pageModal
+
1
;
updatePagedItems
()"
>
{{'Next' |
translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div
class=
"border-t mt-3"
>
<div
class=
"ti-modal-footer flex justify-end gap-3 mb-3 mt-3 mr-3"
>
<button
type=
"button"
class=
"ti-btn bg-danger text-white !font-medium"
(
click
)="
closeModalexcel_portal
()"
>
{{'Cancel' | translate}}
</button>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template
#
videoModal
let-modal
>
<div
style=
"width: 100%; height: 100%;"
>
<iframe
style=
"width: 100%; height: 100%;"
[
src
]="
videoLink
|
safeUrl
"
frameborder=
"0"
allow=
"autoplay; encrypted-media"
allowfullscreen
>
</iframe>
</div>
</ng-template>
<ng-template
#
printModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
Excel Report
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalprintModal
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<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=
"flex items-center mb-4"
>
<!-- Label -->
<label
class=
"w-1/4 text-right pr-4 font-semibold text-sm"
>
{{ item.label }}
</label>
<!-- Input -->
<div
class=
"w-3/4"
>
<ng-container
[
ngSwitch
]="
item
.
type
"
>
<!-- Text -->
<input
*
ngSwitchCase=
"'text'"
type=
"text"
class=
"form-input w-full"
[(
ngModel
)]="
item
.
value
"
/>
<!-- List -->
<select
*
ngSwitchCase=
"'list'"
class=
"form-select w-full"
[(
ngModel
)]="
item
.
value
"
>
<option
*
ngFor=
"let list of item.option"
[
value
]="
list
.
value
"
>
{{ list.text }}
</option>
</select>
<!-- Radio -->
<div
*
ngSwitchCase=
"'radio'"
class=
"flex flex-wrap gap-4"
>
<label
*
ngFor=
"let radioItem of item.option"
class=
"inline-flex items-center"
>
<input
type=
"radio"
class=
"form-radio mr-2"
[
name
]="'
group-
'
+
item
.
label
"
[
id
]="
radioItem
.
text
+
radioItem
.
value
"
[
value
]="
radioItem
.
value
"
[(
ngModel
)]="
item
.
value
"
/>
{{ radioItem.text }}
</label>
</div>
<!-- Help -->
<div
*
ngSwitchCase=
"'help'"
class=
"flex items-stretch"
>
<input
type=
"text"
readonly
class=
"form-input w-1/2 bg-white cursor-pointer"
[
value
]="
item
.
value
.
tdesc
"
(
click
)="
openModalData
(
item
)"
/>
<button
class=
"bg-primary hover:bg-primary text-white px-3 flex items-center justify-center rounded-none border"
type=
"button"
(
click
)="
openModalData
(
item
)"
>
<i
class=
"ri-search-line font-semibold align-middle"
></i>
</button>
<button
type=
"button"
class=
"bg-red hover:bg-red text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
item
.
value=
{id:'',tdesc:'',edesc:''}"
>
<i
class=
"fa fa-times text-xs"
></i>
</button>
</div>
<!-- Calendar -->
<div
*
ngSwitchCase=
"'calendar'"
class=
"flex items-stretch"
>
<!-- Input -->
<input
class=
"form-input w-1/2 bg-white cursor-pointer rounded-r-none"
style=
"border-color: #e9edf6;"
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
)"
container=
"body"
>
<!-- Calendar Button -->
<button
type=
"button"
class=
"bg-white hover:bg-primary text-primary hover:text-white px-3 flex items-center justify-center rounded-none border"
style=
"border-color: #154c9c;"
(
click
)="
d1
.
toggle
()"
>
<i
class=
"ri-calendar-2-line"
></i>
</button>
<!-- Clear Button -->
<button
type=
"button"
class=
"bg-red hover:bg-red text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
select
[
item
.
key
]=
null
;
formatNgbDate
(
item
.
key
)"
>
<i
class=
"fa fa-times text-xs"
></i>
</button>
</div>
</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
class=
"row col-12 flex justify-center"
*
ngIf=
"variableSheet.length&&(excelReport.isDataGrid=='1'||excelReport.isPivot=='1')"
>
<div
class=
"col-12 d-flex justify-content-center align-content-center"
>
<button
type=
"button"
*
ngIf=
"excelReport.isDataGrid=='1'"
class=
"ti-btn ti-btn-primary-full"
(
click
)="
getExcelData
('
grid
')"
>
Datagrid
</button>
<ng-container
*
ngIf=
"excelReport.isDataGrid=='1'&&excelReport.isPivot=='1'"
>
</ng-container>
<button
type=
"button"
*
ngIf=
"excelReport.isPivot=='1'"
class=
"ti-btn ti-btn-primary-full"
(
click
)="
getExcelData
('
pivot
')"
>
Pivot
</button>
</div>
</div>
</ng-container>
</div>
</div>
<div
class=
"border-t mt-3"
>
<div
class=
"ti-modal-footer flex justify-end gap-1 mb-3 mt-3 mr-3"
>
<ng-container
*
ngIf=
"variableSheet.length"
>
<button
type=
"submit"
class=
"ti-btn ti-btn-info-full waves-effect waves-light btn-w-100"
[
disabled
]="
loadingExcel
"
(
click
)="
dowloadExcelReport
()"
>
{{"Print" }}
</button>
</ng-container>
<button
type=
"button"
class=
"ti-btn bg-danger text-white !font-medium"
(
click
)="
closeModalprintModal
()"
>
ปิด
</button>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template
#
modalData
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
{{modalDetail.text.cardHead }}
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalmodalData
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<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 "
style=
"width: 100%"
>
<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 * pageSizeModal : (pageModal+1) * pageSizeModal; let i=index"
(
click
)="
selectData
(
item
);
closeModalmodalData
()"
(
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>
<div
class=
"box-footer !border-t-0"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"valueDetailFilter().length > 0"
>
<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
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"Items per page"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{valueDetailFilter().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"pageModal>0"
class=
"page-item {{pageModal==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
pageModal =
pageModal-1;updatePagedItems()"
>
{{'Previous' |
translate}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageModal-1>0"
(
click
)="
pageModal =
pageModal-2;updatePagedItems()"
>
{{pageModal-1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageModal>0 && ((pageModal-1)*10 < (searchText == '' ? valueDetailFilter().length : valueDetailFilter().length))"
(
click
)="
pageModal =
pageModal-1;updatePagedItems()"
>
{{pageModal}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{pageModal +1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageModal+1)*10 < (searchText == '' ? valueDetailFilter().length : valueDetailFilter().length)"
(
click
)="
pageModal =
pageModal+1;updatePagedItems()"
>
{{pageModal +2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageModal+2)*10 < (searchText == '' ? valueDetailFilter().length : valueDetailFilter().length)"
(
click
)="
pageModal =
pageModal+2;updatePagedItems()"
>
{{pageModal +3}}
</a></li>
<li
*
ngIf=
"(pageModal+1)*10 < (searchText == '' ? valueDetailFilter().length : valueDetailFilter().length)"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
pageModal =
pageModal+1;updatePagedItems()"
>
{{'Next' |
translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div
class=
"border-t"
>
<div
class=
"ti-modal-footer flex justify-end gap-3 mb-3 mt-3 mr-3"
>
<button
type=
"button"
class=
"ti-btn bg-danger text-white !font-medium"
(
click
)="
closeModalmodalData
()"
>
ปิด
</button>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template
#
gridModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
GridData
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalgridModal
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<app-datagrid-syncfution
#
pivotComponent
[
searchSettings
]="
searchSettings
"
[
dataSource
]="
dataList
"
[
columns
]="
columns
"
[
gridLayout
]="
setPerspective
"
[
sendLayout
]="
gridLayout
.
stimulate
"
(
layout
)="
gridLayout
.
data=
$event"
>
</app-datagrid-syncfution>
</div>
<div
class=
"border-t"
>
<div
class=
"ti-modal-footer flex justify-end gap-3 mb-3 mt-3 mr-3"
>
<button
*
ngIf=
"!loadingExcel"
type=
"button"
class=
"ti-btn ti-btn-info-full"
(
click
)="
gridLayout
.
stimulate=
!gridLayout.stimulate;savePerspective('grid')"
>
{{"Save Perspective"}}
</button>
<div
*
ngIf=
"loadingExcel"
class=
"row"
style=
"width: 120px;"
>
<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>
<button
type=
"button"
class=
"ti-btn ti-btn-danger-full text-white !font-medium"
(
click
)="
closeModalgridModal
()"
>
ปิด
</button>
</div>
</div>
</div>
</div>
</ng-template>
<!-- <ng-template #gridModals 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">×</span>
</button>
</div>
<div class="modal-body">
<app-datagrid-syncfution [searchSettings]="searchSettings" [dataSource]="dataList" [columns]="columns"
[gridLayout]="setPerspective" [sendLayout]="gridLayout.stimulate" (layout)="gridLayout.data=$event">
</app-datagrid-syncfution>
</div>
<div class="modal-footer">
<button *ngIf="!loadingExcel" type="button" class="btn btn-info"
(click)="gridLayout.stimulate=!gridLayout.stimulate;savePerspective('grid')">
{{"Save Perspective"}}
</button>
<div *ngIf="loadingExcel" class="row" style="width: 120px;">
<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>
<button type="button" class="btn btn-danger" (click)="modal.close()">
{{"ปิด"}}
</button>
</div>
</ng-template> -->
<ng-template
#
pivotModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
Pivot
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalpivotModal
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<app-pivot-syncfution
[
dataSource
]="
dataList
"
[
columns
]="
pivotColumns
"
[
templateId
]="
excelReport
.
templateId
"
[
fileName
]="
excelReport
.
fileName
"
[
pivotLayout
]="
setPerspective
"
[
sendLayout
]="
pivotLayout
.
stimulate
"
(
layout
)="
pivotLayout
.
data=
$event"
>
</app-pivot-syncfution>
</div>
<div
class=
"border-t"
>
<div
class=
"ti-modal-footer flex justify-end gap-3 mb-3 mt-3 mr-3"
>
<button
*
ngIf=
"!loadingExcel"
type=
"button"
class=
"ti-btn ti-btn-info-full"
(
click
)="
pivotLayout
.
stimulate=
!pivotLayout.stimulate;savePerspective('pivot')"
>
{{"Save Perspective"}}
</button>
<div
*
ngIf=
"loadingExcel"
class=
"row"
style=
"width: 120px;"
>
<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>
<button
type=
"button"
class=
"ti-btn ti-btn-danger-full text-white !font-medium"
(
click
)="
closeModalpivotModal
()"
>
ปิด
</button>
</div>
</div>
</div>
</div>
</ng-template>
<!-- <ng-template #pivotModals 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">×</span>
</button>
</div>
<div class="modal-body">
<app-pivot-syncfution [dataSource]="dataList" [columns]="pivotColumns" [templateId]="excelReport.templateId"
[fileName]="excelReport.fileName" [pivotLayout]="setPerspective" [sendLayout]="pivotLayout.stimulate"
(layout)="pivotLayout.data=$event">
</app-pivot-syncfution>
</div>
<div class="modal-footer">
<button *ngIf="!loadingExcel" type="button" class="btn btn-info"
(click)="pivotLayout.stimulate=!pivotLayout.stimulate;savePerspective('pivot')">
{{"Save Perspective"}}
</button>
<div *ngIf="loadingExcel" class="row" style="width: 120px;">
<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>
<button type="button" class="btn btn-danger" (click)="modal.close()">
{{"ปิด"}}
</button>
</div>
</ng-template> -->
\ No newline at end of file
src/app/DPU/myskill-x/myportal/set-excel-reports/excel-list/excel-list.component.scss
0 → 100644
View file @
73e72e5e
.ti-modal-header
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
border-bottom-width
:
1px
;
padding-top
:
0
.75rem
;
padding-bottom
:
0
.75rem
;
padding-left
:
1rem
;
padding-right
:
1rem
;
}
::ng-deep
[
ngbDatepickerDayView
]
.today
{
background-color
:
#e0f2fe
!
important
;
}
::ng-deep
[
ngbDatepickerDayView
]
.bg-primary
{
background-color
:
rgb
(
var
(
--
primary
))
!
important
;
color
:
#ffffff
!
important
;
}
/* ให้ datepicker popup ทะลุ modal ได้ */
::ng-deep
ngb-datepicker
,
::ng-deep
.ngb-datepicker-container
{
z-index
:
2000
!
important
;
}
/* เผื่อ modal มี overflow ซ่อนอยู่ */
::ng-deep
.ti-modal-content
{
overflow
:
visible
!
important
;
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/set-excel-reports/excel-list/excel-list.component.ts
0 → 100644
View file @
73e72e5e
import
{
ChangeDetectorRef
,
Component
,
ElementRef
,
OnInit
,
TemplateRef
,
ViewChild
}
from
'@angular/core'
;
import
{
ActivatedRoute
,
RouterModule
}
from
'@angular/router'
;
import
{
forkJoin
,
Subscription
}
from
'rxjs'
;
import
{
NgbDate
,
NgbDatepickerModule
,
NgbModal
,
NgbModalRef
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
ColumnModel
}
from
'@syncfusion/ej2-angular-grids'
;
import
*
as
FileSaver
from
'file-saver'
;
import
{
MyTemplateFileModel
,
MyTemplateModel
,
TemplateFileModel
,
TemplateModel
}
from
'../../../../models/template.model'
;
import
{
ModuleModel
,
MyModuleModel
}
from
'../../../../models/module.model'
;
import
{
ExcelPortalGroupModel
,
ExcelPortalModel
,
ExcelPortalTagsModel
,
MyExcelPortalGroupModel
,
MyExcelPortalModel
,
MyExcelPortalTagsModel
}
from
'../../../../models/excel-portal.model'
;
import
{
ExcelReportService
}
from
'../../../../services/excel-report.service'
;
import
{
CustomCubeService
}
from
'../../../../services/custom-cube.service'
;
import
{
AlertModalComponent
}
from
'../../../../../alert-modal/alert-modal.component'
;
import
{
ConfirmModalComponent
}
from
'../../../../../confirm-modal/confirm-modal.component'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../../shared/shared.module'
;
import
{
MatPaginator
}
from
'@angular/material/paginator'
;
import
{
QuillModule
}
from
'ngx-quill'
;
import
{
MatDialog
,
MatDialogModule
,
MatDialogRef
}
from
'@angular/material/dialog'
;
import
{
FileUploadModule
}
from
'ng2-file-upload'
;
import
{
FormsModule
,
NgModel
}
from
'@angular/forms'
;
import
{
DatagridSyncfutionComponent
}
from
'../../../../../datagrid-syncfution/datagrid-syncfution.component'
;
import
{
PivotSyncfutionComponent
}
from
"../../../../../pivot-syncfution/pivot-syncfution.component"
;
import
{
SafeUrlPipe
}
from
'../../../../../../pipe/safe-url.pipe'
;
import
Swal
from
'sweetalert2'
;
import
{
DatasourceTableModel
,
MyDatasourceTableModel
}
from
'../../../../models/datasource-table.model'
;
import
{
DatasourseTableService
}
from
'../../../../services/datasourse-table.service'
;
import
swal
from
'sweetalert'
;
export
interface
ModalDetail
{
text
:
{
cardHead
:
string
,
search
:
string
[],
tableHead
:
string
[]
}
}
interface
ValueDetailItem
{
id
:
string
;
tdesc
:
string
;
edesc
:
string
;
}
@
Component
({
standalone
:
true
,
selector
:
'app-excel-list'
,
templateUrl
:
'./excel-list.component.html'
,
styleUrls
:
[
'./excel-list.component.scss'
],
imports
:
[
CommonModule
,
SharedModule
,
TranslateModule
,
NgSelectModule
,
FormsModule
,
RouterModule
,
FileUploadModule
,
QuillModule
,
MatDialogModule
,
NgbPaginationModule
,
DatagridSyncfutionComponent
,
PivotSyncfutionComponent
,
NgbDatepickerModule
,
SafeUrlPipe
],
})
export
class
ExcelListComponent
implements
OnInit
{
template
:
{
data
:
TemplateModel
[],
filter
:
TemplateModel
[],
loading
:
boolean
}
=
{
data
:
[],
filter
:
[],
loading
:
false
}
templateFile
:
TemplateFileModel
=
new
MyTemplateFileModel
()
module
:
{
data
:
ModuleModel
[],
loading
:
boolean
}
=
{
data
:
[],
loading
:
false
}
pagedItems
:
TemplateModel
[]
=
[];
pageIndex
:
number
=
0
;
itemsPerPage
:
number
=
10
;
page
=
0
pageSize
=
10
pageModal
=
0
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
,
companyId
:
string
,
}
}
=
{
status
:
'add'
,
data
:
{
templateId
:
''
,
tname
:
''
,
ename
:
''
,
tdesc
:
''
,
edesc
:
''
,
module
:
''
,
companyId
:
''
}
}
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
:
ValueDetailItem
[]
=
[];
modalDetail
:
ModalDetail
=
{
text
:
{
cardHead
:
''
,
search
:
[],
tableHead
:
[]
}
}
keySelect
=
""
searchModal
=
""
getTemplateFileSubscription
?:
Subscription
searchSettings
=
{
fields
:
[],
operator
:
'contains'
,
ignoreCase
:
false
};
columns
:
ColumnModel
[]
=
[]
pivotColumns
:
any
[]
=
[]
dataList
:
any
[]
=
[]
gridLayout
:
{
stimulate
:
boolean
,
data
:
string
}
=
{
stimulate
:
false
,
data
:
''
}
pivotLayout
:
{
stimulate
:
boolean
,
data
:
string
}
=
{
stimulate
:
false
,
data
:
''
}
setPerspective
=
""
isSearching
=
false
;
modalRef
:
any
;
modalRefaddChild
:
any
;
modalRefexcel_portal
:
MatDialogRef
<
any
>
;
modalRefvideoModal
:
any
;
modalRefprintModal
:
any
;
modalRefmodalData
:
any
;
modalRefgridModal
:
MatDialogRef
<
any
>
;
modalRefpivotModal
:
MatDialogRef
<
any
>
;
searchText
:
string
=
''
;
itemsList
:
DatasourceTableModel
[]
=
[];
@
ViewChild
(
'addGroupModal'
)
addGroupModal
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'addChildModal'
)
addChildModal
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'excel_portalModal'
)
excel_portalModal
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'videoModal'
)
videoModal
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'printModal'
)
printModal
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'modalData'
)
modalData
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'gridModal'
)
gridModal
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'pivotModal'
)
pivotModal
!
:
TemplateRef
<
any
>
;
constructor
(
private
excelReportService
:
ExcelReportService
,
private
modalService
:
NgbModal
,
private
customCubeService
:
CustomCubeService
,
private
cdr
:
ChangeDetectorRef
,
private
modal
:
MatDialog
,
private
datasourceTable
:
DatasourseTableService
)
{
}
ngOnInit
():
void
{
this
.
getExcelList
()
this
.
getModuleList
()
this
.
getExcelPortalList
()
this
.
getExcelPortalgGroupList
()
this
.
getExcelPortalTagsList
()
this
.
getData
()
}
get
totalItems
():
number
{
return
this
.
searchText
==
''
?
this
.
template
.
data
.
length
:
this
.
template
.
filter
.
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalItems
/
this
.
itemsPerPage
);
}
get
totalPagesArray
():
number
[]
{
return
Array
(
this
.
totalPages
).
fill
(
0
);
}
goToPage
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
totalPages
)
return
;
this
.
pageIndex
=
index
;
this
.
updatePagedItems
();
}
updatePagedItems
()
{
const
data
=
this
.
searchText
==
''
?
this
.
template
.
data
:
this
.
template
.
filter
;
const
start
=
this
.
page
*
this
.
pageSize
;
// ถ้า page = 1 → เริ่มที่ index 10
const
end
=
start
+
this
.
pageSize
;
this
.
pagedItems
=
data
.
slice
(
start
,
end
);
}
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
()
{
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
})
}
getModuleList
()
{
this
.
module
.
loading
=
true
this
.
excelReportService
.
getModuleList
().
subscribe
(
response
=>
{
this
.
module
.
data
=
response
.
map
(
e
=>
new
MyModuleModel
(
e
))
this
.
module
.
loading
=
false
},
error
=>
{
this
.
module
.
loading
=
false
})
}
postTemplate
()
{
console
.
log
(
"wait for function"
)
this
.
modalRef
?.
close
()
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
},
reason
=>
{
})
}
openAddGroupModal
(
data
?:
TemplateModel
)
{
if
(
data
)
{
this
.
bodyTemplate
.
status
=
'edit'
;
this
.
bodyTemplate
.
data
=
{
templateId
:
data
.
templateId
,
tname
:
data
.
tname
,
ename
:
data
.
ename
,
tdesc
:
data
.
tdesc
,
edesc
:
data
.
edesc
,
module
:
data
.
module
,
companyId
:
data
.
companyId
};
}
else
{
this
.
bodyTemplate
.
status
=
'add'
;
this
.
bodyTemplate
.
data
=
{
templateId
:
''
,
tname
:
''
,
ename
:
''
,
tdesc
:
''
,
edesc
:
''
,
module
:
''
,
companyId
:
''
};
}
this
.
openModalAddGroup
()
}
deleteTemplate
(
template
:
TemplateModel
)
{
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
(
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
.
templateFile
.
realFileNameOld
=
this
.
templateFile
.
fileName
}
this
.
openModaladdChild
()
}
openExcelPortalModal
()
{
this
.
pageModal
=
0
;
this
.
pageSizeModal
=
5
;
this
.
modalRefexcel_portal
=
this
.
modal
.
open
(
this
.
excel_portalModal
,
{
width
:
'1500px'
,
height
:
'700px'
,
maxWidth
:
'none'
,
disableClose
:
true
,
data
:
{}
});
this
.
modalRefexcel_portal
.
afterClosed
().
subscribe
(
result
=>
{
if
(
result
?.
excelId
)
{
this
.
templateFile
.
portalId
=
result
.
excelId
;
}
});
}
openVideoModal
(
videoLink
:
string
)
{
this
.
videoLink
=
this
.
convertToEmbedUrl
(
videoLink
);
this
.
modalRefvideoModal
=
this
.
modal
.
open
(
this
.
videoModal
,
{
width
:
'50%'
,
height
:
'50%'
,
panelClass
:
'video-preview-dialog'
,
backdropClass
:
'video-backdrop'
});
}
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
()
{
this
.
isSearching
=
true
;
setTimeout
(()
=>
{
if
(
!
this
.
searchBy
||
!
this
.
condition
||
!
this
.
searchValue
)
{
this
.
template
.
filter
=
this
.
template
.
data
.
map
(
e
=>
new
MyTemplateModel
(
e
));
this
.
isSearching
=
false
;
return
;
}
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
.
isSearching
=
false
;
return
;
}
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
));
this
.
isSearching
=
false
;
},
1000
);
// delay mock loading
}
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
(
templateFile
:
TemplateFileModel
)
{
this
.
getTemplateFile
(
templateFile
)
this
.
openModalprintModal
()
}
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
this
.
getExcelColumn
()
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
)
{
this
.
searchModal
=
''
this
.
page
=
0
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
.
openModalmodalData
()
}
valueDetailFilter
():
ValueDetailItem
[]
{
const
search
=
this
.
searchModal
.
toLowerCase
();
return
this
.
valueDetail
.
filter
(
item
=>
item
.
id
.
toLowerCase
().
includes
(
search
)
||
item
.
tdesc
.
toLowerCase
().
includes
(
search
)
||
item
.
edesc
.
toLowerCase
().
includes
(
search
)
);
}
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
=
''
}
}
validateDate
(
control
:
NgModel
)
{
if
(
!
control
.
value
)
{
// ว่าง หรือวันที่ไม่ถูกต้อง
this
.
openAlertModal
(
'กรุณาเลือกวันที่ให้ถูกต้อง'
);
}
}
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
:
TemplateRef
<
any
>
,
setPerspective
:
string
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
'static'
,
windowClass
:
'my-dialog-big-screen'
})
setTimeout
(()
=>
{
this
.
setPerspective
=
setPerspective
},
10
)
}
openPivotModal
(
targetModal
:
TemplateRef
<
any
>
,
setPerspective
:
string
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
'static'
,
windowClass
:
'my-dialog-big-screen'
})
setTimeout
(()
=>
{
this
.
setPerspective
=
setPerspective
},
10
)
}
ngOnDestroy
():
void
{
this
.
getTemplateFileSubscription
?.
unsubscribe
()
}
templateFileTypeChange
()
{
if
(
this
.
templateFileName
||
this
.
templateFile
?.
portalId
)
{
Swal
.
fire
({
title
:
'ยืนยันการดำเนินการ'
,
text
:
'คุณต้องการยกเลิกไฟล์ที่เลือกหรือไม่'
,
icon
:
'warning'
,
showCancelButton
:
true
,
confirmButtonText
:
'ใช่, ยกเลิกไฟล์'
,
cancelButtonText
:
'ไม่'
,
confirmButtonColor
:
'#d33'
,
// สีปุ่มยืนยัน (แดง)
cancelButtonColor
:
'#3085d6'
,
// สีปุ่มยกเลิก (น้ำเงิน)
reverseButtons
:
true
}).
then
((
result
)
=>
{
if
(
result
.
isConfirmed
)
{
this
.
onToggleTemplateFile
();
}
});
}
else
{
this
.
onToggleTemplateFile
();
}
}
onToggleTemplateFile
()
{
if
(
this
.
templateFileType
==
'portal'
)
{
this
.
templateFileType
=
'upload'
this
.
templateFile
.
portalId
=
''
}
else
if
(
this
.
templateFileType
==
'upload'
)
{
this
.
templateFileType
=
'portal'
;
this
.
templateFile
.
fileData
=
''
;
this
.
templateFile
.
fileType
=
''
;
this
.
templateFileName
=
''
}
}
getExcelColumn
()
{
const
body
=
{
templateId
:
this
.
excelReport
.
templateId
,
fileName
:
this
.
excelReport
.
fileName
}
this
.
searchSettings
=
{
fields
:
[],
operator
:
'contains'
,
ignoreCase
:
false
};
this
.
columns
=
[]
this
.
pivotColumns
=
[]
this
.
customCubeService
.
getExcelColumn
(
body
).
subscribe
((
response
:
any
)
=>
{
this
.
searchSettings
=
{
fields
:
response
.
map
((
e
:
any
)
=>
e
.
split
(
':'
)[
0
]),
operator
:
'contains'
,
ignoreCase
:
false
};
response
.
forEach
((
e
:
any
,
i
:
number
)
=>
{
const
[
field
,
headerText
]
=
e
.
split
(
':'
)
this
.
columns
.
push
({
field
:
field
,
headerText
:
headerText
,
type
:
"string"
,
isPrimaryKey
:
i
==
0
,
})
this
.
pivotColumns
.
push
({
name
:
field
,
caption
:
headerText
})
});
},
error
=>
{
})
}
getExcelData
(
type
:
'grid'
|
'pivot'
)
{
this
.
loadingExcel
=
true
this
.
dataList
=
[]
this
.
setPerspective
=
''
const
body
:
any
=
{
templateId
:
this
.
excelReport
.
templateId
,
fileName
:
this
.
excelReport
.
fileName
};
this
.
variableSheet
.
forEach
((
item
:
any
,
index
:
number
)
=>
{
const
i
=
index
+
1
;
body
[
`key
${
i
}
`
]
=
item
.
key
;
if
(
item
.
type
==
'help'
)
{
body
[
`val
${
i
}
`
]
=
item
.
value
.
id
}
else
if
(
item
.
type
==
'calendar'
||
item
.
type
==
'list'
||
item
.
type
==
'radio'
||
item
.
type
==
'text'
)
{
body
[
`val
${
i
}
`
]
=
item
.
value
}
});
forkJoin
({
excelData
:
this
.
customCubeService
.
getExcelData
(
body
),
excelPerspective
:
this
.
customCubeService
.
getExcelPerspective
(
body
),
}).
subscribe
(
response
=>
{
this
.
dataList
=
response
.
excelData
as
any
this
.
loadingExcel
=
false
console
.
log
(
'🟢 dataList:'
,
this
.
dataList
);
// ตรวจสอบว่ามีข้อมูลไหม
console
.
log
(
'🟢 pivotStr:'
,
(
response
.
excelPerspective
as
any
).
pivotStr
);
// ตรวจสอบ layout ที่ส่งมา
console
.
log
(
'🟢 columns:'
,
this
.
pivotColumns
);
// ดูว่า columns ถูกเซ็ตหรือยัง
if
(
type
===
'grid'
)
{
this
.
modalRefgridModal
=
this
.
modal
.
open
(
this
.
gridModal
,
{
width
:
'1000px'
,
height
:
'700px'
,
data
:
{
gridData
:
(
response
.
excelPerspective
as
any
).
dataGridStr
,
dataList
:
this
.
dataList
},
disableClose
:
true
,
autoFocus
:
false
});
}
else
if
(
type
===
'pivot'
)
{
this
.
modalRefpivotModal
=
this
.
modal
.
open
(
this
.
pivotModal
,
{
width
:
'1000px'
,
height
:
'580px'
,
data
:
{
pivotData
:
(
response
.
excelPerspective
as
any
).
pivotStr
,
dataList
:
this
.
dataList
},
disableClose
:
true
,
autoFocus
:
false
});
}
this
.
cdr
.
detectChanges
()
},
error
=>
{
this
.
loadingExcel
=
false
})
}
savePerspective
(
type
:
'grid'
|
'pivot'
)
{
if
(
type
==
'grid'
)
{
this
.
loadingExcel
=
true
setTimeout
(()
=>
{
const
body
=
{
templateId
:
this
.
excelReport
.
templateId
,
fileName
:
this
.
excelReport
.
fileName
,
dataGridStr
:
this
.
gridLayout
.
data
,
pivotStr
:
""
,
}
this
.
customCubeService
.
saveExcelPerspective
(
body
).
subscribe
(
response
=>
{
this
.
loadingExcel
=
false
this
.
openAlertModal
(
response
.
message
)
},
error
=>
{
this
.
loadingExcel
=
false
this
.
openAlertModal
(
error
.
message
)
})
this
.
cdr
.
detectChanges
();
},
500
);
}
else
if
(
type
==
'pivot'
)
{
this
.
loadingExcel
=
true
setTimeout
(()
=>
{
const
body
=
{
templateId
:
this
.
excelReport
.
templateId
,
fileName
:
this
.
excelReport
.
fileName
,
dataGridStr
:
''
,
pivotStr
:
this
.
pivotLayout
.
data
,
}
this
.
customCubeService
.
saveExcelPerspective
(
body
).
subscribe
(
response
=>
{
this
.
loadingExcel
=
false
this
.
openAlertModal
(
response
.
message
)
},
error
=>
{
this
.
loadingExcel
=
false
this
.
openAlertModal
(
error
.
message
)
})
this
.
cdr
.
detectChanges
();
},
500
);
}
}
openModalAddGroup
()
{
this
.
modalRef
=
this
.
modal
.
open
(
this
.
addGroupModal
,
{
width
:
'1000px'
,
height
:
'500px'
})
}
closeModalAddGroup
()
{
this
.
modalRef
?.
close
()
}
openModaladdChild
()
{
this
.
modalRefaddChild
=
this
.
modal
.
open
(
this
.
addChildModal
,
{
width
:
'700px'
,
height
:
'500px'
})
}
closeModaladdChild
()
{
this
.
modalRefaddChild
?.
close
()
}
openModalexcel_portal
()
{
this
.
modalRefexcel_portal
=
this
.
modal
.
open
(
this
.
excel_portalModal
,
{
width
:
'1500px'
,
height
:
'700px'
})
}
closeModalexcel_portal
()
{
this
.
modalRefexcel_portal
?.
close
()
}
openModalvideoModal
()
{
this
.
modalRefvideoModal
=
this
.
modal
.
open
(
this
.
videoModal
,
{
width
:
'1500px'
,
height
:
'700px'
})
}
closeModalvideoModal
()
{
this
.
modalRefvideoModal
?.
close
()
}
openModalprintModal
()
{
this
.
modalRefprintModal
=
this
.
modal
.
open
(
this
.
printModal
,
{
width
:
'700px'
,
height
:
'300px'
})
}
closeModalprintModal
()
{
this
.
modalRefprintModal
?.
close
()
}
openModalmodalData
()
{
this
.
modalRefmodalData
=
this
.
modal
.
open
(
this
.
modalData
,
{
width
:
'800px'
,
height
:
'580px'
})
}
closeModalmodalData
()
{
this
.
modalRefmodalData
?.
close
()
}
closeModalgridModal
()
{
this
.
modalRefgridModal
?.
close
()
}
closeModalpivotModal
()
{
this
.
modalRefpivotModal
?.
close
()
}
getData
()
{
this
.
datasourceTable
.
getList
().
subscribe
({
next
:
(
response
:
DatasourceTableModel
[])
=>
{
this
.
itemsList
=
response
.
map
((
x
:
any
)
=>
new
MyDatasourceTableModel
(
x
));
console
.
log
(
'ข้อมูล (itemsList)'
,
this
.
itemsList
);
this
.
updatePagedItems
();
},
error
:
(
error
)
=>
{
console
.
error
(
'error cant get position'
,
error
);
swal
(
"ข้อผิดพลาด"
,
"ไม่สามารถดึงข้อมูลได้"
,
"error"
);
}
});
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/set-excel-reports/excel-report-toggle/excel-report-toggle.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'เปิด
-
ปิด
การใช้รายงาน
Excel
'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'เปิด
-
ปิด
การใช้รายงาน
Excel
'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายการเอกสาร
</div>
<div
class=
"flex flex-wrap gap-4"
>
<!-- Search By -->
<div
class=
"d-flex flex-column"
style=
"min-width: 200px;"
>
<label
class=
"mb-1 font-medium text-sm"
>
Search By
</label>
<select
class=
"form-control h-100"
[(
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>
<!-- Condition -->
<div
class=
"d-flex flex-column"
style=
"min-width: 200px;"
>
<label
class=
"mb-1 font-medium text-sm"
>
Condition
</label>
<select
class=
"form-control h-100"
[(
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>
<!-- Key Value -->
<div
class=
"d-flex flex-column"
style=
"min-width: 200px;"
>
<label
class=
"mb-1 font-medium text-sm"
>
Key Value
</label>
<input
class=
"form-control h-100"
type=
"text"
placeholder=
"ค้นหา"
aria-label=
".form-control-sm example"
[(
ngModel
)]="
searchValue
"
>
</div>
<!-- Buttons -->
<div
class=
"flex items-end gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full"
style=
"margin-bottom: unset;"
(
click
)="
openTemplate
.
clear
();
templateListSearch
()"
>
<i
class=
"ri-search-line font-semibold align-middle"
></i>
ค้นหา
</a>
<!-- <a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-success-full"
style="margin-bottom: unset;" (click)="openAddGroupModal()">
<i class="ri-add-line font-semibold align-middle"></i>Add Group
</a> -->
</div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover "
>
<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
id=
"tableBody"
*
ngIf=
"isSearching || template.filter.length"
>
<tr
*
ngIf=
"isSearching"
>
<td
colspan=
"7"
class=
"loading"
>
<div
class=
"spinner"
></div>
<div
class=
"spinner"
></div>
<div
class=
"spinner"
></div>
<span>
กำลังค้นหา...
</span>
</td>
</tr>
<ng-container
*
ngIf=
"!isSearching"
>
<ng-container
*
ngFor=
"let items of template.filter | slice: page * pageSize : (page+1) * 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}}
<span
*
ngIf=
"items.tdesc"
>
-{{items.tdesc}}
</span>
</td>
<td
class=
"text-center"
>
<ng-container
*
ngIf=
"items.templateFile.length"
>
<ng-container
*
ngIf=
"!openTemplate.get(items.templateId)"
>
<button
type=
"button"
title=
"เปิด"
(
click
)="
openTemplate
.
set
(
items
.
templateId
,
true
)"
(
mouseenter
)="
buttonHover
.
set
(
items
.
templateId
+'
open
',!
buttonHover
.
get
(
items
.
templateId
))"
(
mouseleave
)="
buttonHover
.
clear
()"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
>
<i
class=
"ri-arrow-right-line"
></i>
</button>
</ng-container>
<ng-container
*
ngIf=
"openTemplate.get(items.templateId)"
>
<button
type=
"button"
title=
"ปิด"
(
click
)="
openTemplate
.
set
(
items
.
templateId
,
false
)"
(
mouseenter
)="
buttonHover
.
set
(
items
.
templateId
+'
close
',!
buttonHover
.
get
(
items
.
templateId
))"
(
mouseleave
)="
buttonHover
.
clear
()"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
>
<i
class=
"ri-arrow-down-line"
></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 * pageSize : (page+1) * 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"
>
<i
*
ngIf=
"item.menuActive=='0'"
class=
"fa fa-times text-danger cursor-pointer"
style=
"text-decoration: underline; font-size: medium;"
(
click
)="
menuActiveTemplateFile
(
item
)"
></i>
<i
*
ngIf=
"item.menuActive=='1'"
class=
"fa fa-check text-success cursor-pointer"
style=
"text-decoration: underline; font-size: medium;"
(
click
)="
menuActiveTemplateFile
(
item
)"
></i>
<a
aria-label=
"anchor"
title=
"Print"
(
mouseenter
)="
buttonHover
.
set
(
item
.
fileName
+'
print
',!
buttonHover
.
get
(
item
.
fileName
))"
(
mouseleave
)="
buttonHover
.
clear
()"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-warning/10 text-warning hover:bg-warning hover:text-white hover:border-warning"
(
click
)="
openPrintModal
(
item
);"
>
<i
class=
"ri-printer-line"
></i></a>
</td>
</tr>
</ng-container>
</ng-container>
</ng-container>
</ng-container>
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"template.filter.length > 0"
>
<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
)]="
pageSize
"
(
ngModelChange
)="
page
"
>
<option
*
ngFor=
"let item of [10,50,100]"
[
ngValue
]="
item
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{template.filter.length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"page > 0"
class=
"page-item {{page==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{'Previous' | translate}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"page > 0"
(
click
)="
page =
page
-
1
;
updatePagedItems
()"
>
{{page}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{page + 1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 1) * pageSize < template.filter.length"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{page + 2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(page + 2) * pageSize < template.filter.length"
(
click
)="
page =
page
+
2
;
updatePagedItems
()"
>
{{page + 3}}
</a></li>
<li
*
ngIf=
"(page + 1) * pageSize < template.filter.length"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
page =
page
+
1
;
updatePagedItems
()"
>
{{'Next' | translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
<div
class=
"flex justify-end items-center flex-wrap gap-4 mt-3"
>
<div><i
class=
"fa fa-times text-danger"
></i>
= used on menu
</div>
<div><i
class=
"fa fa-check text-success"
></i>
= unused on menu
</div>
<!-- <div><i class="ri-file-download-line text-info"></i> = download files</div> -->
<div><i
class=
"ri-printer-line text-warning"
></i>
= print report
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template
#
printModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
Excel Report
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalprintModal
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<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=
"flex items-center mb-4"
>
<!-- Label -->
<label
class=
"w-1/4 text-right pr-4 font-semibold text-sm"
>
{{ item.label }}
</label>
<!-- Input -->
<div
class=
"w-3/4"
>
<ng-container
[
ngSwitch
]="
item
.
type
"
>
<!-- Text -->
<input
*
ngSwitchCase=
"'text'"
type=
"text"
class=
"form-input w-full"
[(
ngModel
)]="
item
.
value
"
/>
<!-- List -->
<select
*
ngSwitchCase=
"'list'"
class=
"form-select w-full"
[(
ngModel
)]="
item
.
value
"
>
<option
*
ngFor=
"let list of item.option"
[
value
]="
list
.
value
"
>
{{ list.text }}
</option>
</select>
<!-- Radio -->
<div
*
ngSwitchCase=
"'radio'"
class=
"flex flex-wrap gap-4"
>
<label
*
ngFor=
"let radioItem of item.option"
class=
"inline-flex items-center"
>
<input
type=
"radio"
class=
"form-radio mr-2"
[
name
]="'
group-
'
+
item
.
label
"
[
id
]="
radioItem
.
text
+
radioItem
.
value
"
[
value
]="
radioItem
.
value
"
[(
ngModel
)]="
item
.
value
"
/>
{{ radioItem.text }}
</label>
</div>
<!-- Help -->
<div
*
ngSwitchCase=
"'help'"
class=
"flex items-stretch"
>
<input
type=
"text"
readonly
class=
"form-input w-1/2 bg-white cursor-pointer"
[
value
]="
item
.
value
.
tdesc
"
(
click
)="
openModalData
(
item
)"
/>
<button
class=
"bg-primary hover:bg-primary text-white px-3 flex items-center justify-center rounded-none border"
type=
"button"
(
click
)="
openModalData
(
item
)"
>
<i
class=
"ri-search-line font-semibold align-middle"
></i>
</button>
<button
type=
"button"
class=
"bg-red hover:bg-red text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
item
.
value=
{id:'',tdesc:'',edesc:''}"
>
<i
class=
"fa fa-times text-xs"
></i>
</button>
</div>
<!-- Calendar -->
<div
*
ngSwitchCase=
"'calendar'"
class=
"flex items-stretch"
>
<!-- Input -->
<input
class=
"form-input w-1/2 bg-white cursor-pointer rounded-r-none"
style=
"border-color: #e9edf6;"
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
)"
container=
"body"
>
<!-- Calendar Button -->
<button
type=
"button"
class=
"bg-white hover:bg-primary text-primary hover:text-white px-3 flex items-center justify-center rounded-none border"
style=
"border-color: #154c9c;"
(
click
)="
d1
.
toggle
()"
>
<i
class=
"ri-calendar-2-line"
></i>
</button>
<!-- Clear Button -->
<button
type=
"button"
class=
"bg-red hover:bg-red text-white text-sm ml-5 w-10 h-10 flex items-center justify-center rounded-full"
(
click
)="
select
[
item
.
key
]=
null
;
formatNgbDate
(
item
.
key
)"
>
<i
class=
"fa fa-times text-xs"
></i>
</button>
</div>
</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
class=
"row col-12 flex justify-center"
*
ngIf=
"variableSheet.length&&(excelReport.isDataGrid=='1'||excelReport.isPivot=='1')"
>
<div
class=
"col-12 d-flex justify-content-center align-content-center"
>
<button
type=
"button"
*
ngIf=
"excelReport.isDataGrid=='1'"
class=
"ti-btn ti-btn-primary-full"
(
click
)="
getExcelData
('
grid
')"
>
Datagrid
</button>
<ng-container
*
ngIf=
"excelReport.isDataGrid=='1'&&excelReport.isPivot=='1'"
>
</ng-container>
<button
type=
"button"
*
ngIf=
"excelReport.isPivot=='1'"
class=
"ti-btn ti-btn-primary-full"
(
click
)="
getExcelData
('
pivot
')"
>
Pivot
</button>
</div>
</div>
</ng-container>
</div>
</div>
<div
class=
"border-t mt-3"
>
<div
class=
"ti-modal-footer flex justify-end gap-1 mb-3 mt-3 mr-3"
>
<ng-container
*
ngIf=
"variableSheet.length"
>
<button
type=
"submit"
class=
"ti-btn ti-btn-info-full waves-effect waves-light btn-w-100"
[
disabled
]="
loadingExcel
"
(
click
)="
dowloadExcelReport
()"
>
{{"Print" }}
</button>
</ng-container>
<button
type=
"button"
class=
"ti-btn bg-danger text-white !font-medium"
(
click
)="
closeModalprintModal
()"
>
ปิด
</button>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template
#
modalData
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
{{modalDetail.text.cardHead }}
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalmodalData
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<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 "
style=
"width: 100%"
>
<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 * pageSizeModal : (pageModal+1) * pageSizeModal; let i=index"
(
click
)="
selectData
(
item
);
closeModalmodalData
()"
(
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>
<div
class=
"box-footer !border-t-0"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"valueDetailFilter().length > 0"
>
<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
"
>
{{"รายการต่อหน้า"}}: {{item}}
</option>
</select>
</div>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{valueDetailFilter().length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"pageModal>0"
class=
"page-item {{pageModal==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
pageModal =
pageModal-1;updatePagedItems()"
>
{{'Previous' |
translate}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageModal-1>0"
(
click
)="
pageModal =
pageModal-2;updatePagedItems()"
>
{{pageModal-1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageModal>0 && ((pageModal-1)*10 < (searchText == '' ? valueDetailFilter().length : valueDetailFilter().length))"
(
click
)="
pageModal =
pageModal-1;updatePagedItems()"
>
{{pageModal}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{pageModal +1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageModal+1)*10 < (searchText == '' ? valueDetailFilter().length : valueDetailFilter().length)"
(
click
)="
pageModal =
pageModal+1;updatePagedItems()"
>
{{pageModal +2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageModal+2)*10 < (searchText == '' ? valueDetailFilter().length : valueDetailFilter().length)"
(
click
)="
pageModal =
pageModal+2;updatePagedItems()"
>
{{pageModal +3}}
</a></li>
<li
*
ngIf=
"(pageModal+1)*10 < (searchText == '' ? valueDetailFilter().length : valueDetailFilter().length)"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem] cursor-pointer"
(
click
)="
pageModal =
pageModal+1;updatePagedItems()"
>
{{'Next' |
translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div
class=
"border-t"
>
<div
class=
"ti-modal-footer flex justify-end gap-3 mb-3 mt-3 mr-3"
>
<button
type=
"button"
class=
"ti-btn bg-danger text-white !font-medium"
(
click
)="
closeModalmodalData
()"
>
ปิด
</button>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template
#
gridModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
GridData
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalgridModal
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<app-datagrid-syncfution
[
searchSettings
]="
searchSettings
"
[
dataSource
]="
dataList
"
[
columns
]="
columns
"
[
gridLayout
]="
setPerspective
"
[
sendLayout
]="
gridLayout
.
stimulate
"
(
layout
)="
gridLayout
.
data=
$event"
>
</app-datagrid-syncfution>
</div>
<div
class=
"border-t"
>
<div
class=
"ti-modal-footer flex justify-end gap-3 mb-3 mt-3 mr-3"
>
<button
*
ngIf=
"!loadingExcel"
type=
"button"
class=
"ti-btn ti-btn-info-full"
(
click
)="
gridLayout
.
stimulate=
!gridLayout.stimulate;savePerspective('grid')"
>
{{"Save Perspective"}}
</button>
<div
*
ngIf=
"loadingExcel"
class=
"row"
style=
"width: 120px;"
>
<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>
<button
type=
"button"
class=
"ti-btn ti-btn-danger-full text-white !font-medium"
(
click
)="
closeModalgridModal
()"
>
ปิด
</button>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template
#
pivotModal
let-modal
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header flex justify-between items-center p-5"
>
<h6
class=
"ti-modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
Pivot
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(
click
)="
closeModalpivotModal
()"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4 mt-3"
>
<app-pivot-syncfution
[
dataSource
]="
dataList
"
[
columns
]="
pivotColumns
"
[
templateId
]="
excelReport
.
templateId
"
[
fileName
]="
excelReport
.
fileName
"
[
pivotLayout
]="
setPerspective
"
[
sendLayout
]="
pivotLayout
.
stimulate
"
(
layout
)="
pivotLayout
.
data=
$event"
>
</app-pivot-syncfution>
</div>
<div
class=
"border-t mt-3"
>
<div
class=
"ti-modal-footer flex justify-end gap-3 mb-3 mt-3 mr-3"
>
<button
*
ngIf=
"!loadingExcel"
type=
"button"
class=
"ti-btn ti-btn-info-full"
(
click
)="
pivotLayout
.
stimulate=
!pivotLayout.stimulate;savePerspective('pivot')"
>
{{"Save Perspective"}}
</button>
<div
*
ngIf=
"loadingExcel"
class=
"row"
style=
"width: 120px;"
>
<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>
<button
type=
"button"
class=
"ti-btn ti-btn-danger-full text-white !font-medium"
(
click
)="
closeModalpivotModal
()"
>
ปิด
</button>
</div>
</div>
</div>
</div>
</ng-template>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/set-excel-reports/excel-report-toggle/excel-report-toggle.component.scss
0 → 100644
View file @
73e72e5e
.ti-modal-header
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
border-bottom-width
:
1px
;
padding-top
:
0
.75rem
;
padding-bottom
:
0
.75rem
;
padding-left
:
1rem
;
padding-right
:
1rem
;
}
::ng-deep
[
ngbDatepickerDayView
]
.today
{
background-color
:
#e0f2fe
!
important
;
}
::ng-deep
[
ngbDatepickerDayView
]
.bg-primary
{
background-color
:
rgb
(
var
(
--
primary
))
!
important
;
color
:
#ffffff
!
important
;
}
/* ให้ datepicker popup ทะลุ modal ได้ */
::ng-deep
ngb-datepicker
,
::ng-deep
.ngb-datepicker-container
{
z-index
:
2000
!
important
;
}
/* เผื่อ modal มี overflow ซ่อนอยู่ */
::ng-deep
.ti-modal-content
{
overflow
:
visible
!
important
;
}
src/app/DPU/myskill-x/myportal/set-excel-reports/excel-report-toggle/excel-report-toggle.component.ts
0 → 100644
View file @
73e72e5e
import
{
ChangeDetectorRef
,
Component
,
OnInit
,
TemplateRef
,
ViewChild
}
from
'@angular/core'
;
import
{
ActivatedRoute
,
RouterModule
}
from
'@angular/router'
;
import
{
NgbDate
,
NgbDatepickerModule
,
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
*
as
FileSaver
from
'file-saver'
;
import
{
IDataOptions
}
from
'@syncfusion/ej2-angular-pivotview'
;
import
{
forkJoin
,
Subscription
}
from
'rxjs'
;
import
{
ColumnModel
}
from
'@syncfusion/ej2-grids'
;
import
{
MyTemplateFileModel
,
MyTemplateModel
,
TemplateFileModel
,
TemplateModel
}
from
'../../../../models/template.model'
;
import
{
ModuleModel
}
from
'../../../../models/module.model'
;
import
{
ExcelReportService
}
from
'../../../../services/excel-report.service'
;
import
{
CustomCubeService
}
from
'../../../../services/custom-cube.service'
;
import
{
ConfirmModalComponent
}
from
'../../../../../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../../../../../alert-modal/alert-modal.component'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
SharedModule
}
from
'../../../../../shared/shared.module'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
FormsModule
,
NgModel
}
from
'@angular/forms'
;
import
{
FileUploadModule
}
from
'ng2-file-upload'
;
import
{
QuillModule
}
from
'ngx-quill'
;
import
{
MatDialog
,
MatDialogModule
,
MatDialogRef
}
from
'@angular/material/dialog'
;
import
{
DatagridSyncfutionComponent
}
from
'../../../../../datagrid-syncfution/datagrid-syncfution.component'
;
import
{
PivotSyncfutionComponent
}
from
'../../../../../pivot-syncfution/pivot-syncfution.component'
;
import
{
SafeUrlPipe
}
from
'../../../../../../pipe/safe-url.pipe'
;
export
interface
ModalDetail
{
text
:
{
cardHead
:
string
,
search
:
string
[],
tableHead
:
string
[]
}
}
interface
ValueDetailItem
{
id
:
string
;
tdesc
:
string
;
edesc
:
string
;
}
@
Component
({
standalone
:
true
,
imports
:
[
CommonModule
,
SharedModule
,
TranslateModule
,
NgSelectModule
,
FormsModule
,
RouterModule
,
FileUploadModule
,
QuillModule
,
MatDialogModule
,
NgbPaginationModule
,
DatagridSyncfutionComponent
,
PivotSyncfutionComponent
,
NgbDatepickerModule
],
selector
:
'app-excel-report-toggle'
,
templateUrl
:
'./excel-report-toggle.component.html'
,
styleUrls
:
[
'./excel-report-toggle.component.scss'
]
})
export
class
ExcelReportToggleComponent
implements
OnInit
{
template
:
{
data
:
TemplateModel
[],
filter
:
TemplateModel
[],
loading
:
boolean
}
=
{
data
:
[],
filter
:
[],
loading
:
false
}
templateFile
:
TemplateFileModel
=
new
MyTemplateFileModel
()
module
:
{
data
:
ModuleModel
[],
loading
:
boolean
}
=
{
data
:
[],
loading
:
false
}
pagedItems
:
TemplateModel
[]
=
[];
pageIndex
:
number
=
0
;
itemsPerPage
:
number
=
10
;
page
=
0
pageSize
=
10
pageModal
=
0
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
:
ValueDetailItem
[]
=
[];
modalDetail
:
ModalDetail
=
{
text
:
{
cardHead
:
''
,
search
:
[],
tableHead
:
[]
}
}
keySelect
=
""
searchModal
=
""
getTemplateFileSubscription
?:
Subscription
searchSettings
=
{
fields
:
[],
operator
:
'contains'
,
ignoreCase
:
false
};
columns
:
ColumnModel
[]
=
[]
pivotColumns
:
any
[]
=
[]
dataList
:
any
[]
=
[]
gridLayout
:
{
stimulate
:
boolean
,
data
:
string
}
=
{
stimulate
:
false
,
data
:
''
}
pivotLayout
:
{
stimulate
:
boolean
,
data
:
string
}
=
{
stimulate
:
false
,
data
:
''
}
setPerspective
=
''
isSearching
=
false
;
modalRefprintModal
:
any
;
modalRefmodalData
:
any
;
modalRefgridModal
:
MatDialogRef
<
any
>
;
modalRefpivotModal
:
MatDialogRef
<
any
>
;
searchText
:
string
=
''
;
@
ViewChild
(
'printModal'
)
printModal
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'modalData'
)
modalData
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'gridModal'
)
gridModal
!
:
TemplateRef
<
any
>
;
@
ViewChild
(
'pivotModal'
)
pivotModal
!
:
TemplateRef
<
any
>
;
constructor
(
private
excelReportService
:
ExcelReportService
,
private
modalService
:
NgbModal
,
private
customCubeService
:
CustomCubeService
,
private
cdr
:
ChangeDetectorRef
,
private
modal
:
MatDialog
)
{
}
ngOnInit
():
void
{
this
.
getExcelList
()
}
get
totalItems
():
number
{
return
this
.
searchText
==
''
?
this
.
template
.
data
.
length
:
this
.
template
.
filter
.
length
;
}
get
totalPages
():
number
{
return
Math
.
ceil
(
this
.
totalItems
/
this
.
itemsPerPage
);
}
get
totalPagesArray
():
number
[]
{
return
Array
(
this
.
totalPages
).
fill
(
0
);
}
goToPage
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
totalPages
)
return
;
this
.
pageIndex
=
index
;
this
.
updatePagedItems
();
}
updatePagedItems
()
{
const
data
=
this
.
searchText
==
''
?
this
.
template
.
data
:
this
.
template
.
filter
;
const
start
=
this
.
page
*
this
.
pageSize
;
// ถ้า page = 1 → เริ่มที่ index 10
const
end
=
start
+
this
.
pageSize
;
this
.
pagedItems
=
data
.
slice
(
start
,
end
);
}
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
()
{
this
.
isSearching
=
true
;
setTimeout
(()
=>
{
if
(
!
this
.
searchBy
||
!
this
.
condition
||
!
this
.
searchValue
)
{
this
.
template
.
filter
=
this
.
template
.
data
.
map
(
e
=>
new
MyTemplateModel
(
e
));
this
.
isSearching
=
false
;
return
;
}
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
.
isSearching
=
false
;
return
;
}
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
));
this
.
isSearching
=
false
;
},
1000
);
// delay mock loading
}
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
(
templateFile
:
TemplateFileModel
)
{
this
.
getTemplateFile
(
templateFile
)
this
.
openModalprintModal
()
}
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
this
.
getExcelColumn
()
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
)
{
this
.
searchModal
=
''
this
.
page
=
0
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
.
openModalmodalData
()
}
valueDetailFilter
():
ValueDetailItem
[]
{
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
=
''
}
}
validateDate
(
control
:
NgModel
)
{
if
(
!
control
.
value
)
{
// ว่าง หรือวันที่ไม่ถูกต้อง
this
.
openAlertModal
(
'กรุณาเลือกวันที่ให้ถูกต้อง'
);
}
}
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
,
setPerspective
:
string
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
'static'
,
windowClass
:
'my-dialog-big-screen'
})
setTimeout
(()
=>
{
this
.
setPerspective
=
setPerspective
},
10
)
}
openPivotModal
(
targetModal
:
NgbModal
,
setPerspective
:
string
)
{
this
.
modalService
.
open
(
targetModal
,
{
centered
:
true
,
backdrop
:
'static'
,
windowClass
:
'my-dialog-big-screen'
})
setTimeout
(()
=>
{
this
.
setPerspective
=
setPerspective
},
10
)
}
ngOnDestroy
():
void
{
this
.
getTemplateFileSubscription
?.
unsubscribe
()
}
getExcelColumn
()
{
const
body
=
{
templateId
:
this
.
excelReport
.
templateId
,
fileName
:
this
.
excelReport
.
fileName
}
this
.
searchSettings
=
{
fields
:
[],
operator
:
'contains'
,
ignoreCase
:
false
};
this
.
columns
=
[]
this
.
pivotColumns
=
[]
this
.
customCubeService
.
getExcelColumn
(
body
).
subscribe
((
response
:
any
)
=>
{
this
.
searchSettings
=
{
fields
:
response
.
map
((
e
:
any
)
=>
e
.
split
(
':'
)[
0
]),
operator
:
'contains'
,
ignoreCase
:
false
};
response
.
forEach
((
e
:
any
,
i
:
number
)
=>
{
const
[
field
,
headerText
]
=
e
.
split
(
':'
)
this
.
columns
.
push
({
field
:
field
,
headerText
:
headerText
,
type
:
"string"
,
isPrimaryKey
:
i
==
0
,
})
this
.
pivotColumns
.
push
({
name
:
field
,
caption
:
headerText
})
});
},
error
=>
{
})
}
getExcelData
(
type
:
'grid'
|
'pivot'
)
{
this
.
loadingExcel
=
true
this
.
dataList
=
[]
const
body
:
any
=
{
templateId
:
this
.
excelReport
.
templateId
,
fileName
:
this
.
excelReport
.
fileName
};
this
.
variableSheet
.
forEach
((
item
:
any
,
index
:
number
)
=>
{
const
i
=
index
+
1
;
body
[
`key
${
i
}
`
]
=
item
.
key
;
if
(
item
.
type
==
'help'
)
{
body
[
`val
${
i
}
`
]
=
item
.
value
.
id
}
else
if
(
item
.
type
==
'calendar'
||
item
.
type
==
'list'
||
item
.
type
==
'radio'
||
item
.
type
==
'text'
)
{
body
[
`val
${
i
}
`
]
=
item
.
value
}
});
forkJoin
({
excelData
:
this
.
customCubeService
.
getExcelData
(
body
),
excelPerspective
:
this
.
customCubeService
.
getExcelPerspective
(
body
),
}).
subscribe
(
response
=>
{
this
.
dataList
=
response
.
excelData
as
any
this
.
loadingExcel
=
false
if
(
type
==
'grid'
)
{
this
.
modalRefgridModal
=
this
.
modal
.
open
(
this
.
gridModal
,
{
width
:
'1000px'
,
height
:
'700px'
,
data
:
{
gridData
:
(
response
.
excelPerspective
as
any
).
dataGridStr
,
dataList
:
this
.
dataList
},
disableClose
:
true
,
autoFocus
:
false
});
}
else
if
(
type
==
'pivot'
)
{
this
.
modalRefpivotModal
=
this
.
modal
.
open
(
this
.
pivotModal
,
{
width
:
'1000px'
,
height
:
'580px'
,
data
:
{
pivotData
:
(
response
.
excelPerspective
as
any
).
pivotStr
,
dataList
:
this
.
dataList
},
disableClose
:
true
,
autoFocus
:
false
});
}
this
.
cdr
.
detectChanges
()
},
error
=>
{
this
.
loadingExcel
=
false
})
}
savePerspective
(
type
:
'grid'
|
'pivot'
)
{
if
(
type
==
'grid'
)
{
this
.
loadingExcel
=
true
setTimeout
(()
=>
{
const
body
=
{
templateId
:
this
.
excelReport
.
templateId
,
fileName
:
this
.
excelReport
.
fileName
,
dataGridStr
:
this
.
gridLayout
.
data
,
pivotStr
:
""
,
}
this
.
customCubeService
.
saveExcelPerspective
(
body
).
subscribe
(
response
=>
{
this
.
loadingExcel
=
false
this
.
openAlertModal
(
response
.
message
)
},
error
=>
{
this
.
loadingExcel
=
false
this
.
openAlertModal
(
error
.
message
)
})
this
.
cdr
.
detectChanges
();
},
500
);
}
else
if
(
type
==
'pivot'
)
{
this
.
loadingExcel
=
true
setTimeout
(()
=>
{
const
body
=
{
templateId
:
this
.
excelReport
.
templateId
,
fileName
:
this
.
excelReport
.
fileName
,
dataGridStr
:
''
,
pivotStr
:
this
.
pivotLayout
.
data
,
}
this
.
customCubeService
.
saveExcelPerspective
(
body
).
subscribe
(
response
=>
{
this
.
loadingExcel
=
false
this
.
openAlertModal
(
response
.
message
)
},
error
=>
{
this
.
loadingExcel
=
false
this
.
openAlertModal
(
error
.
message
)
})
this
.
cdr
.
detectChanges
();
},
500
);
}
}
openModalprintModal
()
{
this
.
modalRefprintModal
=
this
.
modal
.
open
(
this
.
printModal
,
{
width
:
'700px'
,
height
:
'300px'
})
}
closeModalprintModal
()
{
this
.
modalRefprintModal
?.
close
()
}
openModalmodalData
()
{
this
.
modalRefmodalData
=
this
.
modal
.
open
(
this
.
modalData
,
{
width
:
'800px'
,
height
:
'580px'
})
}
closeModalmodalData
()
{
this
.
modalRefmodalData
?.
close
()
}
closeModalgridModal
()
{
this
.
modalRefgridModal
?.
close
()
}
closeModalpivotModal
()
{
this
.
modalRefpivotModal
?.
close
()
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/set-excel-reports/set-excel-reports.component.css
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/set-excel-reports/set-excel-reports.component.html
0 → 100644
View file @
73e72e5e
<p>
set-excel-reports works!
</p>
src/app/DPU/myskill-x/myportal/set-excel-reports/set-excel-reports.component.spec.ts
0 → 100644
View file @
73e72e5e
/* tslint:disable:no-unused-variable */
import
{
async
,
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
By
}
from
'@angular/platform-browser'
;
import
{
DebugElement
}
from
'@angular/core'
;
import
{
SetExcelReportsComponent
}
from
'./set-excel-reports.component'
;
describe
(
'SetExcelReportsComponent'
,
()
=>
{
let
component
:
SetExcelReportsComponent
;
let
fixture
:
ComponentFixture
<
SetExcelReportsComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
SetExcelReportsComponent
]
})
.
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
SetExcelReportsComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/DPU/myskill-x/myportal/set-excel-reports/set-excel-reports.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
@
Component
({
selector
:
'app-set-excel-reports'
,
templateUrl
:
'./set-excel-reports.component.html'
,
styleUrls
:
[
'./set-excel-reports.component.css'
]
})
export
class
SetExcelReportsComponent
implements
OnInit
{
constructor
()
{
}
ngOnInit
()
{
}
}
src/app/DPU/myskill-x/myportal/view-list-course/view-list-course.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการหลักสูตร'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการหลักสูตร'"
></app-page-header>
<!-- <div class="row" *ngIf="checkType == '1'">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการหลักสูตร</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search" >
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col">ประเภทหลักสูตร</th>
<th scope="col">ลิงค์</th>
<th scope="col">สถานะ</th>
<th scope="col" class="text-center">วันที่อัพโหลด</th>
<th scope="col" class="text-center">วันล่าสุดดาวน์โหลด</th>
<th scope="col" class="text-center">จำนวนดาวน์โหลด</th>
<th scope="col" *ngIf="checkType == '1'"></th>
</tr>
</thead>
<tbody>
<tr *ngIf="listCourse.length == 0">
<td colspan="{{checkType == '1' ? '9' : '8'}}" class="text-center">ไม่พบข้อมูล</td>
</tr>
<tr *ngFor="let data of filterListCourse() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}" (click)="openDialog(data.getImage())"></td>
<td>{{ data.thName }}</td>
<td class="text-wrap">{{ data.thDesc }}</td>
<td>{{data.courseType}}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.courseId)"></i></td>
<td class="text-center">{{data.uploadDate}} {{data.uploadTime}}</td>
<td class="text-center">{{data.downloadDate}} {{data.downloadTime}}</td>
<td class="text-center">{{data.dwTime}} ครั้ง</td>
<td *ngIf="checkType == '1'">
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2" (click)="deleteFile(data)" placement="top" ngbTooltip="ลบ"><i class="fas fa-trash-alt"></i></button>
</td>
</tr>
</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]="listCourse.length" [maxSize]="3" [rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div> -->
<!-- <div class="row" *ngIf="checkType != '1'">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListCourse()">
<div class="card border-5 border border-course h-100 shadow">
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}" (click)="openDialog(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.thName }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.courseId)"><i class="fas fa-download mr-1"></i>
ดาวน์โหลด <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}}
{{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i>
ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5">
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div
class=
"box p-4"
>
<div
*
ngIf=
"checkType != '1'"
class=
"flex flex-wrap -mx-2"
>
<div
class=
"w-full"
>
<div
class=
"py-3 px-2"
>
<input
type=
"text"
class=
"block w-full md:w-1/4 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 shadow-sm"
placeholder=
"ค้นหา"
[(
ngModel
)]="
search
"
/>
</div>
</div>
<div
class=
"w-full sm:w-1/2 lg:w-1/3 xl:w-1/3 px-2 mb-4"
*
ngFor=
"let data of filterListCourse()"
>
<div
class=
"group bg-white rounded-lg overflow-hidden shadow-lg border-4 border-blue-600 h-full flex flex-col transform transition-all duration-300 ease-in-out hover:scale-[1.02] hover:shadow-xl"
>
<div
class=
"p-4 flex justify-center items-center flex-shrink-0"
>
<img
class=
"w-full h-full object-cover rounded-md shadow-md transform transition-transform duration-300 group-hover:scale-105 cursor-pointer"
style=
"width: 400px; height: 200px; max-width: 100%;"
src=
"{{ data.getImage() }}"
alt=
"{{ data.thName }}"
(
click
)="
openDialog
(
data
.
getImage
())"
/>
</div>
<div
class=
"p-4 flex-grow"
>
<span
class=
"text-xl font-semibold text-gray-800 mb-2"
style=
"font-size: 18px;"
>
{{ data.thName }}
</span>
<p
class=
"text-gray-700 text-sm mb-3"
>
{{ data.thDesc }}
</p>
<div
class=
"mb-0 flex items-center justify-center sm:justify-start gap-2 w-1/2 mt-5"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ตัวอย่างวิธีใช้งาน'"
(
click
)="
openLink
(
data
.
link1
)"
style=
"background-color: rgb(76, 117, 207, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
</div>
<div
class=
"mb-2 flex items-center justify-center sm:justify-start gap-2 w-1/2"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ดาวน์โหลด'"
(
click
)="
downloadFile
(
data
.
courseId
)"
style=
"background-color: rgb(34, 197, 94, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
<small
class=
"text-gray-500 text-xs ml-auto hidden sm:block flex-shrink-0"
*
ngIf=
"data.dwTime > 0"
>
{{
coverDate(data.downloadDate) }} {{ data.downloadTime }} (
{{ data.dwTime }} ครั้ง)
</small>
</div>
</div>
<div
class=
"px-4 py-3 border-t border-gray-200 text-right flex-shrink-0"
>
<small
class=
"text-gray-500 text-xs"
>
วันที่อัพโหลด {{ coverDate(data.uploadDate) }}
{{ data.uploadTime }}
</small>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/view-list-course/view-list-course.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/view-list-course/view-list-course.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
AlertModalComponent
}
from
'../alert-modal/alert-modal.component'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
CourseContentModel
}
from
'../../../models/course-content.model'
;
import
{
CourseService
}
from
'../../../services/course.service'
;
import
{
ActivatedRoute
,
RouterModule
}
from
'@angular/router'
;
import
{
ConfirmModalComponent
}
from
'../confirm-modal/confirm-modal.component'
;
import
{
OpenImageComponent
}
from
'../open-image/open-image.component'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
saveAs
from
'file-saver'
;
@
Component
({
selector
:
'app-view-list-course'
,
templateUrl
:
'./view-list-course.component.html'
,
styleUrls
:
[
'./view-list-course.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
NgbPaginationModule
,
TranslateModule
,
],
})
export
class
ViewListCourseComponent
implements
OnInit
{
page
=
1
;
pageSize
=
10
;
listCourse
:
CourseContentModel
[]
=
[]
dialogRef
:
any
;
search
:
string
=
''
checkType
:
string
=
'0'
constructor
(
private
modalService
:
NgbModal
,
private
courseService
:
CourseService
,
private
activatedRoute
:
ActivatedRoute
,
private
dialog
:
MatDialog
,)
{
this
.
activatedRoute
.
paramMap
.
subscribe
(
result
=>
{
this
.
checkType
=
result
.
get
(
"type"
)
!
;
});
}
openDialog
(
image
:
string
)
{
const
dialogConfig
=
{
width
:
'750px'
,
disableClose
:
false
,
data
:
{
linkImage
:
image
},
panelClass
:
'my-dialog-img-preview'
,
};
this
.
dialogRef
=
this
.
dialog
.
open
(
OpenImageComponent
,
dialogConfig
);
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
any
)
=>
{
console
.
log
(
'The dialog was closed'
,
result
);
},
(
reason
:
any
)
=>
{
});
}
// openEmployeeModal(image: string) {
// const modalRef = this.modalService.open(OpenImageComponent, {
// centered: true,
// windowClass: 'my-dialog-img-preview'
// })
// modalRef.componentInstance.linkImage = image
// modalRef.result.then(result => {
// }, reason => {
// this.modalService.dismissAll()
// })
// }
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
courseService
.
downloadFileContent
(
logId
).
toPromise
();
if
(
data
)
{
saveAs
(
new
Blob
([
data
]),
"file_download.json"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
// async downloadFile(logId: string) {
// try {
// const data = await this.courseService.downloadFileContent(logId).toPromise();
// if (data) {
// FileSaver.saveAs(new Blob([data]), "file_download.json");
// }
// } catch (error) {
// console.error('Error loading data:', error);
// }
// }
filterListCourse
()
{
return
this
.
listCourse
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListCourse
()
{
try
{
const
data
=
await
this
.
courseService
.
getListCourseContent
().
toPromise
();
this
.
listCourse
=
data
!
.
map
(
x
=>
new
CourseContentModel
(
x
))
console
.
log
(
"🚀 ~ ViewListCourseComponent ~ getListCourse ~ this.listCourse :"
,
this
.
listCourse
)
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
deleteFile
(
item
:
CourseContentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
this
.
courseService
.
deleteCourseContent
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
)
this
.
getListCourse
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
ngOnInit
()
{
this
.
getListCourse
();
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
this
.
modalService
.
dismissAll
()
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
coverDate
(
date
:
string
)
{
return
date
.
split
(
'-'
).
reverse
().
join
(
'/'
)
}
}
src/app/DPU/myskill-x/myportal/view-list-doc/view-list-doc.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการเอกสาร'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการเอกสาร'"
></app-page-header>
<!-- <div class="row" *ngIf="checkType == '1'">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">รายการเอกสาร</h4>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
<div class="table-responsive">
<table class="table table-striped mb-0 no-wrap v-middle ">
<thead class="bg-info text-white">
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">รูปภาพ</th>
<th scope="col">ชื่อ</th>
<th scope="col">รายละเอียด</th>
<th scope="col" class="text-center">ลิงค์</th>
<th scope="col" class="text-center">ไฟล์ (ไทย)</th>
<th scope="col" class="text-center">ไฟล์ (อังกฤษ)</th>
<th scope="col" class="text-center">วันที่อัพโหลด</th>
<th scope="col" class="text-center">วันล่าสุดดาวน์โหลด</th>
<th scope="col" class="text-center">จำนวนดาวน์โหลด</th>
<th scope="col" *ngIf="checkType == '1'"></th>
</tr>
</thead>
<tbody>
<tr *ngIf="listDoc.length == 0">
<td colspan="{{checkType == '1' ? '9' : '10'}}" class="text-center">ไม่พบข้อมูล</td>
</tr>
<tr
*ngFor="let data of filterListDoc() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index">
<td class="text-center">{{i+1}}</td>
<td><img width="100" class="border p-1" src="{{data.getImage()}}" (click)="openDialog(data.getImage())">
</td>
<td>{{ data.thName }}</td>
<td>{{ data.thDesc }}</td>
<td class="text-center"><i class="fas fa-link pointer" (click)="openLink(data.link1)"></i></td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.docId,'tha')"></i>
</td>
<td class="text-center"> <i class="fas fa-download pointer" (click)="downloadFile(data.docId,'eng')"></i>
</td>
<td class="text-center">{{data.uploadDate}} {{data.uploadTime}}</td>
<td class="text-center">{{data.downloadDate}} {{data.downloadTime}}</td>
<td class="text-center">{{data.dwTime}} ครั้ง</td>
<td *ngIf="checkType == '1'">
<button type="button" class="btn btn-circle btn-danger rounded-circle btn-sm mr-2"
(click)="deleteFile(data)" placement="top" ngbTooltip="ลบ"><i class="fas fa-trash-alt"></i></button>
</td>
</tr>
</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]="listDoc.length" [maxSize]="3"
[rotate]="true">
<ng-template ngbPaginationPrevious>ก่อนหน้า</ng-template>
<ng-template ngbPaginationNext>ถัดไป</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div> -->
<!-- <div class="row" *ngIf="checkType != '1'">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListDoc()">
<div class="card border-5 border border-doc h-100 shadow">
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}" (click)="openDialog(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.thName }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.docId,'tha')"><i class="fas fa-download mr-1"></i>
ดาวน์โหลด (ไทย) <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}}
{{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.docId,'eng')"><i class="fas fa-download mr-1"></i>
ดาวน์โหลด (อังกฤษ) <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}}
{{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i>
ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5">
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div
class=
"box p-4"
>
<div
*
ngIf=
"checkType != '1'"
class=
"flex flex-wrap -mx-2"
>
<div
class=
"w-full"
>
<div
class=
"py-3 px-2"
>
<input
type=
"text"
class=
"block w-full md:w-1/4 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 shadow-sm"
placeholder=
"ค้นหา"
[(
ngModel
)]="
search
"
/>
</div>
</div>
<div
class=
"w-full sm:w-1/2 lg:w-1/3 xl:w-1/3 px-2 mb-4"
*
ngFor=
"let data of filterListDoc()"
>
<div
class=
"group bg-white rounded-lg overflow-hidden shadow-lg border-4 border-blue-600 h-full flex flex-col transform transition-all duration-300 ease-in-out hover:scale-[1.02] hover:shadow-xl"
>
<div
class=
"p-4 flex justify-center items-center flex-shrink-0"
>
<img
class=
"w-full h-full object-cover rounded-md shadow-md transform transition-transform duration-300 group-hover:scale-105 cursor-pointer"
style=
"width: 400px; height: 200px; max-width: 100%;"
src=
"{{ data.getImage() }}"
alt=
"{{ data.thName }}"
(
click
)="
openDialog
(
data
.
getImage
())"
/>
</div>
<div
class=
"p-4 flex-grow"
>
<span
class=
"text-xl font-semibold text-gray-800 mb-2"
style=
"font-size: 18px;"
>
{{ data.thName }}
</span>
<p
class=
"text-gray-700 text-sm mb-3"
>
{{ data.thDesc }}
</p>
<div
class=
"mb-0 flex items-center justify-center sm:justify-start gap-2 w-1/2 mt-5"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ตัวอย่างวิธีใช้งาน'"
(
click
)="
openLink
(
data
.
link1
)"
style=
"background-color: rgb(76, 117, 207, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
</div>
<div
class=
"mb-2 flex items-center justify-center sm:justify-start gap-2 w-full mt-2"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ดาวน์โหลด
(ไทย)'"
(
click
)="
downloadFile
(
data
.
docId
,
'
tha
')"
style=
"background-color: rgb(34, 197, 94, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 cursor-pointer hover:opacity-90 focus:outline-none focus:ring-1 focus:ring-green-700 transition-all duration-200"
readonly
/>
<small
class=
"text-gray-500 text-xs ml-auto hidden sm:block flex-shrink-0"
*
ngIf=
"data.dwTime > 0"
>
{{coverDate(data.downloadDate)}} {{data.downloadTime}} ( {{data.dwTime}} ครั้ง)
</small>
</div>
<div
class=
"mb-2 flex items-center justify-center sm:justify-start gap-2 w-full"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ดาวน์โหลด
(อังกฤษ)'"
(
click
)="
downloadFile
(
data
.
docId
,
'
eng
')"
style=
"background-color: rgb(34, 197, 94, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 cursor-pointer hover:opacity-90 focus:outline-none focus:ring-1 focus:ring-green-700 transition-all duration-200"
readonly
/>
<small
class=
"text-gray-500 text-xs ml-auto hidden sm:block flex-shrink-0"
*
ngIf=
"data.dwTime > 0"
>
{{coverDate(data.downloadDate)}} {{data.downloadTime}} ( {{data.dwTime}} ครั้ง)
</small>
</div>
</div>
<div
class=
"px-4 py-3 border-t border-gray-200 text-right flex-shrink-0"
>
<small
class=
"text-gray-500 text-xs"
>
วันที่อัพโหลด {{ coverDate(data.uploadDate) }}
{{ data.uploadTime }}
</small>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/view-list-doc/view-list-doc.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/view-list-doc/view-list-doc.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
AlertModalComponent
}
from
'../alert-modal/alert-modal.component'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
DocumentContentModel
}
from
'../../../models/document-content.model'
;
import
{
ActivatedRoute
,
RouterModule
}
from
'@angular/router'
;
import
{
ConfirmModalComponent
}
from
'../confirm-modal/confirm-modal.component'
;
import
{
OpenImageComponent
}
from
'../open-image/open-image.component'
;
import
{
DocumentService
}
from
'../../../services/document.service'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
saveAs
}
from
'file-saver'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
@
Component
({
selector
:
'app-view-list-doc'
,
templateUrl
:
'./view-list-doc.component.html'
,
styleUrls
:
[
'./view-list-doc.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
NgbPaginationModule
,
TranslateModule
,
],
})
export
class
ViewListDocComponent
implements
OnInit
{
page
=
1
;
pageSize
=
10
;
listDoc
:
DocumentContentModel
[]
=
[]
search
:
string
=
''
dialogRef
:
any
;
checkType
:
string
=
'0'
constructor
(
private
modalService
:
NgbModal
,
private
documentService
:
DocumentService
,
private
activatedRoute
:
ActivatedRoute
,
private
dialog
:
MatDialog
,)
{
this
.
activatedRoute
.
paramMap
.
subscribe
(
result
=>
{
this
.
checkType
=
result
.
get
(
"type"
)
!
;
});
}
openDialog
(
image
:
string
)
{
const
dialogConfig
=
{
width
:
'750px'
,
disableClose
:
false
,
data
:
{
linkImage
:
image
},
panelClass
:
'my-dialog-img-preview'
,
};
this
.
dialogRef
=
this
.
dialog
.
open
(
OpenImageComponent
,
dialogConfig
);
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
any
)
=>
{
console
.
log
(
'The dialog was closed'
,
result
);
},
(
reason
:
any
)
=>
{
});
}
deleteFile
(
item
:
DocumentContentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
})
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
modalRef
.
result
.
then
(
result
=>
{
this
.
documentService
.
deleteExcelContent
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
)
this
.
getListDoc
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
)
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
)
})
},
reject
=>
{
})
}
async
downloadFile
(
logId
:
string
,
lang
:
string
)
{
try
{
const
data
=
await
this
.
documentService
.
downloadFileContent
(
logId
,
lang
).
toPromise
();
if
(
data
)
{
saveAs
(
new
Blob
([
data
]),
"file_download.doc"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
filterListDoc
()
{
return
this
.
listDoc
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListDoc
()
{
try
{
const
data
=
await
this
.
documentService
.
getListExcelContent
().
toPromise
();
this
.
listDoc
=
data
!
.
map
(
x
=>
new
DocumentContentModel
(
x
))
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
ngOnInit
()
{
this
.
getListDoc
();
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
this
.
modalService
.
dismissAll
()
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
coverDate
(
date
:
string
)
{
return
date
.
split
(
'-'
).
reverse
().
join
(
'/'
)
}
}
src/app/DPU/myskill-x/myportal/view-list-excel/view-list-excel.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการเอกสาร
Excel
'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการเอกสาร
Excel
'"
></app-page-header>
<div
class=
"row"
*
ngIf=
"checkType == '1'"
>
<div
class=
"col-12"
>
<div
class=
"card card-body"
>
<h4
class=
"card-title"
>
รายการ Excel
</h4>
<div
class=
"d-flex mb-3 mt-3"
>
<input
type=
"text"
class=
"form-control w-25"
placeholder=
"ค้นหา"
[(
ngModel
)]="
search
"
>
</div>
<div
class=
"table-responsive"
>
<table
class=
"table table-striped mb-0 no-wrap v-middle "
>
<thead
class=
"bg-info text-white"
>
<tr>
<th
class=
"text-center"
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
รูปภาพ
</th>
<th
scope=
"col"
>
ชื่อ
</th>
<th
scope=
"col"
>
รายละเอียด
</th>
<th
scope=
"col"
class=
"text-center"
>
ลิงค์
</th>
<th
scope=
"col"
class=
"text-center"
>
ไฟล์
</th>
<th
scope=
"col"
class=
"text-center"
>
วันที่อัพโหลด
</th>
<th
scope=
"col"
class=
"text-center"
>
วันล่าสุดดาวน์โหลด
</th>
<th
scope=
"col"
class=
"text-center"
>
จำนวนดาวน์โหลด
</th>
<th
scope=
"col"
*
ngIf=
"checkType == '1'"
></th>
</tr>
</thead>
<tbody>
<tr
*
ngIf=
"listExcel.length == 0"
>
<td
[
colSpan
]="
checkType =
=
'
1
'
?
8
:
7
"
class=
"text-center"
>
ไม่พบข้อมูล
</td>
</tr>
<tr
*
ngFor=
"let data of filterListExcel() | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize ; let i = index"
>
<td
class=
"text-center"
>
{{i+1}}
</td>
<td><img
width=
"100"
class=
"border p-1"
src=
"{{data.getImage()}}"
(
click
)="
openDialog
(
data
.
getImage
())"
></td>
<td>
{{ data.thName }}
</td>
<td>
{{ data.thDesc }}
</td>
<td
class=
"text-center"
><i
class=
"fas fa-link pointer"
(
click
)="
openLink
(
data
.
link1
)"
></i></td>
<td
class=
"text-center"
>
<i
class=
"fas fa-download pointer"
(
click
)="
downloadFile
(
data
.
excelId
)"
></i></td>
<td
class=
"text-center"
>
{{data.uploadDate}} {{data.uploadTime}}
</td>
<td
class=
"text-center"
>
{{data.downloadDate}} {{data.downloadTime}}
</td>
<td
class=
"text-center"
>
{{data.dwTime}} ครั้ง
</td>
<td
*
ngIf=
"checkType == '1'"
>
<button
type=
"button"
class=
"btn btn-circle btn-danger rounded-circle btn-sm mr-2"
(
click
)="
deleteFile
(
data
)"
placement=
"top"
ngbTooltip=
"ลบ"
><i
class=
"fas fa-trash-alt"
></i></button>
</td>
</tr>
</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
]="
listExcel
.
length
"
[
maxSize
]="
3
"
[
rotate
]="
true
"
>
<ng-template
ngbPaginationPrevious
>
ก่อนหน้า
</ng-template>
<ng-template
ngbPaginationNext
>
ถัดไป
</ng-template>
</ngb-pagination>
</div>
</div>
</div>
</div>
<!-- <div class="row" *ngIf="checkType != '1'">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListExcel()">
<div class="card border-5 border border-excel h-100 shadow">
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}"
(click)="openEmployeeModal(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.thName }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.excelId)"><i class="fas fa-download mr-1"></i>
ดาวน์โหลด <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}}
{{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i>
ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5">
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div
class=
"box p-4"
>
<div
*
ngIf=
"checkType != '1'"
class=
"flex flex-wrap -mx-2"
>
<div
class=
"w-full"
>
<div
class=
"py-3 px-2"
>
<input
type=
"text"
class=
"block w-full md:w-1/4 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 shadow-sm"
placeholder=
"ค้นหา"
[(
ngModel
)]="
search
"
/>
</div>
</div>
<div
class=
"w-full sm:w-1/2 lg:w-1/3 xl:w-1/3 px-2 mb-4"
*
ngFor=
"let data of filterListExcel()"
>
<div
class=
"group bg-white rounded-lg overflow-hidden shadow-lg border-4 border-blue-600 h-full flex flex-col transform transition-all duration-300 ease-in-out hover:scale-[1.02] hover:shadow-xl"
>
<div
class=
"p-4 flex justify-center items-center flex-shrink-0"
>
<img
class=
"w-full h-full object-cover rounded-md shadow-md transform transition-transform duration-300 group-hover:scale-105 cursor-pointer"
style=
"width: 400px; height: 200px; max-width: 100%;"
src=
"{{ data.getImage() }}"
alt=
"{{ data.thName }}"
(
click
)="
openDialog
(
data
.
getImage
())"
/>
</div>
<div
class=
"p-4 flex-grow"
>
<span
class=
"text-xl font-semibold text-gray-800 mb-2"
style=
"font-size: 18px;"
>
{{ data.thName }}
</span>
<p
class=
"text-gray-700 text-sm mb-3"
>
{{ data.thDesc }}
</p>
<div
class=
"mb-0 flex items-center justify-center sm:justify-start gap-2 w-1/2 mt-5"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ตัวอย่างวิธีใช้งาน'"
(
click
)="
openLink
(
data
.
link1
)"
style=
"background-color: rgb(76, 117, 207, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
</div>
<div
class=
"mb-2 flex items-center justify-center sm:justify-start gap-2 w-1/2"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ดาวน์โหลด'"
(
click
)="
downloadFile
(
data
.
excelId
)"
style=
"background-color: rgb(34, 197, 94, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
<small
class=
"text-gray-500 text-xs ml-auto hidden sm:block flex-shrink-0"
*
ngIf=
"data.dwTime > 0"
>
{{
coverDate(data.downloadDate) }} {{ data.downloadTime }} (
{{ data.dwTime }} ครั้ง)
</small>
</div>
</div>
<div
class=
"px-4 py-3 border-t border-gray-200 text-right flex-shrink-0"
>
<small
class=
"text-gray-500 text-xs"
>
วันที่อัพโหลด {{ coverDate(data.uploadDate) }}
{{ data.uploadTime }}
</small>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/view-list-excel/view-list-excel.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/view-list-excel/view-list-excel.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
ExcelService
}
from
'../../../services/excel.service'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
ActivatedRoute
,
RouterModule
}
from
'@angular/router'
;
import
{
ExcelContentModel
}
from
'../../../models/excel-content.model'
;
import
{
OpenImageComponent
}
from
'../open-image/open-image.component'
;
import
{
ConfirmModalComponent
}
from
'../confirm-modal/confirm-modal.component'
;
import
{
AlertModalComponent
}
from
'../alert-modal/alert-modal.component'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
saveAs
}
from
'file-saver'
;
@
Component
({
selector
:
'app-view-list-excel'
,
templateUrl
:
'./view-list-excel.component.html'
,
styleUrls
:
[
'./view-list-excel.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
RouterModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
TranslateModule
,
NgbPaginationModule
,
],
})
export
class
ViewListExcelComponent
implements
OnInit
{
page
=
1
;
pageSize
=
10
;
listExcel
:
ExcelContentModel
[]
=
[];
search
:
string
=
''
;
checkType
:
string
=
'0'
;
dialogRef
:
any
;
constructor
(
private
modalService
:
NgbModal
,
private
excelService
:
ExcelService
,
private
activatedRoute
:
ActivatedRoute
,
private
dialog
:
MatDialog
,
)
{
this
.
activatedRoute
.
paramMap
.
subscribe
(
result
=>
{
this
.
checkType
=
result
.
get
(
"type"
)
!
;
});
}
openDialog
(
image
:
string
)
{
const
dialogConfig
=
{
width
:
'750px'
,
disableClose
:
false
,
data
:
{
linkImage
:
image
},
panelClass
:
'my-dialog-img-preview'
,
};
this
.
dialogRef
=
this
.
dialog
.
open
(
OpenImageComponent
,
dialogConfig
);
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
any
)
=>
{
console
.
log
(
'The dialog was closed'
,
result
);
},
(
reason
:
any
)
=>
{
});
}
// openEmployeeModal(image: string) {
// const modalRef = this.modalService.open(OpenImageComponent, {
// centered: true,
// windowClass: 'my-dialog-img-preview'
// });
// modalRef.componentInstance.linkImage = image;
// modalRef.result.then(result => {
// }, reason => {
// this.modalService.dismissAll();
// });
// }
deleteFile
(
item
:
ExcelContentModel
)
{
const
modalRef
=
this
.
modalService
.
open
(
ConfirmModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
,
});
modalRef
.
componentInstance
.
message
=
'คุณต้องการลบข้อมูลหรือไม่'
;
modalRef
.
result
.
then
(
result
=>
{
this
.
excelService
.
deleteExcelContent
(
item
).
subscribe
(
result
=>
{
if
(
result
)
{
this
.
openAlertModal
(
'ลบข้อมูลสำเร็จ'
);
this
.
getListExcel
();
}
else
{
this
.
openAlertModal
(
'ไม่สามารถลบข้อมูลได้'
);
}
},
error
=>
{
this
.
openAlertModal
(
error
.
message
);
});
},
reject
=>
{
});
}
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
excelService
.
downloadFileContent
(
logId
).
toPromise
();
if
(
data
)
{
saveAs
(
new
Blob
([
data
]),
"file_download.xlsx"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
getStatus
(
status
:
string
):
string
{
if
(
status
==
'0'
)
{
return
'รออนุมัติ'
;
}
else
if
(
status
==
'1'
)
{
return
'เปิดใช้งาน'
;
}
else
if
(
status
==
'2'
)
{
return
'ไม่อนุมัติ'
;
}
return
''
;
}
filterListExcel
()
{
return
this
.
listExcel
.
filter
(
x
=>
x
.
thName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
engName
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()));
}
async
getListExcel
()
{
try
{
const
data
=
await
this
.
excelService
.
getListExcelContent
().
toPromise
();
this
.
listExcel
=
data
!
.
map
(
x
=>
new
ExcelContentModel
(
x
));
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
ngOnInit
()
{
this
.
getListExcel
();
}
openLink
(
url
:
string
)
{
window
.
open
(
url
,
"_blank"
);
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
});
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
;
modalRef
.
result
.
then
(
result
=>
{
this
.
modalService
.
dismissAll
();
},
reason
=>
{
this
.
modalService
.
dismissAll
();
});
}
coverDate
(
date
:
string
)
{
return
date
.
split
(
'-'
).
reverse
().
join
(
'/'
);
}
}
\ No newline at end of file
src/app/DPU/myskill-x/myportal/view-list-widgets/view-list-widgets.component.html
0 → 100644
View file @
73e72e5e
<app-page-header
[
title
]="'รายการวิทเจ็ท'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'รายการวิทเจ็ท'"
></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListWidget()">
<div class="card border-5 border border-widget h-100 shadow">
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}"
(click)="openEmployeeModal(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.widgetTname }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.widgetId)"><i class="fas fa-download mr-1"></i>
ดาวน์โหลด <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}}
{{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i>
ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5">
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div
class=
"box p-4"
>
<div
class=
"flex flex-wrap -mx-2"
>
<div
class=
"w-full"
>
<div
class=
"py-3 px-2"
>
<input
type=
"text"
class=
"block w-full md:w-1/4 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 shadow-sm"
placeholder=
"ค้นหา"
[(
ngModel
)]="
search
"
/>
</div>
</div>
<div
class=
"w-full sm:w-1/2 lg:w-1/3 xl:w-1/3 px-2 mb-4"
*
ngFor=
"let data of filterListWidget()"
>
<div
class=
"group bg-white rounded-lg overflow-hidden shadow-lg border-4 border-blue-600 h-full flex flex-col transform transition-all duration-300 ease-in-out hover:scale-[1.02] hover:shadow-xl"
>
<div
class=
"p-4 flex justify-center items-center flex-shrink-0"
>
<img
class=
"w-full h-full object-cover rounded-md shadow-md transform transition-transform duration-300 group-hover:scale-105 cursor-pointer"
style=
"width: 400px; height: 200px; max-width: 100%;"
src=
"{{ data.getImage() }}"
alt=
"{{ data.widgetTname }}"
(
click
)="
openDialog
(
data
.
getImage
())"
/>
</div>
<div
class=
"p-4 flex-grow"
>
<span
class=
"text-xl font-semibold text-gray-800 mb-2"
style=
"font-size: 18px;"
>
{{ data.widgetTname }}
</span>
<p
class=
"text-gray-700 text-sm mb-3"
>
{{ data.thDesc }}
</p>
<div
class=
"mb-0 flex items-center justify-center sm:justify-start gap-2 w-1/2 mt-5"
>
<i
class=
"fa fa-link text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ตัวอย่างวิธีใช้งาน'"
(
click
)="
openLink
(
data
.
link1
)"
style=
"background-color: rgb(76, 117, 207, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
</div>
<div
class=
"mb-2 flex items-center justify-center sm:justify-start gap-2 w-1/2"
>
<i
class=
"fa fa-download text-blue-600 text-base flex-shrink-0"
aria-hidden=
"true"
></i>
<input
type=
"text"
[
value
]="'ดาวน์โหลด'"
(
click
)="
downloadFile
(
data
.
widgetId
)"
style=
"background-color: rgb(34, 197, 94, 1); color: #FFF;"
class=
"flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly
/>
</div>
</div>
<div
class=
"px-4 py-3 border-t border-gray-200 text-right flex-shrink-0"
>
<small
class=
"text-gray-500 text-xs"
>
วันที่อัพโหลด {{ coverDate(data.uploadDate) }}
{{ data.uploadTime }}
</small>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/DPU/myskill-x/myportal/view-list-widgets/view-list-widgets.component.scss
0 → 100644
View file @
73e72e5e
src/app/DPU/myskill-x/myportal/view-list-widgets/view-list-widgets.component.ts
0 → 100644
View file @
73e72e5e
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
NgbModal
,
NgbPaginationModule
}
from
'@ng-bootstrap/ng-bootstrap'
;
import
{
AlertModalComponent
}
from
'../alert-modal/alert-modal.component'
;
import
{
OpenImageComponent
}
from
'../open-image/open-image.component'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
MatDialog
,
MatDialogModule
}
from
'@angular/material/dialog'
;
import
{
SharedModule
}
from
'../../../../shared/shared.module'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
saveAs
from
'file-saver'
;
import
{
WidgetModel
}
from
'../../../models/widgets.model'
;
import
{
WidgetService
}
from
'../../../services/widgets.service'
;
@
Component
({
selector
:
'app-view-list-widgets'
,
templateUrl
:
'./view-list-widgets.component.html'
,
styleUrls
:
[
'./view-list-widgets.component.scss'
],
standalone
:
true
,
imports
:
[
CommonModule
,
FormsModule
,
NgSelectModule
,
SharedModule
,
MatDialogModule
,
NgbPaginationModule
,
TranslateModule
,
],
})
export
class
ViewListWidgetsComponent
implements
OnInit
{
page
=
1
;
pageSize
=
10
;
listWidget
:
WidgetModel
[]
=
[]
search
:
string
=
''
dialogRef
:
any
;
constructor
(
private
modalService
:
NgbModal
,
private
widgetService
:
WidgetService
,
private
dialog
:
MatDialog
,)
{
}
openDialog
(
image
:
string
)
{
const
dialogConfig
=
{
width
:
'750px'
,
disableClose
:
false
,
data
:
{
linkImage
:
image
},
panelClass
:
'my-dialog-img-preview'
,
};
this
.
dialogRef
=
this
.
dialog
.
open
(
OpenImageComponent
,
dialogConfig
);
this
.
dialogRef
.
afterClosed
().
subscribe
((
result
:
any
)
=>
{
console
.
log
(
'The dialog was closed'
,
result
);
},
(
reason
:
any
)
=>
{
});
}
async
downloadFile
(
logId
:
string
)
{
try
{
const
data
=
await
this
.
widgetService
.
downloadFile
(
logId
).
toPromise
();
if
(
data
)
{
saveAs
(
new
Blob
([
data
]),
"file_download.xlsx"
);
}
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
// getStatus(status: string) {
// if (status == '0') {
// return 'Private'
// } else if (status == '1') {
// return 'Public'
// }
// }
filterListWidget
(){
return
this
.
listWidget
.
filter
(
x
=>
x
.
widgetTname
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
())
||
x
.
widgetEname
.
toLowerCase
().
includes
(
this
.
search
.
toLowerCase
()))
}
async
getListExcel
(){
try
{
const
data
=
await
this
.
widgetService
.
getListWidgets
().
toPromise
();
this
.
listWidget
=
data
!
.
map
(
x
=>
new
WidgetModel
(
x
))
}
catch
(
error
)
{
console
.
error
(
'Error loading data:'
,
error
);
}
}
ngOnInit
()
{
this
.
getListExcel
();
}
openLink
(
url
:
string
){
window
.
open
(
url
,
"_blank"
);
}
openAlertModal
(
message
?:
string
)
{
const
modalRef
=
this
.
modalService
.
open
(
AlertModalComponent
,
{
centered
:
true
,
backdrop
:
'static'
})
modalRef
.
componentInstance
.
message
=
message
?
message
:
""
modalRef
.
result
.
then
(
result
=>
{
this
.
modalService
.
dismissAll
()
},
reason
=>
{
this
.
modalService
.
dismissAll
()
})
}
coverDate
(
date
:
string
){
return
date
.
split
(
'-'
).
reverse
().
join
(
'/'
)
}
}
src/app/DPU/myskill-x/myskill-x.module.ts
View file @
73e72e5e
...
@@ -7,137 +7,137 @@ import { QuillModule } from 'ngx-quill';
...
@@ -7,137 +7,137 @@ import { QuillModule } from 'ngx-quill';
export
const
myportal
:
Routes
=
[
export
const
myportal
:
Routes
=
[
{
{
path
:
'my
portal
'
,
children
:
[
path
:
'my
skill-x
'
,
children
:
[
//////////////MyPortal/////////////////
//////////////MyPortal/////////////////
{
{
path
:
'portal-category-list'
,
path
:
'portal-category-list'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/portal-category-list/portal-category-list.component'
).
then
((
m
)
=>
m
.
PortalCategoryListComponent
),
import
(
'../
myskill-x
/myportal/portal-category-list/portal-category-list.component'
).
then
((
m
)
=>
m
.
PortalCategoryListComponent
),
},
},
{
{
path
:
'view-list-excel'
,
path
:
'view-list-excel'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/view-list-excel/view-list-excel.component'
).
then
((
m
)
=>
m
.
ViewListExcelComponent
),
import
(
'../
myskill-x
/myportal/view-list-excel/view-list-excel.component'
).
then
((
m
)
=>
m
.
ViewListExcelComponent
),
},
},
{
{
path
:
'view-list-doc'
,
path
:
'view-list-doc'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/view-list-doc/view-list-doc.component'
).
then
((
m
)
=>
m
.
ViewListDocComponent
),
import
(
'../
myskill-x
/myportal/view-list-doc/view-list-doc.component'
).
then
((
m
)
=>
m
.
ViewListDocComponent
),
},
},
{
{
path
:
'view-list-course'
,
path
:
'view-list-course'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/view-list-course/view-list-course.component'
).
then
((
m
)
=>
m
.
ViewListCourseComponent
),
import
(
'../
myskill-x
/myportal/view-list-course/view-list-course.component'
).
then
((
m
)
=>
m
.
ViewListCourseComponent
),
},
},
{
{
path
:
'view-list-widgets'
,
path
:
'view-list-widgets'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/view-list-widgets/view-list-widgets.component'
).
then
((
m
)
=>
m
.
ViewListWidgetsComponent
),
import
(
'../
myskill-x
/myportal/view-list-widgets/view-list-widgets.component'
).
then
((
m
)
=>
m
.
ViewListWidgetsComponent
),
},
},
{
{
path
:
'excel-report'
,
path
:
'excel-report'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/excel-report/excel-report.component'
).
then
((
m
)
=>
m
.
ExcelReportComponent
),
import
(
'../
myskill-x
/myportal/excel-report/excel-report.component'
).
then
((
m
)
=>
m
.
ExcelReportComponent
),
},
},
{
{
path
:
'portal-create-category'
,
path
:
'portal-create-category'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/portal-create-category/portal-create-category.component'
).
then
((
m
)
=>
m
.
PortalCreateCategoryComponent
),
import
(
'../
myskill-x
/myportal/portal-create-category/portal-create-category.component'
).
then
((
m
)
=>
m
.
PortalCreateCategoryComponent
),
},
},
{
{
path
:
'list-excell'
,
path
:
'list-excell'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/list-excell/list-excell.component'
).
then
((
m
)
=>
m
.
ListExcelComponent
),
import
(
'../
myskill-x
/myportal/list-excell/list-excell.component'
).
then
((
m
)
=>
m
.
ListExcelComponent
),
},
},
{
{
path
:
'list-course'
,
path
:
'list-course'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/list-course/list-course.component'
).
then
((
m
)
=>
m
.
ListCourseComponent
),
import
(
'../
myskill-x
/myportal/list-course/list-course.component'
).
then
((
m
)
=>
m
.
ListCourseComponent
),
},
},
{
{
path
:
'list-doc'
,
path
:
'list-doc'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/list-doc/list-doc.component'
).
then
((
m
)
=>
m
.
ListDocComponent
),
import
(
'../
myskill-x
/myportal/list-doc/list-doc.component'
).
then
((
m
)
=>
m
.
ListDocComponent
),
},
},
{
{
path
:
'list-widgets'
,
path
:
'list-widgets'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/list-widgets/list-widgets.component'
).
then
((
m
)
=>
m
.
ListWidgetsComponent
),
import
(
'../
myskill-x
/myportal/list-widgets/list-widgets.component'
).
then
((
m
)
=>
m
.
ListWidgetsComponent
),
},
},
{
{
path
:
'excel-list'
,
path
:
'excel-list'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/set-excel-reports/excel-list/excel-list.component'
).
then
((
m
)
=>
m
.
ExcelListComponent
),
import
(
'../
myskill-x
/myportal/set-excel-reports/excel-list/excel-list.component'
).
then
((
m
)
=>
m
.
ExcelListComponent
),
},
},
{
{
path
:
'datasource-table'
,
path
:
'datasource-table'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/datasource-table/datasource-table.component'
).
then
((
m
)
=>
m
.
DatasourceTableComponent
),
import
(
'../
myskill-x
/myportal/datasource-table/datasource-table.component'
).
then
((
m
)
=>
m
.
DatasourceTableComponent
),
},
},
{
{
path
:
'excel-report-toggle'
,
path
:
'excel-report-toggle'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/set-excel-reports/excel-report-toggle/excel-report-toggle.component'
).
then
((
m
)
=>
m
.
ExcelReportToggleComponent
),
import
(
'../
myskill-x
/myportal/set-excel-reports/excel-report-toggle/excel-report-toggle.component'
).
then
((
m
)
=>
m
.
ExcelReportToggleComponent
),
},
},
{
{
path
:
'management'
,
path
:
'management'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/management.component'
).
then
((
m
)
=>
m
.
ManagementComponent
),
import
(
'../
myskill-x
/myportal/management/management.component'
).
then
((
m
)
=>
m
.
ManagementComponent
),
},
},
{
{
path
:
'portal-category-list-approve'
,
path
:
'portal-category-list-approve'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/portal-category-list-approve/portal-category-list-approve.component'
).
then
((
m
)
=>
m
.
PortalCategoryListApproveComponent
),
import
(
'../
myskill-x
/myportal/management/portal-category-list-approve/portal-category-list-approve.component'
).
then
((
m
)
=>
m
.
PortalCategoryListApproveComponent
),
},
},
{
{
path
:
'approve-excel'
,
path
:
'approve-excel'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/portal-category-list-approve/approve-excel/approve-excel.component'
).
then
((
m
)
=>
m
.
ApproveExcelComponent
),
import
(
'../
myskill-x
/myportal/management/portal-category-list-approve/approve-excel/approve-excel.component'
).
then
((
m
)
=>
m
.
ApproveExcelComponent
),
},
},
{
{
path
:
'approve-doc'
,
path
:
'approve-doc'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/portal-category-list-approve/approve-doc/approve-doc.component'
).
then
((
m
)
=>
m
.
ApproveDocComponent
),
import
(
'../
myskill-x
/myportal/management/portal-category-list-approve/approve-doc/approve-doc.component'
).
then
((
m
)
=>
m
.
ApproveDocComponent
),
},
},
{
{
path
:
'approve-course'
,
path
:
'approve-course'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/portal-category-list-approve/approve-course/approve-course.component'
).
then
((
m
)
=>
m
.
ApproveCourseComponent
),
import
(
'../
myskill-x
/myportal/management/portal-category-list-approve/approve-course/approve-course.component'
).
then
((
m
)
=>
m
.
ApproveCourseComponent
),
},
},
{
{
path
:
'approved-list'
,
path
:
'approved-list'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/approved-list/approved-list.component'
).
then
((
m
)
=>
m
.
ApprovedListComponent
),
import
(
'../
myskill-x
/myportal/management/approved-list/approved-list.component'
).
then
((
m
)
=>
m
.
ApprovedListComponent
),
},
},
{
{
path
:
'view-list-excel'
,
path
:
'view-list-excel'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/approved-list/view-list-excel/view-list-excel.component'
).
then
((
m
)
=>
m
.
ViewListExcelComponent
),
import
(
'../
myskill-x
/myportal/management/approved-list/view-list-excel/view-list-excel.component'
).
then
((
m
)
=>
m
.
ViewListExcelComponent
),
},
},
{
{
path
:
'view-list-excel/:type'
,
path
:
'view-list-excel/:type'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/approved-list/view-list-excel/view-list-excel.component'
).
then
((
m
)
=>
m
.
ViewListExcelComponent
),
import
(
'../
myskill-x
/myportal/management/approved-list/view-list-excel/view-list-excel.component'
).
then
((
m
)
=>
m
.
ViewListExcelComponent
),
},
},
{
{
path
:
'view-list-doc'
,
path
:
'view-list-doc'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/approved-list/view-list-doc/view-list-doc.component'
).
then
((
m
)
=>
m
.
ViewListDocComponent
),
import
(
'../
myskill-x
/myportal/management/approved-list/view-list-doc/view-list-doc.component'
).
then
((
m
)
=>
m
.
ViewListDocComponent
),
},
},
{
{
path
:
'view-list-doc/:type'
,
path
:
'view-list-doc/:type'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/approved-list/view-list-doc/view-list-doc.component'
).
then
((
m
)
=>
m
.
ViewListDocComponent
),
import
(
'../
myskill-x
/myportal/management/approved-list/view-list-doc/view-list-doc.component'
).
then
((
m
)
=>
m
.
ViewListDocComponent
),
},
},
{
{
path
:
'view-list-course'
,
path
:
'view-list-course'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/approved-list/view-list-course/view-list-course.component'
).
then
((
m
)
=>
m
.
ViewListCourseComponent
),
import
(
'../
myskill-x
/myportal/management/approved-list/view-list-course/view-list-course.component'
).
then
((
m
)
=>
m
.
ViewListCourseComponent
),
},
},
{
{
path
:
'view-list-course/:type'
,
path
:
'view-list-course/:type'
,
loadComponent
:
()
=>
loadComponent
:
()
=>
import
(
'../
common
/myportal/management/approved-list/view-list-course/view-list-course.component'
).
then
((
m
)
=>
m
.
ViewListCourseComponent
),
import
(
'../
myskill-x
/myportal/management/approved-list/view-list-course/view-list-course.component'
).
then
((
m
)
=>
m
.
ViewListCourseComponent
),
},
},
]
]
}
}
...
...
src/app/shared/components/header/header.component.html
View file @
73e72e5e
...
@@ -363,7 +363,7 @@
...
@@ -363,7 +363,7 @@
</div>
</div>
<div
class=
""
>
<div
class=
""
>
<a
routerLink=
"/my
portal
/portal-category-list"
<a
routerLink=
"/my
skill-x
/portal-category-list"
class=
"p-4 items-center related-app block text-center rounded-sm hover:bg-gray-50 dark:hover:bg-black/20"
>
class=
"p-4 items-center related-app block text-center rounded-sm hover:bg-gray-50 dark:hover:bg-black/20"
>
<img
src=
"./assets/images/logoallHR/mySkill-x.png"
alt=
"miscrosoft"
<img
src=
"./assets/images/logoallHR/mySkill-x.png"
alt=
"miscrosoft"
class=
"leading-[1.75] text-2xl !h-[1.75rem] align-middle flex justify-center mx-auto"
>
class=
"leading-[1.75] text-2xl !h-[1.75rem] align-middle flex justify-center mx-auto"
>
...
...
src/app/shared/components/sidebar/sidebar.component.ts
View file @
73e72e5e
...
@@ -114,7 +114,7 @@ export class SidebarComponent {
...
@@ -114,7 +114,7 @@ export class SidebarComponent {
this
.
currentUrl
=
this
.
router
.
url
this
.
currentUrl
=
this
.
router
.
url
this
.
isCommonRoute
=
this
.
currentUrl
.
includes
(
'/admin'
);
this
.
isCommonRoute
=
this
.
currentUrl
.
includes
(
'/admin'
);
this
.
isInstallerRoute
=
this
.
currentUrl
.
includes
(
'/company'
);
this
.
isInstallerRoute
=
this
.
currentUrl
.
includes
(
'/company'
);
this
.
isMyportalRoute
=
this
.
currentUrl
.
includes
(
'/my
portal
'
);
this
.
isMyportalRoute
=
this
.
currentUrl
.
includes
(
'/my
skill-x
'
);
this
.
isMylearnRoute
=
this
.
currentUrl
.
includes
(
'/mylearn'
);
this
.
isMylearnRoute
=
this
.
currentUrl
.
includes
(
'/mylearn'
);
this
.
isMyJobRoute
=
this
.
currentUrl
.
includes
(
'/myjob'
);
this
.
isMyJobRoute
=
this
.
currentUrl
.
includes
(
'/myjob'
);
this
.
isMyhrLiteRoute
=
this
.
currentUrl
.
includes
(
'/myhr-lite'
);
this
.
isMyhrLiteRoute
=
this
.
currentUrl
.
includes
(
'/myhr-lite'
);
...
@@ -149,7 +149,7 @@ export class SidebarComponent {
...
@@ -149,7 +149,7 @@ export class SidebarComponent {
checkInitialUrl
():
void
{
checkInitialUrl
():
void
{
this
.
isCommonRoute
=
this
.
currentUrl
.
includes
(
'/admin'
);
this
.
isCommonRoute
=
this
.
currentUrl
.
includes
(
'/admin'
);
this
.
isInstallerRoute
=
this
.
currentUrl
.
includes
(
'/company'
);
this
.
isInstallerRoute
=
this
.
currentUrl
.
includes
(
'/company'
);
this
.
isMyportalRoute
=
this
.
currentUrl
.
includes
(
'/my
portal
'
);
this
.
isMyportalRoute
=
this
.
currentUrl
.
includes
(
'/my
skill-x
'
);
this
.
isMylearnRoute
=
this
.
currentUrl
.
includes
(
'/mylearn'
);
this
.
isMylearnRoute
=
this
.
currentUrl
.
includes
(
'/mylearn'
);
this
.
isMyJobRoute
=
this
.
currentUrl
.
includes
(
'/myjob'
);
this
.
isMyJobRoute
=
this
.
currentUrl
.
includes
(
'/myjob'
);
this
.
isMyhrLiteRoute
=
this
.
currentUrl
.
includes
(
'/myhr-lite'
);
this
.
isMyhrLiteRoute
=
this
.
currentUrl
.
includes
(
'/myhr-lite'
);
...
@@ -161,7 +161,7 @@ export class SidebarComponent {
...
@@ -161,7 +161,7 @@ export class SidebarComponent {
console
.
log
(
'Initial URL:'
,
this
.
currentUrl
);
console
.
log
(
'Initial URL:'
,
this
.
currentUrl
);
console
.
log
(
'Is Common Route:'
,
this
.
isCommonRoute
);
console
.
log
(
'Is Common Route:'
,
this
.
isCommonRoute
);
console
.
log
(
'Is Installer Route:'
,
this
.
isInstallerRoute
);
console
.
log
(
'Is Installer Route:'
,
this
.
isInstallerRoute
);
console
.
log
(
'Is My
portal
Route:'
,
this
.
isMyportalRoute
);
console
.
log
(
'Is My
skill-X
Route:'
,
this
.
isMyportalRoute
);
console
.
log
(
'mylearn routes'
,
this
.
isMylearnRoute
);
console
.
log
(
'mylearn routes'
,
this
.
isMylearnRoute
);
console
.
log
(
'myhrlite routes'
,
this
.
isMyhrLiteRoute
);
console
.
log
(
'myhrlite routes'
,
this
.
isMyhrLiteRoute
);
console
.
log
(
'myface routes'
,
this
.
isMyFaceRoute
);
console
.
log
(
'myface routes'
,
this
.
isMyFaceRoute
);
...
@@ -197,7 +197,7 @@ export class SidebarComponent {
...
@@ -197,7 +197,7 @@ export class SidebarComponent {
// Update the boolean values
// Update the boolean values
this
.
isCommonRoute
=
this
.
currentUrl
.
includes
(
'/admin'
);
this
.
isCommonRoute
=
this
.
currentUrl
.
includes
(
'/admin'
);
this
.
isInstallerRoute
=
this
.
currentUrl
.
includes
(
'/company'
);
this
.
isInstallerRoute
=
this
.
currentUrl
.
includes
(
'/company'
);
this
.
isMyportalRoute
=
this
.
currentUrl
.
includes
(
'/my
portal
'
);
this
.
isMyportalRoute
=
this
.
currentUrl
.
includes
(
'/my
skill-x
'
);
this
.
isMylearnRoute
=
this
.
currentUrl
.
includes
(
'/mylearn'
);
this
.
isMylearnRoute
=
this
.
currentUrl
.
includes
(
'/mylearn'
);
this
.
isMyJobRoute
=
this
.
currentUrl
.
includes
(
'/myjob'
);
this
.
isMyJobRoute
=
this
.
currentUrl
.
includes
(
'/myjob'
);
this
.
isMyhrLiteRoute
=
this
.
currentUrl
.
includes
(
'/myhr-lite'
);
this
.
isMyhrLiteRoute
=
this
.
currentUrl
.
includes
(
'/myhr-lite'
);
...
...
src/app/shared/services/nav.service.ts
View file @
73e72e5e
...
@@ -224,45 +224,45 @@ export class NavService implements OnDestroy {
...
@@ -224,45 +224,45 @@ export class NavService implements OnDestroy {
{
headTitle
:
'MyPortal'
},
{
headTitle
:
'MyPortal'
},
{
{
icon
:
'receipt'
,
icon
:
'receipt'
,
path
:
'/my
portal
/portal-category-list'
,
path
:
'/my
skill-x
/portal-category-list'
,
title
:
'รายการเอกสาร'
,
title
:
'รายการเอกสาร'
,
type
:
'link'
,
type
:
'link'
,
},
},
{
{
icon
:
'receipt'
,
icon
:
'receipt'
,
path
:
'/my
portal
/portal-create-category'
,
path
:
'/my
skill-x
/portal-create-category'
,
title
:
'รายการอัพโหลดเอกสาร'
,
title
:
'รายการอัพโหลดเอกสาร'
,
type
:
'link'
,
type
:
'link'
,
},
},
{
{
icon
:
'cog'
,
icon
:
'cog'
,
path
:
'/my
portal
/management'
,
path
:
'/my
skill-x
/management'
,
title
:
'การจัดการ'
,
title
:
'การจัดการ'
,
type
:
'sub'
,
type
:
'sub'
,
children
:
[
children
:
[
{
path
:
'/my
portal
/portal-category-list-approve'
,
title
:
'รายการรอการอนุมัติ'
,
type
:
'link'
},
{
path
:
'/my
skill-x
/portal-category-list-approve'
,
title
:
'รายการรอการอนุมัติ'
,
type
:
'link'
},
{
path
:
'/my
portal
/approved-list'
,
title
:
'รายการผ่านการอนุมัติ'
,
type
:
'link'
}
{
path
:
'/my
skill-x
/approved-list'
,
title
:
'รายการผ่านการอนุมัติ'
,
type
:
'link'
}
],
],
},
},
{
{
icon
:
'user'
,
icon
:
'user'
,
path
:
'/my
portal
/set-excel-reports'
,
path
:
'/my
skill-x
/set-excel-reports'
,
title
:
'ตั้งรายงานเอ็กเซล'
,
title
:
'ตั้งรายงานเอ็กเซล'
,
type
:
'sub'
,
type
:
'sub'
,
children
:
[
children
:
[
{
path
:
'/my
portal
/excel-list'
,
title
:
'เพิ่มรายงาน Excel'
,
type
:
'link'
},
{
path
:
'/my
skill-x
/excel-list'
,
title
:
'เพิ่มรายงาน Excel'
,
type
:
'link'
},
{
path
:
'/my
portal
/excel-report-toggle'
,
title
:
'เปิด-ปิด การใช้รายงาน Excel'
,
type
:
'link'
}
{
path
:
'/my
skill-x
/excel-report-toggle'
,
title
:
'เปิด-ปิด การใช้รายงาน Excel'
,
type
:
'link'
}
],
],
},
},
{
{
icon
:
'data'
,
icon
:
'data'
,
path
:
'/my
portal
/datasource-table'
,
path
:
'/my
skill-x
/datasource-table'
,
title
:
'DataSource Table'
,
title
:
'DataSource Table'
,
type
:
'link'
,
type
:
'link'
,
},
},
{
{
icon
:
'file'
,
icon
:
'file'
,
path
:
'/my
portal
/excel-report'
,
path
:
'/my
skill-x
/excel-report'
,
title
:
'รายงาน Excel'
,
title
:
'รายงาน Excel'
,
type
:
'link'
,
type
:
'link'
,
},
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment