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
c21d15b2
Commit
c21d15b2
authored
Sep 16, 2025
by
Ooh-Ao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
pivot
parent
f0065caa
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
409 additions
and
45 deletions
+409
-45
widget-config-registry.service.ts
.../widget-config/services/widget-config-registry.service.ts
+84
-3
syncfusion-pivot-config.component.ts
...cfusion-pivot-config/syncfusion-pivot-config.component.ts
+0
-0
syncfusion-pivot-widget.component.html
...usion-pivot-widget/syncfusion-pivot-widget.component.html
+64
-24
syncfusion-pivot-widget.component.scss
...usion-pivot-widget/syncfusion-pivot-widget.component.scss
+261
-18
syncfusion-pivot-widget.component.ts
...cfusion-pivot-widget/syncfusion-pivot-widget.component.ts
+0
-0
No files found.
src/app/portal-manage/dashboard-management/widget-config/services/widget-config-registry.service.ts
View file @
c21d15b2
...
...
@@ -1118,23 +1118,104 @@ export class WidgetConfigRegistryService {
// ========================================
'SyncfusionPivotWidgetComponent'
:
{
...
baseConfig
,
// Basic Configuration
expandAll
:
false
,
displayOptionView
:
'Both'
,
chartType
:
'Column'
,
dataSource
:
'static'
,
apiEndpoint
:
''
,
// Pivot Features
showToolbar
:
true
,
showFieldList
:
true
,
showGroupingBar
:
true
,
showPager
:
true
,
allowCalculatedField
:
false
,
allowConditionalFormatting
:
false
,
allowNumberFormatting
:
true
,
allowFieldDragDrop
:
true
,
allowSubTotal
:
true
,
allowGrandTotal
:
true
,
allowDrillThrough
:
false
,
allowSorting
:
true
,
allowExcelExport
:
true
,
allowPdfExport
:
true
,
allowCsvExport
:
true
,
allowPrint
:
true
,
aggregationType
:
'sum'
,
numberFormat
:
'N'
,
// Pivot Fields
rows
:
[],
columns
:
[],
values
:
[],
filters
:
[],
enableDrillThrough
:
true
,
enableSorting
:
true
,
// Enhanced UI Configuration
dataCount
:
0
,
lastUpdated
:
new
Date
(),
shadow
:
'medium'
,
isLoading
:
false
,
hasError
:
false
,
errorMessage
:
''
,
isEmpty
:
false
,
// Enhanced Interaction Configuration
enableKeyboard
:
true
,
enableFocus
:
true
,
hoverEffect
:
true
,
clickEffect
:
true
,
enableTooltip
:
true
,
enableSelection
:
true
,
enableExport
:
true
,
enableRefresh
:
true
,
clickAction
:
'none'
,
customClickHandler
:
''
,
// Enhanced Layout Configuration
fullWidth
:
false
,
fullHeight
:
false
,
widthUnit
:
'px'
,
heightUnit
:
'px'
,
sizeOption
:
'medium'
,
aspectRatio
:
'auto'
,
// Enhanced Data Configuration
enableFiltering
:
true
,
enableSorting
:
true
,
enableGrouping
:
true
,
enablePaging
:
true
,
pageSize
:
10
,
currentPage
:
1
,
totalPages
:
1
,
// Enhanced Security Configuration
requireHttps
:
false
,
allowedRoles
:
''
,
dataEncryption
:
false
,
auditLog
:
false
,
rateLimit
:
0
,
// Enhanced Animation Configuration
enableAnimations
:
true
,
animationType
:
'fade'
,
animationDuration
:
300
,
animationDelay
:
0
,
// Enhanced Style Configuration
customCSS
:
''
,
theme
:
'light'
,
fontSize
:
14
,
fontWeight
:
'normal'
,
fontFamily
:
'system-ui, -apple-system, sans-serif'
,
padding
:
16
,
margin
:
8
,
// Additional Pivot Configuration
showGrandTotals
:
true
,
showSubTotals
:
true
,
showRowTotals
:
true
,
showColumnTotals
:
true
,
enableExport
:
true
,
exportFormats
:
[
'excel'
,
'pdf'
,
'csv'
]
},
...
...
src/app/portal-manage/dashboard-management/widgets/configs/syncfusion-pivot-config/syncfusion-pivot-config.component.ts
View file @
c21d15b2
This diff is collapsed.
Click to expand it.
src/app/portal-manage/dashboard-management/widgets/syncfusion-pivot-widget/syncfusion-pivot-widget.component.html
View file @
c21d15b2
<div
class=
"syncfusion-pivot-widget"
[
ngStyle
]="
getAllStyles
()"
[
ngClass
]="['
custom-styled
',
getInteractionClasses
()]"
[
ngClass
]="['
custom-styled
',
getInteractionClasses
()
,
'
shadow-
'
+
shadow
]"
[
attr
.
data-widget-id
]="
widgetId
"
[
attr
.
data-source
]="
dataSource
"
[
title
]="
enableTooltip
?
(
title
+
'
-
Pivot
Table
Widget
')
:
null
"
...
...
@@ -21,13 +21,24 @@
<div
class=
"header-content"
>
<div
class=
"header-left"
>
<h4
class=
"widget-title"
>
{{ title }}
</h4>
<div
class=
"data-count"
*
ngIf=
"dataCount > 0"
>
<i
class=
"bi bi-database"
></i>
<span>
{{ dataCount }} records
</span>
</div>
<div
class=
"last-updated"
*
ngIf=
"lastUpdated"
>
<i
class=
"bi bi-clock"
></i>
<span>
{{ lastUpdated | date:'short' }}
</span>
</div>
</div>
<div
class=
"header-actions"
>
<div
*
ngIf=
"enableExport"
class=
"
export-button"
(
click
)="
exportData
($
event
)
"
>
<div
*
ngIf=
"enableExport"
class=
"
action-button export-button"
(
click
)="
exportData
($
event
)"
title=
"Export Data
"
>
<i
class=
"bi bi-download"
></i>
</div>
<div
*
ngIf=
"enableRefresh && dataSource !== 'static'"
class=
"refresh-button"
(
click
)="
refreshData
($
event
)"
>
<i
class=
"bi bi-arrow-clockwise"
></i>
<div
*
ngIf=
"enableRefresh && dataSource !== 'static'"
class=
"action-button refresh-button"
(
click
)="
refreshData
($
event
)"
title=
"Refresh Data"
>
<i
class=
"bi bi-arrow-clockwise"
[
class
.
rotating
]="
isLoading
"
></i>
</div>
<div
*
ngIf=
"enableFiltering"
class=
"action-button filter-button"
(
click
)="
toggleFilter
($
event
)"
title=
"Toggle Filter"
>
<i
class=
"bi bi-funnel"
></i>
</div>
</div>
</div>
...
...
@@ -35,6 +46,10 @@
<i
class=
"bi bi-info-circle"
></i>
<span>
{{ getDataSourceInfo() }}
</span>
</div>
<div
*
ngIf=
"requireHttps && !dataSource.includes('https')"
class=
"security-warning"
>
<i
class=
"bi bi-shield-exclamation"
></i>
<span>
HTTPS required for secure data transmission
</span>
</div>
</div>
<!-- Security Warning -->
...
...
@@ -47,32 +62,57 @@
<div
*
ngIf=
"hasRequiredRole()"
class=
"widget-body"
>
<!-- Loading State -->
<div
*
ngIf=
"isLoading"
class=
"flex justify-center items-center h-full"
>
<div
class=
"animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"
></div>
<div
*
ngIf=
"isLoading"
class=
"loading-state"
>
<div
class=
"loading-spinner"
>
<div
class=
"spinner"
></div>
</div>
<p
class=
"loading-text"
>
Loading pivot data...
</p>
</div>
<!-- Error State -->
<div
*
ngIf=
"hasError"
class=
"flex flex-col justify-center items-center h-full text-red-500"
>
<i
class=
"bi bi-exclamation-circle-fill text-4xl"
></i>
<p
class=
"mt-2 font-semibold"
>
{{ errorMessage }}
</p>
<div
*
ngIf=
"hasError"
class=
"error-state"
>
<div
class=
"error-icon"
>
<i
class=
"bi bi-exclamation-circle-fill"
></i>
</div>
<h3
class=
"error-title"
>
Error Loading Data
</h3>
<p
class=
"error-message"
>
{{ errorMessage }}
</p>
<button
class=
"retry-button"
(
click
)="
refreshData
($
event
)"
>
<i
class=
"bi bi-arrow-clockwise"
></i>
Retry
</button>
</div>
<!-- Empty State -->
<div
*
ngIf=
"isEmpty && !isLoading && !hasError"
class=
"empty-state"
>
<div
class=
"empty-icon"
>
<i
class=
"bi bi-table"
></i>
</div>
<h3
class=
"empty-title"
>
No Data Available
</h3>
<p
class=
"empty-message"
>
There is no data to display in the pivot table.
</p>
<button
class=
"refresh-button"
(
click
)="
refreshData
($
event
)"
>
<i
class=
"bi bi-arrow-clockwise"
></i>
Refresh
</button>
</div>
<!-- Pivot View -->
<ejs-pivotview
#
pivotview
*
ngIf=
"!isLoading && !hasError"
[
dataSourceSettings
]="
dataSourceSettings
"
[
allowCalculatedField
]="
allowCalculatedField
"
[
showFieldList
]="
showFieldList
"
[
showToolbar
]="
showToolbar
"
[
showGroupingBar
]="
showGroupingBar
"
[
allowPdfExport
]="
allowPdfExport
&&
enableExport
"
[
allowExcelExport
]="
allowExcelExport
&&
enableExport
"
(
toolbarClick
)="
toolbarClick
($
event
)"
[
toolbar
]="
toolbar
"
[
displayOption
]="
displayOption
"
[
chartSettings
]="
chartSettings
"
(
dataBound
)="
onDataBound
($
event
)"
[
height
]="'
100
%'"
>
</ejs-pivotview>
<div
*
ngIf=
"!isLoading && !hasError && !isEmpty"
class=
"pivot-container"
>
<ejs-pivotview
#
pivotview
[
dataSourceSettings
]="
dataSourceSettings
"
[
allowCalculatedField
]="
allowCalculatedField
"
[
showFieldList
]="
showFieldList
"
[
showToolbar
]="
showToolbar
"
[
showGroupingBar
]="
showGroupingBar
"
[
allowPdfExport
]="
allowPdfExport
&&
enableExport
"
[
allowExcelExport
]="
allowExcelExport
&&
enableExport
"
(
toolbarClick
)="
toolbarClick
($
event
)"
[
toolbar
]="
toolbar
"
[
displayOption
]="
displayOption
"
[
chartSettings
]="
chartSettings
"
(
dataBound
)="
onDataBound
($
event
)"
[
height
]="'
100
%'"
>
</ejs-pivotview>
</div>
</div>
</div>
src/app/portal-manage/dashboard-management/widgets/syncfusion-pivot-widget/syncfusion-pivot-widget.component.scss
View file @
c21d15b2
...
...
@@ -5,13 +5,36 @@
height
:
100%
;
position
:
relative
;
overflow
:
hidden
;
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
);
transition
:
all
0
.3s
ease
;
background
:
linear-gradient
(
135deg
,
#ffffff
0%
,
#f8fafc
100%
);
// Shadow variants
&
.shadow-none
{
box-shadow
:
none
;
}
&
.shadow-small
{
box-shadow
:
0
1px
3px
0
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
1px
2px
0
rgba
(
0
,
0
,
0
,
0
.06
);
}
&
.shadow-medium
{
box-shadow
:
0
4px
6px
-1px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
2px
4px
-1px
rgba
(
0
,
0
,
0
,
0
.06
);
}
&
.shadow-large
{
box-shadow
:
0
10px
15px
-3px
rgba
(
0
,
0
,
0
,
0
.1
)
,
0
4px
6px
-2px
rgba
(
0
,
0
,
0
,
0
.05
);
}
// Widget Header
.widget-header
{
flex-shrink
:
0
;
padding
:
1
2px
16
px
;
padding
:
1
6px
20
px
;
border-bottom
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.5
);
position
:
relative
;
background
:
linear-gradient
(
135deg
,
#f8fafc
0%
,
#e2e8f0
100%
);
border-radius
:
12px
12px
0
0
;
.header-content
{
display
:
flex
;
...
...
@@ -20,14 +43,41 @@
.header-left
{
display
:
flex
;
align-items
:
center
;
gap
:
8
px
;
flex-direction
:
column
;
gap
:
4
px
;
.widget-title
{
font-size
:
1
6
px
;
font-weight
:
6
00
;
font-size
:
1
8
px
;
font-weight
:
7
00
;
margin
:
0
;
color
:
inherit
;
text-shadow
:
0
1px
2px
rgba
(
0
,
0
,
0
,
0
.1
);
}
.data-count
{
display
:
flex
;
align-items
:
center
;
gap
:
4px
;
font-size
:
12px
;
color
:
#6b7280
;
font-weight
:
500
;
i
{
font-size
:
10px
;
}
}
.last-updated
{
display
:
flex
;
align-items
:
center
;
gap
:
4px
;
font-size
:
11px
;
color
:
#9ca3af
;
font-weight
:
400
;
i
{
font-size
:
9px
;
}
}
}
...
...
@@ -35,32 +85,39 @@
display
:
flex
;
gap
:
8px
;
.export-button
,
.refresh-button
{
width
:
32px
;
height
:
32px
;
border-radius
:
6px
;
.action-button
{
width
:
36px
;
height
:
36px
;
border-radius
:
8px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
transition
:
all
0
.2s
ease
;
background
:
rgba
(
255
,
255
,
255
,
0
.1
);
color
:
inherit
;
opacity
:
0
.7
;
transition
:
all
0
.3s
ease
;
background
:
rgba
(
255
,
255
,
255
,
0
.8
);
color
:
#374151
;
border
:
1px
solid
rgba
(
229
,
231
,
235
,
0
.5
);
box-shadow
:
0
1px
3px
rgba
(
0
,
0
,
0
,
0
.1
);
&
:hover
{
opacity
:
1
;
background
:
rgba
(
255
,
255
,
255
,
0
.2
);
transform
:
translateY
(
-1px
);
background
:
rgba
(
59
,
130
,
246
,
0
.1
);
border-color
:
rgba
(
59
,
130
,
246
,
0
.3
);
color
:
#3b82f6
;
transform
:
translateY
(
-2px
);
box-shadow
:
0
4px
8px
rgba
(
0
,
0
,
0
,
0
.15
);
}
&
:active
{
transform
:
translateY
(
0
);
box-shadow
:
0
1px
3px
rgba
(
0
,
0
,
0
,
0
.1
);
}
i
{
font-size
:
14px
;
font-size
:
16px
;
}
&
.rotating
i
{
animation
:
spin
1s
linear
infinite
;
}
}
}
...
...
@@ -120,6 +177,174 @@
display
:
flex
;
flex-direction
:
column
;
overflow
:
hidden
;
position
:
relative
;
}
// Loading State
.loading-state
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
padding
:
40px
;
background
:
linear-gradient
(
135deg
,
#f8fafc
0%
,
#e2e8f0
100%
);
.loading-spinner
{
margin-bottom
:
16px
;
.spinner
{
width
:
40px
;
height
:
40px
;
border
:
4px
solid
#e2e8f0
;
border-top
:
4px
solid
#3b82f6
;
border-radius
:
50%
;
animation
:
spin
1s
linear
infinite
;
}
}
.loading-text
{
font-size
:
14px
;
color
:
#6b7280
;
font-weight
:
500
;
margin
:
0
;
}
}
// Error State
.error-state
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
padding
:
40px
;
background
:
linear-gradient
(
135deg
,
#fef2f2
0%
,
#fee2e2
100%
);
text-align
:
center
;
.error-icon
{
margin-bottom
:
16px
;
i
{
font-size
:
48px
;
color
:
#ef4444
;
}
}
.error-title
{
font-size
:
18px
;
font-weight
:
600
;
color
:
#dc2626
;
margin
:
0
0
8px
0
;
}
.error-message
{
font-size
:
14px
;
color
:
#7f1d1d
;
margin
:
0
0
20px
0
;
}
.retry-button
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
padding
:
10px
20px
;
background
:
#ef4444
;
color
:
white
;
border
:
none
;
border-radius
:
8px
;
font-size
:
14px
;
font-weight
:
500
;
cursor
:
pointer
;
transition
:
all
0
.3s
ease
;
&
:hover
{
background
:
#dc2626
;
transform
:
translateY
(
-2px
);
box-shadow
:
0
4px
8px
rgba
(
239
,
68
,
68
,
0
.3
);
}
&
:active
{
transform
:
translateY
(
0
);
}
i
{
font-size
:
16px
;
}
}
}
// Empty State
.empty-state
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
padding
:
40px
;
background
:
linear-gradient
(
135deg
,
#f8fafc
0%
,
#e2e8f0
100%
);
text-align
:
center
;
.empty-icon
{
margin-bottom
:
16px
;
i
{
font-size
:
48px
;
color
:
#9ca3af
;
}
}
.empty-title
{
font-size
:
18px
;
font-weight
:
600
;
color
:
#374151
;
margin
:
0
0
8px
0
;
}
.empty-message
{
font-size
:
14px
;
color
:
#6b7280
;
margin
:
0
0
20px
0
;
}
.refresh-button
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
padding
:
10px
20px
;
background
:
#3b82f6
;
color
:
white
;
border
:
none
;
border-radius
:
8px
;
font-size
:
14px
;
font-weight
:
500
;
cursor
:
pointer
;
transition
:
all
0
.3s
ease
;
&
:hover
{
background
:
#2563eb
;
transform
:
translateY
(
-2px
);
box-shadow
:
0
4px
8px
rgba
(
59
,
130
,
246
,
0
.3
);
}
&
:active
{
transform
:
translateY
(
0
);
}
i
{
font-size
:
16px
;
}
}
}
// Pivot Container
.pivot-container
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
overflow
:
hidden
;
background
:
white
;
border-radius
:
0
0
12px
12px
;
}
// Interaction States
...
...
@@ -189,6 +414,15 @@
}
// Animation Keyframes
@keyframes
spin
{
0
%
{
transform
:
rotate
(
0deg
);
}
100
%
{
transform
:
rotate
(
360deg
);
}
}
@keyframes
fadeIn
{
from
{
opacity
:
0
;
...
...
@@ -238,6 +472,15 @@
}
}
@keyframes
shimmer
{
0
%
{
background-position
:
-200px
0
;
}
100
%
{
background-position
:
calc
(
200px
+
100%
)
0
;
}
}
// Aspect Ratio Constraints
&
.aspect-ratio-16-9
{
aspect-ratio
:
16
/
9
;
...
...
src/app/portal-manage/dashboard-management/widgets/syncfusion-pivot-widget/syncfusion-pivot-widget.component.ts
View file @
c21d15b2
This diff is collapsed.
Click to expand it.
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