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
7ba8fc42
Commit
7ba8fc42
authored
Sep 15, 2025
by
Ooh-Ao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ss
parent
67977999
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
52 additions
and
554 deletions
+52
-554
dashboard-viewer.component.html
...nagement/dashboard-viewer/dashboard-viewer.component.html
+49
-73
widget-config.component.html
...ard-management/widget-config/widget-config.component.html
+0
-433
widget-config.component.ts
...board-management/widget-config/widget-config.component.ts
+3
-48
No files found.
src/app/portal-manage/dashboard-management/dashboard-viewer/dashboard-viewer.component.html
View file @
7ba8fc42
<div
class=
"min-h-screen dashboard-background"
>
<!-- Enhanced Dashboard Header -->
<div
class=
"dashboard-header-container"
>
<div
class=
"header-content"
>
<div
class=
"header-flex"
>
<div
class=
"header-left"
>
<!-- Dashboard Title with Icon -->
<div
class=
"header-title-section"
>
<!-- <div class="title-icon">
<i class="bi bi-grid-3x3-gap"></i>
</div> -->
<div
class=
"title-content"
>
<h1>
{{dashboardData?.thName}}
</h1>
<!-- <p>Create and manage your dashboards</p> -->
</div>
</div>
</div>
</div>
</div>
<!-- Enhanced Dashboard Content Area -->
<div
class=
"dashboard-content-area"
>
<!-- Dashboard Content -->
<div
class=
"dashboard-content-card"
>
<div
*
ngIf=
"!panels || panels.length === 0"
class=
"empty-state"
>
<div
class=
"empty-state-icon"
>
<i
class=
"bi bi-grid-3x3-gap"
></i>
</div>
<h3
class=
"empty-state-title"
>
Empty Dashboard
</h3>
<p
class=
"empty-state-description"
>
To get started, select a dashboard from the dropdown above or create
a new one. Then, click on a widget from the sidebar on the left to
add it to this canvas.
</p>
</div>
<!-- Error Message -->
<div
*
ngIf=
"errorMessage"
class=
"error-message"
>
<div
class=
"error-message-content"
>
<i
class=
"bi bi-exclamation-triangle-fill error-icon"
></i>
<span
class=
"error-text"
>
Error:
</span>
<span
class=
"error-description"
>
{{ errorMessage }}
</span>
</div>
</div>
<!-- Dashboard Layout -->
<div
*
ngIf=
"panels.length > 0"
class=
"dashboard-layout-container"
>
<ejs-dashboardlayout
id=
"dashboard_default"
[
columns
]="
columns
"
[
cellSpacing
]="
cellSpacing
"
[
panels
]="
panels
"
#
editLayout
[
allowResizing
]="
false
"
[
allowDragging
]="
false
"
class=
"dashboard-layout"
>
<e-panels>
<e-panel
*
ngFor=
"let panel of panels"
[
id
]="
panel
.
id
+
'
-
'
+
panel
.
row
+
'
-
'
+
panel
.
col
"
[
sizeX
]="
panel
.
sizeX
"
[
sizeY
]="
panel
.
sizeY
"
[
row
]="
panel
.
row
"
[
col
]="
panel
.
col
"
[
zIndex
]="
999
"
>
<ng-template
#
header
>
</ng-template>
<ng-template
#
content
>
<ng-container
[
ngComponentOutlet
]="
panel
.
componentType
"
[
ngComponentOutletInputs
]="
panel
.
componentInputs
"
></ng-container>
</ng-template>
</e-panel>
</e-panels>
</ejs-dashboardlayout>
</div>
</div>
</div>
<!-- Dashboard Viewer Container - Clean Layout -->
<div
*
ngIf=
"dashboardData"
class=
"viewer-container-clean"
>
<!-- Dashboard Content Only -->
<div
class=
"viewer-content-clean"
>
<ejs-dashboardlayout
id=
"dashboard_default"
#
editLayout
[
cellSpacing
]="
cellSpacing
"
[
panels
]="
panels
"
[
columns
]="
columns
"
[
allowResizing
]="
false
"
[
allowDragging
]="
false
"
[
allowFloating
]="
false
"
[
showGridLines
]="
false
"
class=
"dashboard-layout"
>
<e-panels>
<e-panel
*
ngFor=
"let panel of panels"
[
zIndex
]="
999
"
[
row
]="
panel
.
row
"
[
col
]="
panel
.
col
"
[
sizeX
]="
panel
.
sizeX
"
[
sizeY
]="
panel
.
sizeY
"
[
id
]="
panel
.
id
+
'
-
'
+
panel
.
row
+
'
-
'
+
panel
.
col
"
class=
"widget-panel-clean"
>
<ng-template
#
header
>
<!-- No header -->
</ng-template>
<ng-template
#
content
>
<div
class=
"widget-content-clean"
>
<ng-container
[
ngComponentOutlet
]="
panel
.
componentType
"
[
ngComponentOutletInputs
]="
panel
.
componentInputs
"
></ng-container>
</div>
</ng-template>
</e-panel>
</e-panels>
</ejs-dashboardlayout>
</div>
</div>
src/app/portal-manage/dashboard-management/widget-config/widget-config.component.html
View file @
7ba8fc42
...
...
@@ -2,11 +2,6 @@
<mat-dialog-content>
<form>
<!-- Dynamic Config Component Container -->
<div
#
configContainer
></div>
<!-- Fallback Config for widgets without specific config components -->
<div
*
ngIf=
"!widgetConfigRegistry.hasConfigComponent(widgetType)"
>
<div
*
ngIf=
"widgetType === 'CompanyInfoWidgetComponent' || widgetType === 'CompanyInfoSubfolderWidgetComponent'"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Title
</mat-label>
...
...
@@ -1451,434 +1446,6 @@
</div>
</div>
<div
*
ngIf=
"widgetType === 'SyncfusionPivotWidgetComponent'"
>
<!-- Basic Configuration -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-blue-600"
>
Basic Configuration
</h3>
<mat-form-field
appearance=
"fill"
class=
"w-full"
>
<mat-label>
Title
</mat-label>
<input
matInput
[(
ngModel
)]="
currentConfig
.
title
"
name=
"title"
aria-label=
"Widget title"
>
<mat-hint>
Widget title displayed in header
</mat-hint>
</mat-form-field>
<div
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Display As
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
displayOptionView
"
name=
"displayOptionView"
>
<mat-option
value=
"Both"
>
Both (Grid
&
Chart)
</mat-option>
<mat-option
value=
"Grid"
>
Grid Only
</mat-option>
<mat-option
value=
"Chart"
>
Chart Only
</mat-option>
</mat-select>
<mat-hint>
What to display
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Chart Type
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
chartType
"
name=
"chartType"
>
<mat-option
value=
"Column"
>
Column
</mat-option>
<mat-option
value=
"Bar"
>
Bar
</mat-option>
<mat-option
value=
"Line"
>
Line
</mat-option>
<mat-option
value=
"Area"
>
Area
</mat-option>
<mat-option
value=
"Pie"
>
Pie
</mat-option>
<mat-option
value=
"Doughnut"
>
Doughnut
</mat-option>
</mat-select>
<mat-hint>
Chart type when displaying chart
</mat-hint>
</mat-form-field>
</div>
</div>
<!-- Pivot Functionality -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-green-600"
>
Pivot Functionality
</h3>
<div
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
showFieldList
"
name=
"showFieldList"
class=
"mr-2"
>
Show Field List
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
showToolbar
"
name=
"showToolbar"
class=
"mr-2"
>
Show Toolbar
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
showGroupingBar
"
name=
"showGroupingBar"
class=
"mr-2"
>
Show Grouping Bar
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
allowCalculatedField
"
name=
"allowCalculatedField"
class=
"mr-2"
>
Allow Calculated Fields
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
allowConditionalFormatting
"
name=
"allowConditionalFormatting"
class=
"mr-2"
>
Allow Conditional Formatting
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
allowNumberFormatting
"
name=
"allowNumberFormatting"
class=
"mr-2"
>
Allow Number Formatting
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
allowSubTotal
"
name=
"allowSubTotal"
class=
"mr-2"
>
Allow Sub Total
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
allowGrandTotal
"
name=
"allowGrandTotal"
class=
"mr-2"
>
Allow Grand Total
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
allowExcelExport
"
name=
"allowExcelExport"
class=
"mr-2"
>
Allow Excel Export
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
allowPdfExport
"
name=
"allowPdfExport"
class=
"mr-2"
>
Allow PDF Export
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
allowCsvExport
"
name=
"allowCsvExport"
class=
"mr-2"
>
Allow CSV Export
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
showChart
"
name=
"showChart"
class=
"mr-2"
>
Show Chart
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
showGrid
"
name=
"showGrid"
class=
"mr-2"
>
Show Grid
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableDrillThrough
"
name=
"enableDrillThrough"
class=
"mr-2"
>
Enable Drill Through
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableSorting
"
name=
"enableSorting"
class=
"mr-2"
>
Enable Sorting
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableFiltering
"
name=
"enableFiltering"
class=
"mr-2"
>
Enable Filtering
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableGrouping
"
name=
"enableGrouping"
class=
"mr-2"
>
Enable Grouping
</mat-checkbox>
</div>
</div>
</div>
<!-- Style Configuration -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-purple-600"
>
Style
&
Colors
</h3>
<div
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Background Color
</mat-label>
<input
matInput
type=
"color"
[(
ngModel
)]="
currentConfig
.
backgroundColor
"
name=
"backgroundColor"
class=
"h-[40px]"
aria-label=
"Background color"
>
<mat-hint>
Widget background color
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Header Background Color
</mat-label>
<input
matInput
type=
"color"
[(
ngModel
)]="
currentConfig
.
headerBackgroundColor
"
name=
"headerBackgroundColor"
class=
"h-[40px]"
aria-label=
"Header background color"
>
<mat-hint>
Header background color
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Text Color
</mat-label>
<input
matInput
type=
"color"
[(
ngModel
)]="
currentConfig
.
textColor
"
name=
"textColor"
class=
"h-[40px]"
aria-label=
"Text color"
>
<mat-hint>
Text color
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Header Text Color
</mat-label>
<input
matInput
type=
"color"
[(
ngModel
)]="
currentConfig
.
headerTextColor
"
name=
"headerTextColor"
class=
"h-[40px]"
aria-label=
"Header text color"
>
<mat-hint>
Header text color
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Border Color
</mat-label>
<input
matInput
type=
"color"
[(
ngModel
)]="
currentConfig
.
borderColor
"
name=
"borderColor"
class=
"h-[40px]"
aria-label=
"Border color"
>
<mat-hint>
Widget border color
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Accent Color
</mat-label>
<input
matInput
type=
"color"
[(
ngModel
)]="
currentConfig
.
accentColor
"
name=
"accentColor"
class=
"h-[40px]"
aria-label=
"Accent color"
>
<mat-hint>
Selection and hover color
</mat-hint>
</mat-form-field>
</div>
<div
class=
"grid grid-cols-1 md:grid-cols-3 gap-4"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Border Radius (px)
</mat-label>
<input
matInput
type=
"number"
[(
ngModel
)]="
currentConfig
.
borderRadius
"
name=
"borderRadius"
min=
"0"
max=
"20"
aria-label=
"Border radius"
>
<mat-hint>
Widget border radius
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Padding (px)
</mat-label>
<input
matInput
type=
"number"
[(
ngModel
)]="
currentConfig
.
padding
"
name=
"padding"
min=
"0"
max=
"50"
aria-label=
"Padding"
>
<mat-hint>
Internal spacing
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Font Size (px)
</mat-label>
<input
matInput
type=
"number"
[(
ngModel
)]="
currentConfig
.
fontSize
"
name=
"fontSize"
min=
"10"
max=
"20"
aria-label=
"Font size"
>
<mat-hint>
Font size for content
</mat-hint>
</mat-form-field>
</div>
<mat-form-field
appearance=
"fill"
class=
"w-full"
>
<mat-label>
Font Weight
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
fontWeight
"
name=
"fontWeight"
>
<mat-option
value=
"normal"
>
Normal
</mat-option>
<mat-option
value=
"bold"
>
Bold
</mat-option>
<mat-option
value=
"lighter"
>
Lighter
</mat-option>
<mat-option
value=
"bolder"
>
Bolder
</mat-option>
</mat-select>
<mat-hint>
Font weight
</mat-hint>
</mat-form-field>
</div>
<!-- Animation Configuration -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-orange-600"
>
Animation Settings
</h3>
<div
class=
"flex items-center mb-3"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableAnimations
"
name=
"enableAnimations"
class=
"mr-2"
>
Enable Animations
</mat-checkbox>
</div>
<div
*
ngIf=
"currentConfig.enableAnimations"
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Animation Type
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
animationType
"
name=
"animationType"
>
<mat-option
value=
"fade"
>
Fade
</mat-option>
<mat-option
value=
"slide"
>
Slide
</mat-option>
<mat-option
value=
"bounce"
>
Bounce
</mat-option>
<mat-option
value=
"pulse"
>
Pulse
</mat-option>
<mat-option
value=
"none"
>
None
</mat-option>
</mat-select>
<mat-hint>
Animation effect type
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Animation Duration (ms)
</mat-label>
<input
matInput
type=
"number"
[(
ngModel
)]="
currentConfig
.
animationDuration
"
name=
"animationDuration"
min=
"100"
max=
"2000"
step=
"100"
aria-label=
"Animation duration"
>
<mat-hint>
Duration of animation
</mat-hint>
</mat-form-field>
</div>
<div
*
ngIf=
"currentConfig.enableAnimations"
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
hoverEffects
"
name=
"hoverEffects"
class=
"mr-2"
>
Enable Hover Effects
</mat-checkbox>
</div>
</div>
<!-- Interaction Settings -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-indigo-600"
>
Interaction Settings
</h3>
<div
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableTooltip
"
name=
"enableTooltip"
class=
"mr-2"
>
Enable Tooltips
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableClick
"
name=
"enableClick"
class=
"mr-2"
>
Enable Click Events
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableHover
"
name=
"enableHover"
class=
"mr-2"
>
Enable Hover Effects
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
enableExport
"
name=
"enableExport"
class=
"mr-2"
>
Enable Export
</mat-checkbox>
</div>
</div>
<mat-form-field
appearance=
"fill"
class=
"w-full"
>
<mat-label>
Click Action
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
clickAction
"
name=
"clickAction"
>
<mat-option
value=
"none"
>
None
</mat-option>
<mat-option
value=
"drill_down"
>
Drill Down
</mat-option>
<mat-option
value=
"open_modal"
>
Open Modal
</mat-option>
<mat-option
value=
"navigate"
>
Navigate
</mat-option>
<mat-option
value=
"custom"
>
Custom
</mat-option>
</mat-select>
<mat-hint>
Action when widget is clicked
</mat-hint>
</mat-form-field>
<mat-form-field
*
ngIf=
"currentConfig.clickAction === 'custom'"
appearance=
"fill"
class=
"w-full"
>
<mat-label>
Custom Click Handler
</mat-label>
<textarea
matInput
[(
ngModel
)]="
currentConfig
.
customClickHandler
"
name=
"customClickHandler"
rows=
"3"
placeholder=
"function(event) { console.log('Widget clicked:', event); }"
></textarea>
<mat-hint>
Custom JavaScript function for click events
</mat-hint>
</mat-form-field>
</div>
<!-- Layout Configuration -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-teal-600"
>
Layout Settings
</h3>
<div
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Width (px)
</mat-label>
<input
matInput
type=
"number"
[(
ngModel
)]="
currentConfig
.
width
"
name=
"width"
min=
"600"
max=
"1400"
aria-label=
"Widget width"
>
<mat-hint>
Widget width
</mat-hint>
</mat-form-field>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Height (px)
</mat-label>
<input
matInput
type=
"number"
[(
ngModel
)]="
currentConfig
.
height
"
name=
"height"
min=
"400"
max=
"1000"
aria-label=
"Widget height"
>
<mat-hint>
Widget height
</mat-hint>
</mat-form-field>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
responsive
"
name=
"responsive"
class=
"mr-2"
>
Responsive Layout
</mat-checkbox>
</div>
</div>
<!-- Data Configuration -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-red-600"
>
Data Settings
</h3>
<mat-form-field
appearance=
"fill"
class=
"w-full"
>
<mat-label>
Data Source
</mat-label>
<mat-select
[(
ngModel
)]="
currentConfig
.
dataSource
"
name=
"dataSource"
>
<mat-option
value=
"static"
>
Static Data
</mat-option>
<mat-option
value=
"api"
>
API Endpoint
</mat-option>
<mat-option
value=
"websocket"
>
WebSocket
</mat-option>
<mat-option
value=
"file"
>
File Upload
</mat-option>
</mat-select>
<mat-hint>
Data source type
</mat-hint>
</mat-form-field>
<mat-form-field
*
ngIf=
"currentConfig.dataSource === 'api'"
appearance=
"fill"
class=
"w-full"
>
<mat-label>
API Endpoint
</mat-label>
<input
matInput
[(
ngModel
)]="
currentConfig
.
apiEndpoint
"
name=
"apiEndpoint"
placeholder=
"/api/pivot-data"
aria-label=
"API endpoint"
>
<mat-hint>
API endpoint URL
</mat-hint>
</mat-form-field>
<div
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Refresh Interval (ms)
</mat-label>
<input
matInput
type=
"number"
[(
ngModel
)]="
currentConfig
.
refreshInterval
"
name=
"refreshInterval"
min=
"0"
step=
"1000"
aria-label=
"Refresh interval"
>
<mat-hint>
0 = No auto-refresh
</mat-hint>
</mat-form-field>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
cacheEnabled
"
name=
"cacheEnabled"
class=
"mr-2"
>
Enable Data Caching
</mat-checkbox>
</div>
</div>
<mat-form-field
appearance=
"fill"
class=
"w-full"
>
<mat-label>
Data Transform Function
</mat-label>
<textarea
matInput
[(
ngModel
)]="
currentConfig
.
dataTransform
"
name=
"dataTransform"
rows=
"3"
placeholder=
"data => data.map(item => ({ ...item, formattedValue: formatCurrency(item.value) }))"
></textarea>
<mat-hint>
JavaScript function to transform data
</mat-hint>
</mat-form-field>
</div>
<!-- Security Configuration -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-gray-600"
>
Security Settings
</h3>
<div
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
requireAuth
"
name=
"requireAuth"
class=
"mr-2"
>
Require Authentication
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
dataEncryption
"
name=
"dataEncryption"
class=
"mr-2"
>
Enable Data Encryption
</mat-checkbox>
</div>
<div
class=
"flex items-center"
>
<mat-checkbox
[(
ngModel
)]="
currentConfig
.
auditLog
"
name=
"auditLog"
class=
"mr-2"
>
Enable Audit Logging
</mat-checkbox>
</div>
<mat-form-field
appearance=
"fill"
>
<mat-label>
Rate Limit (requests/min)
</mat-label>
<input
matInput
type=
"number"
[(
ngModel
)]="
currentConfig
.
rateLimit
"
name=
"rateLimit"
min=
"0"
aria-label=
"Rate limit"
>
<mat-hint>
0 = No limit
</mat-hint>
</mat-form-field>
</div>
<mat-form-field
appearance=
"fill"
class=
"w-full"
>
<mat-label>
Allowed Roles (comma-separated)
</mat-label>
<input
matInput
[(
ngModel
)]="
currentConfig
.
allowedRoles
"
name=
"allowedRoles"
placeholder=
"admin, analyst, manager"
aria-label=
"Allowed roles"
>
<mat-hint>
Roles that can access this widget
</mat-hint>
</mat-form-field>
</div>
<!-- Custom CSS -->
<div
class=
"config-section border p-4 rounded-lg mb-4"
>
<h3
class=
"text-lg font-semibold mb-3 text-purple-600"
>
Custom Styling
</h3>
<mat-form-field
appearance=
"fill"
class=
"w-full"
>
<mat-label>
Custom CSS
</mat-label>
<textarea
matInput
[(
ngModel
)]="
currentConfig
.
customCSS
"
name=
"customCSS"
rows=
"4"
placeholder=
"/* Add custom CSS rules here */ .syncfusion-pivot-widget:hover { transform: translateY(-4px); }"
></textarea>
<mat-hint>
Add custom CSS for advanced styling
</mat-hint>
</mat-form-field>
</div>
</div>
<!-- End Fallback Config -->
</div>
</form>
</mat-dialog-content>
...
...
src/app/portal-manage/dashboard-management/widget-config/widget-config.component.ts
View file @
7ba8fc42
import
{
Component
,
Inject
,
OnInit
,
OnDestroy
,
AfterViewInit
,
ViewChild
,
ViewContainerRef
,
ComponentRef
}
from
'@angular/core'
;
import
{
Component
,
Inject
,
OnInit
}
from
'@angular/core'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
MAT_DIALOG_DATA
,
MatDialogRef
}
from
'@angular/material/dialog'
;
import
{
MatDialogModule
}
from
'@angular/material/dialog'
;
...
...
@@ -10,7 +10,6 @@ import { MatIconModule } from '@angular/material/icon';
import
{
MatCheckboxModule
}
from
'@angular/material/checkbox'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
WidgetConfigGeneratorService
}
from
'../services/widget-config-generator.service'
;
import
{
WidgetConfigRegistryService
}
from
'./services/widget-config-registry.service'
;
import
{
WidgetModel
}
from
'../models/widgets.model'
;
export
interface
WidgetConfigDialogData
{
...
...
@@ -36,20 +35,16 @@ export interface WidgetConfigDialogData {
templateUrl
:
'./widget-config.component.html'
,
styleUrls
:
[
'./widget-config.component.scss'
]
})
export
class
WidgetConfigComponent
implements
OnInit
,
AfterViewInit
,
OnDestroy
{
@
ViewChild
(
'configContainer'
,
{
read
:
ViewContainerRef
})
configContainer
!
:
ViewContainerRef
;
export
class
WidgetConfigComponent
implements
OnInit
{
currentConfig
:
any
;
availableColumns
:
string
[];
widgetType
:
string
;
comboChartTypes
:
string
[]
=
[
'Line'
,
'Column'
,
'Area'
,
'Spline'
];
private
configComponentRef
:
ComponentRef
<
any
>
|
null
=
null
;
constructor
(
public
dialogRef
:
MatDialogRef
<
WidgetConfigComponent
>
,
@
Inject
(
MAT_DIALOG_DATA
)
public
data
:
WidgetConfigDialogData
,
private
widgetConfigGenerator
:
WidgetConfigGeneratorService
,
public
widgetConfigRegistry
:
WidgetConfigRegistryService
private
widgetConfigGenerator
:
WidgetConfigGeneratorService
)
{
}
ngOnInit
():
void
{
...
...
@@ -72,13 +67,6 @@ export class WidgetConfigComponent implements OnInit, AfterViewInit, OnDestroy {
}
}
// Use fallback config if no config is available
if
(
!
this
.
currentConfig
||
Object
.
keys
(
this
.
currentConfig
).
length
===
0
)
{
this
.
currentConfig
=
this
.
widgetConfigRegistry
.
getFallbackConfig
(
this
.
widgetType
);
}
// Load dynamic config component will be called in ngAfterViewInit
const
gridLikeWidgets
=
[
'SyncfusionDatagridWidgetComponent'
,
'NewDataTableWidget'
,
'MatrixWidgetComponent'
];
if
(
gridLikeWidgets
.
includes
(
this
.
widgetType
)
&&
!
this
.
currentConfig
.
columns
)
{
this
.
currentConfig
.
columns
=
[];
...
...
@@ -285,45 +273,12 @@ export class WidgetConfigComponent implements OnInit, AfterViewInit, OnDestroy {
addPivotFilter
()
{
this
.
currentConfig
.
filters
.
push
({
name
:
''
});
}
removePivotFilter
(
index
:
number
)
{
this
.
currentConfig
.
filters
.
splice
(
index
,
1
);
}
ngAfterViewInit
():
void
{
// Load dynamic config component after view is initialized
this
.
loadConfigComponent
();
}
private
loadConfigComponent
():
void
{
const
configComponentType
=
this
.
widgetConfigRegistry
.
getConfigComponent
(
this
.
widgetType
);
if
(
configComponentType
)
{
// Load the specific config component
this
.
configComponentRef
=
this
.
configContainer
.
createComponent
(
configComponentType
);
this
.
configComponentRef
.
instance
.
currentConfig
=
this
.
currentConfig
;
this
.
configComponentRef
.
instance
.
availableColumns
=
this
.
availableColumns
;
// Subscribe to config changes
if
(
this
.
configComponentRef
.
instance
.
configChange
)
{
this
.
configComponentRef
.
instance
.
configChange
.
subscribe
((
config
:
any
)
=>
{
this
.
currentConfig
=
config
;
});
}
}
// If no specific config component is found, the template will show the fallback config
}
onSave
():
void
{
// Get the latest config from the dynamic component if it exists
if
(
this
.
configComponentRef
&&
this
.
configComponentRef
.
instance
.
currentConfig
)
{
this
.
currentConfig
=
this
.
configComponentRef
.
instance
.
currentConfig
;
}
this
.
dialogRef
.
close
(
this
.
currentConfig
);
}
onCancel
():
void
{
this
.
dialogRef
.
close
();
}
ngOnDestroy
():
void
{
if
(
this
.
configComponentRef
)
{
this
.
configComponentRef
.
destroy
();
}
}
}
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