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
ed89bf27
Commit
ed89bf27
authored
Oct 27, 2025
by
sawit
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
แก้ไข widget
parent
aac8ace4
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
843 additions
and
623 deletions
+843
-623
dashboard-management.component.scss
.../dashboard-management/dashboard-management.component.scss
+21
-21
dashboard-management.component.ts
...ge/dashboard-management/dashboard-management.component.ts
+6
-0
dashboard-viewer.component.scss
...nagement/dashboard-viewer/dashboard-viewer.component.scss
+560
-560
dashboard-viewer.component.ts
...management/dashboard-viewer/dashboard-viewer.component.ts
+8
-1
widget-config.component.html
...ard-management/widget-config/widget-config.component.html
+17
-5
widget-config.component.ts
...board-management/widget-config/widget-config.component.ts
+4
-1
bar-chart-widget.component.ts
...nt/widgets/bar-chart-widget/bar-chart-widget.component.ts
+63
-7
base-widget.component.ts
...age/dashboard-management/widgets/base-widget.component.ts
+16
-2
pie-chart-widget.component.ts
...nt/widgets/pie-chart-widget/pie-chart-widget.component.ts
+78
-9
simple-kpi-widget.component.ts
.../widgets/simple-kpi-widget/simple-kpi-widget.component.ts
+30
-3
syncfusion-datagrid-widget.component.html
...datagrid-widget/syncfusion-datagrid-widget.component.html
+1
-0
syncfusion-datagrid-widget.component.scss
...datagrid-widget/syncfusion-datagrid-widget.component.scss
+25
-0
syncfusion-datagrid-widget.component.ts
...n-datagrid-widget/syncfusion-datagrid-widget.component.ts
+9
-9
syncfusion-pivot-widget.component.ts
...cfusion-pivot-widget/syncfusion-pivot-widget.component.ts
+5
-5
No files found.
src/app/portal-manage/dashboard-management/dashboard-management.component.scss
View file @
ed89bf27
...
@@ -135,7 +135,7 @@
...
@@ -135,7 +135,7 @@
border-radius
:
0
.75rem
;
border-radius
:
0
.75rem
;
box-shadow
:
0
10px
15px
-3px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
4px
6px
-2px
rgba
(
0
,
0
,
0
,
0
.05
);
box-shadow
:
0
10px
15px
-3px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
4px
6px
-2px
rgba
(
0
,
0
,
0
,
0
.05
);
border
:
1px
solid
#e5e7eb
;
border
:
1px
solid
#e5e7eb
;
min-height
:
6
00px
;
min-height
:
12
00px
;
}
}
/* Empty State */
/* Empty State */
...
@@ -144,7 +144,7 @@
...
@@ -144,7 +144,7 @@
flex-direction
:
column
;
flex-direction
:
column
;
justify-content
:
center
;
justify-content
:
center
;
align-items
:
center
;
align-items
:
center
;
height
:
6
00px
;
height
:
12
00px
;
text-align
:
center
;
text-align
:
center
;
color
:
#6b7280
;
color
:
#6b7280
;
}
}
...
@@ -437,39 +437,39 @@
...
@@ -437,39 +437,39 @@
/* Ensure widgets don't exceed panel boundaries and fill full space */
/* Ensure widgets don't exceed panel boundaries and fill full space */
.e-panel
.e-panel-container
.content
>
*
{
.e-panel
.e-panel-container
.content
>
*
{
max-width
:
100%
!
important
;
max-height
:
100%
!
important
;
width
:
100%
!
important
;
width
:
100%
!
important
;
height
:
100%
!
important
;
height
:
100%
!
important
;
overflow
:
hidden
!
important
;
max-width
:
100%
!
important
;
box-sizing
:
border-box
!
important
;
min-width
:
0
!
important
;
flex
:
1
!
important
;
display
:
flex
!
important
;
flex-direction
:
column
!
important
;
}
}
/* Specific
widget component styling
*/
/* Specific
styling for Syncfusion Datagrid Widget
*/
.e-panel
.e-panel-container
.content
>
*
{
.e-panel
.e-panel-container
.content
app-syncfusion-datagrid-widget
{
width
:
100%
!
important
;
width
:
100%
!
important
;
height
:
100%
!
important
;
height
:
100%
!
important
;
flex
:
1
!
important
;
display
:
flex
!
important
;
display
:
flex
!
important
;
flex-direction
:
column
!
important
;
flex-direction
:
column
!
important
;
min-height
:
0
!
important
;
margin
:
0
!
important
;
}
padding
:
0
!
important
;
/* Ensure all child elements fill the space */
.e-panel
.e-panel-container
.content
>
*
>
*
{
width
:
100%
!
important
;
height
:
100%
!
important
;
flex
:
1
!
important
;
min-height
:
0
!
important
;
}
}
/* Force all nested elements to use full space */
/* Force all nested elements to use full space */
.e-panel
.e-panel-container
.content
*
{
.e-panel
.e-panel-container
.content
*
{
box-sizing
:
border-box
!
important
;
box-sizing
:
border-box
!
important
;
}
}
/* Remove margin/padding from grid container and grid */
.e-panel
.e-panel-container
.content
app-syncfusion-datagrid-widget
.grid-container
{
margin
:
0
!
important
;
padding
:
0
!
important
;
}
.e-panel
.e-panel-container
.content
app-syncfusion-datagrid-widget
.grid-container
.ejs-grid
{
margin
:
0
!
important
;
padding
:
0
!
important
;
width
:
100%
!
important
;
max-width
:
100%
!
important
;
}
}
}
}
}
...
...
src/app/portal-manage/dashboard-management/dashboard-management.component.ts
View file @
ed89bf27
...
@@ -486,6 +486,12 @@ export class DashboardManagementComponent implements OnInit, OnDestroy {
...
@@ -486,6 +486,12 @@ export class DashboardManagementComponent implements OnInit, OnDestroy {
originalWidget
:
widget
originalWidget
:
widget
};
};
// Force SyncfusionDatagridWidgetComponent to use full width
if
(
widget
.
component
===
'SyncfusionDatagridWidgetComponent'
)
{
panel
.
sizeX
=
this
.
columns
;
panel
.
maxSizeX
=
this
.
columns
;
}
return
panel
;
return
panel
;
})
})
...
...
src/app/portal-manage/dashboard-management/dashboard-viewer/dashboard-viewer.component.scss
View file @
ed89bf27
/* Dashboard Viewer Styles - Clean and Responsive */
// /* Dashboard Viewer Styles - Clean and Responsive */
/* Background */
// /* Background */
// .dashboard-background {
// // .dashboard-background {
// background: linear-gradient(to bottom right, #f8fafc, #e0e7ff);
// // background: linear-gradient(to bottom right, #f8fafc, #e0e7ff);
// // min-height: 100vh;
// // }
// /* Error Message */
// .error-message {
// display: flex;
// justify-content: center;
// align-items: center;
// min-height: 100vh;
// min-height: 100vh;
// background: linear-gradient(to bottom right, #f8fafc, #e0e7ff);
// }
// }
/* Error Message */
// .error-message-content {
.error-message
{
// background: white;
display
:
flex
;
// padding: 2rem;
justify-content
:
center
;
// border-radius: 12px;
align-items
:
center
;
// box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
min-height
:
100vh
;
// border: 1px solid #e5e7eb;
background
:
linear-gradient
(
to
bottom
right
,
#f8fafc
,
#e0e7ff
);
// text-align: center;
}
// max-width: 500px;
// }
.error-message-content
{
background
:
white
;
padding
:
2rem
;
border-radius
:
12px
;
box-shadow
:
0
10px
15px
-3px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
4px
6px
-2px
rgba
(
0
,
0
,
0
,
0
.05
);
border
:
1px
solid
#e5e7eb
;
text-align
:
center
;
max-width
:
500px
;
}
.error-icon
{
//
.error-icon {
font-size
:
3rem
;
//
font-size: 3rem;
color
:
#ef4444
;
//
color: #ef4444;
margin-bottom
:
1rem
;
//
margin-bottom: 1rem;
}
//
}
.error-text
{
//
.error-text {
font-size
:
1
.25rem
;
//
font-size: 1.25rem;
font-weight
:
600
;
//
font-weight: 600;
color
:
#374151
;
//
color: #374151;
display
:
block
;
//
display: block;
margin-bottom
:
0
.5rem
;
//
margin-bottom: 0.5rem;
}
//
}
.error-description
{
//
.error-description {
color
:
#6b7280
;
//
color: #6b7280;
font-size
:
1rem
;
//
font-size: 1rem;
}
//
}
/* Layout Classes */
/
/ /
* Layout Classes */
.action-buttons
{
//
.action-buttons {
display
:
flex
;
//
display: flex;
align-items
:
center
;
//
align-items: center;
gap
:
0
.75rem
;
//
gap: 0.75rem;
flex-shrink
:
0
;
//
flex-shrink: 0;
flex-wrap
:
wrap
;
//
flex-wrap: wrap;
}
//
}
.view-dashboard-section
{
//
.view-dashboard-section {
margin-bottom
:
1rem
;
//
margin-bottom: 1rem;
}
//
}
.dashboard-header-container
{
.dashboard-header-container
{
background
:
white
;
background
:
white
;
...
@@ -126,34 +126,34 @@
...
@@ -126,34 +126,34 @@
margin-top
:
0
.25rem
;
margin-top
:
0
.25rem
;
}
}
.dashboard-selector
{
// .dashboard-selector {
display
:
flex
;
// display: flex;
align-items
:
center
;
// align-items: center;
gap
:
0
.75rem
;
// gap: 0.75rem;
flex-shrink
:
0
;
// flex-shrink: 0;
}
// }
.selector-label
{
font-size
:
0
.875rem
;
font-weight
:
500
;
color
:
#374151
;
}
.dashboard-select
{
// .selector-label {
padding
:
0
.5rem
1rem
;
// font-size: 0.875rem;
border
:
1px
solid
#d1d5db
;
// font-weight: 500;
border-radius
:
0
.5rem
;
// color: #374151;
background
:
white
;
// }
box-shadow
:
0
1px
2px
0
rgba
(
0
,
0
,
0
,
0
.05
);
min-width
:
200px
;
font-size
:
0
.875rem
;
&
:focus
{
// .dashboard-select {
outline
:
none
;
// padding: 0.5rem 1rem;
border-color
:
#4f46e5
;
// border: 1px solid #d1d5db;
box-shadow
:
0
0
0
3px
rgba
(
79
,
70
,
229
,
0
.1
);
// border-radius: 0.5rem;
}
// background: white;
}
// box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
// min-width: 200px;
// font-size: 0.875rem;
// &:focus {
// outline: none;
// border-color: #4f46e5;
// box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
// }
// }
.dataset-picker-section
{
.dataset-picker-section
{
display
:
flex
;
display
:
flex
;
...
@@ -162,541 +162,541 @@
...
@@ -162,541 +162,541 @@
flex-shrink
:
0
;
flex-shrink
:
0
;
}
}
/* Dashboard Content Area - Full Width and Responsive */
// /* Dashboard Content Area - Full Width and Responsive */
.dashboard-content-area
{
// .dashboard-content-area {
width
:
100%
;
min-height
:
100vh
;
padding
:
0
;
margin
:
0
;
background
:
linear-gradient
(
to
bottom
right
,
#f8fafc
,
#e0e7ff
);
}
/* Dashboard Layout Container - Clean and Responsive */
// .dashboard-layout-container {
// width: 100%;
// width: 100%;
// min-height: 100vh;
// min-height: 100vh;
// padding: 1rem;
// padding: 0;
// box-sizing: border-box;
// margin: 0;
// }
// background: linear-gradient(to bottom right, #f8fafc, #e0e7ff);
// }
/* Dashboard Layout - Responsive Grid */
.dashboard-layout
{
width
:
100%
!
important
;
height
:
auto
!
important
;
min-height
:
calc
(
100vh
-
2rem
);
background
:
transparent
;
.e-panel
{
border-radius
:
12px
;
box-shadow
:
0
4px
6px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
2px
4px
-1px
rgba
(
0
,
0
,
0
,
0
.06
);
border
:
1px
solid
#e5e7eb
;
background
:
white
;
transition
:
all
0
.3s
ease
;
position
:
relative
;
overflow
:
hidden
;
margin
:
0
;
&
:hover
{
box-shadow
:
0
10px
15px
-3px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
4px
6px
-2px
rgba
(
0
,
0
,
0
,
0
.05
);
transform
:
translateY
(
-2px
);
}
}
.e-panel-header
{
display
:
none
!
important
;
/* Hide panel headers in viewer mode */
}
.e-panel-content
{
border-radius
:
12px
;
overflow
:
hidden
;
position
:
relative
;
width
:
100%
;
height
:
100%
;
padding
:
0
;
margin
:
0
;
}
}
.dashboard-content-card
{
background
:
white
;
border-radius
:
0
.75rem
;
box-shadow
:
0
10px
15px
-3px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
4px
6px
-2px
rgba
(
0
,
0
,
0
,
0
.05
);
border
:
1px
solid
#e5e7eb
;
min-height
:
600px
;
}
/* Empty State */
// /* Dashboard Layout Container - Clean and Responsive */
.empty-state
{
// // .dashboard-layout-container {
display
:
flex
;
// // width: 100%;
flex-direction
:
column
;
// // min-height: 100vh;
justify-content
:
center
;
// // padding: 1rem;
align-items
:
center
;
// // box-sizing: border-box;
height
:
600px
;
// // }
text-align
:
center
;
color
:
#6b7280
;
// /* Dashboard Layout - Responsive Grid */
}
// .dashboard-layout {
// width: 100% !important;
// height: auto !important;
// min-height: calc(100vh - 2rem);
// background: transparent;
// .e-panel {
// border-radius: 12px;
// box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
// border: 1px solid #e5e7eb;
// background: white;
// transition: all 0.3s ease;
// position: relative;
// overflow: hidden;
// margin: 0;
// &:hover {
// box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
// transform: translateY(-2px);
// }
// }
// .e-panel-header {
// display: none !important; /* Hide panel headers in viewer mode */
// }
// .e-panel-content {
// border-radius: 12px;
// overflow: hidden;
// position: relative;
// width: 100%;
// height: 100%;
// padding: 0;
// margin: 0;
// }
// }
.empty-state-icon
{
// .dashboard-content-card {
padding
:
2rem
;
// background: white;
background
:
linear-gradient
(
to
bottom
right
,
#dbeafe
,
#e0e7ff
);
// border-radius: 0.75rem;
border-radius
:
50%
;
// box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
margin-bottom
:
1
.5rem
;
// border: 1px solid #e5e7eb;
}
// min-height: 600px;
// }
.empty-state-icon
i
{
// /* Empty State */
font-size
:
3
.75rem
;
// .empty-state {
color
:
#60a5fa
;
// display: flex;
}
// flex-direction: column;
// justify-content: center;
// align-items: center;
// height: 600px;
// text-align: center;
// color: #6b7280;
// }
.empty-state-title
{
// .empty-state-icon
{
font-size
:
1
.5
rem
;
// padding: 2
rem;
font-weight
:
600
;
// background: linear-gradient(to bottom right, #dbeafe, #e0e7ff)
;
color
:
#374151
;
// border-radius: 50%
;
margin-bottom
:
0
.5rem
;
// margin-bottom: 1
.5rem;
}
//
}
.empty-state-description
{
// .empty-state-icon i {
color
:
#6b7280
;
// font-size: 3.75rem;
max-width
:
28rem
;
// color: #60a5fa;
margin-bottom
:
1
.5rem
;
// }
}
/* Custom Button Styles (fallback for Tailwind) */
// .empty-state-title {
.custom-btn
{
// font-size: 1.5rem;
display
:
inline-flex
;
// font-weight: 600;
align-items
:
center
;
// color: #374151;
padding
:
0
.5rem
1rem
;
// margin-bottom: 0.5rem;
font-size
:
0
.875rem
;
// }
font-weight
:
500
;
border-radius
:
0
.5rem
;
box-shadow
:
0
1px
2px
0
rgba
(
0
,
0
,
0
,
0
.05
);
transition
:
all
0
.2s
ease-in-out
;
border
:
none
;
cursor
:
pointer
;
text-decoration
:
none
;
&
:focus
{
outline
:
none
;
box-shadow
:
0
0
0
3px
rgba
(
59
,
130
,
246
,
0
.5
);
}
&
:hover
{
transform
:
translateY
(
-1px
);
box-shadow
:
0
4px
6px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
2px
4px
-1px
rgba
(
0
,
0
,
0
,
0
.06
);
}
i
{
margin-right
:
0
.5rem
;
}
}
.btn-indigo
{
// .empty-state-description {
background-color
:
#4f46e5
;
// color: #6b7280;
color
:
white
;
// max-width: 28rem;
// margin-bottom: 1.5rem;
// }
&
:hover
{
// /* Custom Button Styles (fallback for Tailwind) */
background-color
:
#4338ca
;
// .custom-btn {
}
// display: inline-flex;
// align-items: center;
// padding: 0.5rem 1rem;
// font-size: 0.875rem;
// font-weight: 500;
// border-radius: 0.5rem;
// box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
// transition: all 0.2s ease-in-out;
// border: none;
// cursor: pointer;
// text-decoration: none;
// &:focus {
// outline: none;
// box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.5);
// }
// &:hover {
// transform: translateY(-1px);
// box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
// }
// i {
// margin-right: 0.5rem;
// }
// }
&
:focus
{
// .btn-indigo {
box-shadow
:
0
0
0
3px
rgba
(
79
,
70
,
229
,
0
.5
);
// background-color: #4f46e5;
}
// color: white;
}
.btn-emerald
{
// &:hover
{
background-color
:
#10b981
;
// background-color: #4338ca
;
color
:
white
;
// }
&
:hover
{
// &:focus {
background-color
:
#059669
;
// box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.5);
}
// }
// }
&
:focus
{
// .btn-emerald {
box-shadow
:
0
0
0
3px
rgba
(
16
,
185
,
129
,
0
.5
);
// background-color: #10b981;
}
// color: white;
}
.btn-red
{
// &:hover
{
background-color
:
#ef4444
;
// background-color: #059669
;
color
:
white
;
// }
&
:hover
{
// &:focus {
background-color
:
#dc2626
;
// box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.5);
}
// }
// }
&
:focus
{
// .btn-red {
box-shadow
:
0
0
0
3px
rgba
(
239
,
68
,
68
,
0
.5
);
// background-color: #ef4444;
}
// color: white;
}
.btn-green
{
// &:hover
{
background-color
:
#22c55e
;
// background-color: #dc2626
;
color
:
white
;
// }
&
:hover
{
// &:focus {
background-color
:
#16a34a
;
// box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.5);
}
// }
// }
&
:focus
{
// .btn-green {
box-shadow
:
0
0
0
3px
rgba
(
34
,
197
,
94
,
0
.5
);
// background-color: #22c55e;
}
// color: white;
}
.btn-blue
{
// &:hover
{
background-color
:
#3b82f6
;
// background-color: #16a34a
;
color
:
white
;
// }
&
:hover
{
// &:focus {
background-color
:
#2563eb
;
// box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.5);
}
// }
// }
&
:focus
{
// .btn-blue {
box-shadow
:
0
0
0
3px
rgba
(
59
,
130
,
246
,
0
.5
);
// background-color: #3b82f6;
}
// color: white;
}
.btn-gray
{
// &:hover
{
background-color
:
#6b7280
;
// background-color: #2563eb
;
color
:
white
;
// }
&
:hover
{
// &:focus {
background-color
:
#4b5563
;
// box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.5);
}
// }
// }
&
:focus
{
// .btn-gray {
box-shadow
:
0
0
0
3px
rgba
(
107
,
114
,
128
,
0
.5
);
// background-color: #6b7280;
}
// color: white;
}
/* Dashboard Layout Styling */
// &:hover {
.dashboard-layout
{
// background-color: #4b5563;
.e-panel
{
// }
border-radius
:
12px
;
box-shadow
:
0
4px
6px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
2px
4px
-1px
rgba
(
0
,
0
,
0
,
0
.06
);
border
:
1px
solid
#e5e7eb
;
transition
:
all
0
.3s
ease
;
position
:
relative
;
max-width
:
100%
;
overflow
:
hidden
;
&
:hover
{
box-shadow
:
0
10px
15px
-3px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
4px
6px
-2px
rgba
(
0
,
0
,
0
,
0
.05
);
transform
:
translateY
(
-2px
);
}
}
.e-panel-header
{
background
:
linear-gradient
(
135deg
,
#667eea
0%
,
#764ba2
100%
);
color
:
white
;
border-radius
:
12px
12px
0
0
;
padding
:
12px
16px
;
font-weight
:
600
;
position
:
relative
;
}
.e-panel-content
{
border-radius
:
0
0
12px
12px
;
overflow
:
hidden
;
position
:
relative
;
}
}
/* Syncfusion DashboardLayout Override for Viewer */
// &:focus {
::ng-deep
{
// box-shadow: 0 0 0 3px rgba(107, 114, 128, 0.5);
#dashboard_default
.e-dashboardlayout
{
// }
width
:
100%
!
important
;
// }
height
:
auto
!
important
;
min-height
:
calc
(
100vh
-
2rem
)
!
important
;
max-height
:
none
!
important
;
overflow
:
visible
!
important
;
position
:
relative
!
important
;
background
:
transparent
!
important
;
padding
:
0
!
important
;
margin
:
0
!
important
;
.e-panel
{
max-width
:
100%
!
important
;
overflow
:
hidden
!
important
;
position
:
relative
!
important
;
background
:
white
!
important
;
border
:
1px
solid
#e5e7eb
!
important
;
border-radius
:
12px
!
important
;
box-shadow
:
0
4px
6px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
2px
4px
-1px
rgba
(
0
,
0
,
0
,
0
.06
)
!
important
;
margin
:
0
!
important
;
}
.e-panel-header
{
display
:
none
!
important
;
/* Completely hide headers in viewer */
}
.e-panel-content
{
overflow
:
hidden
!
important
;
max-width
:
100%
!
important
;
width
:
100%
!
important
;
height
:
100%
!
important
;
padding
:
0
!
important
;
margin
:
0
!
important
;
background
:
white
!
important
;
border-radius
:
12px
!
important
;
}
/* Ensure widgets don't overflow */
.e-panel
.e-panel-container
{
width
:
100%
!
important
;
height
:
100%
!
important
;
overflow
:
hidden
!
important
;
position
:
relative
!
important
;
}
/* Widget content styling */
.e-panel
.e-panel-container
.content
{
width
:
100%
!
important
;
height
:
100%
!
important
;
overflow
:
hidden
!
important
;
position
:
relative
!
important
;
padding
:
0
!
important
;
margin
:
0
!
important
;
}
}
}
/* Widget Panel Enhancements */
// /* Dashboard Layout Styling */
.widget-panel
{
// .dashboard-layout {
.e-panel
{
// .e-panel {
background
:
white
;
// border-radius: 12px;
border
:
1px
solid
#e5e7eb
;
// box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
border-radius
:
12px
;
// border: 1px solid #e5e7eb;
overflow
:
hidden
;
// transition: all 0.3s ease;
transition
:
all
0
.3s
cubic-bezier
(
0
.4
,
0
,
0
.2
,
1
);
// position: relative;
// max-width: 100%;
&
:hover
{
// overflow: hidden;
border-color
:
#3b82f6
;
box-shadow
:
0
20px
25px
-5px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
10px
10px
-5px
rgba
(
0
,
0
,
0
,
0
.04
);
// &:hover {
}
// box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
// transform: translateY(-2px);
}
// }
// }
// .e-panel-header {
// background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
// color: white;
// border-radius: 12px 12px 0 0;
// padding: 12px 16px;
// font-weight: 600;
// position: relative;
// }
// .e-panel-content {
// border-radius: 0 0 12px 12px;
// overflow: hidden;
// position: relative;
// }
// }
/* Loading States */
// /* Syncfusion DashboardLayout Override for Viewer */
.loading-shimmer
{
// ::ng-deep {
background
:
linear-gradient
(
90deg
,
#f0f0f0
25%
,
#e0e0e0
50%
,
#f0f0f0
75%
);
// #dashboard_default.e-dashboardlayout {
background-size
:
200%
100%
;
// width: 100% !important;
animation
:
shimmer
2s
infinite
;
// height: auto !important;
}
// min-height: calc(100vh - 2rem) !important;
// max-height: none !important;
// overflow: visible !important;
// position: relative !important;
// background: transparent !important;
// padding: 0 !important;
// margin: 0 !important;
// .e-panel {
// max-width: 100% !important;
// overflow: hidden !important;
// position: relative !important;
// background: white !important;
// border: 1px solid #e5e7eb !important;
// border-radius: 12px !important;
// box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !important;
// margin: 0 !important;
// }
// .e-panel-header {
// display: none !important; /* Completely hide headers in viewer */
// }
// .e-panel-content {
// overflow: hidden !important;
// max-width: 100% !important;
// width: 100% !important;
// height: 100% !important;
// padding: 0 !important;
// margin: 0 !important;
// background: white !important;
// border-radius: 12px !important;
// }
// /* Ensure widgets don't overflow */
// .e-panel .e-panel-container {
// width: 100% !important;
// height: 100% !important;
// overflow: hidden !important;
// position: relative !important;
// }
// /* Widget content styling */
// .e-panel .e-panel-container .content {
// width: 100% !important;
// height: 100% !important;
// overflow: hidden !important;
// position: relative !important;
// padding: 0 !important;
// margin: 0 !important;
// }
// }
// }
@keyframes
shimmer
{
// /* Widget Panel Enhancements */
0
%
{
background-position
:
-200%
0
;
}
// .widget-panel {
100
%
{
background-position
:
200%
0
;
}
// .e-panel {
}
// background: white;
// border: 1px solid #e5e7eb;
// border-radius: 12px;
// overflow: hidden;
// transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
// &:hover {
// border-color: #3b82f6;
// box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
// }
// }
// }
/* Responsive Design for Dashboard Viewer */
// /* Loading States */
@media
(
max-width
:
1200px
)
{
// .loading-shimmer {
.dashboard-layout-container
{
// background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
padding
:
0
.75rem
;
// background-size: 200% 100%;
}
// animation: shimmer 2s infinite;
// }
::ng-deep
{
#dashboard_default
.e-dashboardlayout
{
min-height
:
calc
(
100vh
-
1
.5rem
)
!
important
;
}
}
}
@media
(
max-width
:
1024px
)
{
// @keyframes shimmer {
.dashboard-layout-container
{
// 0% { background-position: -200% 0; }
padding
:
0
.5rem
;
// 100% { background-position: 200% 0; }
}
// }
.dashboard-layout
{
.e-panel
{
margin
:
0
.25rem
;
}
}
::ng-deep
{
#dashboard_default
.e-dashboardlayout
{
min-height
:
calc
(
100vh
-
1rem
)
!
important
;
.e-panel
{
border-radius
:
8px
!
important
;
}
}
}
}
@media
(
max-width
:
768px
)
{
// /* Responsive Design for Dashboard Viewer */
.dashboard-layout-container
{
// @media (max-width: 1200px) {
padding
:
0
.25rem
;
// .dashboard-layout-container {
}
// padding: 0.75rem;
// }
.dashboard-layout
{
.e-panel
{
// ::ng-deep {
margin
:
0
.125rem
;
// #dashboard_default.e-dashboardlayout {
border-radius
:
8px
;
// min-height: calc(100vh - 1.5rem) !important;
}
// }
}
// }
// }
::ng-deep
{
#dashboard_default
.e-dashboardlayout
{
min-height
:
calc
(
100vh
-
0
.5rem
)
!
important
;
.e-panel
{
border-radius
:
8px
!
important
;
box-shadow
:
0
2px
4px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
1px
2px
-1px
rgba
(
0
,
0
,
0
,
0
.06
)
!
important
;
}
}
}
}
@media
(
max-width
:
480px
)
{
// @media (max-width: 1024px) {
.dashboard-layout-container
{
// .dashboard-layout-container {
padding
:
0
.125rem
;
// padding: 0.5rem;
}
// }
.dashboard-layout
{
// .dashboard-layout {
.e-panel
{
// .e-panel {
margin
:
0
.0625rem
;
// margin: 0.25rem;
border-radius
:
6px
;
// }
}
// }
}
// ::ng-deep {
::ng-deep
{
// #dashboard_default.e-dashboardlayout {
#dashboard_default
.e-dashboardlayout
{
// min-height: calc(100vh - 1rem) !important;
min-height
:
calc
(
100vh
-
0
.25rem
)
!
important
;
// .e-panel {
.e-panel
{
// border-radius: 8px !important;
border-radius
:
6px
!
important
;
// }
box-shadow
:
0
1px
3px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
1px
2px
-1px
rgba
(
0
,
0
,
0
,
0
.06
)
!
important
;
// }
}
// }
}
// }
}
}
// @media (max-width: 768px) {
// .dashboard-layout-container {
// padding: 0.25rem;
// }
// .dashboard-layout {
// .e-panel {
// margin: 0.125rem;
// border-radius: 8px;
// }
// }
// ::ng-deep {
// #dashboard_default.e-dashboardlayout {
// min-height: calc(100vh - 0.5rem) !important;
// .e-panel {
// border-radius: 8px !important;
// box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.06) !important;
// }
// }
// }
// }
.dashboard-container
{
// @media (max-width: 480px) {
display
:
flex
;
// .dashboard-layout-container {
height
:
100vh
;
// padding: 0.125rem;
background-color
:
#f3f4f6
;
/* bg-gray-100 */
// }
}
// .dashboard-layout {
// .e-panel {
// margin: 0.0625rem;
// border-radius: 6px;
// }
// }
// ::ng-deep {
// #dashboard_default.e-dashboardlayout {
// min-height: calc(100vh - 0.25rem) !important;
// .e-panel {
// border-radius: 6px !important;
// box-shadow: 0 1px 3px -1px rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.06) !important;
// }
// }
// }
// }
.widget-sidebar
{
width
:
18rem
;
/* w-72 */
background-color
:
#ffffff
;
/* bg-white */
padding
:
1rem
;
/* p-4 */
overflow-y
:
auto
;
box-shadow
:
0
4px
6px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
2px
4px
-1px
rgba
(
0
,
0
,
0
,
0
.06
);
/* shadow-lg */
border-right
:
1px
solid
#e5e7eb
;
/* border-r border-gray-200 */
display
:
flex
;
flex-direction
:
column
;
}
.widget-list
{
// .dashboard-container {
flex-grow
:
1
;
// display: flex;
/* space-y-2 is handled by margin-bottom on widget-item */
// height: 100vh;
}
// background-color: #f3f4f6; /* bg-gray-100 */
// }
.widget-item
{
// .widget-sidebar {
padding
:
0
.75rem
;
/* p-3 */
// width: 18rem; /* w-72 */
margin-bottom
:
0
.5rem
;
/* mb-2 */
// background-color: #ffffff; /* bg-white */
background-color
:
#f9fafb
;
/* bg-gray-50 */
// padding: 1rem; /* p-4 */
border-radius
:
0
.5rem
;
/* rounded-lg */
// overflow-y: auto;
border
:
1px
solid
#e5e7eb
;
/* border border-gray-200 */
// box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* shadow-lg */
cursor
:
pointer
;
// border-right: 1px solid #e5e7eb; /* border-r border-gray-200 */
transition
:
all
0
.2s
ease-in-out
;
// display: flex;
// flex-direction: column;
&
:hover
{
// }
background-color
:
#e0e7ff
;
/* hover:bg-indigo-50 */
border-color
:
#c7d2fe
;
/* hover:border-indigo-100 */
box-shadow
:
0
10px
15px
-3px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
4px
6px
-2px
rgba
(
0
,
0
,
0
,
0
.05
);
/* hover:shadow-md */
}
}
.dashboard-area
{
// .widget-list {
flex
:
1
;
// flex-grow: 1;
display
:
flex
;
// /* space-y-2 is handled by margin-bottom on widget-item */
flex-direction
:
column
;
// }
background-color
:
#f3f4f6
;
/* bg-gray-100 */
}
.dashboard-header
{
// .widget-item {
padding
:
1rem
;
/* p-4 */
// padding: 0.75rem; /* p-3 */
background-color
:
#ffffff
;
/* bg-white */
// margin-bottom: 0.5rem; /* mb-2 */
border-bottom
:
1px
solid
#e5e7eb
;
/* border-b border-gray-200 */
// background-color: #f9fafb; /* bg-gray-50 */
box-shadow
:
0
1px
3px
0
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
1px
2px
0
rgba
(
0
,
0
,
0
,
0
.06
);
/* shadow-sm */
// border-radius: 0.5rem; /* rounded-lg */
}
// border: 1px solid #e5e7eb; /* border border-gray-200 */
// cursor: pointer;
// transition: all 0.2s ease-in-out;
// &:hover {
// background-color: #e0e7ff; /* hover:bg-indigo-50 */
// border-color: #c7d2fe; /* hover:border-indigo-100 */
// box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* hover:shadow-md */
// }
// }
.dashboard-content
{
// .dashboard-area
{
//
flex: 1;
//
flex: 1;
padding
:
1rem
;
/* p-4 */
// display: flex;
overflow
:
auto
;
// flex-direction: column
;
min-height
:
600px
;
/* min-h-[600px]
*/
// background-color: #f3f4f6; /* bg-gray-100
*/
}
//
}
/* Button styles (assuming ti-btn is a base class) */
// .dashboard-header {
.ti-btn
{
// padding: 1rem; /* p-4 */
font-weight
:
bold
;
// background-color: #ffffff; /* bg-white */
padding
:
0
.5rem
1rem
;
/* py-2 px-4 */
// border-bottom: 1px solid #e5e7eb; /* border-b border-gray-200 */
border-radius
:
0
.5rem
;
/* rounded-lg */
// box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); /* shadow-sm */
box-shadow
:
0
4px
6px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
2px
4px
-1px
rgba
(
0
,
0
,
0
,
0
.06
);
/* shadow-md */
// }
transition
:
transform
0
.2s
ease-in-out
;
/* transition-transform */
transform
:
scale
(
1
);
/* transform */
&
:hover
{
transform
:
scale
(
1
.05
);
/* hover:scale-105 */
}
}
.ti-btn-primary-full
{
// .dashboard-content {
background-color
:
#4f46e5
;
/* bg-indigo-600 */
// // flex: 1;
color
:
#ffffff
;
/* text-white */
// padding: 1rem; /* p-4 */
&
:hover
{
// overflow: auto;
background-color
:
#4338ca
;
/* hover:bg-indigo-700 */
// min-height: 600px; /* min-h-[600px] */
}
// }
}
.ti-btn-info-full
{
// /* Button styles (assuming ti-btn is a base class) */
background-color
:
#14b8a6
;
/* bg-teal-600 */
// .ti-btn {
color
:
#ffffff
;
/* text-white */
// font-weight: bold;
&
:hover
{
// padding: 0.5rem 1rem; /* py-2 px-4 */
background-color
:
#0d9488
;
/* hover:bg-teal-700 */
// border-radius: 0.5rem; /* rounded-lg */
}
// box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* shadow-md */
}
// transition: transform 0.2s ease-in-out; /* transition-transform */
// transform: scale(1); /* transform */
// &:hover {
// transform: scale(1.05); /* hover:scale-105 */
// }
// }
.ti-btn-danger
-full
{
// .ti-btn-primary
-full {
background-color
:
#ef4444
;
/* bg-rose
-600 */
// background-color: #4f46e5; /* bg-indigo
-600 */
color
:
#ffffff
;
/* text-white */
//
color: #ffffff; /* text-white */
&
:hover
{
//
&:hover {
background-color
:
#dc2626
;
/* hover:bg-rose
-700 */
// background-color: #4338ca; /* hover:bg-indigo
-700 */
}
//
}
}
//
}
.ti-btn-success
-full
{
// .ti-btn-info
-full {
background-color
:
#10b981
;
/* bg-emerald
-600 */
// background-color: #14b8a6; /* bg-teal
-600 */
color
:
#ffffff
;
/* text-white */
//
color: #ffffff; /* text-white */
&
:hover
{
//
&:hover {
background-color
:
#059669
;
/* hover:bg-emerald
-700 */
// background-color: #0d9488; /* hover:bg-teal
-700 */
}
//
}
}
//
}
.ti-btn-secondary-full
{
// .ti-btn-danger-full {
background-color
:
#6b7280
;
/* A shade of gray, similar to default secondary */
// background-color: #ef4444; /* bg-rose-600 */
color
:
#ffffff
;
// color: #ffffff; /* text-white */
&
:hover
{
// &:hover {
background-color
:
#4b5563
;
// background-color: #dc2626; /* hover:bg-rose-700 */
}
// }
}
// .control-section {
// margin: 0 auto;
// width: 500px;
// }
// }
// #defaultLayout {
// .ti-btn-success-full {
// padding: 10px;
// background-color: #10b981; /* bg-emerald-600 */
// color: #ffffff; /* text-white */
// &:hover {
// background-color: #059669; /* hover:bg-emerald-700 */
// }
// }
// }
//
#dashboard_default .e-panel .e-panel-container .content
{
//
.ti-btn-secondary-full
{
//
vertical-align: middle;
//
background-color: #6b7280; /* A shade of gray, similar to default secondary */
//
font-weight: 600
;
//
color: #ffffff
;
//
font-size: 20px;
//
&:hover {
//
text-align: center
;
//
background-color: #4b5563
;
//
line-height: 90px;
//
}
// }
// }
// // .control-section {
// // margin: 0 auto;
// // width: 500px;
// // }
// // #defaultLayout {
// // padding: 10px;
// // }
// // #dashboard_default .e-panel .e-panel-container .content {
// // vertical-align: middle;
// // font-weight: 600;
// // font-size: 20px;
// // text-align: center;
// // line-height: 90px;
// // }
src/app/portal-manage/dashboard-management/dashboard-viewer/dashboard-viewer.component.ts
View file @
ed89bf27
...
@@ -163,7 +163,7 @@ export class DashboardViewerComponent implements OnInit, OnDestroy {
...
@@ -163,7 +163,7 @@ export class DashboardViewerComponent implements OnInit, OnDestroy {
return
null
;
return
null
;
}
}
return
{
const
panel
=
{
id
:
`
${(
widget
as
any
).
instanceId
}
-
${
widget
.
y
}
-
${
widget
.
x
}
`
,
id
:
`
${(
widget
as
any
).
instanceId
}
-
${
widget
.
y
}
-
${
widget
.
x
}
`
,
header
:
widget
.
thName
,
header
:
widget
.
thName
,
sizeX
:
widget
.
cols
||
4
,
// Default size if not specified
sizeX
:
widget
.
cols
||
4
,
// Default size if not specified
...
@@ -177,6 +177,13 @@ export class DashboardViewerComponent implements OnInit, OnDestroy {
...
@@ -177,6 +177,13 @@ export class DashboardViewerComponent implements OnInit, OnDestroy {
data
:
JSON
.
stringify
(
dataObject
)
data
:
JSON
.
stringify
(
dataObject
)
},
},
};
};
// Force SyncfusionDatagridWidgetComponent to use full width in viewer
if
(
widget
.
component
===
'SyncfusionDatagridWidgetComponent'
)
{
panel
.
sizeX
=
this
.
columns
;
}
return
panel
;
})
})
.
filter
(
panel
=>
panel
!==
null
)
as
DashboardPanel
[];
.
filter
(
panel
=>
panel
!==
null
)
as
DashboardPanel
[];
}
}
...
...
src/app/portal-manage/dashboard-management/widget-config/widget-config.component.html
View file @
ed89bf27
...
@@ -609,6 +609,10 @@
...
@@ -609,6 +609,10 @@
<div
*
ngIf=
"widgetType === 'PieChartWidgetComponent' || widgetType === 'BarChartWidgetComponent' || widgetType === 'AreaChartWidgetComponent' || widgetType === 'DoughnutChartWidgetComponent' || widgetType === 'FunnelChartWidgetComponent'"
>
<div
*
ngIf=
"widgetType === 'PieChartWidgetComponent' || widgetType === 'BarChartWidgetComponent' || widgetType === 'AreaChartWidgetComponent' || widgetType === 'DoughnutChartWidgetComponent' || widgetType === 'FunnelChartWidgetComponent'"
>
<mat-form-field
appearance=
"fill"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Title
</mat-label>
<input
matInput
[(
ngModel
)]="
currentConfig
.
title
"
name=
"title"
>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
X-Axis Field
</mat-label>
<mat-label>
X-Axis Field
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
xField
"
name=
"xField"
>
<mat-select
[(
ngModel
)]="
currentConfig
.
xField
"
name=
"xField"
>
<mat-option
*
ngFor=
"let col of availableColumns"
[
value
]="
col
"
>
{{ col }}
</mat-option>
<mat-option
*
ngFor=
"let col of availableColumns"
[
value
]="
col
"
>
{{ col }}
</mat-option>
...
@@ -620,18 +624,26 @@
...
@@ -620,18 +624,26 @@
<mat-option
*
ngFor=
"let col of availableColumns"
[
value
]="
col
"
>
{{ col }}
</mat-option>
<mat-option
*
ngFor=
"let col of availableColumns"
[
value
]="
col
"
>
{{ col }}
</mat-option>
</mat-select>
</mat-select>
</mat-form-field>
</mat-form-field>
<mat-form-field
appearance=
"fill"
*
ngIf=
"widgetType === 'PieChartWidgetComponent' || widgetType === 'DoughnutChartWidgetComponent' || widgetType === 'FunnelChartWidgetComponent'"
>
<mat-label>
Label Field
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
labelField
"
name=
"labelField"
>
<mat-option
*
ngFor=
"let col of availableColumns"
[
value
]="
col
"
>
{{ col }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field
appearance=
"fill"
*
ngIf=
"widgetType === 'PieChartWidgetComponent' || widgetType === 'DoughnutChartWidgetComponent' || widgetType === 'FunnelChartWidgetComponent'"
>
<mat-label>
Value Field
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
valueField
"
name=
"valueField"
>
<mat-option
*
ngFor=
"let col of availableColumns"
[
value
]="
col
"
>
{{ col }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Aggregation
(for Pie/Doughnut/Funnel)
</mat-label>
<mat-label>
Aggregation
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
aggregation
"
name=
"aggregation"
>
<mat-select
[(
ngModel
)]="
currentConfig
.
aggregation
"
name=
"aggregation"
>
<mat-option
value=
"none"
>
None
</mat-option>
<mat-option
value=
"none"
>
None
</mat-option>
<mat-option
value=
"count"
>
Count
</mat-option>
<mat-option
value=
"count"
>
Count
</mat-option>
<mat-option
value=
"sum"
>
Sum
</mat-option>
<mat-option
value=
"sum"
>
Sum
</mat-option>
</mat-select>
</mat-select>
</mat-form-field>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Title
</mat-label>
<input
matInput
[(
ngModel
)]="
currentConfig
.
title
"
name=
"title"
>
</mat-form-field>
</div>
</div>
<div
*
ngIf=
"widgetType === 'GaugeChartWidgetComponent'"
>
<div
*
ngIf=
"widgetType === 'GaugeChartWidgetComponent'"
>
...
...
src/app/portal-manage/dashboard-management/widget-config/widget-config.component.ts
View file @
ed89bf27
...
@@ -218,9 +218,11 @@ export class WidgetConfigComponent implements OnInit, AfterViewInit, OnDestroy {
...
@@ -218,9 +218,11 @@ export class WidgetConfigComponent implements OnInit, AfterViewInit, OnDestroy {
if
(
!
this
.
currentConfig
.
clickAction
)
this
.
currentConfig
.
clickAction
=
'none'
;
if
(
!
this
.
currentConfig
.
clickAction
)
this
.
currentConfig
.
clickAction
=
'none'
;
// Layout configuration defaults
// Layout configuration defaults
if
(
this
.
currentConfig
.
width
===
undefined
)
this
.
currentConfig
.
width
=
6
00
;
if
(
this
.
currentConfig
.
width
===
undefined
)
this
.
currentConfig
.
width
=
1
00
;
if
(
this
.
currentConfig
.
height
===
undefined
)
this
.
currentConfig
.
height
=
400
;
if
(
this
.
currentConfig
.
height
===
undefined
)
this
.
currentConfig
.
height
=
400
;
if
(
this
.
currentConfig
.
responsive
===
undefined
)
this
.
currentConfig
.
responsive
=
true
;
if
(
this
.
currentConfig
.
responsive
===
undefined
)
this
.
currentConfig
.
responsive
=
true
;
if
(
this
.
currentConfig
.
widthUnit
===
undefined
)
this
.
currentConfig
.
widthUnit
=
'%'
;
if
(
this
.
currentConfig
.
fullWidth
===
undefined
)
this
.
currentConfig
.
fullWidth
=
true
;
// Data configuration defaults
// Data configuration defaults
if
(
!
this
.
currentConfig
.
dataSource
)
this
.
currentConfig
.
dataSource
=
'static'
;
if
(
!
this
.
currentConfig
.
dataSource
)
this
.
currentConfig
.
dataSource
=
'static'
;
...
@@ -257,6 +259,7 @@ export class WidgetConfigComponent implements OnInit, AfterViewInit, OnDestroy {
...
@@ -257,6 +259,7 @@ export class WidgetConfigComponent implements OnInit, AfterViewInit, OnDestroy {
if
(
!
this
.
currentConfig
.
yAxisField
)
this
.
currentConfig
.
yAxisField
=
''
;
if
(
!
this
.
currentConfig
.
yAxisField
)
this
.
currentConfig
.
yAxisField
=
''
;
if
(
!
this
.
currentConfig
.
valueField
)
this
.
currentConfig
.
valueField
=
''
;
if
(
!
this
.
currentConfig
.
valueField
)
this
.
currentConfig
.
valueField
=
''
;
if
(
!
this
.
currentConfig
.
labelField
)
this
.
currentConfig
.
labelField
=
''
;
if
(
!
this
.
currentConfig
.
labelField
)
this
.
currentConfig
.
labelField
=
''
;
if
(
!
this
.
currentConfig
.
aggregation
)
this
.
currentConfig
.
aggregation
=
'count'
;
if
(
!
this
.
currentConfig
.
apiEndpoint
)
this
.
currentConfig
.
apiEndpoint
=
''
;
if
(
!
this
.
currentConfig
.
apiEndpoint
)
this
.
currentConfig
.
apiEndpoint
=
''
;
// Chart options defaults
// Chart options defaults
...
...
src/app/portal-manage/dashboard-management/widgets/bar-chart-widget/bar-chart-widget.component.ts
View file @
ed89bf27
...
@@ -31,18 +31,74 @@ export class BarChartWidgetComponent extends BaseWidgetComponent {
...
@@ -31,18 +31,74 @@ export class BarChartWidgetComponent extends BaseWidgetComponent {
}
}
onDataUpdate
(
data
:
any
[]):
void
{
onDataUpdate
(
data
:
any
[]):
void
{
if
(
!
data
||
data
.
length
===
0
)
{
// Check if data is an array
if
(
!
Array
.
isArray
(
data
)
||
data
.
length
===
0
)
{
this
.
chartData
=
[];
this
.
chartData
=
[];
return
;
return
;
}
}
const
xField
=
this
.
configObj
.
xField
||
'x'
;
// Support multiple field name formats from config
const
yField
=
this
.
configObj
.
yField
||
'y'
;
const
xField
=
this
.
configObj
.
xField
||
this
.
configObj
.
xAxisField
||
'x'
;
const
yField
=
this
.
configObj
.
yField
||
this
.
configObj
.
yAxisField
||
'y'
;
const
valueField
=
this
.
configObj
.
valueField
||
this
.
configObj
.
aggregation
?
this
.
configObj
.
valueField
:
'y'
;
this
.
chartData
=
data
.
map
(
item
=>
({
console
.
log
(
'BarChart onDataUpdate:'
,
{
x
:
item
[
xField
]
||
''
,
data
:
data
.
slice
(
0
,
3
),
y
:
item
[
yField
]
||
0
xField
,
}));
yField
,
valueField
,
aggregation
:
this
.
configObj
.
aggregation
,
config
:
this
.
configObj
});
// Handle aggregation if needed
// Auto-detect if using ID field
let
effectiveAggregation
=
this
.
configObj
.
aggregation
;
if
(
this
.
configObj
.
aggregation
===
'sum'
&&
valueField
)
{
const
fieldLower
=
valueField
.
toLowerCase
();
if
(
fieldLower
.
includes
(
'id'
)
||
(
fieldLower
.
includes
(
'employee'
)
&&
fieldLower
.
includes
(
'id'
)))
{
effectiveAggregation
=
'count'
;
console
.
warn
(
`BarChart: Detected ID field "
${
valueField
}
", switching from sum to count`
);
}
}
if
(
effectiveAggregation
===
'sum'
||
effectiveAggregation
===
'count'
)
{
const
groupedData
=
data
.
reduce
((
acc
,
item
)
=>
{
const
key
=
item
[
xField
]
||
''
;
if
(
!
acc
[
key
])
{
acc
[
key
]
=
0
;
}
if
(
effectiveAggregation
===
'count'
)
{
// Count: เพียงแค่นับจำนวน record
acc
[
key
]
+=
1
;
}
else
if
(
effectiveAggregation
===
'sum'
&&
valueField
&&
item
[
valueField
])
{
// Sum: ใช้ valueField ในการรวมค่า (เช่น salary, amount)
const
value
=
typeof
item
[
valueField
]
===
'number'
?
item
[
valueField
]
:
parseFloat
(
item
[
valueField
])
||
0
;
acc
[
key
]
+=
value
;
}
else
{
// ถ้าไม่มี valueField หรือไม่ใช่ number ให้ใช้ count แทน
acc
[
key
]
+=
1
;
}
return
acc
;
},
{});
this
.
chartData
=
Object
.
keys
(
groupedData
).
map
(
key
=>
({
x
:
key
,
y
:
groupedData
[
key
]
}));
}
else
{
// No aggregation - map directly
const
fieldToUse
=
valueField
||
yField
;
this
.
chartData
=
data
.
map
(
item
=>
({
x
:
item
[
xField
]
||
''
,
y
:
item
[
fieldToUse
]
||
0
}));
}
console
.
log
(
'BarChart chartData:'
,
this
.
chartData
.
slice
(
0
,
5
));
}
}
onReset
():
void
{
onReset
():
void
{
...
...
src/app/portal-manage/dashboard-management/widgets/base-widget.component.ts
View file @
ed89bf27
...
@@ -35,22 +35,34 @@ export abstract class BaseWidgetComponent implements OnInit, OnDestroy {
...
@@ -35,22 +35,34 @@ export abstract class BaseWidgetComponent implements OnInit, OnDestroy {
next
:
(
selectedDataset
:
SelectedDataset
|
null
)
=>
{
next
:
(
selectedDataset
:
SelectedDataset
|
null
)
=>
{
this
.
isLoading
=
true
;
this
.
isLoading
=
true
;
this
.
hasError
=
false
;
this
.
hasError
=
false
;
if
(
selectedDataset
&&
selectedDataset
.
data
)
{
console
.
log
(
'BaseWidget received dataset:'
,
{
selectedDataset
,
hasData
:
selectedDataset
?.
data
?.
length
,
widgetConfig
:
this
.
configObj
});
if
(
selectedDataset
&&
selectedDataset
.
data
&&
Array
.
isArray
(
selectedDataset
.
data
))
{
try
{
try
{
this
.
originalData
=
selectedDataset
.
data
;
this
.
originalData
=
selectedDataset
.
data
;
console
.
log
(
'BaseWidget applying filters on data of length:'
,
this
.
originalData
.
length
);
this
.
applyFilters
();
this
.
applyFilters
();
console
.
log
(
'BaseWidget filtered data length:'
,
this
.
filteredData
.
length
);
this
.
onDataUpdate
(
this
.
filteredData
);
this
.
onDataUpdate
(
this
.
filteredData
);
this
.
isLoading
=
false
;
this
.
isLoading
=
false
;
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
'BaseWidget error in data processing:'
,
error
);
this
.
handleError
(
error
);
this
.
handleError
(
error
);
}
}
}
else
{
}
else
{
console
.
warn
(
'BaseWidget no dataset available, showing loading state'
);
// If no dataset is selected, just keep showing the initial config with a loading state.
// If no dataset is selected, just keep showing the initial config with a loading state.
// The initial state is set by applyInitialConfig().
// The initial state is set by applyInitialConfig().
this
.
isLoading
=
true
;
this
.
isLoading
=
true
;
}
}
},
},
error
:
(
err
)
=>
{
error
:
(
err
)
=>
{
console
.
error
(
'BaseWidget error in subscription:'
,
err
);
this
.
handleError
(
err
);
this
.
handleError
(
err
);
}
}
});
});
...
@@ -105,7 +117,9 @@ export abstract class BaseWidgetComponent implements OnInit, OnDestroy {
...
@@ -105,7 +117,9 @@ export abstract class BaseWidgetComponent implements OnInit, OnDestroy {
// Parse data string to array
// Parse data string to array
try
{
try
{
this
.
originalData
=
JSON
.
parse
(
this
.
data
);
const
parsedData
=
JSON
.
parse
(
this
.
data
);
// Ensure parsed data is an array, not an object
this
.
originalData
=
Array
.
isArray
(
parsedData
)
?
parsedData
:
[];
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
warn
(
'Failed to parse data JSON:'
,
error
);
console
.
warn
(
'Failed to parse data JSON:'
,
error
);
this
.
originalData
=
[];
this
.
originalData
=
[];
...
...
src/app/portal-manage/dashboard-management/widgets/pie-chart-widget/pie-chart-widget.component.ts
View file @
ed89bf27
...
@@ -21,33 +21,102 @@ export class PieChartWidgetComponent extends BaseWidgetComponent {
...
@@ -21,33 +21,102 @@ export class PieChartWidgetComponent extends BaseWidgetComponent {
applyInitialConfig
():
void
{
applyInitialConfig
():
void
{
this
.
title
=
this
.
configObj
.
title
||
'Pie Chart'
;
this
.
title
=
this
.
configObj
.
title
||
'Pie Chart'
;
this
.
legendSettings
=
{
visible
:
true
};
this
.
legendSettings
=
{
visible
:
true
,
position
:
'Bottom'
,
textStyle
:
{
size
:
'14px'
},
height
:
'50px'
,
width
:
'100%'
,
alignment
:
'Center'
};
this
.
chartData
=
[];
this
.
chartData
=
[];
}
}
onDataUpdate
(
data
:
any
[]):
void
{
onDataUpdate
(
data
:
any
[]):
void
{
if
(
!
data
||
data
.
length
===
0
)
{
// Check if data is an array
if
(
!
Array
.
isArray
(
data
)
||
data
.
length
===
0
)
{
this
.
chartData
=
[];
this
.
chartData
=
[];
return
;
return
;
}
}
const
xField
=
this
.
configObj
.
xField
||
'x'
;
// Support multiple field name formats from config
const
yField
=
this
.
configObj
.
yField
||
'y'
;
const
labelField
=
this
.
configObj
.
labelField
||
this
.
configObj
.
xField
||
this
.
configObj
.
xAxisField
||
'x'
;
const
valueField
=
this
.
configObj
.
valueField
||
this
.
configObj
.
yField
||
this
.
configObj
.
yAxisField
||
'y'
;
console
.
log
(
'PieChart onDataUpdate:'
,
{
title
:
this
.
title
,
dataLength
:
data
.
length
,
labelField
,
valueField
,
aggregation
:
this
.
configObj
.
aggregation
,
sampleData
:
data
.
slice
(
0
,
2
)
});
let
transformedData
=
data
;
let
transformedData
=
data
;
if
(
this
.
configObj
.
aggregation
===
'count'
)
{
// Handle aggregation if needed
// Default to count if using any id field as value
let
effectiveAggregation
=
this
.
configObj
.
aggregation
;
if
(
this
.
configObj
.
aggregation
===
'sum'
&&
valueField
)
{
const
fieldLower
=
valueField
.
toLowerCase
();
if
(
fieldLower
.
includes
(
'id'
)
||
fieldLower
.
includes
(
'employee'
)
&&
fieldLower
.
includes
(
'id'
))
{
effectiveAggregation
=
'count'
;
console
.
warn
(
`Detected ID field "
${
valueField
}
", switching from sum to count aggregation`
);
}
}
console
.
log
(
'Effective aggregation:'
,
effectiveAggregation
,
'original:'
,
this
.
configObj
.
aggregation
,
'labelField:'
,
labelField
,
'valueField:'
,
valueField
);
if
(
effectiveAggregation
===
'count'
||
(
effectiveAggregation
===
'sum'
&&
!
valueField
))
{
// Count: นับจำนวนรายการตาม labelField
// หรือ Sum ถ้าไม่ระบุ valueField (คล้าย count)
const
counts
=
transformedData
.
reduce
((
acc
,
item
)
=>
{
const
counts
=
transformedData
.
reduce
((
acc
,
item
)
=>
{
const
key
=
item
[
x
Field
]
||
''
;
const
key
=
item
[
label
Field
]
||
''
;
acc
[
key
]
=
(
acc
[
key
]
||
0
)
+
1
;
acc
[
key
]
=
(
acc
[
key
]
||
0
)
+
1
;
return
acc
;
return
acc
;
},
{});
},
{});
transformedData
=
Object
.
keys
(
counts
).
map
(
key
=>
({
x
:
key
,
y
:
counts
[
key
]
}));
transformedData
=
Object
.
keys
(
counts
).
map
(
key
=>
({
x
:
key
||
'(Empty)'
,
y
:
counts
[
key
],
text
:
`
${
key
||
'(Empty)'
}
:
${
counts
[
key
]}
`
}));
console
.
log
(
'PieChart using COUNT aggregation, result:'
,
transformedData
);
}
else
if
(
effectiveAggregation
===
'sum'
&&
valueField
)
{
// Sum: รวมค่า valueField ตาม labelField (เฉพาะกรณีที่ระบุ valueField)
// ตรวจสอบว่า valueField มีค่าที่สมเหตุสมผลหรือไม่
const
groupedData
=
transformedData
.
reduce
((
acc
,
item
)
=>
{
const
key
=
item
[
labelField
]
||
''
;
const
value
=
item
[
valueField
]
||
0
;
if
(
!
acc
[
key
])
{
acc
[
key
]
=
0
;
}
// ถ้า value เป็น ID หรือ string ที่ไม่ได้เป็นตัวเลข ให้ไม่ sum
if
(
typeof
value
===
'string'
&&
isNaN
(
Number
(
value
)))
{
// ถ้าเป็น ID หรือ string ธรรมดา ให้ข้าม
return
acc
;
}
acc
[
key
]
+=
typeof
value
===
'number'
?
value
:
parseFloat
(
value
)
||
0
;
return
acc
;
},
{});
transformedData
=
Object
.
keys
(
groupedData
).
map
(
key
=>
({
x
:
key
||
'(Empty)'
,
y
:
groupedData
[
key
],
text
:
`
${
key
||
'(Empty)'
}
:
${
groupedData
[
key
]}
`
}));
}
else
{
}
else
{
// No aggregation: map directly
transformedData
=
transformedData
.
map
(
item
=>
({
transformedData
=
transformedData
.
map
(
item
=>
({
x
:
item
[
xField
]
||
''
,
x
:
item
[
labelField
]
||
'(Empty)'
,
y
:
item
[
yField
]
||
0
y
:
item
[
valueField
]
||
0
,
text
:
`
${
item
[
labelField
]
||
'(Empty)'
}
:
${
item
[
valueField
]
||
0
}
`
}));
}));
}
}
console
.
log
(
'PieChart chartData:'
,
transformedData
.
slice
(
0
,
10
));
this
.
chartData
=
transformedData
;
this
.
chartData
=
transformedData
;
}
}
...
...
src/app/portal-manage/dashboard-management/widgets/simple-kpi-widget/simple-kpi-widget.component.ts
View file @
ed89bf27
...
@@ -325,17 +325,37 @@ export class SimpleKpiWidgetComponent extends BaseWidgetComponent {
...
@@ -325,17 +325,37 @@ export class SimpleKpiWidgetComponent extends BaseWidgetComponent {
return
;
return
;
}
}
console
.
log
(
'SimpleKpiWidget onDataUpdate:'
,
{
title
:
this
.
title
,
dataLength
:
data
?.
length
,
hasFilter
:
this
.
enableFilter
,
filterField
:
this
.
filterField
,
filterValue
:
this
.
filterValue
});
// Transform data if transform function is provided
// Transform data if transform function is provided
let
transformedData
=
this
.
transformData
(
data
);
let
transformedData
=
this
.
transformData
(
data
);
// Apply filtering if enabled
// Apply filtering if enabled
if
(
this
.
enableFilter
&&
this
.
filterField
&&
this
.
filterValue
)
{
if
(
this
.
enableFilter
&&
this
.
filterField
&&
this
.
filterValue
)
{
transformedData
=
this
.
applyFilter
(
transformedData
);
transformedData
=
this
.
applyFilter
(
transformedData
);
console
.
log
(
'SimpleKpiWidget after filter:'
,
{
filteredLength
:
transformedData
?.
length
});
}
}
// Handle count aggregation separately as it doesn't need a valueField
// Handle count aggregation separately as it doesn't need a valueField
if
(
this
.
aggregation
===
'count'
)
{
if
(
this
.
aggregation
===
'count'
)
{
this
.
value
=
(
transformedData
?.
length
||
0
).
toLocaleString
();
// If valueField is specified and it's a date/unique field, count unique values
if
(
this
.
valueField
&&
[
'dateid'
,
'date'
,
'datetime'
,
'day'
].
some
(
part
=>
this
.
valueField
.
toLowerCase
().
includes
(
part
)))
{
// Count unique values instead of all records
const
uniqueValues
=
new
Set
(
transformedData
.
map
(
item
=>
item
[
this
.
valueField
]));
this
.
value
=
uniqueValues
.
size
.
toLocaleString
();
console
.
log
(
`SimpleKpiWidget counting unique
${
this
.
valueField
}
:
${
uniqueValues
.
size
}
from
${
transformedData
.
length
}
records`
);
}
else
{
// Regular count: count all records
this
.
value
=
(
transformedData
?.
length
||
0
).
toLocaleString
();
}
this
.
updateTrendData
(
transformedData
);
this
.
updateTrendData
(
transformedData
);
this
.
updateLabel
(
transformedData
);
this
.
updateLabel
(
transformedData
);
return
;
return
;
...
@@ -914,15 +934,22 @@ export class SimpleKpiWidgetComponent extends BaseWidgetComponent {
...
@@ -914,15 +934,22 @@ export class SimpleKpiWidgetComponent extends BaseWidgetComponent {
return
data
;
return
data
;
}
}
console
.
log
(
'SimpleKpiWidget applying filter:'
,
{
filterField
:
this
.
filterField
,
filterValue
:
this
.
filterValue
,
filterOperator
:
this
.
filterOperator
,
dataLength
:
data
?.
length
});
return
data
.
filter
(
item
=>
{
return
data
.
filter
(
item
=>
{
const
fieldValue
=
item
[
this
.
filterField
];
const
fieldValue
=
item
[
this
.
filterField
];
const
filterValue
=
this
.
filterValue
;
const
filterValue
=
this
.
filterValue
;
switch
(
this
.
filterOperator
)
{
switch
(
this
.
filterOperator
)
{
case
'equals'
:
case
'equals'
:
return
fieldValue
==
filterValue
;
return
String
(
fieldValue
).
toLowerCase
()
===
String
(
filterValue
).
toLowerCase
()
;
case
'not_equals'
:
case
'not_equals'
:
return
fieldValue
!=
filterValue
;
return
String
(
fieldValue
).
toLowerCase
()
!==
String
(
filterValue
).
toLowerCase
()
;
case
'greater_than'
:
case
'greater_than'
:
return
Number
(
fieldValue
)
>
Number
(
filterValue
);
return
Number
(
fieldValue
)
>
Number
(
filterValue
);
case
'less_than'
:
case
'less_than'
:
...
...
src/app/portal-manage/dashboard-management/widgets/syncfusion-datagrid-widget/syncfusion-datagrid-widget.component.html
View file @
ed89bf27
...
@@ -115,6 +115,7 @@
...
@@ -115,6 +115,7 @@
(
actionComplete
)="
actionComplete
($
event
)"
(
actionComplete
)="
actionComplete
($
event
)"
(
dataBound
)="
onDataBound
($
event
)"
(
dataBound
)="
onDataBound
($
event
)"
[
height
]="'
100
%'"
[
height
]="'
100
%'"
[
width
]="'
100
%'"
[
allowResizing
]="
allowResizing
"
[
allowResizing
]="
allowResizing
"
[
rowHeight
]="
rowHeight
"
>
[
rowHeight
]="
rowHeight
"
>
...
...
src/app/portal-manage/dashboard-management/widgets/syncfusion-datagrid-widget/syncfusion-datagrid-widget.component.scss
View file @
ed89bf27
...
@@ -5,6 +5,9 @@
...
@@ -5,6 +5,9 @@
height
:
100%
;
height
:
100%
;
position
:
relative
;
position
:
relative
;
overflow
:
hidden
;
overflow
:
hidden
;
width
:
100%
;
margin
:
0
;
padding
:
0
;
// Widget Header
// Widget Header
.widget-header
{
.widget-header
{
...
@@ -300,6 +303,10 @@
...
@@ -300,6 +303,10 @@
background
:
white
;
background
:
white
;
border-radius
:
8px
;
border-radius
:
8px
;
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0
.1
);
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0
.1
);
width
:
100%
;
height
:
100%
;
margin
:
0
;
padding
:
0
;
}
}
// Interaction States
// Interaction States
...
@@ -454,10 +461,18 @@
...
@@ -454,10 +461,18 @@
.e-grid
{
.e-grid
{
border
:
none
!
important
;
border
:
none
!
important
;
font-family
:
inherit
;
font-family
:
inherit
;
width
:
100%
!
important
;
height
:
100%
!
important
;
min-width
:
0
!
important
;
min-height
:
0
!
important
;
margin
:
0
!
important
;
padding
:
0
!
important
;
max-width
:
100%
!
important
;
.e-gridheader
{
.e-gridheader
{
background-color
:
inherit
;
background-color
:
inherit
;
border-bottom
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.5
);
border-bottom
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.5
);
width
:
100%
!
important
;
.e-headercell
{
.e-headercell
{
background-color
:
inherit
;
background-color
:
inherit
;
...
@@ -466,6 +481,10 @@
...
@@ -466,6 +481,10 @@
font-size
:
13px
;
font-size
:
13px
;
padding
:
12px
8px
;
padding
:
12px
8px
;
border-right
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.3
);
border-right
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.3
);
min-width
:
0
!
important
;
overflow
:
hidden
!
important
;
text-overflow
:
ellipsis
!
important
;
white-space
:
nowrap
!
important
;
&
:last-child
{
&
:last-child
{
border-right
:
none
;
border-right
:
none
;
...
@@ -475,6 +494,8 @@
...
@@ -475,6 +494,8 @@
.e-content
{
.e-content
{
background-color
:
transparent
;
background-color
:
transparent
;
width
:
100%
!
important
;
min-width
:
0
!
important
;
.e-row
{
.e-row
{
border-bottom
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.2
);
border-bottom
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.2
);
...
@@ -497,6 +518,10 @@
...
@@ -497,6 +518,10 @@
border-right
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.2
);
border-right
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.2
);
font-size
:
13px
;
font-size
:
13px
;
color
:
inherit
;
color
:
inherit
;
min-width
:
0
!
important
;
overflow
:
hidden
!
important
;
text-overflow
:
ellipsis
!
important
;
white-space
:
nowrap
!
important
;
&
:last-child
{
&
:last-child
{
border-right
:
none
;
border-right
:
none
;
...
...
src/app/portal-manage/dashboard-management/widgets/syncfusion-datagrid-widget/syncfusion-datagrid-widget.component.ts
View file @
ed89bf27
...
@@ -167,7 +167,7 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
...
@@ -167,7 +167,7 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
public
animateConditionalChange
:
boolean
=
true
;
public
animateConditionalChange
:
boolean
=
true
;
// Layout properties
// Layout properties
public
width
:
number
=
6
00
;
public
width
:
number
=
1
00
;
public
height
:
number
=
400
;
public
height
:
number
=
400
;
public
minWidth
:
number
=
400
;
public
minWidth
:
number
=
400
;
public
minHeight
:
number
=
300
;
public
minHeight
:
number
=
300
;
...
@@ -175,11 +175,11 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
...
@@ -175,11 +175,11 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
public
maxHeight
:
number
=
800
;
public
maxHeight
:
number
=
800
;
public
aspectRatio
:
string
=
'auto'
;
public
aspectRatio
:
string
=
'auto'
;
public
responsive
:
boolean
=
true
;
public
responsive
:
boolean
=
true
;
public
widthUnit
:
string
=
'
px
'
;
public
widthUnit
:
string
=
'
%
'
;
public
heightUnit
:
string
=
'px'
;
public
heightUnit
:
string
=
'px'
;
public
fullWidth
:
boolean
=
fals
e
;
public
fullWidth
:
boolean
=
tru
e
;
public
fullHeight
:
boolean
=
false
;
public
fullHeight
:
boolean
=
false
;
public
sizeOption
:
string
=
'
medium
'
;
public
sizeOption
:
string
=
'
full-width
'
;
// Data properties
// Data properties
public
dataSource
:
string
=
'static'
;
public
dataSource
:
string
=
'static'
;
...
@@ -392,7 +392,7 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
...
@@ -392,7 +392,7 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
this
.
customClickHandler
=
this
.
configObj
.
customClickHandler
||
''
;
this
.
customClickHandler
=
this
.
configObj
.
customClickHandler
||
''
;
// Layout configuration
// Layout configuration
this
.
width
=
this
.
configObj
.
width
||
6
00
;
this
.
width
=
this
.
configObj
.
width
||
1
00
;
this
.
height
=
this
.
configObj
.
height
||
400
;
this
.
height
=
this
.
configObj
.
height
||
400
;
this
.
minWidth
=
this
.
configObj
.
minWidth
||
400
;
this
.
minWidth
=
this
.
configObj
.
minWidth
||
400
;
this
.
minHeight
=
this
.
configObj
.
minHeight
||
300
;
this
.
minHeight
=
this
.
configObj
.
minHeight
||
300
;
...
@@ -400,9 +400,9 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
...
@@ -400,9 +400,9 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
this
.
maxHeight
=
this
.
configObj
.
maxHeight
||
800
;
this
.
maxHeight
=
this
.
configObj
.
maxHeight
||
800
;
this
.
aspectRatio
=
this
.
configObj
.
aspectRatio
||
'auto'
;
this
.
aspectRatio
=
this
.
configObj
.
aspectRatio
||
'auto'
;
this
.
responsive
=
this
.
configObj
.
responsive
!==
undefined
?
this
.
configObj
.
responsive
:
true
;
this
.
responsive
=
this
.
configObj
.
responsive
!==
undefined
?
this
.
configObj
.
responsive
:
true
;
this
.
widthUnit
=
this
.
configObj
.
widthUnit
||
'
px
'
;
this
.
widthUnit
=
this
.
configObj
.
widthUnit
||
'
%
'
;
this
.
heightUnit
=
this
.
configObj
.
heightUnit
||
'px'
;
this
.
heightUnit
=
this
.
configObj
.
heightUnit
||
'px'
;
this
.
fullWidth
=
this
.
configObj
.
fullWidth
!==
undefined
?
this
.
configObj
.
fullWidth
:
fals
e
;
this
.
fullWidth
=
this
.
configObj
.
fullWidth
!==
undefined
?
this
.
configObj
.
fullWidth
:
tru
e
;
this
.
fullHeight
=
this
.
configObj
.
fullHeight
!==
undefined
?
this
.
configObj
.
fullHeight
:
false
;
this
.
fullHeight
=
this
.
configObj
.
fullHeight
!==
undefined
?
this
.
configObj
.
fullHeight
:
false
;
this
.
sizeOption
=
this
.
configObj
.
sizeOption
||
'medium'
;
this
.
sizeOption
=
this
.
configObj
.
sizeOption
||
'medium'
;
...
@@ -843,8 +843,8 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
...
@@ -843,8 +843,8 @@ export class SyncfusionDatagridWidgetComponent extends BaseWidgetComponent imple
'border-color'
:
this
.
borderColor
,
'border-color'
:
this
.
borderColor
,
'border-radius'
:
`
${
this
.
borderRadius
}
px`
,
'border-radius'
:
`
${
this
.
borderRadius
}
px`
,
'border-width'
:
`
${
this
.
borderWidth
}
px`
,
'border-width'
:
`
${
this
.
borderWidth
}
px`
,
'padding'
:
`
${
this
.
padding
}
px`
,
'padding'
:
'0px'
,
// Force no padding for full width
'margin'
:
`
${
this
.
margin
}
px`
,
'margin'
:
'0px'
,
// Force no margin for full width
'font-size'
:
`
${
this
.
fontSize
}
px`
,
'font-size'
:
`
${
this
.
fontSize
}
px`
,
'font-weight'
:
this
.
fontWeight
,
'font-weight'
:
this
.
fontWeight
,
'font-family'
:
this
.
fontFamily
,
'font-family'
:
this
.
fontFamily
,
...
...
src/app/portal-manage/dashboard-management/widgets/syncfusion-pivot-widget/syncfusion-pivot-widget.component.ts
View file @
ed89bf27
...
@@ -469,11 +469,11 @@ export class SyncfusionPivotWidgetComponent extends BaseWidgetComponent implemen
...
@@ -469,11 +469,11 @@ export class SyncfusionPivotWidgetComponent extends BaseWidgetComponent implemen
onDataBound
(
args
:
any
):
void
{
onDataBound
(
args
:
any
):
void
{
// Apply perspective after data is loaded and rendered, but only once.
// Apply perspective after data is loaded and rendered, but only once.
if
(
this
.
perspective
&&
!
this
.
isPerspectiveApplied
&&
this
.
perspective
!==
'{}'
)
{
//
if (this.perspective && !this.isPerspectiveApplied && this.perspective !== '{}') {
setTimeout
(()
=>
{
//
setTimeout(() => {
this
.
setWidgetState
(
this
.
perspective
as
string
);
//
this.setWidgetState(this.perspective as string);
},
50
);
// Small delay to ensure rendering is complete
//
}, 50); // Small delay to ensure rendering is complete
}
//
}
}
}
onReset
():
void
{
onReset
():
void
{
...
...
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