Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mySkill-x
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
mySkill-x
Commits
396dec01
Commit
396dec01
authored
Sep 15, 2025
by
Nattana Chaiyamat
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
แก้ไข Individual KPI ตัวเอง
parent
9bae4e07
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
602 additions
and
159 deletions
+602
-159
indicators-and-curriculum.component.html
...s-and-curriculum/indicators-and-curriculum.component.html
+1
-1
indicators-and-curriculum.component.ts
...ors-and-curriculum/indicators-and-curriculum.component.ts
+2
-2
competency-topic.component.html
...stration/competency-topic/competency-topic.component.html
+1
-1
competency-topic.component.ts
...gistration/competency-topic/competency-topic.component.ts
+22
-25
setting-individual-kpi.component.html
...ting-individual-kpi/setting-individual-kpi.component.html
+163
-69
setting-individual-kpi.component.ts
...etting-individual-kpi/setting-individual-kpi.component.ts
+392
-40
file.service.ts
src/app/shared/services/file.service.ts
+1
-1
navservice.ts
src/app/shared/services/navservice.ts
+20
-20
No files found.
src/app/components/competency-assessment/competency-management/indicators-and-curriculum/indicators-and-curriculum.component.html
View file @
396dec01
...
...
@@ -27,7 +27,7 @@
[
dataSource
]="
indicatorsCoursesList
"
[
checkBoxSetting
]="
false
"
[
columns
]="
columns
"
[
childView
]="
true
"
[
canDownload
]="
true
"
(
sendNextPageView
)="
onViewClicked
($
event
)"
(
sendSelectData
)="
selectIndicatorsCourses
($
event
);
onEditClicked
($
event
)"
(
sendFileDownload
)="
dowloadExam
($
event
)"
>
(
sendFileDownload
)="
dow
n
loadExam
($
event
)"
>
</app-datagrid-syncfution>
</div>
</ng-container>
...
...
src/app/components/competency-assessment/competency-management/indicators-and-curriculum/indicators-and-curriculum.component.ts
View file @
396dec01
...
...
@@ -63,8 +63,8 @@ export class IndicatorsAndCurriculumComponent {
this
.
getIndicatorsCoursesList
()
}
dowloadExam
(
data
:
CompetencytopicModel
)
{
this
.
fileService
.
dowloadFiles
(
data
.
competencyFiles
).
subscribe
({
dow
n
loadExam
(
data
:
CompetencytopicModel
)
{
this
.
fileService
.
dow
n
loadFiles
(
data
.
competencyFiles
).
subscribe
({
next
:
response
=>
{
const
url
=
window
.
URL
.
createObjectURL
(
response
);
const
a
=
document
.
createElement
(
"a"
);
...
...
src/app/components/competency-assessment/name-registration/competency-topic/competency-topic.component.html
View file @
396dec01
...
...
@@ -124,7 +124,7 @@
<div
class=
"flex"
*
ngIf=
"examFileName==competencyTopic.select.competencyFiles"
>
<h1
class=
"cursor-pointer justify-center -mb-px inline-flex items-center gap-2 font-weight-500 font-size-12px
text-center text-secondary border-secondary border-b-2 align-items-end"
(
click
)="
dowloadExam
(
examFileName
)"
>
(
click
)="
dow
n
loadExam
(
examFileName
)"
>
ดาวน์โหลดไฟล์ข้อสอบ
</h1>
</div>
</mat-dialog-content>
...
...
src/app/components/competency-assessment/name-registration/competency-topic/competency-topic.component.ts
View file @
396dec01
...
...
@@ -102,12 +102,12 @@ export class CompetencyTopic implements OnInit {
private
cdr
:
ChangeDetectorRef
,
private
fileService
:
FileService
,
private
competencytopicService
:
CompetencytopicService
,
//
private competencytypeService: CompetencytypeService,
private
competencytypeService
:
CompetencytypeService
,
private
tokenService
:
TokenService
)
{
}
ngOnInit
():
void
{
this
.
getCompetencytopicList
()
//
this.getCompetencytypeList()
this
.
getCompetencytypeList
()
}
onExamSelected
(
event
:
any
)
{
...
...
@@ -140,8 +140,8 @@ export class CompetencyTopic implements OnInit {
dowloadExam
(
fileName
:
string
)
{
this
.
fileService
.
dowloadFiles
(
fileName
).
subscribe
({
dow
n
loadExam
(
fileName
:
string
)
{
this
.
fileService
.
dow
n
loadFiles
(
fileName
).
subscribe
({
next
:
response
=>
{
const
url
=
window
.
URL
.
createObjectURL
(
response
);
const
a
=
document
.
createElement
(
"a"
);
...
...
@@ -176,7 +176,7 @@ export class CompetencyTopic implements OnInit {
next
:
response
=>
{
if
(
response
.
success
)
{
this
.
showAlert
(
response
.
message
,
'success'
)
//
this.getCompetencytypeList()
this
.
getCompetencytypeList
()
this
.
getCompetencytopicList
()
}
else
{
this
.
showAlert
(
response
.
message
,
'error'
)
...
...
@@ -211,23 +211,20 @@ export class CompetencyTopic implements OnInit {
}
getCompetencytypeList
()
{
// this.competencytypeListLoading = true
// this.selectedItems.data.clear()
// this.competencytypeService.getList().subscribe({
// next: response => {
// this.typeList = response.map(x => {
// this.selectedItems.data.set(x.competencyTypeId, false)
// return new MyCompetencytypeModel(x)
// })
// this.selectedItems.key = 'competencyTypeId'
// this.selectedItems.count = 0
// this.competencytypeListLoading = false
// this.cdr.detectChanges()
// }, error: error => {
// this.competencytypeListLoading = false
// this.cdr.detectChanges()
// }
// })
this
.
competencytypeListLoading
=
true
this
.
selectedItems
.
data
.
clear
()
this
.
competencytypeService
.
getList
().
subscribe
({
next
:
response
=>
{
this
.
typeList
=
response
.
map
(
x
=>
{
return
new
MyCompetencytypeModel
(
x
)
})
this
.
competencytypeListLoading
=
false
this
.
cdr
.
detectChanges
()
},
error
:
error
=>
{
this
.
competencytypeListLoading
=
false
this
.
cdr
.
detectChanges
()
}
})
}
...
...
@@ -292,7 +289,7 @@ export class CompetencyTopic implements OnInit {
next
:
response
=>
{
if
(
response
.
success
)
{
this
.
showAlert
(
response
.
message
,
'success'
);
//
this.getCompetencytypeList();
this
.
getCompetencytypeList
();
this
.
getCompetencytopicList
();
this
.
closeDialog
()
}
else
{
...
...
@@ -355,7 +352,7 @@ export class CompetencyTopic implements OnInit {
this
.
competencyTopic
.
loading
=
false
;
if
(
response
.
success
)
{
this
.
showAlert
(
response
.
message
,
'success'
);
//
this.getCompetencytypeList();
this
.
getCompetencytypeList
();
this
.
getCompetencytopicList
();
}
else
{
this
.
showAlert
(
response
.
message
,
'error'
);
...
...
@@ -370,7 +367,7 @@ export class CompetencyTopic implements OnInit {
});
}
});
}
}
showAlert
(
text
:
string
,
type
:
'success'
|
'error'
)
{
...
...
src/app/components/setting-individual-kpi/setting-individual-kpi.component.html
View file @
396dec01
...
...
@@ -289,7 +289,7 @@
<ng-container
*
ngIf=
"true"
>
<button
type=
"button"
class=
"flex text-start items-center cursor-default"
>
<i
class=
"ti ti-circle-plus text-green-500 cursor-pointer"
style=
"font-size: 20px;"
data-hs-overlay=
"#assessment-table-modal
"
></i>
(
click
)="
assessmentDialogOpen
()
"
></i>
</button>
</ng-container>
<ng-container
*
ngIf=
"false"
>
...
...
@@ -373,7 +373,8 @@
</tr>
<tr>
<td
class=
"py-2 text-center"
style=
"vertical-align: center;justify-items:center"
colspan=
"6"
>
<button
type=
"button"
class=
"flex text-start items-center cursor-default"
>
<button
type=
"button"
class=
"flex text-start items-center cursor-default"
(
click
)="
competencyTopicDialogOpen
()"
>
<i
class=
"ti ti-circle-plus text-green-500 cursor-pointer"
style=
"font-size: 20px;"
></i>
</button>
</td>
...
...
@@ -387,28 +388,17 @@
</ng-template>
<div
id=
"assessment-table-modal"
class=
"hs-overlay hidden ti-modal"
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out lg:!max-w-4xl lg:w-full m-3 lg:!mx-auto !max-w-3/4"
>
<div
class=
"max-h-full overflow-hidden ti-modal-content"
>
<div
class=
"ti-modal-header"
>
<h3
class=
"text-xxl font-bold text-primary"
>
<ng-template
#
assessmentDialog
let-modal
>
<h3
mat-dialog-title
>
รายการประเมิน
</h3>
<div
class=
"flex justify-end"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-modal-clode-btn text-danger"
data-hs-overlay=
"#assessment-table-modal"
>
<span
class=
"sr-only"
>
Close
</span>
<i
class=
"ti ti-circle-x fs-xxl"
></i>
</button>
</div>
</div>
<div
class=
"ti-modal-body"
>
<mat-dialog-content>
<div
class=
"flex justify-end pb-1rem"
>
<div
class=
"px-1"
>
<div
class=
"relative shadow-md"
>
<input
type=
"text"
id=
"hs-leading-icon"
name=
"hs-leading-icon"
class=
"ti-form-input ltr:pl-11 rtl:pr-11 focus:z-10 "
placeholder=
"Search by No. or Name"
[(
ngModel
)]="
modal
.
search
"
(
ngModelChange
)="
searchModalChange
(
pmstopicListFilter
())
"
>
[(
ngModel
)]="
modalData
.
search
"
>
<div
class=
"absolute inset-y-0 ltr:left-0 rtl:right-0 flex items-center pointer-events-none z-20 ltr:pl-4 rtl:pr-4"
>
<i
class=
"ri-search-line text-gray"
></i>
...
...
@@ -416,9 +406,7 @@
</div>
</div>
</div>
<div
class=
"page px-rem"
>
<div
class=
"overflow-auto table-bordered rounded-t-md"
>
<div
class=
"overflow-auto shadow-md rounded-t-md"
>
<div
class=
"overflow-auto border"
>
<table
class=
"ti-custom-table ti-custom-table-head ti-custom-table-hover"
>
<thead>
<tr>
...
...
@@ -452,15 +440,14 @@
</tbody>
<tbody
*
ngIf=
"!pmstopic.loading&&pmstopicListFilter().length"
>
<tr
*
ngFor=
"let item of pmstopicListFilter() | slice:((modal.currentPage-1) * 10) : (((modal
.currentPage-1) * 10) + 10);let i = index"
>
*
ngFor=
"let item of pmstopicListFilter() | slice:((modalData.currentPage-1) * 10) : (((modalData
.currentPage-1) * 10) + 10);let i = index"
>
<td
class=
"text-center"
>
{{item.data.pmsTopicId}}
</td>
<td>
{{item.data.tdesc}}
</td>
<td>
{{item.data.pmsType.tdesc}}
</td>
<td>
{{item.data.weight}}
</td>
<td
class=
"text-center"
>
<button
type=
"button"
class=
"ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md"
<td
class=
"text-center"
>
<button
type=
"button"
class=
"ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md"
data-hs-overlay=
"#assessment-table-modal"
(
click
)="
selectPmstopic
(
item
.
data
)"
>
<i
class=
"ri-add-line"
></i>
Select
...
...
@@ -469,55 +456,162 @@
</tbody>
</table>
</div>
<app-pagination
[
totalItems
]="
pmstopicListFilter
().
length
"
[
pageSize
]="
modalData
.
pageSize
"
(
pageChange
)="
modalData
.
currentPage =
$event"
(
pageSizeChange
)="
modalData
.
pageSize =
$event;modalData.currentPage
=
1
"
></app-pagination>
</mat-dialog-content>
<mat-dialog-actions
align=
"end"
>
<button
type=
"button"
mat-button
[
mat-dialog-close
]
(
click
)="
assessmentDialogClose
()"
class=
"hs-dropdown-toggle ti-btn ti-border font-medium bg-white text-gray-700 shadow-sm align-middle hover:bg-gray-50 focus:ring-offset-white focus:ring-primary dark:bg-bgdark dark:hover:bg-black/20 dark:border-white/10 dark:text-white/70 dark:hover:text-white dark:focus:ring-offset-white/10"
>
ย้อนกลับ
</button>
</mat-dialog-actions>
</ng-template>
<ng-template
#
competencyTopicDialog
let-modal
>
<h3
mat-dialog-title
>
เพิ่ม Individual KPI
</h3>
<div
class=
"w-full flex justify-end mb-1rem"
>
<div
class=
"absolute flex"
>
<div
class=
"px-1"
>
<button
type=
"button"
class=
"ti-btn ti-btn-soft-indigo h-45px m-0 shadow-md"
>
<i
class=
"ti ti-eraser text-base"
></i>
Clear
</button>
</div>
</div>
<nav
class=
"pagination-style-3 my-5"
*
ngIf=
"modal.page.length"
>
<ul
class=
"ti-pagination"
>
<li>
<a
aria-label=
"anchor"
class=
"page-link"
href=
"javascript:void(0);"
(
click
)="
modal
.
currentPage =
(modal.currentPage-1
||
1
)"
>
<i
class=
"ri-arrow-left-s-line align-middle rtl:rotate-180"
></i>
</a>
</li>
<li
*
ngFor=
"let item of modal.page;let f = first;let l = last"
>
<ng-container
*
ngIf=
"item==3&&modal.currentPage!=1&&modal.currentPage!=2&&modal.currentPage!=3"
>
<a
aria-label=
"anchor"
class=
"page-link"
href=
"javascript:void(0);"
><i
class=
"ri-more-line"
></i>
</a>
</ng-container>
<ng-container
*
ngIf=
"(f||l)||(item==modal.currentPage-1||item==modal.currentPage||item==modal.currentPage+1)"
>
<a
class=
"page-link"
href=
"javascript:void(0);"
[
class
.
active
]="
item=
=modal.currentPage"
(
click
)="
modal
.
currentPage=
item"
>
{{item}}
</a>
</ng-container>
<ng-container
*
ngIf=
"item==modal.page.length-2&&modal.currentPage!=modal.page.length&&modal.currentPage!=modal.page.length-1&&modal.currentPage!=modal.page.length-2"
>
<a
aria-label=
"anchor"
class=
"page-link"
href=
"javascript:void(0);"
><i
class=
"ri-more-line"
></i>
</a>
</ng-container>
</li>
<li>
<a
aria-label=
"anchor"
class=
"page-link"
href=
"javascript:void(0);"
(
click
)="
modal
.
currentPage =
(modal.currentPage
>
modal.page.length-1 ? modal.currentPage: modal.currentPage+1 )">
<i
class=
"ri-arrow-right-s-line align-middle rtl:rotate-180"
></i>
</a>
</li>
</ul>
<ul
class=
"nav-tabs mt-3"
>
<span>
Show {{((modal.currentPage-1) * 10)+1}} to {{pmstopicListFilter().length
<10
?
pmstopicListFilter
().
length:
(
modal
.
currentPage=
=modal.page.length
?
((
modal
.
currentPage
*
10
)
-
((
modal
.
currentPage
*
10
)
-
pmstopicListFilter
().
length
)
)
:
(
modal
.
currentPage
*
10
)
)
}}
of
{{
pmstopicListFilter
().
length
}}
items
</
span
>
</ul>
</nav>
</div>
<div
class=
"flex justify-end mt-2rem mb-1rem space-x-4"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-border font-medium bg-white text-gray-700 shadow-sm align-middle hover:bg-gray-50 focus:ring-offset-white focus:ring-primary dark:bg-bgdark dark:hover:bg-black/20 dark:border-white/10 dark:text-white/70 dark:hover:text-white dark:focus:ring-offset-white/10"
data-hs-overlay=
"#assessment-table-modal"
>
</div>
<mat-dialog-content>
<label
for=
"detail_th"
class=
"ti-form-label mt-2rem"
>
ชื่อหัวข้อ (ไทย)
<span
class=
"text-danger"
>
*
</span></label>
<input
type=
"text"
id=
"detail_th"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyTopic
.
select
.
tdesc
"
>
<label
for=
"detail_eng"
class=
"ti-form-label mt-2rem"
>
ชื่อหัวข้อ (อังกฤษ)
</label>
<input
type=
"text"
id=
"detail_eng"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyTopic
.
select
.
edesc
"
>
<label
for=
"detail_eng"
class=
"ti-form-label mt-2rem"
>
นิยามสมรรถนะ
</label>
<textarea
type=
"text"
id=
"detail_eng"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
[(
ngModel
)]="
competencyTopic
.
select
.
competencyDetail
"
>
</textarea>
<label
class=
"ti-form-label mt-2rem"
>
ประเภท Competency
<span
class=
"text-danger"
>
*
</span></label>
<div
class=
"flex"
>
<div
class=
"relative flex rounded-md w-1/2"
>
<input
type=
"text"
id=
"hs-leading-button-add-on-with-icon-and-button"
name=
"hs-leading-button-add-on-with-icon-and-button"
class=
"ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10"
style=
"padding-right: 2.5rem;"
readonly
[(
ngModel
)]="
competencyTopic
.
select
.
competencyType
.
shortName
"
>
<div
class=
"absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2"
>
<button
type=
"button"
class=
"flex items-center text-red-500"
(
click
)="
selectCompetencytype
()"
>
<i
class=
"ti ti-circle-x cursor-pointer"
></i>
</button>
<button
type=
"button"
class=
"flex items-center text-gray-500 dark:text-white/70"
(
click
)="
competencyTypeDialogOpen
()"
>
<i
class=
"ri-search-line cursor-pointer text-gray"
></i>
</button>
</div>
</div>
</div>
<label
class=
"ti-form-label mt-2rem"
>
แนบไฟล์ข้อสอบ
</label>
<div
class=
"flex rounded-md"
>
<label
class=
"sr-only"
>
อัปโหลดไฟล์
</label>
<input
#
fileInputMedium
id=
"fileInputMedium"
type=
"file"
(
change
)="
onExamSelected
($
event
)"
hidden
>
<input
type=
"text"
[
value
]="
examFileName
"
readonly
onclick=
"fileInputMedium.click();"
class=
" cursor-pointer block w-full border border-gray-200 focus:shadow-sm dark:focus:shadow-white/10 ltr:rounded-l-md rtl:rounded-r-none text-sm focus:z-10 focus:outline-0 focus:border-gray-200 dark:focus:border-white/10 dark:border-white/10 dark:text-white/70 file:border-0 file:bg-gray-100 ltr:file:mr-4 rtl:file:ml-4 file:py-3 file:px-4 dark:file:bg-black/20 dark:file:text-white/70"
>
<span
class=
"px-4 inline-flex items-center min-w-fit ltr:rounded-r-md rtl:rounded-l-none border ltr:border-l-0 rtl:border-r-0 border-gray-200 bg-gray-50 text-sm dark:bg-black/20 dark:border-white/10"
>
<button
class=
"text-sm text-gray-500 dark:text-white/70"
onclick=
"fileInputMedium.click();"
>
Browse
</button>
</span>
<div
class=
"flex items-center ml-2"
>
<button
href=
"javascript:void(0);"
class=
"ti-btn ti-btn-soft-danger h-10px m-0 shadow-md rounded-md"
(
click
)="
fileInputMedium
.
value =
''
;
examFile=
null;examFileName
=
'กรุณาเลือกไฟล์'"
>
<i
class=
"ri-delete-bin-6-line"
></i>
Delete
</button>
</div>
</div>
<div
class=
"flex"
*
ngIf=
"examFileName==competencyTopic.select.competencyFiles"
>
<h1
class=
"cursor-pointer justify-center -mb-px inline-flex items-center gap-2 font-weight-500 font-size-12px
text-center text-secondary border-secondary border-b-2 align-items-end"
(
click
)="
downloadExam
(
examFileName
)"
>
ดาวน์โหลดไฟล์ข้อสอบ
</h1>
</div>
</mat-dialog-content>
<mat-dialog-actions
align=
"end"
>
<button
type=
"button"
mat-button
[
mat-dialog-close
]
class=
"hs-dropdown-toggle ti-btn ti-border font-medium bg-white text-gray-700 shadow-sm align-middle hover:bg-gray-50 focus:ring-offset-white focus:ring-primary dark:bg-bgdark dark:hover:bg-black/20 dark:border-white/10 dark:text-white/70 dark:hover:text-white dark:focus:ring-offset-white/10"
>
ย้อนกลับ
</button>
<button
type=
"button"
class=
"ti-btn ti-btn-success"
mat-button
(
click
)="
confirmCompetencyTopic
()"
[
class
.
ti-btn-disabled
]="!
competencyTopic
.
select
.
competencyType
.
competencyTypeId
||!
competencyTopic
.
select
.
tdesc
||!
competencyTopic
.
select
.
competencyType
.
shortName
"
[
disabled
]="!
competencyTopic
.
select
.
competencyType
.
competencyTypeId
||!
competencyTopic
.
select
.
tdesc
||!
competencyTopic
.
select
.
competencyType
.
shortName
"
>
บันทึกข้อมูล
</button>
</mat-dialog-actions>
</ng-template>
<ng-template
#
competencyTypeDialog
let-modal
>
<h3
mat-dialog-title
>
ประเภทสมรรถนะ
</h3>
<mat-dialog-content>
<div
class=
"flex justify-end pb-1rem"
>
<div
class=
"px-1"
>
<div
class=
"relative shadow-md"
>
<input
type=
"text"
id=
"hs-leading-icon"
name=
"hs-leading-icon"
class=
"ti-form-input ltr:pl-11 rtl:pr-11 focus:z-10 "
placeholder=
"Search by No. or Name"
[(
ngModel
)]="
modalData
.
search
"
>
<div
class=
"absolute inset-y-0 ltr:left-0 rtl:right-0 flex items-center pointer-events-none z-20 ltr:pl-4 rtl:pr-4"
>
<i
class=
"ri-search-line text-gray"
></i>
</div>
</div>
</div>
</div>
<div
class=
"overflow-auto border"
>
<table
class=
"ti-custom-table ti-custom-table-head ti-custom-table-hover"
>
<thead>
<tr>
<ng-container
*
ngFor=
"let item of ['รหัส','ชื่อประเภท','ชื่อย่อ','การจัดการ']; let f = first; let l = last"
>
<th
scope=
"col"
class=
"relative px-10px py-10px bg-soft-secondary text-primary !text-center"
>
<span
class=
"text-sm"
>
{{ item }}
</span>
<div
class=
"absolute top-1/2 transform -translate-y-1/2 right-0"
*
ngIf=
"!l"
>
<i
class=
"ti ti-dots-vertical fs-l"
></i>
</div>
</div>
\ No newline at end of file
</th>
</ng-container>
</tr>
</thead>
<tbody
*
ngIf=
"!competencytypeListFilter().length"
>
<tr>
<td
class=
"text-center"
colspan=
"100%"
>
ไม่พบข้อมูล
</td>
</tr>
</tbody>
<tbody
*
ngIf=
"competencytypeListFilter().length"
>
<tr
*
ngFor=
"let item of competencytypeListFilter()| slice:((modalData.currentPage-1) * 10) : (((modalData.currentPage-1) * 10) + 10);let i = index"
>
<td>
{{item.competencyTypeId}}
</td>
<td>
{{item.tdesc}}
</td>
<td>
{{item.shortName}}
</td>
<td
class=
"flex justify-center"
>
<div
class=
"px-1"
>
<button
type=
"button"
class=
"ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md"
(
click
)="
selectCompetencytype
(
item
)"
>
<i
class=
"ri-add-line"
></i>
Select
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<app-pagination
[
totalItems
]="
competencytypeListFilter
().
length
"
[
pageSize
]="
modalData
.
pageSize
"
(
pageChange
)="
modalData
.
currentPage =
$event"
(
pageSizeChange
)="
modalData
.
pageSize =
$event;modalData.currentPage
=
1
"
></app-pagination>
</mat-dialog-content>
<mat-dialog-actions
align=
"end"
>
<button
type=
"button"
mat-button
[
mat-dialog-close
]
class=
"hs-dropdown-toggle ti-btn ti-border font-medium bg-white text-gray-700 shadow-sm align-middle hover:bg-gray-50 focus:ring-offset-white focus:ring-primary dark:bg-bgdark dark:hover:bg-black/20 dark:border-white/10 dark:text-white/70 dark:hover:text-white dark:focus:ring-offset-white/10"
>
ย้อนกลับ
</button>
</mat-dialog-actions>
</ng-template>
\ No newline at end of file
src/app/components/setting-individual-kpi/setting-individual-kpi.component.ts
View file @
396dec01
import
{
ChangeDetectorRef
,
Component
,
EventEmitter
,
Input
,
Output
}
from
'@angular/core'
;
import
{
ChangeDetectorRef
,
Component
,
EventEmitter
,
Input
,
Output
,
ViewChild
}
from
'@angular/core'
;
import
{
MatDialog
,
MatDialogRef
}
from
'@angular/material/dialog'
;
import
{
Router
,
ActivatedRoute
}
from
'@angular/router'
;
import
{
CompetencytopicModel
,
MyCompetencytopicModel
}
from
'src/app/shared/model/competencytopic.model'
;
import
{
CompetencytypeModel
,
MyCompetencytypeModel
}
from
'src/app/shared/model/competencytype.model'
;
import
{
EmployeeModel
,
MyEmployeeModel
}
from
'src/app/shared/model/employee.model'
;
import
{
MyPmsGroupAssessment1Model
}
from
'src/app/shared/model/pms-group-assessment1.model'
;
import
{
MyPmstopicModel
,
PmstopicModel
}
from
'src/app/shared/model/pmstopic.model'
;
import
{
AppraisalService
}
from
'src/app/shared/services/appraisal.service'
;
import
{
CompetencytopicService
}
from
'src/app/shared/services/competencytopic.service'
;
import
{
CompetencytypeService
}
from
'src/app/shared/services/competencytype.service'
;
import
{
EmployeeService
}
from
'src/app/shared/services/employee.service'
;
import
{
FileService
}
from
'src/app/shared/services/file.service'
;
import
{
PmstopicService
}
from
'src/app/shared/services/pmstopic.service'
;
import
{
TokenService
}
from
'src/app/shared/services/token.service'
;
export
interface
DataModal
{
import
Swal
from
'sweetalert2'
;
export
interface
ModalData
{
search
:
string
,
currentPage
:
number
,
page
:
number
[]
page
Size
:
number
}
@
Component
({
selector
:
'app-setting-individual-kpi'
,
...
...
@@ -20,20 +26,31 @@ export interface DataModal {
})
export
class
SettingIndividualKpiComponent
{
@
Input
()
evaluateeId
=
""
individualKPI
:
{
loading
:
boolean
,
list
:
any
[]
}
=
{
loading
:
false
,
list
:
[]
}
@
Input
()
evaluationForm
:
'self'
|
'sup'
=
"self"
@
Output
()
sendReturnPath
:
EventEmitter
<
any
>
=
new
EventEmitter
<
any
>
();
@
ViewChild
(
"assessmentDialog"
)
assessmentDialog
:
any
;
@
ViewChild
(
"competencyTypeDialog"
)
competencyTypeDialog
:
any
;
@
ViewChild
(
"competencyTopicDialog"
)
competencyTopicDialog
:
any
;
@
ViewChild
(
"fileInputMedium"
)
fileInputMedium
:
any
;
examFile
:
File
|
null
=
null
;
examFileName
:
string
=
'กรุณาเลือกไฟล์'
;
assessmentDialogRef
?:
MatDialogRef
<
unknown
,
any
>
competencyTypeDialogRef
?:
MatDialogRef
<
unknown
,
any
>
competencyTopicDialogRef
?:
MatDialogRef
<
unknown
,
any
>
competencytype
:
{
loading
:
boolean
,
select
:
CompetencytypeModel
,
dataList
:
CompetencytypeModel
[]
}
=
{
loading
:
false
,
select
:
new
MyCompetencytypeModel
({}),
dataList
:
[]
}
competencyTopic
:
{
loading
:
boolean
,
select
:
CompetencytopicModel
,
dataList
:
CompetencytopicModel
[]
}
=
{
loading
:
false
,
select
:
new
MyCompetencytopicModel
({}),
dataList
:
[]
}
evaluatee
:
{
loading
:
boolean
,
data
:
EmployeeModel
}
=
{
loading
:
false
,
data
:
new
MyEmployeeModel
()
}
pmstopic
:
{
loading
:
boolean
,
select
:
PmstopicModel
,
dataList
:
{
check
:
boolean
,
data
:
PmstopicModel
}[]
}
=
{
loading
:
false
,
select
:
new
MyPmstopicModel
(),
dataList
:
[]
}
individualKPI
:
{
loading
:
boolean
,
list
:
any
[]
}
=
{
loading
:
false
,
list
:
[]
}
menuClose
:
Map
<
string
,
boolean
>
=
new
Map
<
string
,
boolean
>
()
tableHover
:
Map
<
string
,
boolean
>
=
new
Map
<
string
,
boolean
>
()
evaluatee
:
{
loading
:
boolean
,
data
:
EmployeeModel
}
=
{
loading
:
false
,
data
:
new
MyEmployeeModel
()
}
@
Output
()
sendReturnPath
:
EventEmitter
<
any
>
=
new
EventEmitter
<
any
>
();
modal
:
DataModal
=
{
modalData
:
ModalData
=
{
search
:
""
,
currentPage
:
1
,
page
:
Array
.
from
({
length
:
1
},
(
_
,
i
)
=>
i
+
1
)
page
Size
:
10
}
pmstopic
:
{
loading
:
boolean
,
select
:
PmstopicModel
,
dataList
:
{
check
:
boolean
,
data
:
PmstopicModel
}[]
}
=
{
loading
:
false
,
select
:
new
MyPmstopicModel
(),
dataList
:
[]
}
constructor
(
private
dialog
:
MatDialog
,
private
router
:
Router
,
private
employeeService
:
EmployeeService
,
private
appraisalService
:
AppraisalService
,
...
...
@@ -41,47 +58,43 @@ export class SettingIndividualKpiComponent {
private
tokenService
:
TokenService
,
private
route
:
ActivatedRoute
,
private
fileService
:
FileService
,
private
pmstopicService
:
PmstopicService
)
{
}
private
pmstopicService
:
PmstopicService
,
private
competencytopicService
:
CompetencytopicService
,
private
competencytypeService
:
CompetencytypeService
)
{
}
ngOnInit
():
void
{
this
.
getEvaluatee
()
this
.
getPmstopicList
()
this
.
getCompetencytypeList
()
}
get
Evaluatee
()
{
this
.
evaluate
e
.
loading
=
true
this
.
employeeService
.
getWorkingById
(
this
.
evaluateeId
).
subscribe
({
get
CompetencytypeList
()
{
this
.
competencytyp
e
.
loading
=
true
this
.
competencytypeService
.
getList
(
).
subscribe
({
next
:
response
=>
{
this
.
evaluatee
.
data
=
new
MyEmployeeModel
(
response
)
this
.
evaluatee
.
loading
=
false
this
.
competencytype
.
dataList
=
response
.
map
(
x
=>
{
return
new
MyCompetencytypeModel
(
x
)
})
this
.
competencytype
.
loading
=
false
this
.
cdr
.
detectChanges
()
},
error
:
error
=>
{
this
.
evaluate
e
.
loading
=
false
this
.
competencytyp
e
.
loading
=
false
this
.
cdr
.
detectChanges
()
}
})
}
returnPath
()
{
this
.
sendReturnPath
.
emit
()
}
getImg
(
text
:
string
)
{
return
this
.
fileService
.
getImg
(
text
)
competencytypeListFilter
()
{
return
this
.
competencytype
.
dataList
.
filter
(
x
=>
x
.
competencyTypeId
.
toLowerCase
().
includes
(
this
.
modalData
.
search
.
toLowerCase
())
||
x
.
tdesc
.
toLowerCase
().
includes
(
this
.
modalData
.
search
.
toLowerCase
())
||
x
.
shortName
.
toLowerCase
().
includes
(
this
.
modalData
.
search
.
toLowerCase
()))
}
onImageError
(
event
:
Event
)
{
const
imgElement
=
event
.
target
as
HTMLImageElement
;
imgElement
.
src
=
'./assets/img/users/defaultperson.jpg'
;
}
searchModalChange
(
dataList
:
any
[])
{
this
.
modal
.
currentPage
=
1
this
.
modal
.
page
=
Array
.
from
({
length
:
Math
.
ceil
(
dataList
.
length
/
10
)
},
(
_
,
i
)
=>
i
+
1
);
selectCompetencytype
(
data
?:
CompetencytypeModel
)
{
this
.
competencyTopic
.
select
.
competencyType
=
new
MyCompetencytypeModel
(
data
)
this
.
cdr
.
markForCheck
()
this
.
competencyTypeDialogClose
()
}
getPmstopicList
()
{
this
.
pmstopic
.
loading
=
true
this
.
pmstopicService
.
getList
().
subscribe
({
...
...
@@ -98,14 +111,353 @@ export class SettingIndividualKpiComponent {
pmstopicListFilter
()
{
return
this
.
pmstopic
.
dataList
.
filter
(
x
=>
{
const
data
=
x
.
data
const
match
=
data
.
pmsTopicId
.
toLowerCase
().
includes
(
this
.
modal
.
search
.
toLowerCase
())
||
data
.
tdesc
.
toLowerCase
().
includes
(
this
.
modal
.
search
.
toLowerCase
())
||
data
.
pmsType
.
tdesc
.
toLowerCase
().
includes
(
this
.
modal
.
search
.
toLowerCase
())
||
(
data
.
weight
+
""
).
toLowerCase
().
includes
(
this
.
modal
.
search
.
toLowerCase
())
const
match
=
data
.
pmsTopicId
.
toLowerCase
().
includes
(
this
.
modal
Data
.
search
.
toLowerCase
())
||
data
.
tdesc
.
toLowerCase
().
includes
(
this
.
modal
Data
.
search
.
toLowerCase
())
||
data
.
pmsType
.
tdesc
.
toLowerCase
().
includes
(
this
.
modal
Data
.
search
.
toLowerCase
())
||
(
data
.
weight
+
""
).
toLowerCase
().
includes
(
this
.
modal
Data
.
search
.
toLowerCase
())
return
match
})
}
selectPmstopic
(
data
?:
PmstopicModel
)
{
this
.
cdr
.
markForCheck
()
}
assessmentDialogOpen
()
{
this
.
modalData
.
search
=
''
this
.
modalData
.
currentPage
=
1
this
.
modalData
.
pageSize
=
10
this
.
assessmentDialogRef
=
this
.
dialog
.
open
(
this
.
assessmentDialog
,
{
width
:
'80vw'
,
disableClose
:
false
,
});
}
assessmentDialogClose
()
{
this
.
assessmentDialogRef
?.
close
()
}
competencyTypeDialogOpen
()
{
this
.
modalData
.
search
=
''
this
.
modalData
.
currentPage
=
1
this
.
modalData
.
pageSize
=
10
this
.
competencyTypeDialogRef
=
this
.
dialog
.
open
(
this
.
competencyTypeDialog
,
{
width
:
'80vw'
,
disableClose
:
false
,
});
}
competencyTypeDialogClose
()
{
this
.
competencyTypeDialogRef
?.
close
()
}
competencyTopicDialogOpen
()
{
if
(
this
.
fileInputMedium
)
{
this
.
fileInputMedium
.
value
=
""
}
this
.
competencyTopicDialogRef
=
this
.
dialog
.
open
(
this
.
competencyTopicDialog
,
{
width
:
'50vw'
,
disableClose
:
false
,
});
}
competencyTopicDialogClose
()
{
this
.
competencyTypeDialogRef
?.
close
()
}
getEvaluatee
()
{
this
.
evaluatee
.
loading
=
true
this
.
employeeService
.
getWorkingById
(
this
.
evaluateeId
).
subscribe
({
next
:
response
=>
{
this
.
evaluatee
.
data
=
new
MyEmployeeModel
(
response
)
this
.
evaluatee
.
loading
=
false
this
.
cdr
.
detectChanges
()
},
error
:
error
=>
{
this
.
evaluatee
.
loading
=
false
this
.
cdr
.
detectChanges
()
}
})
}
getImg
(
text
:
string
)
{
return
this
.
fileService
.
getImg
(
text
)
}
onImageError
(
event
:
Event
)
{
const
imgElement
=
event
.
target
as
HTMLImageElement
;
imgElement
.
src
=
'./assets/img/users/defaultperson.jpg'
;
}
returnPath
()
{
this
.
sendReturnPath
.
emit
()
}
onExamSelected
(
event
:
any
)
{
this
.
examFile
=
event
.
target
.
files
.
length
>
0
?
event
.
target
.
files
[
0
]
:
null
;
this
.
examFileName
=
this
.
examFile
?.
name
||
"กรุณาเลือกไฟล์"
}
downloadExam
(
fileName
:
string
)
{
this
.
fileService
.
downloadFiles
(
fileName
).
subscribe
({
next
:
response
=>
{
const
url
=
window
.
URL
.
createObjectURL
(
response
);
const
a
=
document
.
createElement
(
"a"
);
a
.
href
=
url
;
a
.
download
=
fileName
;
document
.
body
.
appendChild
(
a
);
a
.
click
();
document
.
body
.
removeChild
(
a
);
window
.
URL
.
revokeObjectURL
(
url
);
this
.
cdr
.
detectChanges
()
},
error
:
error
=>
{
this
.
showAlert
(
error
.
message
,
'error'
)
this
.
cdr
.
detectChanges
()
}
})
}
showAlert
(
text
:
string
,
type
:
'success'
|
'error'
)
{
Swal
.
fire
({
title
:
'แจ้งเตือน'
,
text
:
text
,
icon
:
type
,
confirmButtonText
:
'ตกลง'
,
});
}
confirmCompetencyTopic
()
{
Swal
.
fire
({
icon
:
'question'
,
title
:
'แจ้งเตือน'
,
text
:
'ยืนยันการบันทึกข้อมูลหรือไม่'
,
showCancelButton
:
true
,
confirmButtonText
:
'บันทึกข้อมูล'
,
cancelButtonText
:
'ย้อนกลับ'
,
reverseButtons
:
true
,
}).
then
(
result
=>
{
if
(
result
.
isConfirmed
)
{
this
.
addCompetencyTopic
();
}
});
}
addCompetencyTopic
(
competencyFiles
?:
string
)
{
if
(
this
.
examFile
)
{
this
.
uploadExam
();
return
;
}
const
user
=
this
.
tokenService
.
getUser
();
const
body
=
new
MyCompetencytopicModel
({
...
this
.
competencyTopic
.
select
,
companyId
:
user
?.
companyid
,
competencyFiles
:
competencyFiles
||
((
this
.
examFileName
==
this
.
competencyTopic
.
select
.
competencyFiles
)
?
this
.
competencyTopic
.
select
.
competencyFiles
:
''
)
});
this
.
competencyTopic
.
loading
=
true
;
this
.
competencytopicService
.
post
(
body
).
subscribe
({
next
:
response
=>
{
if
(
response
.
success
)
{
this
.
showAlert
(
response
.
message
,
'success'
);
this
.
getCompetencytypeList
();
this
.
competencyTopicDialogClose
()
}
else
{
this
.
showAlert
(
response
.
message
,
'error'
);
this
.
competencyTopic
.
loading
=
false
;
this
.
cdr
.
detectChanges
();
}
},
error
:
error
=>
{
this
.
showAlert
(
error
.
message
,
'error'
);
this
.
competencyTopic
.
loading
=
false
;
this
.
cdr
.
detectChanges
();
}
});
}
uploadExam
()
{
if
(
!
this
.
examFile
)
return
;
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
this
.
examFile
);
this
.
fileService
.
uploadFiles
(
formData
).
subscribe
({
next
:
response
=>
{
if
(
response
.
success
)
{
this
.
examFile
=
null
;
this
.
addCompetencyTopic
(
response
.
resultObject
);
}
else
{
this
.
showAlert
(
response
.
message
,
'error'
);
this
.
cdr
.
detectChanges
();
}
},
error
:
error
=>
{
this
.
showAlert
(
error
.
message
,
'error'
);
this
.
cdr
.
detectChanges
();
}
});
}
//
//
// modal: DataModal = {
// search: "",
// currentPage: 1,
// page: Array.from({ length: 1 }, (_, i) => i + 1)
// }
//
// @ViewChild("addKpiDialog") addKpiDialog: any;
// addKpiDialogRef: any
// @ViewChild("competencyTypeTableDialog") competencyTypeTableDialog: any;
// competencyTypeTableDialogRef: any
// @ViewChild("fileInputMedium") fileInputMedium: any;
// examFile: File | null = null;
// examFileName: string = 'กรุณาเลือกไฟล์';
// typeModal: table = {
// currentPage: 1,
// page: Array.from({ length: 1 }, (_, i) => i + 1),
// search: "",
// pageSize: 10
// }
// constructor(
// private dialog: MatDialog,
// private router: Router,
// private employeeService: EmployeeService,
// private appraisalService: AppraisalService,
// private cdr: ChangeDetectorRef,
// private tokenService: TokenService,
// private route: ActivatedRoute,
// private fileService: FileService,
// private pmstopicService: PmstopicService,
// private competencytopicService: CompetencytopicService,
// private competencytypeService: CompetencytypeService
// ) {
// }
// getCompetencytypeList() {
// this.competencytype.loading = true
// this.competencytypeService.getList().subscribe({
// next: response => {
// this.competencytype.dataList = response.map(x => {
// return new MyCompetencytypeModel(x)
// })
// this.competencytype.loading = false
// this.cdr.detectChanges()
// }, error: error => {
// this.competencytype.loading = false
// this.cdr.detectChanges()
// }
// })
// }
// selectPmstopic(data?: PmstopicModel) {
// this.cdr.markForCheck()
// }
// searchCompetencytypeChange() {
// this.typeModal.currentPage = 1
// this.typeModal.page = Array.from({ length: Math.ceil(this.competencytypeListFilter().length / 10) }, (_, i) => i + 1);
// }
// openAddKpiDialog() {
// this.addKpiDialogRef = this.dialog.open(this.addKpiDialog, {
// width: '500px',
// disableClose: false,
// });
// }
// openCompetencyTypeTableDialog() {
// this.competencyTypeTableDialogRef = this.dialog.open(this.competencyTypeTableDialog, {
// width: '500px',
// disableClose: false,
// });
// }
// showAlert(text: string, type: 'success' | 'error') {
// Swal.fire({
// title: 'แจ้งเตือน',
// text: text,
// icon: type,
// confirmButtonText: 'ตกลง',
// });
// }
// onExamSelected(event: any) {
// this.examFile = event.target.files.length > 0 ? event.target.files[0] : null;
// this.examFileName = this.examFile?.name || "กรุณาเลือกไฟล์"
// }
// downloadExam(fileName: string) {
// this.fileService.downloadFiles(fileName).subscribe({
// next: response => {
// const url = window.URL.createObjectURL(response);
// const a = document.createElement("a");
// a.href = url;
// a.download = fileName;
// document.body.appendChild(a);
// a.click();
// document.body.removeChild(a);
// window.URL.revokeObjectURL(url);
// this.cdr.detectChanges()
// }, error: error => {
// this.showAlert(error.message, 'error')
// this.cdr.detectChanges()
// }
// })
// }
// confirmAddCompetency_topic() {
// Swal.fire({
// icon: 'question',
// title: 'แจ้งเตือน',
// text: 'ยืนยันการบันทึกข้อมูลหรือไม่',
// showCancelButton: true,
// confirmButtonText: 'บันทึกข้อมูล',
// cancelButtonText: 'ย้อนกลับ',
// reverseButtons: true,
// }).then(result => {
// if (result.isConfirmed) {
// this.addCompetency_topic();
// }
// });
// }
// addCompetency_topic(competencyFiles?: string) {
// if (this.examFile) {
// this.uploadExam();
// return;
// }
// const user = this.tokenService.getUser();
// const body = new MyCompetencytopicModel({
// ...this.competencyTopic.select,
// companyId: user?.companyid,
// competencyFiles: competencyFiles || ((this.examFileName == this.competencyTopic.select.competencyFiles) ? this.competencyTopic.select.competencyFiles : '')
// });
// this.competencyTopic.loading = true;
// this.competencytopicService.post(body).subscribe({
// next: response => {
// if (response.success) {
// this.showAlert(response.message, 'success');
// // this.getCompetencytopicList();
// // this.closeDialog()
// } else {
// this.showAlert(response.message, 'error');
// this.competencyTopic.loading = false;
// this.cdr.detectChanges();
// }
// },
// error: error => {
// this.showAlert(error.message, 'error');
// this.competencyTopic.loading = false;
// this.cdr.detectChanges();
// }
// });
// }
// uploadExam() {
// if (!this.examFile) return;
// const formData = new FormData();
// formData.append('file', this.examFile);
// this.fileService.uploadFiles(formData).subscribe({
// next: response => {
// if (response.success) {
// this.examFile = null;
// this.addCompetency_topic(response.resultObject);
// } else {
// this.showAlert(response.message, 'error');
// this.cdr.detectChanges();
// }
// },
// error: error => {
// this.showAlert(error.message, 'error');
// this.cdr.detectChanges();
// }
// });
// }
// selectCompetencytype(data: CompetencytypeModel) {
// this.competencyTopic.select.competencyType = JSON.parse(JSON.stringify(data));
// }
}
src/app/shared/services/file.service.ts
View file @
396dec01
...
...
@@ -12,7 +12,7 @@ export class FileService {
uploadFiles
(
formData
:
any
):
Observable
<
AlertModel
>
{
return
this
.
http
.
post
<
AlertModel
>
(
environment
.
baseUrl
+
'/files/upload'
,
formData
)
}
dowloadFiles
(
filename
:
string
)
{
dow
n
loadFiles
(
filename
:
string
)
{
return
this
.
http
.
get
(
environment
.
baseUrl
+
'/files/download/'
+
filename
,
{
responseType
:
"blob"
})
}
uploadExcel
(
formData
:
any
,
table
:
string
):
Observable
<
AlertModel
>
{
...
...
src/app/shared/services/navservice.ts
View file @
396dec01
...
...
@@ -122,26 +122,26 @@ export class NavService implements OnDestroy {
// { id: 'm12', path: 'ess/supervisor-evaluation', title: 'ประเมินโดยหัวหน้า', type: 'link', show: true },
// ],
},
//
{
//
title: 'แก้ไข Individual KPI ตนเอง',
//
type: 'link',
//
selected: false,
//
active: false,
//
path: 'ess/self-setting-individual-kpi',
//
id: 'm3',
// show: fals
e,
//
icon: ''
//
},
//
{
//
title: 'แก้ไข Individual KPI โดยหัวหน้า',
//
type: 'link',
//
selected: false,
//
active: false,
//
path: 'ess/supervisor-setting-individual-kpi',
//
id: 'm4',
// show: fals
e,
//
icon: ''
//
},
{
title
:
'แก้ไข Individual KPI ตนเอง'
,
type
:
'link'
,
selected
:
false
,
active
:
false
,
path
:
'ess/self-setting-individual-kpi'
,
id
:
'm3'
,
show
:
tru
e
,
icon
:
''
},
{
title
:
'แก้ไข Individual KPI โดยหัวหน้า'
,
type
:
'link'
,
selected
:
false
,
active
:
false
,
path
:
'ess/supervisor-setting-individual-kpi'
,
id
:
'm4'
,
show
:
tru
e
,
icon
:
''
},
];
}
...
...
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