Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
BookingMyHrManagement
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
Chanachai
BookingMyHrManagement
Commits
0987f285
Commit
0987f285
authored
Mar 18, 2025
by
Ooh-Ao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
จัดการสมาชิก
parent
d2625cfd
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
260 additions
and
243 deletions
+260
-243
project_member_controller.cpython-312.pyc
...ers/__pycache__/project_member_controller.cpython-312.pyc
+0
-0
project_member_controller.py
API-Fast/src/controllers/project_member_controller.py
+26
-6
member.cpython-312.pyc
API-Fast/src/models/__pycache__/member.cpython-312.pyc
+0
-0
project_member.cpython-312.pyc
...ast/src/models/__pycache__/project_member.cpython-312.pyc
+0
-0
member.py
API-Fast/src/models/member.py
+1
-1
project_member.py
API-Fast/src/models/project_member.py
+4
-18
project_member_routes.cpython-312.pyc
.../routes/__pycache__/project_member_routes.cpython-312.pyc
+0
-0
project_member_routes.py
API-Fast/src/routes/project_member_routes.py
+11
-1
project_member_schema.cpython-312.pyc
...schemas/__pycache__/project_member_schema.cpython-312.pyc
+0
-0
project_member_schema.py
API-Fast/src/schemas/project_member_schema.py
+4
-4
admin-project-emp-manage.component.html
...roject-emp-manage/admin-project-emp-manage.component.html
+124
-116
admin-project-emp-manage.component.ts
...-project-emp-manage/admin-project-emp-manage.component.ts
+71
-79
project-members.ts
Web-Manage/src/app/DPU/models/project-members.ts
+13
-10
project-members.service.ts
Web-Manage/src/app/DPU/services/project-members.service.ts
+6
-8
No files found.
API-Fast/src/controllers/__pycache__/project_member_controller.cpython-312.pyc
View file @
0987f285
No preview for this file type
API-Fast/src/controllers/project_member_controller.py
View file @
0987f285
...
...
@@ -24,15 +24,21 @@ async def create_project_member(db: AsyncSession, pm_in: ProjectMemberCreate):
raise
HTTPException
(
status_code
=
400
,
detail
=
str
(
e
.
orig
))
return
new_pm
# READ ALL (โหลดข้อมูล
ของ Project
ด้วย)
# READ ALL (โหลดข้อมูล
Project และ Member
ด้วย)
async
def
get_all_project_members
(
db
:
AsyncSession
):
stmt
=
select
(
ProjectMember
)
.
options
(
selectinload
(
ProjectMember
.
project
))
stmt
=
select
(
ProjectMember
)
.
options
(
selectinload
(
ProjectMember
.
project
),
selectinload
(
ProjectMember
.
member
)
)
result
=
await
db
.
execute
(
stmt
)
return
result
.
scalars
()
.
all
()
# READ ONE (โหลดข้อมูล
ของ Project
ด้วย)
# READ ONE (โหลดข้อมูล
Project และ Member
ด้วย)
async
def
get_project_member_by_id
(
db
:
AsyncSession
,
pm_id
:
UUID
):
stmt
=
select
(
ProjectMember
)
.
options
(
selectinload
(
ProjectMember
.
project
))
.
where
(
ProjectMember
.
pmId
==
pm_id
)
stmt
=
select
(
ProjectMember
)
.
options
(
selectinload
(
ProjectMember
.
project
),
selectinload
(
ProjectMember
.
member
)
)
.
where
(
ProjectMember
.
pmId
==
pm_id
)
result
=
await
db
.
execute
(
stmt
)
return
result
.
scalar_one_or_none
()
...
...
@@ -73,8 +79,22 @@ async def delete_project_member(db: AsyncSession, pm_id: UUID):
return
{
"message"
:
"ProjectMember deleted successfully"
}
# READ Projects by MemberId (โหลดข้อมูล Project
ที่สัมพันธ์กับ ProjectMember
ด้วย)
# READ Projects by MemberId (โหลดข้อมูล Project ด้วย)
async
def
get_projects_by_member_id
(
db
:
AsyncSession
,
member_id
:
UUID
):
stmt
=
select
(
ProjectMember
)
.
options
(
selectinload
(
ProjectMember
.
project
))
.
where
(
ProjectMember
.
memberId
==
member_id
)
stmt
=
select
(
ProjectMember
)
.
options
(
selectinload
(
ProjectMember
.
project
),
selectinload
(
ProjectMember
.
member
)
)
.
where
(
ProjectMember
.
memberId
==
member_id
)
result
=
await
db
.
execute
(
stmt
)
return
result
.
scalars
()
.
all
()
async
def
get_members_by_project_id
(
db
:
AsyncSession
,
project_id
:
UUID
):
"""
ดึงข้อมูล ProjectMember ทั้งหมดที่สัมพันธ์กับ project_id ที่กำหนด
พร้อมโหลดข้อมูลของ Member ด้วย (nested)
"""
stmt
=
select
(
ProjectMember
)
.
options
(
selectinload
(
ProjectMember
.
member
)
)
.
where
(
ProjectMember
.
projectId
==
project_id
)
result
=
await
db
.
execute
(
stmt
)
return
result
.
scalars
()
.
all
()
API-Fast/src/models/__pycache__/member.cpython-312.pyc
View file @
0987f285
No preview for this file type
API-Fast/src/models/__pycache__/project_member.cpython-312.pyc
View file @
0987f285
No preview for this file type
API-Fast/src/models/member.py
View file @
0987f285
...
...
@@ -34,7 +34,7 @@ class Member(Base):
updatedAt
=
Column
(
DateTime
,
nullable
=
False
,
default
=
datetime
.
utcnow
,
onupdate
=
datetime
.
utcnow
)
# ProjectEmployees = relationship("ProjectEmployee", back_populates="member")
project_member
=
relationship
(
"ProjectMember"
,
back_populates
=
"member"
)
# ฟังก์ชันเพื่อแฮชรหัสผ่านก่อนบันทึก
def
hash_password
(
self
,
password
):
self
.
passwordHash
=
bcrypt
.
hash
(
password
)
...
...
API-Fast/src/models/project_member.py
View file @
0987f285
...
...
@@ -10,23 +10,9 @@ class ProjectMember(Base):
__tablename__
=
'project_member'
pmId
=
Column
(
UUID
(
as_uuid
=
True
),
primary_key
=
True
,
default
=
uuid
.
uuid4
)
# Foreign Keys
memberId
=
Column
(
UUID
(
as_uuid
=
True
),
ForeignKey
(
"member.memberId"
),
# หรือ "users.userId" ตามตารางจริง
nullable
=
False
)
projectId
=
Column
(
UUID
(
as_uuid
=
True
),
ForeignKey
(
"project.projectId"
),
nullable
=
False
)
memberId
=
Column
(
UUID
(
as_uuid
=
True
),
ForeignKey
(
"member.memberId"
),
nullable
=
False
)
projectId
=
Column
(
UUID
(
as_uuid
=
True
),
ForeignKey
(
"project.projectId"
),
nullable
=
False
)
role_in_project
=
Column
(
String
(
100
),
nullable
=
True
)
# Relationship เชื่อมกลับไปยัง Project
project
=
relationship
(
"Project"
,
back_populates
=
"project_member"
)
# ถ้ามี Model Member/User ก็สามารถประกาศ relationship ได้ เช่น
# member = relationship("Member", back_populates="project_members")
project
=
relationship
(
"Project"
,
back_populates
=
"project_member"
,
lazy
=
"joined"
)
member
=
relationship
(
"Member"
,
back_populates
=
"project_member"
,
lazy
=
"joined"
)
API-Fast/src/routes/__pycache__/project_member_routes.cpython-312.pyc
View file @
0987f285
No preview for this file type
API-Fast/src/routes/project_member_routes.py
View file @
0987f285
...
...
@@ -12,7 +12,8 @@ from ..controllers.project_member_controller import (
get_project_member_by_id
,
update_project_member
,
delete_project_member
,
get_projects_by_member_id
get_projects_by_member_id
,
get_members_by_project_id
)
from
..schemas.project_member_schema
import
(
ProjectMemberCreate
,
...
...
@@ -75,3 +76,11 @@ async def get_projects_for_member(
"""
pms
=
await
get_projects_by_member_id
(
db
,
memberId
)
return
pms
@router.get
(
"/project/{projectId}"
,
response_model
=
List
[
ProjectMemberResponse
])
async
def
get_member_for_project
(
projectId
:
UUID
,
db
:
AsyncSession
=
Depends
(
get_db
)
):
pms
=
await
get_members_by_project_id
(
db
,
projectId
)
return
pms
\ No newline at end of file
API-Fast/src/schemas/__pycache__/project_member_schema.cpython-312.pyc
View file @
0987f285
No preview for this file type
API-Fast/src/schemas/project_member_schema.py
View file @
0987f285
# myproject/schemas/project_member_schema.py
from
pydantic
import
BaseModel
from
typing
import
Optional
from
uuid
import
UUID
from
.project_schema
import
ProjectResponse
# Import schema ของ Project
from
.project_schema
import
ProjectResponse
# Schema ของ Project
from
.member_schema
import
MemberResponse
# Schema ของ Member
class
ProjectMemberBase
(
BaseModel
):
memberId
:
UUID
...
...
@@ -15,7 +14,8 @@ class ProjectMemberCreate(ProjectMemberBase):
class
ProjectMemberResponse
(
ProjectMemberBase
):
pmId
:
UUID
projectId
:
UUID
project
:
Optional
[
ProjectResponse
]
=
None
# เพิ่ม field นี้เพื่อแสดงข้อมูลของ Project
project
:
Optional
[
ProjectResponse
]
=
None
# ข้อมูลของ Project ที่สัมพันธ์กัน
member
:
Optional
[
MemberResponse
]
=
None
# ข้อมูลของ Member ที่สัมพันธ์กัน
class
Config
:
orm_mode
=
True
Web-Manage/src/app/DPU/company-management/admin-project-emp-manage/admin-project-emp-manage.component.html
View file @
0987f285
<app-page-header
[
title
]="'จัดการสมาชิก'"
[
activeTitle
]="'ผู้ดูแลระบบ'"
[
title1
]="'จัดการสมาชิก'"
></app-page-header>
<app-page-header
[
title
]="'จัดการสมาชิกในโครงการ'"
[
activeTitle
]="'จัดการข้อมูลโครงการ'"
[
title1
]="'จัดการสมาชิกในโครงการ'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
...
...
@@ -11,27 +12,17 @@
</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' |
data-hs-overlay=
"#modal-detail"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{
'เพิ่มพนักงานเข้าโครงการ' |
translate}}
</a>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-success-full me-2"
*
ngIf=
"someSelected"
(
click
)="
adjustSelect
(
1
)"
><i
class=
"ri-user-follow-line font-semibold align-middle"
></i>
{{ 'Active' |
translate}}
</a>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-secondary-full me-2"
*
ngIf=
"someSelected"
(
click
)="
adjustSelect
(
0
)"
><i
class=
"ri-user-unfollow-line font-semibold align-middle"
></i>
{{ 'Unactive' |
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=
"ค้นหา
สมาชิก
"
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหา
พนักงานในโครงการ
"
aria-label=
".form-control-sm example"
[(
ngModel
)]='
searchTerm
'
>
</div>
<!-- <div>
...
...
@@ -56,13 +47,10 @@
<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"
>
{{ 'Username' | translate}}
</th
>
<
!-- <th scope="col" class="text-start">{{ 'Username' | translate}}</th> --
>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Fullname' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Email' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Mobile' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'User Group' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Status' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Update Date' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
></th>
</tr>
</thead>
...
...
@@ -70,19 +58,18 @@
@for(item of filterList;track filterList){
<tr
class=
"border border-defaultborder dark:border-defaultborder/10"
>
<td
class=
"product-checkbox"
><input
class=
"form-check-input"
type=
"checkbox"
[
checked
]="
selectedItems
.
get
(
item
.
memberId
)"
(
change
)="
onCheckboxChange
(
item
.
memberId
)"
aria-label=
"..."
value=
""
>
<td
class=
"product-checkbox"
><input
class=
"form-check-input"
type=
"checkbox"
[
checked
]="
selectedItems
.
get
(
item
.
memberId
)"
(
change
)="
onCheckboxChange
(
item
.
memberId
)"
aria-label=
"..."
value=
""
>
</td>
<td>
<div
class=
"flex items-center"
>
<span
class=
"avatar avatar-sm p-1 me-1 bg-light !rounded-full"
>
<img
[
src
]="
item
.
getPicture
()"
alt=
""
id=
"profile-img"
>
<img
[
src
]="
item
.
member
.
getPicture
()"
alt=
""
id=
"profile-img"
>
</span>
<div
class=
"ms-2"
>
<p
class=
"font-semibold mb-0 flex items-center text-primary"
><a
(
click
)="
view
(
item
)"
>
{{item.username
}}
</a></p>
{{item.member.getFullname()
}}
</a></p>
<p
class=
"text-[0.75rem] text-muted mb-0"
>
{{item.memberId}}
</p>
</div>
</div>
...
...
@@ -98,34 +85,22 @@
</div>
</div>
</td> -->
<
td>
{{item.firstName}} {{item.lastName}}
</td
>
<
!-- <td> {{item.member.getFullname()}}</td> --
>
<td>
<div>
<span
class=
"block mb-1"
><i
class=
"ri-mail-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"
></i>
{{item.email}}
</span>
class=
"ri-mail-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"
></i>
{{item.
member.
email}}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block"
><i
class=
"ri-phone-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"
></i>
{{item.phoneNumber}}
</span>
class=
"ri-phone-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"
></i>
{{item.
member.
phoneNumber}}
</span>
</div>
</td>
<td>
<span
class=
"badge bg-{{ item.role == 1 ? 'primary' : 'info'}} text-white"
>
{{item.getRole()}}
</span>
</td>
<td>
<span
class=
"badge bg-{{ item.status == 1 ? 'primary' : 'danger'}} text-white"
>
{{item.getStatus()}}
</span>
</td>
<td><span
class=
"badge bg-info/10 text-primary"
><i
class=
"bi bi-clock me-1"
></i>
{{item.updatedAt | date : 'medium'}}
</span></td>
<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>
...
...
@@ -186,11 +161,11 @@
<!-- 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=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out
lg:!max-w-4xl lg:w-full m-3 lg:!mx-auto
"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header"
>
<h6
class=
"modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
{{
'Create' |
translate }} {{ 'User' | translate
}}
<h6
class=
"modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
{{
'เพิ่มพนักงานเข้าโครงการ'
}}
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay=
"#modal-detail"
#
closeModal
>
...
...
@@ -199,100 +174,133 @@
</button>
</div>
<div
class=
"ti-modal-body px-4"
>
<div
class=
"grid grid-cols-12 gap-4"
>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"mb-0 text-center"
>
<span
class=
"avatar avatar-xxl avatar-rounded"
>
<img
[
src
]="
selectModel
.
getPicture
()"
alt=
""
id=
"profile-img"
>
<span
class=
"badge rounded-full bg-primary avatar-badge"
>
<input
ng2FileSelect
[
uploader
]="
uploaderProfile
"
type=
"file"
name=
"photo"
class=
"absolute w-full h-full opacity-[0]"
id=
"profile-change"
>
<i
class=
"fe fe-camera text-[.625rem]"
></i>
</span>
</span>
</div>
<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=
"xl:col-span-12 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'Username' | 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=
"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"
></th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Fullname' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Email' | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
{{ 'Mobile' | translate}}
</th>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'Password' | translate}}
</label>
<input
type=
"password"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
password
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.password"
>
{{'Please fill in information' | translate}}
</tr>
</thead>
<tbody>
@for(item of userList;track userList){
<tr
class=
"border border-defaultborder dark:border-defaultborder/10"
>
<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> -->
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(
click
)="
selectMember
(
item
)"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'เลือก' |
translate}}
</a>
</td>
<td>
<div
class=
"flex items-center"
>
<span
class=
"avatar avatar-sm p-1 me-1 bg-light !rounded-full"
>
<img
[
src
]="
item
.
getPicture
()"
alt=
""
id=
"profile-img"
>
</span>
<div
class=
"ms-2"
>
<p
class=
"font-semibold mb-0 flex items-center text-primary"
><a>
{{item.firstName}} {{item.lastName}}
</a></p>
<p
class=
"text-[0.75rem] text-muted mb-0"
>
{{item.memberId}}
</p>
</div>
</div>
</td>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'Confirm Password' | translate}}
</label>
<input
type=
"password"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
confirmPassword
"
>
<div
class=
"text-danger"
*
ngIf=
"!confirmPassword"
>
{{'Please fill in information' | translate}}
</div>
<div
class=
"text-danger"
*
ngIf=
"confirmPassword && (confirmPassword != selectModel.password)"
>
{{'Password Not Match' | translate}}
<!-- <td>
<div class="flex">
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary"><a (click)="view(item)"
data-hs-overlay="#modal-detail">
{{item.username}}</a></p>
<p class="text-[0.75rem] text-muted mb-0">{{item.memberId}}</p>
</div>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'ชื่อ' | translate}}
</label
>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
firstName
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.firstName"
>
{{'Please fill in information' | translate}}
</td> -->
<!-- <td> {{item.firstName}} {{item.lastName}}</td> --
>
<td
>
<div
>
<span
class=
"block mb-1"
><i
class=
"ri-mail-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"
></i>
{{item.email}}
</span>
</div>
</td>
<td>
<div>
<span
class=
"block"
><i
class=
"ri-phone-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"
></i>
{{item.phoneNumber}}
</span>
</div>
</td>
</tr>
}
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'นามสกุล' | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
lastName
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.lastName"
>
{{'Please fill in information' | translate}}
</tbody>
</table>
</div>
</div>
<div
class=
"xl:col-span-6 col-span-12
"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'อีเมล' | translate}}
</label
>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
email
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.email"
>
{{'Please fill in information' | translate}}
<!-- <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]"
(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>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'เบอร์ติดต่อ' | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-title"
placeholder=
""
[(
ngModel
)]="
selectModel
.
phoneNumber
"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.phoneNumber"
>
{{'Please fill in information' | translate}}
<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]"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"form-label"
>
{{'User Role' | translate}}
</label>
<ng-select
name=
"choices-multiple-remove-button1"
id=
"choices-multiple-remove-button1"
placeholder=
""
[(
ngModel
)]="
selectModel
.
role
"
>
<ng-option
[
value
]="
0
"
>
{{'ผู้ใช้งานทั่วไป' | translate}}
</ng-option>
<ng-option
[
value
]="
1
"
>
{{'ผู้ดูแลบริษัท' | translate}}
</ng-option>
</ng-select>
</div> -->
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"form-label"
>
{{'Status' | translate}}
</label>
<ng-select
name=
"choices-multiple-remove-button2"
id=
"choices-multiple-remove-button2"
placeholder=
""
[(
ngModel
)]="
selectModel
.
status
"
>
<ng-option
[
value
]="
0
"
>
{{'Unactive' | translate}}
</ng-option>
<ng-option
[
value
]="
1
"
>
{{'Active' | translate}}
</ng-option>
</ng-select>
</div>
</div>
</div>
<div
class=
"ti-modal-footer"
>
...
...
@@ -300,8 +308,8 @@
data-hs-overlay=
"#modal-detail"
>
{{'Cancel' | translate}}
</button>
<button
type=
"button"
(
click
)="
save
()"
class=
"ti-btn bg-primary text-white !font-medium"
>
{{'Save' |
translate}}
</button>
<
!-- <
button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}</button>
-->
</div>
</div>
</div>
...
...
Web-Manage/src/app/DPU/company-management/admin-project-emp-manage/admin-project-emp-manage.component.ts
View file @
0987f285
import
{
CommonModule
}
from
"@angular/common"
;
import
{
ChangeDetectionStrategy
,
Component
,
ElementRef
,
ViewChild
}
from
'@angular/core'
;
import
{
NgSelectModule
}
from
"@ng-select/ng-select"
;
import
{
TranslateModule
,
TranslateService
}
from
"@ngx-translate/core"
;
import
{
SharedModule
}
from
"../../../shared/shared.module"
;
import
{
UserService
}
from
"../../services/user.service"
;
import
{
UserProfileModel
}
from
"../../models/user.model"
;
import
{
FormsModule
}
from
"@angular/forms"
;
import
swal
from
'sweetalert'
;
import
{
MatPaginator
,
PageEvent
}
from
"@angular/material/paginator"
;
import
{
UserRoleModel
}
from
"../../models/user-role-model"
;
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
{
ChangeDetectionStrategy
,
Component
,
ElementRef
,
ViewChild
}
from
'@angular/core'
;
import
{
NgSelectModule
}
from
"@ng-select/ng-select"
;
import
{
TranslateModule
,
TranslateService
}
from
"@ngx-translate/core"
;
import
{
SharedModule
}
from
"../../../shared/shared.module"
;
import
{
FormsModule
}
from
"@angular/forms"
;
import
swal
from
'sweetalert'
;
import
{
MatPaginator
,
PageEvent
}
from
"@angular/material/paginator"
;
import
{
UserRoleModel
}
from
"../../models/user-role-model"
;
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
{
ProjectMemberService
}
from
"../../services/project-members.service"
;
import
{
ProjectMemberModel
}
from
"../../models/project-members"
;
import
{
UserService
}
from
"../../services/user.service"
;
import
{
UserProfileModel
}
from
"../../models/user.model"
;
@
Component
({
selector
:
'app-admin-project-emp-manage'
,
standalone
:
true
,
...
...
@@ -33,16 +35,18 @@ export class AdminProjectEmpManageComponent {
allSelected
=
false
;
someSelected
=
false
;
confirmPassword
=
""
itemsList
:
UserProfile
Model
[]
=
[]
filterList
:
UserProfile
Model
[]
=
[]
selectModel
:
UserProfileModel
=
new
UserProfile
Model
()
itemsList
:
ProjectMember
Model
[]
=
[]
filterList
:
ProjectMember
Model
[]
=
[]
selectModel
:
ProjectMemberModel
=
new
ProjectMember
Model
()
selectedItems
=
new
Map
<
string
,
boolean
>
();
roleList
:
UserRoleModel
[]
=
[]
empList
:
UserProfile
Model
[]
=
[]
empList
:
ProjectMember
Model
[]
=
[]
descName
=
'engName'
pageIndex
=
0
;
uploaderProfile
:
FileUploader
|
undefined
;
uploadErrorMsg
:
string
=
""
;
userList
:
UserProfileModel
[]
=
[]
get
searchTerm
():
string
{
return
this
.
_searchTerm
;
}
...
...
@@ -56,12 +60,21 @@ export class AdminProjectEmpManageComponent {
this
.
updatePagedItems
()
}
}
projectId
=
""
_searchTerm
=
""
;
constructor
(
private
userService
:
UserService
,
public
translate
:
TranslateService
,
private
tokenService
:
TokenService
)
{
constructor
(
private
projectMemberService
:
ProjectMemberService
,
private
userService
:
UserService
,
public
translate
:
TranslateService
,
private
tokenService
:
TokenService
)
{
this
.
projectId
=
this
.
tokenService
.
getSelectCompany
().
projectId
!
;
this
.
getUserProject
()
this
.
getMemberAll
()
this
.
uploadConfig
()
}
getMemberAll
()
{
this
.
userService
.
getLists
().
subscribe
(
result
=>
{
this
.
userList
=
result
})
}
uploadConfig
()
{
this
.
uploaderProfile
=
new
FileUploader
({
url
:
environment
.
baseUrl
+
"/api/upload-image"
,
...
...
@@ -103,7 +116,7 @@ export class AdminProjectEmpManageComponent {
if
(
item
.
isSuccess
)
{
const
res
=
JSON
.
parse
(
response
);
console
.
log
(
"res"
,
res
);
this
.
selectModel
.
picture
=
res
.
filename
this
.
selectModel
.
member
.
picture
=
res
.
filename
swal
(
res
.
message
,
"บันทึกสำเร็จ"
,
"success"
);
}
else
{
...
...
@@ -115,7 +128,14 @@ export class AdminProjectEmpManageComponent {
ngOnInit
():
void
{
this
.
userService
.
getLists
().
subscribe
(
result
=>
{
// this.projectMemberService.getLists(this.projectId).subscribe(result => {
// this.itemsList = result
// this.updatePagedItems()
// })
}
getUserProject
()
{
this
.
projectMemberService
.
getLists
(
this
.
projectId
).
subscribe
(
result
=>
{
this
.
itemsList
=
result
this
.
updatePagedItems
()
})
...
...
@@ -124,17 +144,17 @@ export class AdminProjectEmpManageComponent {
filter
(
v
:
string
)
{
return
this
.
itemsList
?.
filter
(
(
x
)
=>
x
.
memberId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
username
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
email
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
phoneNumber
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
getRole
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
getStatus
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
getFullname
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
x
.
member
.
member
Id
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
username
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
email
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
phoneNumber
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
getRole
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
getStatus
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
getFullname
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
);
}
delete
(
item
:
UserProfile
Model
)
{
delete
(
item
:
ProjectMember
Model
)
{
swal
({
title
:
"Are you sure?"
,
text
:
"You won't be able to revert this!"
,
...
...
@@ -145,9 +165,9 @@ export class AdminProjectEmpManageComponent {
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
this
.
us
erService
.
delete
(
item
).
subscribe
(
result
=>
{
this
.
projectMemb
erService
.
delete
(
item
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnIni
t
()
this
.
getUserProjec
t
()
})
}
...
...
@@ -156,18 +176,18 @@ export class AdminProjectEmpManageComponent {
new
()
{
this
.
action
=
'add'
this
.
selectModel
=
new
UserProfile
Model
()
this
.
selectModel
=
new
ProjectMember
Model
()
}
view
(
item
:
UserProfile
Model
)
{
view
(
item
:
ProjectMember
Model
)
{
this
.
action
=
'edit'
this
.
confirmPassword
=
''
this
.
selectModel
=
new
UserProfile
Model
(
item
)
this
.
selectModel
=
new
ProjectMember
Model
(
item
)
console
.
log
(
this
.
selectModel
)
}
s
ave
(
)
{
s
electMember
(
item
:
UserProfileModel
)
{
swal
({
title
:
"Are you sure?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
...
...
@@ -178,17 +198,21 @@ export class AdminProjectEmpManageComponent {
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
if
(
this
.
action
==
'add'
)
{
this
.
userService
.
save
(
this
.
selectModel
).
subscribe
(
result
=>
{
this
.
projectMemberService
.
save
({
"memberId"
:
item
.
memberId
,
"role_in_project"
:
"employee"
,
"projectId"
:
this
.
projectId
}).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
ngOnIni
t
()
this
.
getUserProjec
t
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
else
if
(
this
.
action
==
'edit'
)
{
this
.
us
erService
.
update
(
this
.
selectModel
).
subscribe
(
result
=>
{
this
.
projectMemb
erService
.
update
(
this
.
selectModel
).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Update Success!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
ngOnIni
t
()
this
.
getUserProjec
t
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
...
...
@@ -228,7 +252,7 @@ export class AdminProjectEmpManageComponent {
if
(
isSelected
)
{
const
user
=
this
.
itemsList
.
find
(
user
=>
user
.
memberId
===
memberId
);
if
(
user
)
{
employeeInfo
+=
`
${
this
.
translate
.
instant
(
'Fullname'
)}
:
${
user
.
getFullname
()}
\n`
;
employeeInfo
+=
`
${
this
.
translate
.
instant
(
'Fullname'
)}
:
${
user
.
member
.
getFullname
()}
\n`
;
}
}
});
...
...
@@ -246,9 +270,9 @@ export class AdminProjectEmpManageComponent {
if
(
isSelected
)
{
const
user
=
this
.
itemsList
.
find
(
user
=>
user
.
memberId
===
memberId
);
if
(
user
)
{
this
.
us
erService
.
delete
(
user
).
subscribe
(
result
=>
{
this
.
projectMemb
erService
.
delete
(
user
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnIni
t
();
this
.
getUserProjec
t
();
});
}
}
...
...
@@ -257,45 +281,13 @@ export class AdminProjectEmpManageComponent {
});
}
adjustSelect
(
status
:
number
)
{
let
title
=
"Are you sure?"
let
employeeInfo
=
''
;
// ตัวแปรสำหรับเก็บข้อมูลพนักงาน
this
.
selectedItems
.
forEach
((
isSelected
,
memberId
)
=>
{
if
(
isSelected
)
{
const
user
=
this
.
itemsList
.
find
(
user
=>
user
.
memberId
===
memberId
);
if
(
user
)
{
employeeInfo
+=
`
${
this
.
translate
.
instant
(
'Fullname'
)}
:
${
user
.
getFullname
()}
\n`
;
}
}
});
swal
({
title
:
title
,
text
:
employeeInfo
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
this
.
selectedItems
.
forEach
((
isSelected
,
memberId
)
=>
{
if
(
isSelected
)
{
const
user
=
this
.
itemsList
.
find
(
user
=>
user
.
memberId
===
memberId
);
if
(
user
)
{
user
.
status
=
status
this
.
userService
.
update
(
user
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnInit
();
});
}
}
});
}
});
}
filterEmp
(
empId
:
string
)
{
this
.
selectModel
=
this
.
empList
.
filter
(
e
=>
e
.
memberId
==
empId
)[
0
]
}
// selectMember(){
// }
}
Web-Manage/src/app/DPU/models/project-members.ts
View file @
0987f285
import
{
TranslateService
}
from
"@ngx-translate/core"
;
import
{
BaseModel
}
from
"./base.model"
;
import
{
ProjectModel
}
from
"./project.model"
;
import
{
UserProfileModel
}
from
"./user.model"
;
export
class
ProjectMemberModel
extends
BaseModel
{
pm_id
:
string
;
user_id
:
string
;
projectId
:
string
;
memberId
:
string
;
role_in_project
:
string
;
created_at
:
string
;
updated_at
:
string
;
pmId
:
string
;
projectId
:
string
;
project
:
ProjectModel
;
member
:
UserProfileModel
;
constructor
(
data
?:
Partial
<
ProjectMemberModel
>
,
translateService
?:
TranslateService
)
{
super
(
data
,
translateService
);
this
.
pm
_id
=
data
?.
pm_i
d
??
''
;
this
.
user_id
=
data
?.
user_i
d
??
''
;
this
.
pm
Id
=
data
?.
pmI
d
??
''
;
this
.
memberId
=
data
?.
memberI
d
??
''
;
this
.
projectId
=
data
?.
projectId
??
''
;
this
.
role_in_project
=
data
?.
role_in_project
??
''
;
this
.
created_at
=
data
?.
created_at
??
new
Date
().
toISOString
();
this
.
updated_at
=
data
?.
updated_at
??
new
Date
().
toISOString
();
}
this
.
project
=
data
?.
project
||
new
ProjectModel
();
this
.
member
=
data
?.
member
?
new
UserProfileModel
(
data
.
member
)
:
new
UserProfileModel
();
}
}
Web-Manage/src/app/DPU/services/project-members.service.ts
View file @
0987f285
...
...
@@ -19,7 +19,7 @@ export class ProjectMemberService {
.
pipe
(
map
((
e
)
=>
new
ProjectMemberModel
(
e
)));
}
getLists
()
{
getLists
(
projectId
:
string
)
{
return
this
.
http
.
get
<
ProjectMemberModel
[]
>
(
this
.
apiBaseUrl
)
.
pipe
(
...
...
@@ -27,25 +27,23 @@ export class ProjectMemberService {
);
}
save
(
body
:
ProjectMemberModel
)
{
return
this
.
http
.
post
<
{
"message"
:
string
,
"user"
:
ProjectMemberModel
}
>
(
this
.
apiBaseUrl
,
new
ProjectMemberModel
(
body
));
save
(
body
:
any
)
{
return
this
.
http
.
post
<
ProjectMemberModel
>
(
this
.
apiBaseUrl
,
body
);
}
update
(
body
:
ProjectMemberModel
)
{
return
this
.
http
.
put
<
{
"message"
:
string
,
"user"
:
ProjectMemberModel
}
>
(
this
.
apiBaseUrl
+
"/"
+
body
.
user_i
d
,
new
ProjectMemberModel
(
body
));
}
>
(
this
.
apiBaseUrl
+
"/"
+
body
.
memberI
d
,
new
ProjectMemberModel
(
body
));
}
delete
(
body
:
ProjectMemberModel
)
{
return
this
.
http
.
delete
<
{
"message"
:
string
,
"user"
:
ProjectMemberModel
}
>
(
this
.
apiBaseUrl
+
"/"
+
body
.
user_i
d
);
}
>
(
this
.
apiBaseUrl
+
"/"
+
body
.
pmI
d
);
}
getCompanyAdmin
(
memberId
:
string
)
{
...
...
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