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
fec4de97
Commit
fec4de97
authored
Sep 16, 2025
by
Ooh-Ao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
config tab
parent
ad76d94b
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1688 additions
and
795 deletions
+1688
-795
base-config.component.ts
...gement/widget-config/base-config/base-config.component.ts
+213
-4
widget-config.component.html
...ard-management/widget-config/widget-config.component.html
+433
-0
attendance-config.component.ts
.../configs/attendance-config/attendance-config.component.ts
+1
-1
chart-config.component.ts
...nt/widgets/configs/chart-config/chart-config.component.ts
+325
-118
company-info-config.component.ts
...figs/company-info-config/company-info-config.component.ts
+1
-1
payroll-config.component.ts
...idgets/configs/payroll-config/payroll-config.component.ts
+1
-1
simple-kpi-config.component.ts
.../configs/simple-kpi-config/simple-kpi-config.component.ts
+358
-327
syncfusion-datagrid-config.component.ts
...n-datagrid-config/syncfusion-datagrid-config.component.ts
+355
-342
syncfusion-pivot-config.component.ts
...cfusion-pivot-config/syncfusion-pivot-config.component.ts
+1
-1
No files found.
src/app/portal-manage/dashboard-management/widget-config/base-config/base-config.component.ts
View file @
fec4de97
import
{
Component
,
Input
,
Output
,
EventEmitter
}
from
'@angular/core'
;
import
{
Component
,
Input
,
Output
,
EventEmitter
,
ChangeDetectorRef
,
OnInit
,
AfterViewInit
}
from
'@angular/core'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
{
MatFormFieldModule
}
from
'@angular/material/form-field'
;
...
...
@@ -7,6 +7,7 @@ import { MatSelectModule } from '@angular/material/select';
import
{
MatCheckboxModule
}
from
'@angular/material/checkbox'
;
import
{
MatButtonModule
}
from
'@angular/material/button'
;
import
{
MatIconModule
}
from
'@angular/material/icon'
;
import
{
MatTabsModule
}
from
'@angular/material/tabs'
;
@
Component
({
selector
:
'app-base-config'
,
...
...
@@ -19,11 +20,22 @@ import { MatIconModule } from '@angular/material/icon';
MatSelectModule
,
MatCheckboxModule
,
MatButtonModule
,
MatIconModule
MatIconModule
,
MatTabsModule
],
template
:
`
<div class="base-config">
<ng-content></ng-content>
<mat-tab-group [(selectedIndex)]="selectedTabIndex" (selectedIndexChange)="onTabChange($event)">
<mat-tab *ngFor="let tab of availableTabs" [label]="tab.label">
<ng-template mat-tab-label>
<mat-icon *ngIf="tab.icon" class="tab-icon">{{ tab.icon }}</mat-icon>
{{ tab.label }}
</ng-template>
<div class="tab-content">
<ng-content></ng-content>
</div>
</mat-tab>
</mat-tab-group>
</div>
`
,
styles
:
[
`
...
...
@@ -31,6 +43,37 @@ import { MatIconModule } from '@angular/material/icon';
padding: 16px;
}
.tab-content {
padding: 16px 0;
min-height: 400px;
}
.tab-icon {
margin-right: 8px;
font-size: 18px;
width: 18px;
height: 18px;
}
::ng-deep .mat-tab-group {
width: 100%;
}
::ng-deep .mat-tab-header {
border-bottom: 1px solid #e5e7eb;
}
::ng-deep .mat-tab-label {
min-width: 120px;
padding: 0 16px;
}
::ng-deep .mat-tab-label-content {
display: flex;
align-items: center;
gap: 8px;
}
.config-section {
border: 1px solid #e5e7eb;
border-radius: 8px;
...
...
@@ -176,17 +219,132 @@ import { MatIconModule } from '@angular/material/icon';
width: 100%;
}
.config-tabs {
display: flex;
border-bottom: 1px solid #e5e7eb;
margin-bottom: 16px;
overflow-x: auto;
}
.tab-button {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 16px;
border: none;
background: none;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all 0.2s;
white-space: nowrap;
font-size: 14px;
font-weight: 500;
color: #6b7280;
}
.tab-button:hover {
background-color: #f3f4f6;
color: #374151;
}
.tab-button.active {
color: #2563eb;
border-bottom-color: #2563eb;
background-color: #eff6ff;
}
.config-content {
min-height: 400px;
}
.size-config {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
.size-option {
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 12px;
cursor: pointer;
transition: all 0.2s;
text-align: center;
}
.size-option:hover {
border-color: #2563eb;
background-color: #eff6ff;
}
.size-option.selected {
border-color: #2563eb;
background-color: #eff6ff;
}
.size-option h4 {
margin: 0 0 8px 0;
font-size: 14px;
font-weight: 600;
}
.size-option p {
margin: 0;
font-size: 12px;
color: #6b7280;
}
.column-config-item {
background: #f9fafb;
border: 1px solid #e5e7eb;
}
`
]
})
export
class
BaseConfigComponent
{
export
class
BaseConfigComponent
implements
OnInit
,
AfterViewInit
{
@
Input
()
currentConfig
:
any
;
@
Input
()
availableColumns
:
string
[]
=
[];
@
Output
()
configChange
=
new
EventEmitter
<
any
>
();
// Tab management
selectedTabIndex
:
number
=
0
;
availableTabs
:
any
[]
=
[
{
id
:
'basic'
,
label
:
'Basic'
,
icon
:
'settings'
},
{
id
:
'columns'
,
label
:
'Columns'
,
icon
:
'view_column'
},
{
id
:
'rows'
,
label
:
'Rows'
,
icon
:
'view_list'
},
{
id
:
'style'
,
label
:
'Style'
,
icon
:
'palette'
},
{
id
:
'filter'
,
label
:
'Filter'
,
icon
:
'filter_list'
},
{
id
:
'aggregate'
,
label
:
'Aggregate'
,
icon
:
'functions'
},
{
id
:
'icon'
,
label
:
'Icon'
,
icon
:
'image'
},
{
id
:
'trend'
,
label
:
'Trend'
,
icon
:
'trending_up'
},
{
id
:
'animation'
,
label
:
'Animation'
,
icon
:
'animation'
},
{
id
:
'condition'
,
label
:
'Condition'
,
icon
:
'rule'
}
];
constructor
(
protected
cdr
:
ChangeDetectorRef
)
{
// Initialize selectedTabIndex
this
.
selectedTabIndex
=
0
;
}
ngOnInit
()
{
// Ensure selectedTabIndex is set during initialization
this
.
selectedTabIndex
=
0
;
}
ngAfterViewInit
()
{
// Ensure selectedTabIndex is properly set after view initialization
setTimeout
(()
=>
{
this
.
selectedTabIndex
=
0
;
this
.
cdr
.
detectChanges
();
},
0
);
}
// Size options
sizeOptions
=
[
{
id
:
'auto'
,
label
:
'Auto'
,
description
:
'Auto fit content'
},
{
id
:
'100%'
,
label
:
'100%'
,
description
:
'Full width/height'
},
{
id
:
'custom'
,
label
:
'Custom'
,
description
:
'Custom dimensions'
}
];
// Common methods that can be used by child components
protected
updateConfig
(
key
:
string
,
value
:
any
):
void
{
this
.
currentConfig
[
key
]
=
value
;
...
...
@@ -207,4 +365,55 @@ export class BaseConfigComponent {
this
.
configChange
.
emit
(
this
.
currentConfig
);
}
}
// Tab management
onTabChange
(
index
:
number
):
void
{
this
.
selectedTabIndex
=
index
;
this
.
cdr
.
detectChanges
();
}
setActiveTab
(
tabId
:
string
):
void
{
const
index
=
this
.
availableTabs
.
findIndex
(
tab
=>
tab
.
id
===
tabId
);
if
(
index
!==
-
1
)
{
this
.
selectedTabIndex
=
index
;
this
.
cdr
.
detectChanges
();
}
}
// Size management
setSizeOption
(
option
:
string
):
void
{
this
.
updateConfig
(
'sizeOption'
,
option
);
if
(
option
===
'100%'
)
{
this
.
updateConfig
(
'width'
,
'100%'
);
this
.
updateConfig
(
'height'
,
'100%'
);
}
else
if
(
option
===
'auto'
)
{
this
.
updateConfig
(
'width'
,
'auto'
);
this
.
updateConfig
(
'height'
,
'auto'
);
}
}
// Initialize default config
protected
initializeDefaultConfig
():
void
{
if
(
!
this
.
currentConfig
)
{
this
.
currentConfig
=
{};
}
// Set default size
if
(
!
this
.
currentConfig
.
sizeOption
)
{
this
.
currentConfig
.
sizeOption
=
'auto'
;
}
// Set default dimensions
if
(
!
this
.
currentConfig
.
width
)
{
this
.
currentConfig
.
width
=
'auto'
;
}
if
(
!
this
.
currentConfig
.
height
)
{
this
.
currentConfig
.
height
=
'auto'
;
}
// Initialize default color values to prevent color format errors
if
(
!
this
.
currentConfig
.
backgroundColor
)
this
.
currentConfig
.
backgroundColor
=
'#FFFFFF'
;
if
(
!
this
.
currentConfig
.
textColor
)
this
.
currentConfig
.
textColor
=
'#374151'
;
if
(
!
this
.
currentConfig
.
borderColor
)
this
.
currentConfig
.
borderColor
=
'#E5E7EB'
;
}
}
src/app/portal-manage/dashboard-management/widget-config/widget-config.component.html
View file @
fec4de97
...
...
@@ -2,6 +2,11 @@
<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>
...
...
@@ -1446,6 +1451,434 @@
</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/widgets/configs/attendance-config/attendance-config.component.ts
View file @
fec4de97
...
...
@@ -201,7 +201,7 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
`
})
export
class
AttendanceConfigComponent
extends
BaseConfigComponent
implements
OnInit
{
ngOnInit
():
void
{
override
ngOnInit
():
void
{
// Initialize default values for attendance widget
if
(
!
this
.
currentConfig
.
layout
)
this
.
currentConfig
.
layout
=
'cards'
;
if
(
!
this
.
currentConfig
.
chartType
)
this
.
currentConfig
.
chartType
=
'pie'
;
...
...
src/app/portal-manage/dashboard-management/widgets/configs/chart-config/chart-config.component.ts
View file @
fec4de97
...
...
@@ -7,6 +7,7 @@ import { MatSelectModule } from '@angular/material/select';
import
{
MatCheckboxModule
}
from
'@angular/material/checkbox'
;
import
{
MatButtonModule
}
from
'@angular/material/button'
;
import
{
MatIconModule
}
from
'@angular/material/icon'
;
import
{
MatTabsModule
}
from
'@angular/material/tabs'
;
import
{
BaseConfigComponent
}
from
'../../../widget-config/base-config/base-config.component'
;
@
Component
({
...
...
@@ -21,17 +22,18 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
MatCheckboxModule
,
MatButtonModule
,
MatIconModule
,
MatTabsModule
,
BaseConfigComponent
],
template
:
`
<app-base-config>
<!-- 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>
<!-- Basic Configuration
Tab
-->
<div class="config-section">
<h3 class="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="
Widge
t title">
<input matInput [(ngModel)]="currentConfig.title" name="title" aria-label="
Char
t title">
<mat-hint>Chart title displayed in header</mat-hint>
</mat-form-field>
...
...
@@ -50,11 +52,13 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
<mat-option value="bar">Bar Chart</mat-option>
<mat-option value="line">Line Chart</mat-option>
<mat-option value="pie">Pie Chart</mat-option>
<mat-option value="doughnut">Doughnut Chart</mat-option>
<mat-option value="area">Area Chart</mat-option>
<mat-option value="doughnut">Doughnut Chart</mat-option>
<mat-option value="scatter">Scatter Chart</mat-option>
<mat-option value="bubble">Bubble Chart</mat-option>
<mat-option value="funnel">Funnel Chart</mat-option>
<mat-option value="waterfall">Waterfall Chart</mat-option>
<mat-option value="combo">Combo Chart</mat-option>
<mat-option value="gauge">Gauge Chart</mat-option>
<mat-option value="treemap">Treemap</mat-option>
</mat-select>
...
...
@@ -62,168 +66,371 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
</mat-form-field>
</div>
<!-- Size Configuration -->
<div class="config-section">
<h3 class="text-blue-600">Size Configuration</h3>
<div class="size-config">
<div
*ngFor="let option of sizeOptions"
class="size-option"
[class.selected]="currentConfig.sizeOption === option.id"
(click)="setSizeOption(option.id)">
<h4>{{ option.label }}</h4>
<p>{{ option.description }}</p>
</div>
</div>
<div *ngIf="currentConfig.sizeOption === 'custom'" class="grid grid-cols-2 gap-4 mt-4">
<mat-form-field appearance="fill">
<mat-label>Width</mat-label>
<input matInput [(ngModel)]="currentConfig.width" name="width" placeholder="e.g., 100%, 600px">
<mat-hint>Chart width</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Height</mat-label>
<input matInput [(ngModel)]="currentConfig.height" name="height" placeholder="e.g., 100%, 400px">
<mat-hint>Chart height</mat-hint>
</mat-form-field>
</div>
</div>
</div>
<!-- Columns Tab -->
<div class="config-section">
<h3 class="text-blue-600">Data Series Configuration</h3>
<div class="flex items-center justify-between mb-4">
<h4>Y-Axis Fields</h4>
<button mat-raised-button color="primary" (click)="addYField()">
<mat-icon>add</mat-icon>
Add Series
</button>
</div>
<div *ngFor="let field of currentConfig.yFields; let i = index" class="column-config-item p-4 mb-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<mat-form-field appearance="fill">
<mat-label>Field Name</mat-label>
<mat-select [(ngModel)]="field.field" name="yField{{i}}">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Series Name</mat-label>
<input matInput [(ngModel)]="field.name" name="yFieldName{{i}}" placeholder="Series display name">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Chart Type</mat-label>
<mat-select [(ngModel)]="field.type" name="yFieldType{{i}}">
<mat-option value="bar">Bar</mat-option>
<mat-option value="line">Line</mat-option>
<mat-option value="area">Area</mat-option>
<mat-option value="scatter">Scatter</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Color</mat-label>
<input matInput type="color" [(ngModel)]="field.color" name="yFieldColor{{i}}">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Y-Axis</mat-label>
<mat-select [(ngModel)]="field.yAxis" name="yFieldAxis{{i}}">
<mat-option value="primary">Primary</mat-option>
<mat-option value="secondary">Secondary</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="flex items-center justify-between mt-4">
<div class="flex items-center space-x-4">
<mat-checkbox [(ngModel)]="field.visible" name="yFieldVisible{{i}}">
Visible
</mat-checkbox>
<mat-checkbox [(ngModel)]="field.showDataLabels" name="yFieldDataLabels{{i}}">
Show Data Labels
</mat-checkbox>
</div>
<button mat-icon-button color="warn" (click)="removeYField(i)">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
</div>
<!-- Rows Tab -->
<div class="config-section">
<h3 class="text-blue-600">Data Configuration</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>
X-Axis Title
</mat-label>
<input matInput
[(ngModel)]="currentConfig.xAxisTitle" name="xAxisTitle
">
<mat-hint>
X-axis label
</mat-hint>
<mat-label>
Data Limit
</mat-label>
<input matInput
type="number" [(ngModel)]="currentConfig.dataLimit" name="dataLimit" min="10" max="1000
">
<mat-hint>
Maximum number of data points
</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Y-Axis Title</mat-label>
<input matInput [(ngModel)]="currentConfig.yAxisTitle" name="yAxisTitle">
<mat-hint>Y-axis label</mat-hint>
<mat-label>Data Sort Field</mat-label>
<mat-select [(ngModel)]="currentConfig.dataSortField" name="dataSortField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
<mat-hint>Field to sort data by</mat-hint>
</mat-form-field>
</div>
</div>
<!-- Y-Axis Fields -->
<div class="config-section border p-3 rounded-lg mb-4">
<h3 class="text-lg font-semibold mb-2">Y-Axis Fields</h3>
<div *ngFor="let yField of currentConfig.yFields; let i = index" class="flex items-center gap-2 mb-2">
<mat-form-field appearance="fill" class="flex-grow">
<mat-label>Field {{i + 1}}</mat-label>
<mat-select [(ngModel)]="currentConfig.yFields[i]" [name]="'yfield_' + i">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Sort Order</mat-label>
<mat-select [(ngModel)]="currentConfig.dataSortOrder" name="dataSortOrder">
<mat-option value="asc">Ascending</mat-option>
<mat-option value="desc">Descending</mat-option>
</mat-select>
<mat-hint>Sort order for data</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Group By Field</mat-label>
<mat-select [(ngModel)]="currentConfig.groupByField" name="groupByField">
<mat-option value="">None</mat-option>
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
<mat-hint>Field to group data by</mat-hint>
</mat-form-field>
<button mat-icon-button color="warn" (click)="removeChartYField(i)" type="button"><mat-icon>delete</mat-icon></button>
</div>
<button mat-stroked-button color="primary" (click)="addChartYField()" type="button"><mat-icon>add</mat-icon> Add Y-Axis Field</button>
<div class="flex items-center space-x-4">
<mat-checkbox [(ngModel)]="currentConfig.showDataTable" name="showDataTable">
Show Data Table
</mat-checkbox>
<mat-checkbox [(ngModel)]="currentConfig.enableDataZoom" name="enableDataZoom">
Enable Data Zoom
</mat-checkbox>
</div>
</div>
<!--
Chart Options
-->
<div class="config-section
border p-4 rounded-lg mb-4
">
<h3 class="text-
lg font-semibold mb-3 text-green-600">Chart Options
</h3>
<!--
Style Tab
-->
<div class="config-section">
<h3 class="text-
blue-600">Style Configuration
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<
div class="flex items-center
">
<mat-
checkbox [(ngModel)]="currentConfig.showLegend" name="showLegend" class="mr-2"
>
Show Legend
<
/mat-checkbox
>
</
div
>
<
mat-form-field appearance="fill
">
<mat-
label>Background Color</mat-label
>
<input matInput type="color" [(ngModel)]="currentConfig.backgroundColor" name="backgroundColor">
<
mat-hint>Chart background color</mat-hint
>
</
mat-form-field
>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.showDataLabels" name="showDataLabels" class="mr-2">
Show Data Labels
</mat-checkbox>
</div>
<mat-form-field appearance="fill">
<mat-label>Text Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.textColor" name="textColor">
<mat-hint>Text color</mat-hint>
</mat-form-field>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.showTooltip" name="showTooltip" class="mr-2">
Show Tooltip
</mat-checkbox>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Grid Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.gridColor" name="gridColor">
<mat-hint>Grid line color</mat-hint>
</mat-form-field>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableAnimation" name="enableAnimation" class="mr-2">
Enable Animation
</mat-checkbox>
</div>
<mat-form-field appearance="fill">
<mat-label>Border Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.borderColor" name="borderColor">
<mat-hint>Chart border color</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Font Size (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.fontSize" name="fontSize" min="8" max="24">
<mat-hint>Base font size</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Legend Font Size (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.legendFontSize" name="legendFontSize" min="8" max="20">
<mat-hint>Legend font size</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Aggregation</mat-label>
<mat-select [(ngModel)]="currentConfig.aggregation" name="aggregation">
<mat-label>Border Radius (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.borderRadius" name="borderRadius" min="0" max="20">
<mat-hint>Corner roundness</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Shadow</mat-label>
<mat-select [(ngModel)]="currentConfig.shadow" name="shadow">
<mat-option value="none">None</mat-option>
<mat-option value="count">Count</mat-option>
<mat-option value="small">Small</mat-option>
<mat-option value="medium">Medium</mat-option>
<mat-option value="large">Large</mat-option>
</mat-select>
<mat-hint>Drop shadow effect</mat-hint>
</mat-form-field>
</div>
</div>
<!-- Filter Tab -->
<div class="config-section">
<h3 class="text-blue-600">Filter Configuration</h3>
<div class="flex items-center mb-4">
<mat-checkbox [(ngModel)]="currentConfig.enableFilter" name="enableFilter">
Enable Filtering
</mat-checkbox>
</div>
<div *ngIf="currentConfig.enableFilter" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Filter Field</mat-label>
<mat-select [(ngModel)]="currentConfig.filterField" name="filterField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
<mat-hint>Field to filter by</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Filter Operator</mat-label>
<mat-select [(ngModel)]="currentConfig.filterOperator" name="filterOperator">
<mat-option value="equals">Equals</mat-option>
<mat-option value="not_equals">Not Equals</mat-option>
<mat-option value="greater_than">Greater Than</mat-option>
<mat-option value="less_than">Less Than</mat-option>
<mat-option value="contains">Contains</mat-option>
<mat-option value="starts_with">Starts With</mat-option>
<mat-option value="ends_with">Ends With</mat-option>
</mat-select>
<mat-hint>Filter comparison operator</mat-hint>
</mat-form-field>
</div>
<div *ngIf="currentConfig.enableFilter" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Filter Value</mat-label>
<input matInput [(ngModel)]="currentConfig.filterValue" name="filterValue" placeholder="Enter filter value">
<mat-hint>Value to filter by</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Filter Label</mat-label>
<input matInput [(ngModel)]="currentConfig.filterLabel" name="filterLabel" placeholder="Filter label">
<mat-hint>Label for the filter</mat-hint>
</mat-form-field>
</div>
</div>
<!-- Aggregate Tab -->
<div class="config-section">
<h3 class="text-blue-600">Aggregate Configuration</h3>
<div class="flex items-center mb-4">
<mat-checkbox [(ngModel)]="currentConfig.showAggregate" name="showAggregate">
Show Aggregate Information
</mat-checkbox>
</div>
<div *ngIf="currentConfig.showAggregate" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Aggregate Type</mat-label>
<mat-select [(ngModel)]="currentConfig.aggregateType" name="aggregateType">
<mat-option value="sum">Sum</mat-option>
<mat-option value="count">Count</mat-option>
<mat-option value="average">Average</mat-option>
<mat-option value="m
ax">Maximum
</mat-option>
<mat-option value="m
in">Minimum
</mat-option>
<mat-option value="m
in">Min
</mat-option>
<mat-option value="m
ax">Max
</mat-option>
</mat-select>
<mat-hint>
How to aggregate data
</mat-hint>
<mat-hint>
Type of aggregation
</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Size Field (for Bubble Chart)</mat-label>
<mat-select [(ngModel)]="currentConfig.sizeField" name="sizeField">
<mat-option value="">None</mat-option>
<mat-label>Aggregate Field</mat-label>
<mat-select [(ngModel)]="currentConfig.aggregateField" name="aggregateField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
<mat-hint>Field
for bubble size (Bubble Chart only)
</mat-hint>
<mat-hint>Field
to aggregate
</mat-hint>
</mat-form-field>
</div>
</div>
<!-- Series Configuration (for Combo Chart) -->
<div *ngIf="currentConfig.chartType === 'combo'" class="config-section border p-3 rounded-lg mb-4">
<h3 class="text-lg font-semibold mb-2">Series Configuration</h3>
<div *ngFor="let series of currentConfig.series; let i = index" class="series-item p-3 mb-3 border rounded-md">
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-4">
<mat-form-field appearance="fill">
<mat-label>Series Name</mat-label>
<input matInput [(ngModel)]="series.name" [name]="'series_name_' + i">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Chart Type</mat-label>
<mat-select [(ngModel)]="series.type" [name]="'series_type_' + i">
<mat-option value="Line">Line</mat-option>
<mat-option value="Column">Column</mat-option>
<mat-option value="Area">Area</mat-option>
<mat-option value="Spline">Spline</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>X-Axis Name</mat-label>
<mat-select [(ngModel)]="series.xName" [name]="'series_xName_' + i">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Y-Axis Name</mat-label>
<mat-select [(ngModel)]="series.yName" [name]="'series_yName_' + i">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="flex justify-end">
<button mat-icon-button color="warn" (click)="removeComboSeries(i)" type="button"><mat-icon>delete</mat-icon></button>
</div>
<div *ngIf="currentConfig.showAggregate" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Aggregate Format</mat-label>
<mat-select [(ngModel)]="currentConfig.aggregateFormat" name="aggregateFormat">
<mat-option value="none">None</mat-option>
<mat-option value="number">Number</mat-option>
<mat-option value="currency">Currency</mat-option>
<mat-option value="percentage">Percentage</mat-option>
</mat-select>
<mat-hint>Format for aggregate value</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Aggregate Position</mat-label>
<mat-select [(ngModel)]="currentConfig.aggregatePosition" name="aggregatePosition">
<mat-option value="top">Top</mat-option>
<mat-option value="bottom">Bottom</mat-option>
<mat-option value="left">Left</mat-option>
<mat-option value="right">Right</mat-option>
</mat-select>
<mat-hint>Position of aggregate info</mat-hint>
</mat-form-field>
</div>
<button mat-stroked-button color="primary" (click)="addComboSeries()" type="button"><mat-icon>add</mat-icon> Add Series</button>
</div>
</app-base-config>
`
`
,
styles
:
[
`
.config-section {
margin-bottom: 24px;
}
.column-config-item {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 8px;
}
`
]
})
export
class
ChartConfigComponent
extends
BaseConfigComponent
implements
OnInit
{
ngOnInit
():
void
{
// Initialize default values for chart widget
if
(
!
this
.
currentConfig
.
yFields
)
this
.
currentConfig
.
yFields
=
[];
if
(
!
this
.
currentConfig
.
chartType
)
this
.
currentConfig
.
chartType
=
'bar'
;
if
(
!
this
.
currentConfig
.
aggregation
)
this
.
currentConfig
.
aggregation
=
'none'
;
if
(
this
.
currentConfig
.
showLegend
===
undefined
)
this
.
currentConfig
.
showLegend
=
true
;
if
(
this
.
currentConfig
.
showDataLabels
===
undefined
)
this
.
currentConfig
.
showDataLabels
=
false
;
if
(
this
.
currentConfig
.
showTooltip
===
undefined
)
this
.
currentConfig
.
showTooltip
=
true
;
if
(
this
.
currentConfig
.
enableAnimation
===
undefined
)
this
.
currentConfig
.
enableAnimation
=
true
;
// Initialize series for combo chart
if
(
!
this
.
currentConfig
.
series
)
this
.
currentConfig
.
series
=
[];
override
ngOnInit
()
{
this
.
initializeDefaultConfig
();
this
.
initializeYFields
();
this
.
initializeColorDefaults
();
}
addChartYField
()
{
this
.
currentConfig
.
yFields
.
push
(
''
);
this
.
configChange
.
emit
(
this
.
currentConfig
);
private
initializeColorDefaults
()
{
if
(
!
this
.
currentConfig
.
backgroundColor
)
this
.
currentConfig
.
backgroundColor
=
'#FFFFFF'
;
if
(
!
this
.
currentConfig
.
textColor
)
this
.
currentConfig
.
textColor
=
'#374151'
;
if
(
!
this
.
currentConfig
.
gridColor
)
this
.
currentConfig
.
gridColor
=
'#E5E7EB'
;
if
(
!
this
.
currentConfig
.
borderColor
)
this
.
currentConfig
.
borderColor
=
'#E5E7EB'
;
}
removeChartYField
(
index
:
number
)
{
this
.
currentConfig
.
yFields
.
splice
(
index
,
1
);
this
.
configChange
.
emit
(
this
.
currentConfig
);
private
initializeYFields
()
{
if
(
!
this
.
currentConfig
.
yFields
)
{
this
.
currentConfig
.
yFields
=
[];
}
}
addComboSeries
()
{
this
.
currentConfig
.
series
.
push
({
addYField
()
{
this
.
addArrayItem
(
'yFields'
,
{
field
:
''
,
name
:
''
,
type
:
'Column'
,
xName
:
''
,
yName
:
''
type
:
'bar'
,
color
:
'#2563eb'
,
yAxis
:
'primary'
,
visible
:
true
,
showDataLabels
:
false
});
this
.
configChange
.
emit
(
this
.
currentConfig
);
}
removeComboSeries
(
index
:
number
)
{
this
.
currentConfig
.
series
.
splice
(
index
,
1
);
this
.
configChange
.
emit
(
this
.
currentConfig
);
removeYField
(
index
:
number
)
{
this
.
removeArrayItem
(
'yFields'
,
index
);
}
}
src/app/portal-manage/dashboard-management/widgets/configs/company-info-config/company-info-config.component.ts
View file @
fec4de97
...
...
@@ -209,7 +209,7 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
`
})
export
class
CompanyInfoConfigComponent
extends
BaseConfigComponent
implements
OnInit
{
ngOnInit
():
void
{
override
ngOnInit
():
void
{
// Initialize default values for company info widget
if
(
!
this
.
currentConfig
.
layout
)
this
.
currentConfig
.
layout
=
'horizontal'
;
if
(
this
.
currentConfig
.
showContactInfo
===
undefined
)
this
.
currentConfig
.
showContactInfo
=
true
;
...
...
src/app/portal-manage/dashboard-management/widgets/configs/payroll-config/payroll-config.component.ts
View file @
fec4de97
...
...
@@ -254,7 +254,7 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
`
})
export
class
PayrollConfigComponent
extends
BaseConfigComponent
implements
OnInit
{
ngOnInit
():
void
{
override
ngOnInit
():
void
{
// Initialize default values for payroll widget
if
(
!
this
.
currentConfig
.
layout
)
this
.
currentConfig
.
layout
=
'summary'
;
if
(
!
this
.
currentConfig
.
chartType
)
this
.
currentConfig
.
chartType
=
'bar'
;
...
...
src/app/portal-manage/dashboard-management/widgets/configs/simple-kpi-config/simple-kpi-config.component.ts
View file @
fec4de97
...
...
@@ -5,6 +5,9 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import
{
MatInputModule
}
from
'@angular/material/input'
;
import
{
MatSelectModule
}
from
'@angular/material/select'
;
import
{
MatCheckboxModule
}
from
'@angular/material/checkbox'
;
import
{
MatButtonModule
}
from
'@angular/material/button'
;
import
{
MatIconModule
}
from
'@angular/material/icon'
;
import
{
MatTabsModule
}
from
'@angular/material/tabs'
;
import
{
BaseConfigComponent
}
from
'../../../widget-config/base-config/base-config.component'
;
@
Component
({
...
...
@@ -17,11 +20,14 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
MatInputModule
,
MatSelectModule
,
MatCheckboxModule
,
MatButtonModule
,
MatIconModule
,
MatTabsModule
,
BaseConfigComponent
],
template
:
`
<app-base-config>
<!-- Basic Configuration -->
<!-- Basic Configuration
Tab
-->
<div class="config-section">
<h3 class="text-blue-600">Basic Configuration</h3>
...
...
@@ -51,462 +57,487 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Value Format</mat-label>
<mat-select [(ngModel)]="currentConfig.valueFormat" name="valueFormat">
<mat-option value="number">Number</mat-option>
<mat-option value="currency">Currency</mat-option>
<mat-option value="percentage">Percentage</mat-option>
<mat-option value="decimal">Decimal</mat-option>
</mat-select>
<mat-hint>Format for displaying the value</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Decimal Places</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.decimalPlaces" name="decimalPlaces" min="0" max="10">
<mat-hint>Number of decimal places to show</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Aggregation</mat-label>
<mat-select [(ngModel)]="currentConfig.aggregation" name="aggregation">
<mat-option value="count">Count</mat-option>
<mat-option value="sum">Sum</mat-option>
<mat-option value="average">Average</mat-option>
<mat-option value="max">Maximum</mat-option>
<mat-option value="min">Minimum</mat-option>
<mat-option value="count">Count</mat-option>
<mat-option value="min">Min</mat-option>
<mat-option value="max">Max</mat-option>
<mat-option value="first">First</mat-option>
<mat-option value="last">Last</mat-option>
</mat-select>
<mat-hint>How to aggregate the data</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Unit</mat-label>
<input matInput [(ngModel)]="currentConfig.unit" name="unit" placeholder="e.g.,
$, %, items" aria-label="Unit
">
<mat-hint>Unit to display
after
the value</mat-hint>
<input matInput [(ngModel)]="currentConfig.unit" name="unit" placeholder="e.g.,
%, $, items
">
<mat-hint>Unit to display
with
the value</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Icon (Bootstrap Icons)</mat-label>
<input matInput [(ngModel)]="currentConfig.icon" name="icon" placeholder="e.g., person-fill, building" aria-label="Icon">
<mat-hint>Find icons at icons.getbootstrap.com</mat-hint>
<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="dataset">Dataset</mat-option>
</mat-select>
<mat-hint>Source of the data</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>
Decimal Places
</mat-label>
<input matInput
type="number" [(ngModel)]="currentConfig.decimalPlaces" name="decimalPlaces" min="0" max="10" aria-label="Decimal places
">
<mat-hint>
Number of decimal places to show
</mat-hint>
<mat-form-field appearance="fill"
*ngIf="currentConfig.dataSource === 'api'"
>
<mat-label>
API Endpoint
</mat-label>
<input matInput
[(ngModel)]="currentConfig.apiEndpoint" name="apiEndpoint" placeholder="https://api.example.com/data
">
<mat-hint>
API endpoint URL
</mat-hint>
</mat-form-field>
</div>
</div>
<!-- Trend Configuration -->
<div class="config-section">
<h3 class="text-green-600">Trend Settings</h3>
<div class="flex items-center mb-3">
<mat-checkbox [(ngModel)]="currentConfig.showTrend" name="showTrend" class="mr-2">
Show Trend Indicator
</mat-checkbox>
</div>
<div *ngIf="currentConfig.showTrend" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Trend Field</mat-label>
<mat-select [(ngModel)]="currentConfig.trendField" name="trendField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
<mat-hint>Field containing trend data</mat-hint>
</mat-form-field>
<!-- Size Configuration -->
<div class="config-section">
<h3 class="text-blue-600">Size Configuration</h3>
<div class="size-config">
<div
*ngFor="let option of sizeOptions"
class="size-option"
[class.selected]="currentConfig.sizeOption === option.id"
(click)="setSizeOption(option.id)">
<h4>{{ option.label }}</h4>
<p>{{ option.description }}</p>
</div>
</div>
<mat-form-field appearance="fill">
<mat-label>Trend Type</mat-label>
<mat-select [(ngModel)]="currentConfig.trendType" name="trendType">
<mat-option value="percentage">Percentage Change</mat-option>
<mat-option value="absolute">Absolute Change</mat-option>
<mat-option value="ratio">Ratio</mat-option>
</mat-select>
<mat-hint>How to calculate trend</mat-hint>
</mat-form-field>
<div *ngIf="currentConfig.sizeOption === 'custom'" class="grid grid-cols-2 gap-4 mt-4">
<mat-form-field appearance="fill">
<mat-label>Width</mat-label>
<input matInput [(ngModel)]="currentConfig.width" name="width" placeholder="e.g., 300px, 50%, auto">
<mat-hint>Widget width</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Height</mat-label>
<input matInput [(ngModel)]="currentConfig.height" name="height" placeholder="e.g., 200px, 50%, auto">
<mat-hint>Widget height</mat-hint>
</mat-form-field>
</div>
</div>
</div>
<!-- Style
Configuration
-->
<!-- Style
Tab
-->
<div class="config-section">
<h3 class="text-
purple-600">Style & Colors
</h3>
<h3 class="text-
blue-600">Style Configuration
</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
[(ngModel)]="currentConfig.backgroundColor" name="backgroundColor" placeholder="#FF0000 or linear-gradient(...)" aria-label="Background c
olor">
<mat-hint>
Header
background color</mat-hint>
<input matInput
type="color" [(ngModel)]="currentConfig.backgroundColor" name="backgroundC
olor">
<mat-hint>
Widget
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
for labels
</mat-hint>
<input matInput type="color" [(ngModel)]="currentConfig.textColor" name="textColor">
<mat-hint>Text color</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<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 c
olor">
<mat-hint>
Color for the main KPI value
</mat-hint>
<mat-label>
Value
Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.
valueColor" name="valueC
olor">
<mat-hint>
KPI value 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 c
olor">
<mat-hint>
Card border
color</mat-hint>
<mat-label>
Label
Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.
labelColor" name="labelC
olor">
<mat-hint>
KPI label
color</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>
Icon Color
</mat-label>
<input matInput type="
color" [(ngModel)]="currentConfig.iconColor" name="iconColor" class="h-[40px]" aria-label="Icon color
">
<mat-hint>
Icon color
</mat-hint>
<mat-label>
Font Size (px)
</mat-label>
<input matInput type="
number" [(ngModel)]="currentConfig.fontSize" name="fontSize" min="10" max="48
">
<mat-hint>
Base font size
</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>
Border Radius
(px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.
borderRadius" name="borderRadius" min="0" max="50" aria-label="Border radius
">
<mat-hint>
Roundness of widget corners
</mat-hint>
<mat-label>
Value Font Size
(px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.
valueFontSize" name="valueFontSize" min="10" max="72
">
<mat-hint>
KPI value font size
</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-
3
gap-4">
<div class="grid grid-cols-1 md:grid-cols-
2
gap-4">
<mat-form-field appearance="fill">
<mat-label>
Padding
(px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.
padding" name="padding" min="0" max="100" aria-label="Padding
">
<mat-hint>
Internal spacing
</mat-hint>
<mat-label>
Border Radius
(px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.
borderRadius" name="borderRadius" min="0" max="20
">
<mat-hint>
Corner roundness
</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="48" aria-label="Font size">
<mat-hint>Font size for values</mat-hint>
<mat-label>Border Width (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.borderWidth" name="borderWidth" min="0" max="10">
<mat-hint>Border thickness</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Border Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.borderColor" name="borderColor">
<mat-hint>Border color</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>
Font Weight
</mat-label>
<mat-select [(ngModel)]="currentConfig.
fontWeight" name="fontWeight
">
<mat-option value="no
rmal">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-label>
Shadow
</mat-label>
<mat-select [(ngModel)]="currentConfig.
shadow" name="shadow
">
<mat-option value="no
ne">None
</mat-option>
<mat-option value="
small">Small
</mat-option>
<mat-option value="
medium">Medium
</mat-option>
<mat-option value="
large">Large
</mat-option>
</mat-select>
<mat-hint>
Font weigh
t</mat-hint>
<mat-hint>
Drop shadow effec
t</mat-hint>
</mat-form-field>
</div>
<mat-form-field appearance="fill" class="w-full">
<mat-label>Font Family</mat-label>
<mat-select [(ngModel)]="currentConfig.fontFamily" name="fontFamily">
<mat-option value="system-ui, -apple-system, sans-serif">System Font</mat-option>
<mat-option value="Arial, sans-serif">Arial</mat-option>
<mat-option value="Helvetica, sans-serif">Helvetica</mat-option>
<mat-option value="Georgia, serif">Georgia</mat-option>
<mat-option value="Times New Roman, serif">Times New Roman</mat-option>
<mat-option value="Courier New, monospace">Courier New</mat-option>
</mat-select>
<mat-hint>Font family for the widget</mat-hint>
</mat-form-field>
<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 */ .simple-kpi-widget:hover { transform: translateY(-4px); }"></textarea>
<mat-hint>Add custom CSS for advanced styling</mat-hint>
</mat-form-field>
</div>
<!--
Animation Configuration
-->
<!--
Icon Tab
-->
<div class="config-section">
<h3 class="text-
orange-600">Animation Settings
</h3>
<h3 class="text-
blue-600">Icon Configuration
</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">
<div 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-label>Icon</mat-label>
<mat-select [(ngModel)]="currentConfig.icon" name="icon">
<mat-option value="none">None</mat-option>
<mat-option value="trending_up">Trending Up</mat-option>
<mat-option value="trending_down">Trending Down</mat-option>
<mat-option value="show_chart">Chart</mat-option>
<mat-option value="assessment">Assessment</mat-option>
<mat-option value="analytics">Analytics</mat-option>
<mat-option value="bar_chart">Bar Chart</mat-option>
<mat-option value="pie_chart">Pie Chart</mat-option>
<mat-option value="donut_large">Donut</mat-option>
<mat-option value="account_balance">Account Balance</mat-option>
<mat-option value="attach_money">Money</mat-option>
<mat-option value="people">People</mat-option>
<mat-option value="business">Business</mat-option>
<mat-option value="home">Home</mat-option>
<mat-option value="star">Star</mat-option>
<mat-option value="favorite">Favorite</mat-option>
</mat-select>
<mat-hint>
Animation effect type
</mat-hint>
<mat-hint>
Icon to display with KPI
</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-label>Icon Position</mat-label>
<mat-select [(ngModel)]="currentConfig.iconPosition" name="iconPosition">
<mat-option value="left">Left</mat-option>
<mat-option value="right">Right</mat-option>
<mat-option value="top">Top</mat-option>
<mat-option value="bottom">Bottom</mat-option>
</mat-select>
<mat-hint>Position of the icon</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 class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Icon Size (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.iconSize" name="iconSize" min="16" max="64">
<mat-hint>Icon size in pixels</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Icon Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.iconColor" name="iconColor">
<mat-hint>Icon color</mat-hint>
</mat-form-field>
</div>
</div>
<!--
Interaction Configuration
-->
<!--
Filter Tab
-->
<div class="config-section">
<h3 class="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>
<h3 class="text-blue-600">Filter Configuration</h3>
<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 mb-4">
<mat-checkbox [(ngModel)]="currentConfig.enableFilter" name="enableFilter">
Enable Filtering
</mat-checkbox>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableHover" name="enableHover" class="mr-2">
Enable Hover Effects
</mat-checkbox>
</div>
<div *ngIf="currentConfig.enableFilter" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Filter Field</mat-label>
<mat-select [(ngModel)]="currentConfig.filterField" name="filterField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
<mat-hint>Field to filter by</mat-hint>
</mat-form-field>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableExport" name="enableExport" class="mr-2">
Enable Export
</mat-checkbox>
</div>
<mat-form-field appearance="fill">
<mat-label>Filter Operator</mat-label>
<mat-select [(ngModel)]="currentConfig.filterOperator" name="filterOperator">
<mat-option value="equals">Equals</mat-option>
<mat-option value="not_equals">Not Equals</mat-option>
<mat-option value="greater_than">Greater Than</mat-option>
<mat-option value="less_than">Less Than</mat-option>
<mat-option value="contains">Contains</mat-option>
<mat-option value="starts_with">Starts With</mat-option>
<mat-option value="ends_with">Ends With</mat-option>
</mat-select>
<mat-hint>Filter comparison operator</mat-hint>
</mat-form-field>
</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">
<h3 class="text-teal-600">Layout Settings</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div *ngIf="currentConfig.enableFilter" 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="100" max="800" aria-label="Widget width
">
<mat-hint>
Widget width
</mat-hint>
<mat-label>
Filter Value
</mat-label>
<input matInput
[(ngModel)]="currentConfig.filterValue" name="filterValue" placeholder="Enter filter value
">
<mat-hint>
Value to filter by
</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="100" max="600" aria-label="Widget height
">
<mat-hint>
Widget height
</mat-hint>
<mat-label>
Filter Label
</mat-label>
<input matInput
[(ngModel)]="currentConfig.filterLabel" name="filterLabel" placeholder="Filter label
">
<mat-hint>
Label for the filter
</mat-hint>
</mat-form-field>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Trend Tab -->
<div class="config-section">
<h3 class="text-blue-600">Trend Configuration</h3>
<div class="flex items-center mb-4">
<mat-checkbox [(ngModel)]="currentConfig.showTrend" name="showTrend">
Show Trend Indicator
</mat-checkbox>
</div>
<div *ngIf="currentConfig.showTrend" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Minimum Width (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.minWidth" name="minWidth" min="50" max="400" aria-label="Minimum width">
<mat-hint>Minimum widget width</mat-hint>
<mat-label>Trend Field</mat-label>
<mat-select [(ngModel)]="currentConfig.trendField" name="trendField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
<mat-hint>Field containing trend data</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Minimum Height (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.minHeight" name="minHeight" min="50" max="300" aria-label="Minimum height">
<mat-hint>Minimum widget height</mat-hint>
<mat-label>Trend Type</mat-label>
<mat-select [(ngModel)]="currentConfig.trendType" name="trendType">
<mat-option value="percentage">Percentage</mat-option>
<mat-option value="absolute">Absolute Value</mat-option>
<mat-option value="ratio">Ratio</mat-option>
</mat-select>
<mat-hint>How to calculate trend</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div
*ngIf="currentConfig.showTrend"
class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>
Aspect Ratio
</mat-label>
<mat-select [(ngModel)]="currentConfig.
aspectRatio" name="aspectRatio
">
<mat-option value="
auto">Auto
</mat-option>
<mat-option value="
16:9">16:9
</mat-option>
<mat-option value="
4:3">4:3
</mat-option>
<mat-option value="
1:1">1:1 (Square)
</mat-option>
<mat-option value="3
:2">3:2
</mat-option>
<mat-label>
Trend Period
</mat-label>
<mat-select [(ngModel)]="currentConfig.
trendPeriod" name="trendPeriod
">
<mat-option value="
1">1 Day
</mat-option>
<mat-option value="
7">1 Week
</mat-option>
<mat-option value="
30">1 Month
</mat-option>
<mat-option value="
90">3 Months
</mat-option>
<mat-option value="3
65">1 Year
</mat-option>
</mat-select>
<mat-hint>
Widget aspect ratio
</mat-hint>
<mat-hint>
Time period for trend calculation
</mat-hint>
</mat-form-field>
<
div class="flex items-center
">
<mat-
checkbox [(ngModel)]="currentConfig.responsive" name="responsive" class="mr-2"
>
Responsive Layout
<
/mat-checkbox
>
</
div
>
<
mat-form-field appearance="fill
">
<mat-
label>Trend Threshold (%)</mat-label
>
<input matInput type="number" [(ngModel)]="currentConfig.trendThreshold" name="trendThreshold" min="0" max="100">
<
mat-hint>Threshold for significant trend</mat-hint
>
</
mat-form-field
>
</div>
</div>
<!--
Data Configuration
-->
<!--
Animation Tab
-->
<div class="config-section">
<h3 class="text-
red-600">Data Settings
</h3>
<h3 class="text-
blue-600">Animation Configuration
</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/kpi-data" aria-label="API endpoint">
<mat-hint>API endpoint URL</mat-hint>
</mat-form-field>
<div class="flex items-center mb-4">
<mat-checkbox [(ngModel)]="currentConfig.enableAnimations" name="enableAnimations">
Enable Animations
</mat-checkbox>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div
*ngIf="currentConfig.enableAnimations"
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-label>Animation Type</mat-label>
<mat-select [(ngModel)]="currentConfig.animationType" name="animationType">
<mat-option value="fade">Fade In</mat-option>
<mat-option value="slide">Slide In</mat-option>
<mat-option value="scale">Scale In</mat-option>
<mat-option value="bounce">Bounce</mat-option>
<mat-option value="pulse">Pulse</mat-option>
</mat-select>
<mat-hint>Type of animation effect</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
>
<
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">
<
mat-hint>Duration of animation in milliseconds</mat-hint
>
</
mat-form-field
>
</div>
<mat-form-field *ngIf="currentConfig.cacheEnabled" appearance="fill" class="w-full">
<mat-label>Cache Duration (seconds)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.cacheDuration" name="cacheDuration" min="1" max="3600" aria-label="Cache duration">
<mat-hint>How long to cache data</mat-hint>
</mat-form-field>
<div *ngIf="currentConfig.enableAnimations" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Animation Delay (ms)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.animationDelay" name="animationDelay" min="0" max="1000">
<mat-hint>Delay before animation starts</mat-hint>
</mat-form-field>
<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>
<mat-form-field appearance="fill">
<mat-label>Animation Easing</mat-label>
<mat-select [(ngModel)]="currentConfig.animationEasing" name="animationEasing">
<mat-option value="ease">Ease</mat-option>
<mat-option value="ease-in">Ease In</mat-option>
<mat-option value="ease-out">Ease Out</mat-option>
<mat-option value="ease-in-out">Ease In Out</mat-option>
<mat-option value="linear">Linear</mat-option>
</mat-select>
<mat-hint>Animation easing function</mat-hint>
</mat-form-field>
</div>
<div class="flex items-center space-x-4">
<mat-checkbox [(ngModel)]="currentConfig.hoverEffects" name="hoverEffects">
Enable Hover Effects
</mat-checkbox>
<mat-checkbox [(ngModel)]="currentConfig.autoRefresh" name="autoRefresh">
Auto Refresh Animation
</mat-checkbox>
</div>
</div>
<!--
Security Configuration
-->
<!--
Condition Tab
-->
<div class="config-section">
<h3 class="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>
<h3 class="text-blue-600">Conditional Formatting</h3>
<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 mb-4">
<mat-checkbox [(ngModel)]="currentConfig.enableConditionalFormatting" name="enableConditionalFormatting">
Enable Conditional Formatting
</mat-checkbox>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.auditLog" name="auditLog" class="mr-2">
Enable Audit Logging
</mat-checkbox>
<div *ngIf="currentConfig.enableConditionalFormatting">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
<mat-form-field appearance="fill">
<mat-label>Condition Field</mat-label>
<mat-select [(ngModel)]="currentConfig.conditionField" name="conditionField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
<mat-hint>Field to evaluate condition</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Condition Operator</mat-label>
<mat-select [(ngModel)]="currentConfig.conditionOperator" name="conditionOperator">
<mat-option value="greater_than">Greater Than</mat-option>
<mat-option value="less_than">Less Than</mat-option>
<mat-option value="equals">Equals</mat-option>
<mat-option value="not_equals">Not Equals</mat-option>
<mat-option value="greater_equal">Greater or Equal</mat-option>
<mat-option value="less_equal">Less or Equal</mat-option>
</mat-select>
<mat-hint>Comparison operator</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Condition Value</mat-label>
<input matInput [(ngModel)]="currentConfig.conditionValue" name="conditionValue" placeholder="Threshold value">
<mat-hint>Threshold value</mat-hint>
</mat-form-field>
</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 class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>True Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.trueColor" name="trueColor">
<mat-hint>Color when condition is true</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>False Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.falseColor" name="falseColor">
<mat-hint>Color when condition is false</mat-hint>
</mat-form-field>
</div>
</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>
</app-base-config>
`
,
styles
:
[]
styles
:
[
`
.config-section {
margin-bottom: 24px;
}
`
]
})
export
class
SimpleKpiConfigComponent
extends
BaseConfigComponent
implements
OnInit
{
ngOnInit
():
void
{
// Initialize default values for Simple KPI widget
this
.
initializeDefaults
();
override
ngOnInit
()
{
this
.
initializeDefaultConfig
();
this
.
initializeColorDefaults
();
}
private
initializeDefaults
():
void
{
if
(
!
this
.
currentConfig
.
title
)
{
this
.
currentConfig
.
title
=
'KPI Widget'
;
}
if
(
!
this
.
currentConfig
.
aggregation
)
{
this
.
currentConfig
.
aggregation
=
'count'
;
}
if
(
this
.
currentConfig
.
enableAnimations
===
undefined
)
{
this
.
currentConfig
.
enableAnimations
=
true
;
}
if
(
!
this
.
currentConfig
.
animationType
)
{
this
.
currentConfig
.
animationType
=
'fade'
;
}
if
(
!
this
.
currentConfig
.
animationDuration
)
{
this
.
currentConfig
.
animationDuration
=
300
;
}
if
(
this
.
currentConfig
.
hoverEffects
===
undefined
)
{
this
.
currentConfig
.
hoverEffects
=
true
;
}
if
(
this
.
currentConfig
.
enableTooltip
===
undefined
)
{
this
.
currentConfig
.
enableTooltip
=
true
;
}
if
(
this
.
currentConfig
.
enableClick
===
undefined
)
{
this
.
currentConfig
.
enableClick
=
true
;
}
if
(
this
.
currentConfig
.
enableHover
===
undefined
)
{
this
.
currentConfig
.
enableHover
=
true
;
}
if
(
this
.
currentConfig
.
enableExport
===
undefined
)
{
this
.
currentConfig
.
enableExport
=
true
;
}
if
(
!
this
.
currentConfig
.
clickAction
)
{
this
.
currentConfig
.
clickAction
=
'none'
;
}
if
(
!
this
.
currentConfig
.
aspectRatio
)
{
this
.
currentConfig
.
aspectRatio
=
'auto'
;
}
if
(
this
.
currentConfig
.
responsive
===
undefined
)
{
this
.
currentConfig
.
responsive
=
true
;
}
if
(
!
this
.
currentConfig
.
dataSource
)
{
this
.
currentConfig
.
dataSource
=
'static'
;
}
if
(
this
.
currentConfig
.
cacheEnabled
===
undefined
)
{
this
.
currentConfig
.
cacheEnabled
=
false
;
}
if
(
!
this
.
currentConfig
.
cacheDuration
)
{
this
.
currentConfig
.
cacheDuration
=
300
;
}
if
(
this
.
currentConfig
.
requireAuth
===
undefined
)
{
this
.
currentConfig
.
requireAuth
=
false
;
}
if
(
this
.
currentConfig
.
dataEncryption
===
undefined
)
{
this
.
currentConfig
.
dataEncryption
=
false
;
}
if
(
this
.
currentConfig
.
auditLog
===
undefined
)
{
this
.
currentConfig
.
auditLog
=
false
;
}
if
(
!
this
.
currentConfig
.
rateLimit
)
{
this
.
currentConfig
.
rateLimit
=
0
;
}
private
initializeColorDefaults
()
{
if
(
!
this
.
currentConfig
.
backgroundColor
)
this
.
currentConfig
.
backgroundColor
=
'#3366FF'
;
if
(
!
this
.
currentConfig
.
textColor
)
this
.
currentConfig
.
textColor
=
'#FFFFFF'
;
if
(
!
this
.
currentConfig
.
valueColor
)
this
.
currentConfig
.
valueColor
=
'#FFFFFF'
;
if
(
!
this
.
currentConfig
.
labelColor
)
this
.
currentConfig
.
labelColor
=
'#FFFFFF'
;
if
(
!
this
.
currentConfig
.
iconColor
)
this
.
currentConfig
.
iconColor
=
'#FFFFFF'
;
if
(
!
this
.
currentConfig
.
borderColor
)
this
.
currentConfig
.
borderColor
=
'#FFFFFF'
;
if
(
!
this
.
currentConfig
.
trueColor
)
this
.
currentConfig
.
trueColor
=
'#10B981'
;
if
(
!
this
.
currentConfig
.
falseColor
)
this
.
currentConfig
.
falseColor
=
'#EF4444'
;
// Initialize new fields
if
(
!
this
.
currentConfig
.
valueFormat
)
this
.
currentConfig
.
valueFormat
=
'number'
;
if
(
!
this
.
currentConfig
.
aggregation
)
this
.
currentConfig
.
aggregation
=
'sum'
;
if
(
!
this
.
currentConfig
.
unit
)
this
.
currentConfig
.
unit
=
''
;
if
(
!
this
.
currentConfig
.
dataSource
)
this
.
currentConfig
.
dataSource
=
'static'
;
if
(
!
this
.
currentConfig
.
apiEndpoint
)
this
.
currentConfig
.
apiEndpoint
=
''
;
if
(
!
this
.
currentConfig
.
showTrend
)
this
.
currentConfig
.
showTrend
=
false
;
if
(
!
this
.
currentConfig
.
trendField
)
this
.
currentConfig
.
trendField
=
''
;
if
(
!
this
.
currentConfig
.
trendType
)
this
.
currentConfig
.
trendType
=
'percentage'
;
if
(
!
this
.
currentConfig
.
trendPeriod
)
this
.
currentConfig
.
trendPeriod
=
'30'
;
if
(
!
this
.
currentConfig
.
trendThreshold
)
this
.
currentConfig
.
trendThreshold
=
5
;
if
(
!
this
.
currentConfig
.
enableAnimations
)
this
.
currentConfig
.
enableAnimations
=
true
;
if
(
!
this
.
currentConfig
.
animationType
)
this
.
currentConfig
.
animationType
=
'fade'
;
if
(
!
this
.
currentConfig
.
animationDuration
)
this
.
currentConfig
.
animationDuration
=
300
;
if
(
!
this
.
currentConfig
.
animationDelay
)
this
.
currentConfig
.
animationDelay
=
0
;
if
(
!
this
.
currentConfig
.
animationEasing
)
this
.
currentConfig
.
animationEasing
=
'ease'
;
if
(
!
this
.
currentConfig
.
hoverEffects
)
this
.
currentConfig
.
hoverEffects
=
true
;
if
(
!
this
.
currentConfig
.
autoRefresh
)
this
.
currentConfig
.
autoRefresh
=
false
;
if
(
!
this
.
currentConfig
.
enableConditionalFormatting
)
this
.
currentConfig
.
enableConditionalFormatting
=
false
;
if
(
!
this
.
currentConfig
.
conditionField
)
this
.
currentConfig
.
conditionField
=
''
;
if
(
!
this
.
currentConfig
.
conditionOperator
)
this
.
currentConfig
.
conditionOperator
=
'greater_than'
;
if
(
!
this
.
currentConfig
.
conditionValue
)
this
.
currentConfig
.
conditionValue
=
''
;
}
}
src/app/portal-manage/dashboard-management/widgets/configs/syncfusion-datagrid-config/syncfusion-datagrid-config.component.ts
View file @
fec4de97
...
...
@@ -5,6 +5,9 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import
{
MatInputModule
}
from
'@angular/material/input'
;
import
{
MatSelectModule
}
from
'@angular/material/select'
;
import
{
MatCheckboxModule
}
from
'@angular/material/checkbox'
;
import
{
MatButtonModule
}
from
'@angular/material/button'
;
import
{
MatIconModule
}
from
'@angular/material/icon'
;
import
{
MatTabsModule
}
from
'@angular/material/tabs'
;
import
{
BaseConfigComponent
}
from
'../../../widget-config/base-config/base-config.component'
;
@
Component
({
...
...
@@ -17,11 +20,14 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
MatInputModule
,
MatSelectModule
,
MatCheckboxModule
,
MatButtonModule
,
MatIconModule
,
MatTabsModule
,
BaseConfigComponent
],
template
:
`
<app-base-config>
<!-- Basic Configuration -->
<!-- Basic Configuration
Tab
-->
<div class="config-section">
<h3 class="text-blue-600">Basic Configuration</h3>
...
...
@@ -34,456 +40,463 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Page Size</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.pageSize" name="pageSize" min="5" max="100"
aria-label="Page size"
>
<input matInput type="number" [(ngModel)]="currentConfig.pageSize" name="pageSize" min="5" max="100">
<mat-hint>Number of rows per page</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"
>
<input matInput type="number" [(ngModel)]="currentConfig.fontSize" name="fontSize" min="10" max="20">
<mat-hint>Font size for grid content</mat-hint>
</mat-form-field>
</div>
</div>
<!-- Grid Functionality -->
<div class="config-section">
<h3 class="text-green-600">Grid Functionality</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enablePaging" name="enablePaging" class="mr-2">
Enable Paging
</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>
<!-- Size Configuration -->
<div class="config-section">
<h3 class="text-blue-600">Size Configuration</h3>
<div class="size-config">
<div
*ngFor="let option of sizeOptions"
class="size-option"
[class.selected]="currentConfig.sizeOption === option.id"
(click)="setSizeOption(option.id)">
<h4>{{ option.label }}</h4>
<p>{{ option.description }}</p>
</div>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableEditing" name="enableEditing" class="mr-2">
Enable Editing
</mat-checkbox>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableSearch" name="enableSearch" class="mr-2">
Enable Search
</mat-checkbox>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableColumnChooser" name="enableColumnChooser" class="mr-2">
Enable Column Chooser
</mat-checkbox>
<div *ngIf="currentConfig.sizeOption === 'custom'" class="grid grid-cols-2 gap-4 mt-4">
<mat-form-field appearance="fill">
<mat-label>Width</mat-label>
<input matInput [(ngModel)]="currentConfig.width" name="width" placeholder="e.g., 100%, 800px">
<mat-hint>Grid width</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Height</mat-label>
<input matInput [(ngModel)]="currentConfig.height" name="height" placeholder="e.g., 100%, 400px">
<mat-hint>Grid height</mat-hint>
</mat-form-field>
</div>
</div>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableColumnResizing" name="enableColumnResizing" class="mr-2">
Enable Column Resizing
</mat-checkbox>
</div>
<!-- Columns Tab -->
<div class="config-section">
<h3 class="text-blue-600">Column Configuration</h3>
<div class="flex items-center justify-between mb-4">
<h4>Available Columns</h4>
<button mat-raised-button color="primary" (click)="addColumn()">
<mat-icon>add</mat-icon>
Add Column
</button>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableColumnReordering" name="enableColumnReordering" class="mr-2">
Enable Column Reordering
</mat-checkbox>
<div *ngFor="let column of currentConfig.columns; let i = index" class="column-config-item p-4 mb-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<mat-form-field appearance="fill">
<mat-label>Field Name</mat-label>
<mat-select [(ngModel)]="column.field" name="columnField{{i}}">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Header Text</mat-label>
<input matInput [(ngModel)]="column.headerText" name="columnHeader{{i}}" placeholder="Column header">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Width</mat-label>
<input matInput [(ngModel)]="column.width" name="columnWidth{{i}}" placeholder="e.g., 100px, 20%">
</mat-form-field>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableRowSelection" name="enableRowSelection" class="mr-2">
Enable Row Selection
</mat-checkbox>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Text Align</mat-label>
<mat-select [(ngModel)]="column.textAlign" name="columnAlign{{i}}">
<mat-option value="left">Left</mat-option>
<mat-option value="center">Center</mat-option>
<mat-option value="right">Right</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Format</mat-label>
<mat-select [(ngModel)]="column.format" name="columnFormat{{i}}">
<mat-option value="none">None</mat-option>
<mat-option value="number">Number</mat-option>
<mat-option value="currency">Currency</mat-option>
<mat-option value="percentage">Percentage</mat-option>
<mat-option value="date">Date</mat-option>
<mat-option value="datetime">Date Time</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableMultiSelection" name="enableMultiSelection" class="mr-2">
Enable Multi Selection
</mat-checkbox>
<div class="flex items-center justify-between mt-4">
<div class="flex items-center space-x-4">
<mat-checkbox [(ngModel)]="column.visible" name="columnVisible{{i}}">
Visible
</mat-checkbox>
<mat-checkbox [(ngModel)]="column.sortable" name="columnSortable{{i}}">
Sortable
</mat-checkbox>
<mat-checkbox [(ngModel)]="column.filterable" name="columnFilterable{{i}}">
Filterable
</mat-checkbox>
</div>
<button mat-icon-button color="warn" (click)="removeColumn(i)">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
</div>
<!--
Display Options
-->
<!--
Rows Tab
-->
<div class="config-section">
<h3 class="text-
purple-600">Display Options
</h3>
<h3 class="text-
blue-600">Row Configuration
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<
div class="flex items-center
">
<mat-
checkbox [(ngModel)]="currentConfig.showHeader" name="showHeader" class="mr-2"
>
Show Header
<
/mat-checkbox
>
</
div
>
<
mat-form-field appearance="fill
">
<mat-
label>Row Height (px)</mat-label
>
<input matInput type="number" [(ngModel)]="currentConfig.rowHeight" name="rowHeight" min="20" max="100">
<
mat-hint>Height of each row</mat-hint
>
</
mat-form-field
>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.showToolbar" name="showToolbar" class="mr-2">
Show Toolbar
</mat-checkbox>
</div>
<mat-form-field appearance="fill">
<mat-label>Alternate Row Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.alternateRowColor" name="alternateRowColor">
<mat-hint>Color for alternate rows</mat-hint>
</mat-form-field>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.showPager" name="showPager" class="mr-2">
Show Pager
</mat-checkbox>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<mat-label>Header Row Height (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.headerRowHeight" name="headerRowHeight" min="20" max="100">
<mat-hint>Height of header row</mat-hint>
</mat-form-field>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.showFooter" name="showFooter" class="mr-2">
Show Footer
</mat-checkbox>
</div>
<mat-form-field appearance="fill">
<mat-label>Header Background Color</mat-label>
<input matInput type="color" [(ngModel)]="currentConfig.headerBackgroundColor" name="headerBackgroundColor">
<mat-hint>Background color for header</mat-hint>
</mat-form-field>
</div>
<div class="flex items-center space-x-4">
<mat-checkbox [(ngModel)]="currentConfig.showAlternateRows" name="showAlternateRows">
Show Alternate Row Colors
</mat-checkbox>
<mat-checkbox [(ngModel)]="currentConfig.allowRowSelection" name="allowRowSelection">
Allow Row Selection
</mat-checkbox>
</div>
</div>
<!-- Style
Configuration
-->
<!-- Style
Tab
-->
<div class="config-section">
<h3 class="text-
orange-600">Style & Colors
</h3>
<h3 class="text-
blue-600">Style Configuration
</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"
>
<input matInput type="color" [(ngModel)]="currentConfig.backgroundColor" name="backgroundColor">
<mat-hint>Grid 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>Grid 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>
<input matInput type="color" [(ngModel)]="currentConfig.textColor" name="textColor">
<mat-hint>Text color</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<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"
>
<input matInput type="color" [(ngModel)]="currentConfig.borderColor" name="borderColor">
<mat-hint>Grid 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-label>
Border Width (px)
</mat-label>
<input matInput type="
number" [(ngModel)]="currentConfig.borderWidth" name="borderWidth" min="0" max="5
">
<mat-hint>
Border thickness
</mat-hint>
</mat-form-field>
</div>
<div class="grid grid-cols-1 md:grid-cols-
3
gap-4">
<div class="grid grid-cols-1 md:grid-cols-
2
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 radiu
s</mat-hint>
<input matInput type="number" [(ngModel)]="currentConfig.borderRadius" name="borderRadius" min="0" max="20">
<mat-hint>
Corner roundnes
s</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-label>Shadow</mat-label>
<mat-select [(ngModel)]="currentConfig.shadow" name="shadow">
<mat-option value="none">None</mat-option>
<mat-option value="small">Small</mat-option>
<mat-option value="medium">Medium</mat-option>
<mat-option value="large">Large</mat-option>
</mat-select>
<mat-hint>Drop shadow effect</mat-hint>
</mat-form-field>
</div>
</div>
<!-- Filter Tab -->
<div class="config-section">
<h3 class="text-blue-600">Filter Configuration</h3>
<div class="flex items-center space-x-4 mb-4">
<mat-checkbox [(ngModel)]="currentConfig.allowFiltering" name="allowFiltering">
Enable Filtering
</mat-checkbox>
<mat-checkbox [(ngModel)]="currentConfig.showFilterBar" name="showFilterBar">
Show Filter Bar
</mat-checkbox>
</div>
<div *ngIf="currentConfig.allowFiltering" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<mat-form-field appearance="fill">
<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-label>Filter Type</mat-label>
<mat-select [(ngModel)]="currentConfig.filterType" name="filterType">
<mat-option value="menu">Menu</mat-option>
<mat-option value="checkbox">Checkbox</mat-option>
<mat-option value="excel">Excel</mat-option>
</mat-select>
<mat-hint>Font weight</mat-hint>
<mat-hint>Type of filter interface</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Filter Bar Height (px)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.filterBarHeight" name="filterBarHeight" min="30" max="100">
<mat-hint>Height of filter bar</mat-hint>
</mat-form-field>
</div>
</div>
<!--
Interaction Settings
-->
<!--
Aggregate Tab
-->
<div class="config-section">
<h3 class="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>
<h3 class="text-blue-600">Aggregate Configuration</h3>
<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 mb-4
">
<mat-checkbox [(ngModel)]="currentConfig.showAggregate" name="showAggregate
">
Show Aggregate Row
</mat-checkbox>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableHover" name="enableHover" class="mr-2">
Enable Hover Effects
</mat-checkbox>
<div *ngIf="currentConfig.showAggregate">
<div class="flex items-center justify-between mb-4">
<h4>Aggregate Columns</h4>
<button mat-raised-button color="primary" (click)="addAggregateColumn()">
<mat-icon>add</mat-icon>
Add Aggregate
</button>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.enableExport" name="enableExport" class="mr-2">
Enable Export
</mat-checkbox>
<div *ngFor="let agg of currentConfig.aggregateColumns; let i = index" class="column-config-item p-4 mb-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<mat-form-field appearance="fill">
<mat-label>Field Name</mat-label>
<mat-select [(ngModel)]="agg.field" name="aggField{{i}}">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Aggregate Type</mat-label>
<mat-select [(ngModel)]="agg.type" name="aggType{{i}}">
<mat-option value="sum">Sum</mat-option>
<mat-option value="count">Count</mat-option>
<mat-option value="average">Average</mat-option>
<mat-option value="min">Min</mat-option>
<mat-option value="max">Max</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Format</mat-label>
<mat-select [(ngModel)]="agg.format" name="aggFormat{{i}}">
<mat-option value="none">None</mat-option>
<mat-option value="number">Number</mat-option>
<mat-option value="currency">Currency</mat-option>
<mat-option value="percentage">Percentage</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="flex items-center justify-between mt-4">
<div class="flex items-center space-x-4">
<mat-checkbox [(ngModel)]="agg.visible" name="aggVisible{{i}}">
Visible
</mat-checkbox>
</div>
<button mat-icon-button color="warn" (click)="removeAggregateColumn(i)">
<mat-icon>delete</mat-icon>
</button>
</div>
</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>
</div>
<!--
Layout Configuration
-->
<!--
Export Tab
-->
<div class="config-section">
<h3 class="text-
teal-600">Layout Settings
</h3>
<h3 class="text-
blue-600">Export Configuration
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="flex items-center mb-4">
<mat-checkbox [(ngModel)]="currentConfig.enableExport" name="enableExport">
Enable Export
</mat-checkbox>
</div>
<div *ngIf="currentConfig.enableExport" 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="300" max="1200" aria-label="Widget width">
<mat-hint>Widget width</mat-hint>
<mat-label>Export Formats</mat-label>
<mat-select [(ngModel)]="currentConfig.exportFormats" name="exportFormats" multiple>
<mat-option value="excel">Excel (.xlsx)</mat-option>
<mat-option value="csv">CSV (.csv)</mat-option>
<mat-option value="pdf">PDF (.pdf)</mat-option>
<mat-option value="json">JSON (.json)</mat-option>
</mat-select>
<mat-hint>Available export formats</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="200" max="800" aria-label="Widget heigh
t">
<mat-hint>
Widget height
</mat-hint>
<mat-label>
Export Filename
</mat-label>
<input matInput
[(ngModel)]="currentConfig.exportFilename" name="exportFilename" placeholder="data-expor
t">
<mat-hint>
Default filename for exports
</mat-hint>
</mat-form-field>
</div>
<div class="flex items-center">
<mat-checkbox [(ngModel)]="currentConfig.responsive" name="responsive" class="mr-2">
Responsive Layout
<div *ngIf="currentConfig.enableExport" class="flex items-center space-x-4">
<mat-checkbox [(ngModel)]="currentConfig.includeHeaders" name="includeHeaders">
Include Headers in Export
</mat-checkbox>
<mat-checkbox [(ngModel)]="currentConfig.includeFilters" name="includeFilters">
Include Applied Filters
</mat-checkbox>
</div>
</div>
<!--
Data Configuration
-->
<!--
Security Tab
-->
<div class="config-section">
<h3 class="text-
red-600">Data Settings
</h3>
<h3 class="text-
blue-600">Security Configuration
</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/grid-data" aria-label="API endpoint">
<mat-hint>API endpoint URL</mat-hint>
</mat-form-field>
<div class="flex items-center mb-4">
<mat-checkbox [(ngModel)]="currentConfig.requireAuth" name="requireAuth">
Require Authentication
</mat-checkbox>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div
*ngIf="currentConfig.requireAuth"
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-label>
Allowed Roles
</mat-label>
<input matInput
[(ngModel)]="currentConfig.allowedRoles" name="allowedRoles" placeholder="admin,user,manager
">
<mat-hint>
Comma-separated list of allowed roles
</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>
<mat-form-field appearance="fill">
<mat-label>Permission Level</mat-label>
<mat-select [(ngModel)]="currentConfig.permissionLevel" name="permissionLevel">
<mat-option value="read">Read Only</mat-option>
<mat-option value="write">Read/Write</mat-option>
<mat-option value="admin">Full Access</mat-option>
</mat-select>
<mat-hint>Required permission level</mat-hint>
</mat-form-field>
</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">
<h3 class="text-gray-600">Security Settings</h3>
<div class="flex items-center space-x-4">
<mat-checkbox [(ngModel)]="currentConfig.dataEncryption" name="dataEncryption">
Enable Data Encryption
</mat-checkbox>
<mat-checkbox [(ngModel)]="currentConfig.auditLog" name="auditLog">
Enable Audit Logging
</mat-checkbox>
</div>
<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/hour)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.rateLimit" name="rateLimit" min="0" max="10000">
<mat-hint>Maximum requests per hour per user</mat-hint>
</mat-form-field>
<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-label>
Session Timeout (minutes
)</mat-label>
<input matInput type="number" [(ngModel)]="currentConfig.
sessionTimeout" name="sessionTimeout" min="5" max="480
">
<mat-hint>
Session timeout in minutes
</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">
<h3 class="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-datagrid-widget:hover { transform: translateY(-4px); }"></textarea>
<mat-hint>Add custom CSS for advanced styling</mat-hint>
</mat-form-field>
</div>
</app-base-config>
`
,
styles
:
[]
styles
:
[
`
.config-section {
margin-bottom: 24px;
}
.column-config-item {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 8px;
}
`
]
})
export
class
SyncfusionDatagridConfigComponent
extends
BaseConfigComponent
implements
OnInit
{
override
ngOnInit
()
{
this
.
initializeDefaultConfig
();
this
.
initializeColumns
();
this
.
initializeColorDefaults
();
}
ngOnInit
():
void
{
// Initialize default values for Syncfusion Datagrid widget
this
.
initializeDefaults
();
private
initializeColorDefaults
()
{
if
(
!
this
.
currentConfig
.
backgroundColor
)
this
.
currentConfig
.
backgroundColor
=
'#FFFFFF'
;
if
(
!
this
.
currentConfig
.
textColor
)
this
.
currentConfig
.
textColor
=
'#374151'
;
if
(
!
this
.
currentConfig
.
headerBackgroundColor
)
this
.
currentConfig
.
headerBackgroundColor
=
'#F9FAFB'
;
if
(
!
this
.
currentConfig
.
headerTextColor
)
this
.
currentConfig
.
headerTextColor
=
'#374151'
;
if
(
!
this
.
currentConfig
.
borderColor
)
this
.
currentConfig
.
borderColor
=
'#E5E7EB'
;
if
(
!
this
.
currentConfig
.
alternateRowColor
)
this
.
currentConfig
.
alternateRowColor
=
'#F9FAFB'
;
}
private
initializeDefaults
():
void
{
if
(
!
this
.
currentConfig
.
title
)
{
this
.
currentConfig
.
title
=
'Data Grid'
;
}
if
(
!
this
.
currentConfig
.
pageSize
)
{
this
.
currentConfig
.
pageSize
=
10
;
}
if
(
!
this
.
currentConfig
.
fontSize
)
{
this
.
currentConfig
.
fontSize
=
14
;
}
if
(
this
.
currentConfig
.
enablePaging
===
undefined
)
{
this
.
currentConfig
.
enablePaging
=
true
;
}
if
(
this
.
currentConfig
.
enableSorting
===
undefined
)
{
this
.
currentConfig
.
enableSorting
=
true
;
}
if
(
this
.
currentConfig
.
enableFiltering
===
undefined
)
{
this
.
currentConfig
.
enableFiltering
=
true
;
}
if
(
this
.
currentConfig
.
enableGrouping
===
undefined
)
{
this
.
currentConfig
.
enableGrouping
=
false
;
}
if
(
this
.
currentConfig
.
enableEditing
===
undefined
)
{
this
.
currentConfig
.
enableEditing
=
false
;
}
if
(
this
.
currentConfig
.
enableSearch
===
undefined
)
{
this
.
currentConfig
.
enableSearch
=
true
;
}
if
(
this
.
currentConfig
.
enableColumnChooser
===
undefined
)
{
this
.
currentConfig
.
enableColumnChooser
=
true
;
}
if
(
this
.
currentConfig
.
enableColumnResizing
===
undefined
)
{
this
.
currentConfig
.
enableColumnResizing
=
true
;
}
if
(
this
.
currentConfig
.
enableColumnReordering
===
undefined
)
{
this
.
currentConfig
.
enableColumnReordering
=
true
;
}
if
(
this
.
currentConfig
.
enableRowSelection
===
undefined
)
{
this
.
currentConfig
.
enableRowSelection
=
true
;
}
if
(
this
.
currentConfig
.
enableMultiSelection
===
undefined
)
{
this
.
currentConfig
.
enableMultiSelection
=
false
;
}
if
(
this
.
currentConfig
.
showHeader
===
undefined
)
{
this
.
currentConfig
.
showHeader
=
true
;
}
if
(
this
.
currentConfig
.
showToolbar
===
undefined
)
{
this
.
currentConfig
.
showToolbar
=
true
;
}
if
(
this
.
currentConfig
.
showPager
===
undefined
)
{
this
.
currentConfig
.
showPager
=
true
;
}
if
(
this
.
currentConfig
.
showFooter
===
undefined
)
{
this
.
currentConfig
.
showFooter
=
false
;
}
if
(
this
.
currentConfig
.
enableTooltip
===
undefined
)
{
this
.
currentConfig
.
enableTooltip
=
true
;
}
if
(
this
.
currentConfig
.
enableClick
===
undefined
)
{
this
.
currentConfig
.
enableClick
=
true
;
}
if
(
this
.
currentConfig
.
enableHover
===
undefined
)
{
this
.
currentConfig
.
enableHover
=
true
;
}
if
(
this
.
currentConfig
.
enableExport
===
undefined
)
{
this
.
currentConfig
.
enableExport
=
true
;
}
if
(
!
this
.
currentConfig
.
clickAction
)
{
this
.
currentConfig
.
clickAction
=
'none'
;
}
if
(
!
this
.
currentConfig
.
width
)
{
this
.
currentConfig
.
width
=
800
;
}
if
(
!
this
.
currentConfig
.
height
)
{
this
.
currentConfig
.
height
=
600
;
}
if
(
this
.
currentConfig
.
responsive
===
undefined
)
{
this
.
currentConfig
.
responsive
=
true
;
}
if
(
!
this
.
currentConfig
.
dataSource
)
{
this
.
currentConfig
.
dataSource
=
'static'
;
}
if
(
this
.
currentConfig
.
cacheEnabled
===
undefined
)
{
this
.
currentConfig
.
cacheEnabled
=
false
;
}
if
(
this
.
currentConfig
.
requireAuth
===
undefined
)
{
this
.
currentConfig
.
requireAuth
=
false
;
}
if
(
this
.
currentConfig
.
dataEncryption
===
undefined
)
{
this
.
currentConfig
.
dataEncryption
=
false
;
}
if
(
this
.
currentConfig
.
auditLog
===
undefined
)
{
this
.
currentConfig
.
auditLog
=
false
;
}
if
(
!
this
.
currentConfig
.
rateLimit
)
{
this
.
currentConfig
.
rateLimit
=
0
;
private
initializeColumns
()
{
if
(
!
this
.
currentConfig
.
columns
)
{
this
.
currentConfig
.
columns
=
[];
}
}
addColumn
()
{
this
.
addArrayItem
(
'columns'
,
{
field
:
''
,
headerText
:
''
,
width
:
''
,
textAlign
:
'left'
,
format
:
'none'
,
visible
:
true
,
sortable
:
true
,
filterable
:
true
});
}
removeColumn
(
index
:
number
)
{
this
.
removeArrayItem
(
'columns'
,
index
);
}
addAggregateColumn
()
{
this
.
addArrayItem
(
'aggregateColumns'
,
{
field
:
''
,
type
:
'sum'
,
format
:
'none'
,
visible
:
true
});
}
removeAggregateColumn
(
index
:
number
)
{
this
.
removeArrayItem
(
'aggregateColumns'
,
index
);
}
}
src/app/portal-manage/dashboard-management/widgets/configs/syncfusion-pivot-config/syncfusion-pivot-config.component.ts
View file @
fec4de97
...
...
@@ -195,7 +195,7 @@ import { BaseConfigComponent } from '../../../widget-config/base-config/base-con
`
})
export
class
SyncfusionPivotConfigComponent
extends
BaseConfigComponent
implements
OnInit
{
ngOnInit
():
void
{
override
ngOnInit
():
void
{
// Initialize default values for pivot widget
if
(
!
this
.
currentConfig
.
rows
)
this
.
currentConfig
.
rows
=
[];
if
(
!
this
.
currentConfig
.
columns
)
this
.
currentConfig
.
columns
=
[];
...
...
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