charthart
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
|
||||
<div style="display: inline;">
|
||||
<button class="btn componentbtn" (click)="toggleMenu()"><clr-icon shape="plus"></clr-icon>component</button>
|
||||
<button class="btn btn-primary" (click)="openCommonFilterModal()" style="margin-left: 10px;">
|
||||
<clr-icon shape="filter"></clr-icon> Common Filter
|
||||
</button>
|
||||
<div style="display: inline;">
|
||||
{{dashboardName}}
|
||||
</div>
|
||||
@@ -208,8 +211,20 @@
|
||||
<h5>Base API Filters</h5>
|
||||
<div class="clr-subtext">Configure filters for the main API (applied regardless of drilldown settings)</div>
|
||||
|
||||
<!-- Common Filter Toggle -->
|
||||
<div class="clr-form-control" style="margin-top: 10px;">
|
||||
<div class="clr-control-container">
|
||||
<div class="clr-checkbox-wrapper">
|
||||
<input type="checkbox" id="commonFilterToggle" [(ngModel)]="gadgetsEditdata.commonFilterEnabled"
|
||||
(change)="onCommonFilterToggle()" [ngModelOptions]="{standalone: true}" class="clr-checkbox" />
|
||||
<label for="commonFilterToggle" class="clr-control-label">Use Common Filter</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Base Filter Button -->
|
||||
<button class="btn btn-sm btn-primary" (click)="addBaseFilter()" style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<button class="btn btn-sm btn-primary" (click)="addBaseFilter()" style="margin-top: 10px; margin-bottom: 10px;"
|
||||
[disabled]="gadgetsEditdata.commonFilterEnabled">
|
||||
<clr-icon shape="plus"></clr-icon> Add Filter
|
||||
</button>
|
||||
|
||||
@@ -218,14 +233,16 @@
|
||||
style="margin-bottom: 10px; padding: 8px; border: 1px solid #eee; border-radius: 4px; background-color: #f9f9f9;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>Filter {{i + 1}}</span>
|
||||
<button class="btn btn-icon btn-danger btn-sm" (click)="removeBaseFilter(i)">
|
||||
<button class="btn btn-icon btn-danger btn-sm" (click)="removeBaseFilter(i)"
|
||||
[disabled]="gadgetsEditdata.commonFilterEnabled">
|
||||
<clr-icon shape="trash"></clr-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="clr-row" style="margin-top: 8px;">
|
||||
<div class="clr-col-sm-5">
|
||||
<select [(ngModel)]="filter.field" [ngModelOptions]="{standalone: true}" class="clr-select">
|
||||
<select [(ngModel)]="filter.field" [ngModelOptions]="{standalone: true}" class="clr-select"
|
||||
[disabled]="gadgetsEditdata.commonFilterEnabled">
|
||||
<option value="">Select Field</option>
|
||||
<!-- Base API filters should always use columnData, not drilldownColumnData -->
|
||||
<option *ngFor="let column of getAvailableFields(gadgetsEditdata.baseFilters, i, columnData)" [value]="column">{{column}}</option>
|
||||
@@ -234,11 +251,13 @@
|
||||
|
||||
<div class="clr-col-sm-5">
|
||||
<input type="text" [(ngModel)]="filter.value" [ngModelOptions]="{standalone: true}"
|
||||
class="clr-input" placeholder="Filter Value" />
|
||||
class="clr-input" placeholder="Filter Value"
|
||||
[disabled]="gadgetsEditdata.commonFilterEnabled"/>
|
||||
</div>
|
||||
|
||||
<div class="clr-col-sm-2">
|
||||
<button class="btn btn-icon btn-danger btn-sm" (click)="removeBaseFilter(i)">
|
||||
<button class="btn btn-icon btn-danger btn-sm" (click)="removeBaseFilter(i)"
|
||||
[disabled]="gadgetsEditdata.commonFilterEnabled">
|
||||
<clr-icon shape="trash"></clr-icon>
|
||||
</button>
|
||||
</div>
|
||||
@@ -324,12 +343,12 @@
|
||||
<h5>Base Drilldown Filters</h5>
|
||||
<div class="clr-subtext">Configure filters for the base drilldown level</div>
|
||||
|
||||
<!-- Add Base Drilldown Filter Button -->
|
||||
<!-- Add Drilldown Filter Button -->
|
||||
<button class="btn btn-sm btn-primary" (click)="addDrilldownFilter()" style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<clr-icon shape="plus"></clr-icon> Add Filter
|
||||
</button>
|
||||
|
||||
<!-- Base Drilldown Filter Fields List -->
|
||||
<!-- Drilldown Filter Fields List -->
|
||||
<div *ngFor="let filter of gadgetsEditdata.drilldownFilters; let i = index"
|
||||
style="margin-bottom: 10px; padding: 8px; border: 1px solid #eee; border-radius: 4px; background-color: #f9f9f9;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
@@ -508,3 +527,86 @@
|
||||
</form>
|
||||
</div>
|
||||
</clr-modal>
|
||||
|
||||
<!-- Common Filter Modal -->
|
||||
<clr-modal [(clrModalOpen)]="commonFilterModalOpen" [clrModalStaticBackdrop]="true" clrModalSize="lg">
|
||||
<h3 class="modal-title">Configure Common Filter</h3>
|
||||
<div class="modal-body">
|
||||
<form [formGroup]="commonFilterForm" class="clr-form-horizontal">
|
||||
<div class="clr-row">
|
||||
<div class="clr-col-sm-12">
|
||||
<label for="commonFilterConnection">Connection</label>
|
||||
<select id="commonFilterConnection" formControlName="connection" [(ngModel)]="commonFilterData.connection" class="clr-select">
|
||||
<option value="">Select Connection</option>
|
||||
<option *ngFor="let conn of sureconnectData" [value]="conn.id">
|
||||
{{conn.connection_name || conn.id}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clr-row">
|
||||
<div class="clr-col-sm-12">
|
||||
<label for="commonFilterApiUrl">API URL</label>
|
||||
<div>
|
||||
<input type="text" id="commonFilterApiUrl" formControlName="apiUrl" class="clr-input"
|
||||
[(ngModel)]="commonFilterData.apiUrl" style="width:90%">
|
||||
<span>
|
||||
<button class="btn btn-icon btn-primary" style="margin: 0px;"
|
||||
(click)="refreshCommonFilterColumns()" [disabled]="!commonFilterData.apiUrl">
|
||||
<clr-icon shape="redo"></clr-icon>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Common Filter Fields List -->
|
||||
<div class="clr-row" style="margin-top: 15px;">
|
||||
<div class="clr-col-sm-12">
|
||||
<h5>Common Filters</h5>
|
||||
|
||||
<!-- Add Common Filter Button -->
|
||||
<button class="btn btn-sm btn-primary" (click)="addCommonFilter()" style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<clr-icon shape="plus"></clr-icon> Add Filter
|
||||
</button>
|
||||
|
||||
<!-- Common Filter Fields List -->
|
||||
<div *ngFor="let filter of commonFilterData.filters; let i = index"
|
||||
style="margin-bottom: 10px; padding: 8px; border: 1px solid #eee; border-radius: 4px; background-color: #f9f9f9;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>Filter {{i + 1}}</span>
|
||||
<button class="btn btn-icon btn-danger btn-sm" (click)="removeCommonFilter(i)">
|
||||
<clr-icon shape="trash"></clr-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="clr-row" style="margin-top: 8px;">
|
||||
<div class="clr-col-sm-5">
|
||||
<select [(ngModel)]="filter.field" [ngModelOptions]="{standalone: true}" class="clr-select">
|
||||
<option value="">Select Field</option>
|
||||
<option *ngFor="let column of commonFilterColumnData" [value]="column">{{column}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="clr-col-sm-5">
|
||||
<input type="text" [(ngModel)]="filter.value" [ngModelOptions]="{standalone: true}"
|
||||
class="clr-input" placeholder="Filter Value" />
|
||||
</div>
|
||||
|
||||
<div class="clr-col-sm-2">
|
||||
<button class="btn btn-icon btn-danger btn-sm" (click)="removeCommonFilter(i)">
|
||||
<clr-icon shape="trash"></clr-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline" (click)="commonFilterModalOpen = false">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" (click)="saveCommonFilter()">Save</button>
|
||||
</div>
|
||||
</clr-modal>
|
||||
|
||||
@@ -40,7 +40,9 @@ export class EditnewdashComponent implements OnInit {
|
||||
editId: number;
|
||||
toggle: boolean;
|
||||
modeledit: boolean = false;
|
||||
commonFilterModalOpen: boolean = false; // Add common filter modal state
|
||||
public entryForm: FormGroup;
|
||||
public commonFilterForm: FormGroup; // Add common filter form
|
||||
|
||||
WidgetsMock: WidgetModel[] = [
|
||||
{
|
||||
@@ -118,6 +120,17 @@ export class EditnewdashComponent implements OnInit {
|
||||
model: any;
|
||||
linesdata: any;
|
||||
id: any;
|
||||
|
||||
// Add common filter data property
|
||||
commonFilterData = {
|
||||
connection: '',
|
||||
apiUrl: '',
|
||||
filters: [] as any[]
|
||||
};
|
||||
|
||||
// Add common filter column data property
|
||||
commonFilterColumnData: any[] = [];
|
||||
|
||||
gadgetsEditdata = {
|
||||
donut: '',
|
||||
chartlegend: '',
|
||||
@@ -146,12 +159,17 @@ export class EditnewdashComponent implements OnInit {
|
||||
drilldownFilters: [] as any[], // Add separate drilldown filters
|
||||
// Multi-layer drilldown configurations
|
||||
drilldownLayers: [] as any[],
|
||||
// Common filter property
|
||||
commonFilterEnabled: false
|
||||
};
|
||||
|
||||
// Add sureconnect data property
|
||||
sureconnectData: any[] = [];
|
||||
layerColumnData: { [key: number]: any[] } = {}; // Add layer column data property
|
||||
|
||||
// Add drilldown column data property
|
||||
drilldownColumnData = []; // Add drilldown column data property
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private dashboardService: Dashboard3Service,
|
||||
@@ -224,8 +242,17 @@ export class EditnewdashComponent implements OnInit {
|
||||
// Note: Dynamic drilldown layers and filters will be handled separately since they're complex objects
|
||||
});
|
||||
|
||||
// Initialize common filter form
|
||||
this.commonFilterForm = this._fb.group({
|
||||
connection: [''],
|
||||
apiUrl: ['']
|
||||
});
|
||||
|
||||
// Load sureconnect data first, then load dashboard data
|
||||
this.loadSureconnectData();
|
||||
|
||||
// Load common filter data if it exists
|
||||
this.loadCommonFilterData();
|
||||
}
|
||||
|
||||
// Add method to load sureconnect data
|
||||
@@ -242,6 +269,13 @@ export class EditnewdashComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
// Add method to load common filter data
|
||||
loadCommonFilterData() {
|
||||
// In a real implementation, this would fetch common filter data from the server
|
||||
// For now, we'll initialize with empty values
|
||||
console.log('Loading common filter data');
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
this.toggle = !this.toggle;
|
||||
}
|
||||
@@ -499,6 +533,10 @@ export class EditnewdashComponent implements OnInit {
|
||||
if (item.showlabel === undefined) { item.showlabel = true; }
|
||||
if (item.chartcolor === undefined) { item.chartcolor = true; }
|
||||
if (item.chartlegend === undefined) { item.chartlegend = true; }
|
||||
// Initialize common filter property if not present
|
||||
if (item['commonFilterEnabled'] === undefined) {
|
||||
this.gadgetsEditdata['commonFilterEnabled'] = false;
|
||||
}
|
||||
this.getStores();
|
||||
|
||||
// Set default connection if none is set and we have connections
|
||||
@@ -662,6 +700,7 @@ export class EditnewdashComponent implements OnInit {
|
||||
xyz.baseFilters = this.gadgetsEditdata.baseFilters; // Add base filters
|
||||
xyz.drilldownFilters = this.gadgetsEditdata.drilldownFilters; // Add drilldown filters
|
||||
xyz.drilldownLayers = this.gadgetsEditdata.drilldownLayers;
|
||||
xyz.commonFilterEnabled = this.gadgetsEditdata.commonFilterEnabled; // Add common filter property
|
||||
|
||||
console.log(xyz);
|
||||
return xyz;
|
||||
@@ -755,6 +794,7 @@ export class EditnewdashComponent implements OnInit {
|
||||
updatedItem.baseFilters = this.gadgetsEditdata.baseFilters; // Add base filters
|
||||
updatedItem.drilldownFilters = this.gadgetsEditdata.drilldownFilters; // Add drilldown filters
|
||||
updatedItem.drilldownLayers = this.gadgetsEditdata.drilldownLayers;
|
||||
updatedItem.commonFilterEnabled = this.gadgetsEditdata.commonFilterEnabled; // Add common filter property
|
||||
|
||||
console.log('Updated item:', updatedItem);
|
||||
return updatedItem;
|
||||
@@ -820,7 +860,6 @@ export class EditnewdashComponent implements OnInit {
|
||||
}
|
||||
selectedyAxis;
|
||||
columnData;
|
||||
drilldownColumnData = []; // Add drilldown column data property
|
||||
|
||||
getColumns(id, table) {
|
||||
const connectionId = this.gadgetsEditdata.connection ? parseInt(this.gadgetsEditdata.connection, 10) : undefined;
|
||||
@@ -1017,4 +1056,97 @@ export class EditnewdashComponent implements OnInit {
|
||||
removeLayerFilter(layerIndex: number, filterIndex: number) {
|
||||
this.gadgetsEditdata.drilldownLayers[layerIndex].filters.splice(filterIndex, 1);
|
||||
}
|
||||
|
||||
// Add method to open common filter modal
|
||||
openCommonFilterModal() {
|
||||
this.commonFilterModalOpen = true;
|
||||
}
|
||||
|
||||
// Add method to add a common filter
|
||||
addCommonFilter() {
|
||||
const newFilter = {
|
||||
field: '',
|
||||
value: ''
|
||||
};
|
||||
this.commonFilterData.filters.push(newFilter);
|
||||
}
|
||||
|
||||
// Add method to remove a common filter
|
||||
removeCommonFilter(index: number) {
|
||||
this.commonFilterData.filters.splice(index, 1);
|
||||
}
|
||||
|
||||
// Add method to refresh common filter columns
|
||||
refreshCommonFilterColumns() {
|
||||
if (this.commonFilterData.apiUrl) {
|
||||
const connectionId = this.commonFilterData.connection ? parseInt(this.commonFilterData.connection, 10) : undefined;
|
||||
this.alertService.getColumnfromurl(this.commonFilterData.apiUrl, connectionId).subscribe(data => {
|
||||
console.log('Common filter column data:', data);
|
||||
this.commonFilterColumnData = data;
|
||||
}, (error) => {
|
||||
console.log('Error fetching common filter columns:', error);
|
||||
this.commonFilterColumnData = [];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add method to save common filter
|
||||
saveCommonFilter() {
|
||||
// Here we would typically make an API call to save the common filter
|
||||
// For now, we'll just close the modal
|
||||
console.log('Saving common filter:', this.commonFilterData);
|
||||
|
||||
// Update all charts that have common filter enabled
|
||||
this.updateChartsWithCommonFilter();
|
||||
|
||||
this.commonFilterModalOpen = false;
|
||||
}
|
||||
|
||||
// Add method to update charts with common filter data
|
||||
updateChartsWithCommonFilter() {
|
||||
// This method will be called when common filter is saved
|
||||
// It will update all charts that have common filter enabled
|
||||
console.log('Updating charts with common filter data');
|
||||
|
||||
// Update the dashboardArray to reflect changes
|
||||
this.dashboardArray = this.dashboardArray.map(item => {
|
||||
if (item.commonFilterEnabled) {
|
||||
// Update the chart with common filter data
|
||||
return {
|
||||
...item,
|
||||
table: this.commonFilterData.apiUrl,
|
||||
connection: this.commonFilterData.connection,
|
||||
baseFilters: [...this.commonFilterData.filters]
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
// Also update the dashboardCollection to persist changes
|
||||
this.dashboardCollection.dashboard = this.dashboardCollection.dashboard.map(item => {
|
||||
if (item.commonFilterEnabled) {
|
||||
// Update the chart with common filter data
|
||||
return {
|
||||
...item,
|
||||
table: this.commonFilterData.apiUrl,
|
||||
connection: this.commonFilterData.connection,
|
||||
baseFilters: [...this.commonFilterData.filters]
|
||||
} as DashboardContentModel;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
// Add method to handle common filter toggle
|
||||
onCommonFilterToggle() {
|
||||
console.log('Common filter toggled:', this.gadgetsEditdata.commonFilterEnabled);
|
||||
|
||||
if (this.gadgetsEditdata.commonFilterEnabled) {
|
||||
// When enabling common filter, save current values and apply common filter data
|
||||
this.gadgetsEditdata.table = this.commonFilterData.apiUrl;
|
||||
this.gadgetsEditdata.connection = this.commonFilterData.connection;
|
||||
this.gadgetsEditdata.baseFilters = [...this.commonFilterData.filters];
|
||||
}
|
||||
// When disabling, the user can edit the filters normally
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
drilldownConfig.apiUrl, 'bar',
|
||||
this.drilldownXAxis, this.drilldownYAxis,
|
||||
this.connection,
|
||||
parameterField, parameterValue,
|
||||
'', parameterValue,
|
||||
drilldownFilterParams
|
||||
).subscribe(
|
||||
(data: any) => {
|
||||
|
||||
@@ -307,32 +307,13 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert drilldownFilters to filter parameters for drilldown level
|
||||
let drilldownFilterParams = '';
|
||||
if (this.drilldownFilters && this.drilldownFilters.length > 0) {
|
||||
const filterObj = {};
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (filter.field && filter.value) {
|
||||
filterObj[filter.field] = filter.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(filterObj).length > 0) {
|
||||
drilldownFilterParams = JSON.stringify(filterObj);
|
||||
}
|
||||
}
|
||||
console.log('Drilldown filter parameters:', drilldownFilterParams);
|
||||
|
||||
// Use drilldown filters if available, otherwise use layer filters
|
||||
const finalFilterParams = drilldownFilterParams || filterParams;
|
||||
console.log('Final filter parameters:', finalFilterParams);
|
||||
|
||||
// Log the URL that will be called
|
||||
const url = `chart/getdashjson/bubble?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`;
|
||||
console.log('Drilldown data URL:', url);
|
||||
|
||||
// Fetch data from the dashboard service with parameter field and value
|
||||
// Backend handles filtering, we just pass the parameter field and value
|
||||
this.dashboardService.getChartData(actualApiUrl, 'bubble', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe(
|
||||
this.dashboardService.getChartData(actualApiUrl, 'bubble', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Received drilldown data:', data);
|
||||
if (data === null) {
|
||||
|
||||
@@ -402,32 +402,13 @@ export class DoughnutChartComponent implements OnInit, OnChanges, AfterViewCheck
|
||||
}
|
||||
}
|
||||
|
||||
// Convert drilldownFilters to filter parameters for drilldown level
|
||||
let drilldownFilterParams = '';
|
||||
if (this.drilldownFilters && this.drilldownFilters.length > 0) {
|
||||
const filterObj = {};
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (filter.field && filter.value) {
|
||||
filterObj[filter.field] = filter.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(filterObj).length > 0) {
|
||||
drilldownFilterParams = JSON.stringify(filterObj);
|
||||
}
|
||||
}
|
||||
console.log('Drilldown filter parameters:', drilldownFilterParams);
|
||||
|
||||
// Use drilldown filters if available, otherwise use layer filters
|
||||
const finalFilterParams = drilldownFilterParams || filterParams;
|
||||
console.log('Final filter parameters:', finalFilterParams);
|
||||
|
||||
// Log the URL that will be called
|
||||
const url = `chart/getdashjson/doughnut?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`;
|
||||
console.log('Drilldown data URL:', url);
|
||||
|
||||
// Fetch data from the dashboard service with parameter field and value
|
||||
// Backend handles filtering, we just pass the parameter field and value
|
||||
this.dashboardService.getChartData(actualApiUrl, 'doughnut', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe(
|
||||
this.dashboardService.getChartData(actualApiUrl, 'doughnut', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Received drilldown data:', data);
|
||||
if (data === null) {
|
||||
|
||||
@@ -298,32 +298,13 @@ export class DynamicChartComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert drilldownFilters to filter parameters for drilldown level
|
||||
let drilldownFilterParams = '';
|
||||
if (this.drilldownFilters && this.drilldownFilters.length > 0) {
|
||||
const filterObj = {};
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (filter.field && filter.value) {
|
||||
filterObj[filter.field] = filter.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(filterObj).length > 0) {
|
||||
drilldownFilterParams = JSON.stringify(filterObj);
|
||||
}
|
||||
}
|
||||
console.log('Drilldown filter parameters:', drilldownFilterParams);
|
||||
|
||||
// Use drilldown filters if available, otherwise use layer filters
|
||||
const finalFilterParams = drilldownFilterParams || filterParams;
|
||||
console.log('Final filter parameters:', finalFilterParams);
|
||||
|
||||
// Log the URL that will be called
|
||||
const url = `chart/getdashjson/dynamic?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`;
|
||||
console.log('Drilldown data URL:', url);
|
||||
|
||||
// Fetch data from the dashboard service with parameter field and value
|
||||
// Backend handles filtering, we just pass the parameter field and value
|
||||
this.dashboardService.getChartData(actualApiUrl, 'dynamic', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe(
|
||||
this.dashboardService.getChartData(actualApiUrl, 'dynamic', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Received drilldown data:', data);
|
||||
if (data === null) {
|
||||
|
||||
@@ -289,32 +289,13 @@ export class FinancialChartComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert drilldownFilters to filter parameters for drilldown level
|
||||
let drilldownFilterParams = '';
|
||||
if (this.drilldownFilters && this.drilldownFilters.length > 0) {
|
||||
const filterObj = {};
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (filter.field && filter.value) {
|
||||
filterObj[filter.field] = filter.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(filterObj).length > 0) {
|
||||
drilldownFilterParams = JSON.stringify(filterObj);
|
||||
}
|
||||
}
|
||||
console.log('Drilldown filter parameters:', drilldownFilterParams);
|
||||
|
||||
// Use drilldown filters if available, otherwise use layer filters
|
||||
const finalFilterParams = drilldownFilterParams || filterParams;
|
||||
console.log('Final filter parameters:', finalFilterParams);
|
||||
|
||||
// Log the URL that will be called
|
||||
const url = `chart/getdashjson/financial?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`;
|
||||
console.log('Drilldown data URL:', url);
|
||||
|
||||
// Fetch data from the dashboard service with parameter field and value
|
||||
// Backend handles filtering, we just pass the parameter field and value
|
||||
this.dashboardService.getChartData(actualApiUrl, 'financial', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe(
|
||||
this.dashboardService.getChartData(actualApiUrl, 'financial', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Received drilldown data:', data);
|
||||
if (data === null) {
|
||||
|
||||
@@ -313,32 +313,13 @@ export class LineChartComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert drilldownFilters to filter parameters for drilldown level
|
||||
let drilldownFilterParams = '';
|
||||
if (this.drilldownFilters && this.drilldownFilters.length > 0) {
|
||||
const filterObj = {};
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (filter.field && filter.value) {
|
||||
filterObj[filter.field] = filter.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(filterObj).length > 0) {
|
||||
drilldownFilterParams = JSON.stringify(filterObj);
|
||||
}
|
||||
}
|
||||
console.log('Drilldown filter parameters:', drilldownFilterParams);
|
||||
|
||||
// Use drilldown filters if available, otherwise use layer filters
|
||||
const finalFilterParams = drilldownFilterParams || filterParams;
|
||||
console.log('Final filter parameters:', finalFilterParams);
|
||||
|
||||
// Log the URL that will be called
|
||||
const url = `chart/getdashjson/line?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`;
|
||||
console.log('Drilldown data URL:', url);
|
||||
|
||||
// Fetch data from the dashboard service with parameter field and value
|
||||
// Backend handles filtering, we just pass the parameter field and value
|
||||
this.dashboardService.getChartData(actualApiUrl, 'line', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe(
|
||||
this.dashboardService.getChartData(actualApiUrl, 'line', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Received drilldown data:', data);
|
||||
if (data === null) {
|
||||
|
||||
@@ -362,32 +362,13 @@ export class PieChartComponent implements OnInit, OnChanges, AfterViewChecked {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert drilldownFilters to filter parameters for drilldown level
|
||||
let drilldownFilterParams = '';
|
||||
if (this.drilldownFilters && this.drilldownFilters.length > 0) {
|
||||
const filterObj = {};
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (filter.field && filter.value) {
|
||||
filterObj[filter.field] = filter.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(filterObj).length > 0) {
|
||||
drilldownFilterParams = JSON.stringify(filterObj);
|
||||
}
|
||||
}
|
||||
console.log('Drilldown filter parameters:', drilldownFilterParams);
|
||||
|
||||
// Use drilldown filters if available, otherwise use layer filters
|
||||
const finalFilterParams = drilldownFilterParams || filterParams;
|
||||
console.log('Final filter parameters:', finalFilterParams);
|
||||
|
||||
// Log the URL that will be called
|
||||
const url = `chart/getdashjson/pie?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`;
|
||||
console.log('Drilldown data URL:', url);
|
||||
|
||||
// Fetch data from the dashboard service with parameter field and value
|
||||
// Backend handles filtering, we just pass the parameter field and value
|
||||
this.dashboardService.getChartData(actualApiUrl, 'pie', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe(
|
||||
this.dashboardService.getChartData(actualApiUrl, 'pie', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Received drilldown data:', data);
|
||||
if (data === null) {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
|
||||
import { Dashboard3Service } from '../../../../../../services/builder/dashboard3.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-polar-chart',
|
||||
templateUrl: './polar-chart.component.html',
|
||||
styleUrls: ['./polar-chart.component.scss']
|
||||
})
|
||||
export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
export class PolarChartComponent implements OnInit, OnChanges {
|
||||
@Input() xAxis: string;
|
||||
@Input() yAxis: string | string[];
|
||||
@Input() table: string;
|
||||
@@ -36,24 +35,6 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
constructor(private dashboardService: Dashboard3Service) { }
|
||||
|
||||
public polarAreaChartLabels: string[] = [ 'Download Sales', 'In-Store Sales', 'Mail Sales', 'Telesales', 'Corporate Sales' ];
|
||||
public polarAreaChartData: any = [
|
||||
{ data: [ 300, 500, 100, 40, 120 ], label: 'Series 1'}
|
||||
];
|
||||
public polarAreaChartType: string = 'polarArea';
|
||||
|
||||
// Multi-layer drilldown state tracking
|
||||
drilldownStack: any[] = []; // Stack to track drilldown navigation history
|
||||
currentDrilldownLevel: number = 0; // Current drilldown level (0 = base level)
|
||||
originalPolarAreaChartLabels: string[] = [];
|
||||
originalPolarAreaChartData: any = [];
|
||||
|
||||
// No data state
|
||||
noDataAvailable: boolean = false;
|
||||
|
||||
// Flag to prevent infinite loops
|
||||
private isFetchingData: boolean = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
// Initialize with default data
|
||||
this.fetchChartData();
|
||||
@@ -85,6 +66,25 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
public polarAreaChartLabels: string[] = [ 'Download Sales', 'In-Store Sales', 'Mail Sales', 'Telesales', 'Corporate Sales' ];
|
||||
public polarAreaChartData: any = [
|
||||
{ data: [ 300, 500, 100, 40, 120 ], label: 'Series 1'}
|
||||
];
|
||||
|
||||
public polarAreaChartType: string = 'polarArea';
|
||||
|
||||
// Multi-layer drilldown state tracking
|
||||
drilldownStack: any[] = []; // Stack to track drilldown navigation history
|
||||
currentDrilldownLevel: number = 0; // Current drilldown level (0 = base level)
|
||||
originalPolarAreaChartLabels: string[] = [];
|
||||
originalPolarAreaChartData: any = [];
|
||||
|
||||
// No data state
|
||||
noDataAvailable: boolean = false;
|
||||
|
||||
// Flag to prevent infinite loops
|
||||
private isFetchingData: boolean = false;
|
||||
|
||||
fetchChartData(): void {
|
||||
// Set flag to prevent recursive calls
|
||||
this.isFetchingData = true;
|
||||
@@ -133,8 +133,6 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.noDataAvailable = true;
|
||||
this.polarAreaChartLabels = [];
|
||||
this.polarAreaChartData = [];
|
||||
// Validate and sanitize data to show default data
|
||||
this.validateChartData();
|
||||
// Reset flag after fetching
|
||||
this.isFetchingData = false;
|
||||
return;
|
||||
@@ -145,36 +143,26 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
// For polar charts, we need to extract the data differently
|
||||
// The first dataset's data array contains the values for the polar chart
|
||||
this.noDataAvailable = data.chartLabels.length === 0;
|
||||
this.polarAreaChartLabels = data.chartLabels || [];
|
||||
this.polarAreaChartLabels = data.chartLabels;
|
||||
if (data.chartData && data.chartData.length > 0) {
|
||||
this.polarAreaChartData = data.chartData[0].data.map(value => {
|
||||
// Convert to number if it's not already
|
||||
const numValue = Number(value);
|
||||
return isNaN(numValue) ? 0 : numValue;
|
||||
return isNaN(Number(value)) ? 0 : Number(value);
|
||||
});
|
||||
} else {
|
||||
this.polarAreaChartData = [];
|
||||
}
|
||||
// Ensure labels and data arrays have the same length
|
||||
this.syncLabelAndDataArrays();
|
||||
// Validate and sanitize data
|
||||
this.validateChartData();
|
||||
// Trigger change detection
|
||||
this.polarAreaChartData = [...this.polarAreaChartData];
|
||||
console.log('Updated polar chart with data:', { labels: this.polarAreaChartLabels, data: this.polarAreaChartData });
|
||||
} else if (data && data.labels && data.data) {
|
||||
// Handle the original expected format as fallback
|
||||
this.noDataAvailable = data.labels.length === 0;
|
||||
this.polarAreaChartLabels = data.labels || [];
|
||||
this.polarAreaChartLabels = data.labels;
|
||||
this.polarAreaChartData = data.data.map(value => {
|
||||
// Convert to number if it's not already
|
||||
const numValue = Number(value);
|
||||
return isNaN(numValue) ? 0 : numValue;
|
||||
return isNaN(Number(value)) ? 0 : Number(value);
|
||||
});
|
||||
// Ensure labels and data arrays have the same length
|
||||
this.syncLabelAndDataArrays();
|
||||
// Validate and sanitize data
|
||||
this.validateChartData();
|
||||
// Trigger change detection
|
||||
this.polarAreaChartData = [...this.polarAreaChartData];
|
||||
console.log('Updated polar chart with legacy data format:', { labels: this.polarAreaChartLabels, data: this.polarAreaChartData });
|
||||
@@ -183,8 +171,6 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.noDataAvailable = true;
|
||||
this.polarAreaChartLabels = [];
|
||||
this.polarAreaChartData = [];
|
||||
// Validate and sanitize data
|
||||
this.validateChartData();
|
||||
}
|
||||
// Reset flag after fetching
|
||||
this.isFetchingData = false;
|
||||
@@ -194,8 +180,6 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.noDataAvailable = true;
|
||||
this.polarAreaChartLabels = [];
|
||||
this.polarAreaChartData = [];
|
||||
// Validate and sanitize data to show default data
|
||||
this.validateChartData();
|
||||
// Reset flag after fetching
|
||||
this.isFetchingData = false;
|
||||
// Keep default data in case of error
|
||||
@@ -206,8 +190,6 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.noDataAvailable = true;
|
||||
this.polarAreaChartLabels = [];
|
||||
this.polarAreaChartData = [];
|
||||
// Validate and sanitize data to show default data
|
||||
this.validateChartData();
|
||||
// Reset flag after fetching
|
||||
this.isFetchingData = false;
|
||||
}
|
||||
@@ -305,32 +287,13 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert drilldownFilters to filter parameters for drilldown level
|
||||
let drilldownFilterParams = '';
|
||||
if (this.drilldownFilters && this.drilldownFilters.length > 0) {
|
||||
const filterObj = {};
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (filter.field && filter.value) {
|
||||
filterObj[filter.field] = filter.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(filterObj).length > 0) {
|
||||
drilldownFilterParams = JSON.stringify(filterObj);
|
||||
}
|
||||
}
|
||||
console.log('Drilldown filter parameters:', drilldownFilterParams);
|
||||
|
||||
// Use drilldown filters if available, otherwise use layer filters
|
||||
const finalFilterParams = drilldownFilterParams || filterParams;
|
||||
console.log('Final filter parameters:', finalFilterParams);
|
||||
|
||||
// Log the URL that will be called
|
||||
const url = `chart/getdashjson/polar?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`;
|
||||
console.log('Drilldown data URL:', url);
|
||||
|
||||
// Fetch data from the dashboard service with parameter field and value
|
||||
// Backend handles filtering, we just pass the parameter field and value
|
||||
this.dashboardService.getChartData(actualApiUrl, 'polar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe(
|
||||
this.dashboardService.getChartData(actualApiUrl, 'polar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Received drilldown data:', data);
|
||||
if (data === null) {
|
||||
@@ -346,36 +309,26 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
// For polar charts, we need to extract the data differently
|
||||
// The first dataset's data array contains the values for the polar chart
|
||||
this.noDataAvailable = data.chartLabels.length === 0;
|
||||
this.polarAreaChartLabels = data.chartLabels || [];
|
||||
this.polarAreaChartLabels = data.chartLabels;
|
||||
if (data.chartData && data.chartData.length > 0) {
|
||||
this.polarAreaChartData = data.chartData[0].data.map(value => {
|
||||
// Convert to number if it's not already
|
||||
const numValue = Number(value);
|
||||
return isNaN(numValue) ? 0 : numValue;
|
||||
return isNaN(Number(value)) ? 0 : Number(value);
|
||||
});
|
||||
} else {
|
||||
this.polarAreaChartData = [];
|
||||
}
|
||||
// Ensure labels and data arrays have the same length
|
||||
this.syncLabelAndDataArrays();
|
||||
// Validate and sanitize data
|
||||
this.validateChartData();
|
||||
// Trigger change detection
|
||||
this.polarAreaChartData = [...this.polarAreaChartData];
|
||||
console.log('Updated polar chart with drilldown data:', { labels: this.polarAreaChartLabels, data: this.polarAreaChartData });
|
||||
} else if (data && data.labels && data.data) {
|
||||
// Handle the original expected format as fallback
|
||||
this.noDataAvailable = data.labels.length === 0;
|
||||
this.polarAreaChartLabels = data.labels || [];
|
||||
this.polarAreaChartLabels = data.labels;
|
||||
this.polarAreaChartData = data.data.map(value => {
|
||||
// Convert to number if it's not already
|
||||
const numValue = Number(value);
|
||||
return isNaN(numValue) ? 0 : numValue;
|
||||
return isNaN(Number(value)) ? 0 : Number(value);
|
||||
});
|
||||
// Ensure labels and data arrays have the same length
|
||||
this.syncLabelAndDataArrays();
|
||||
// Validate and sanitize data
|
||||
this.validateChartData();
|
||||
// Trigger change detection
|
||||
this.polarAreaChartData = [...this.polarAreaChartData];
|
||||
console.log('Updated polar chart with drilldown legacy data format:', { labels: this.polarAreaChartLabels, data: this.polarAreaChartData });
|
||||
@@ -384,8 +337,6 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.noDataAvailable = true;
|
||||
this.polarAreaChartLabels = [];
|
||||
this.polarAreaChartData = [];
|
||||
// Validate and sanitize data
|
||||
this.validateChartData();
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
@@ -454,58 +405,6 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and sanitize chart data
|
||||
*/
|
||||
private validateChartData(): void {
|
||||
// Ensure we have valid arrays
|
||||
if (!Array.isArray(this.polarAreaChartLabels)) {
|
||||
this.polarAreaChartLabels = [];
|
||||
}
|
||||
|
||||
if (!Array.isArray(this.polarAreaChartData)) {
|
||||
this.polarAreaChartData = [];
|
||||
}
|
||||
|
||||
// If we have no data, show default data
|
||||
if (this.polarAreaChartLabels.length === 0 && this.polarAreaChartData.length === 0) {
|
||||
// Add default data to ensure chart visibility
|
||||
this.polarAreaChartLabels = ['Download Sales', 'In-Store Sales', 'Mail Sales', 'Telesales', 'Corporate Sales'];
|
||||
this.polarAreaChartData = [300, 500, 100, 40, 120];
|
||||
}
|
||||
|
||||
// Ensure we have matching arrays
|
||||
if (this.polarAreaChartLabels.length !== this.polarAreaChartData.length) {
|
||||
const maxLength = Math.max(this.polarAreaChartLabels.length, this.polarAreaChartData.length);
|
||||
while (this.polarAreaChartLabels.length < maxLength) {
|
||||
this.polarAreaChartLabels.push(`Label ${this.polarAreaChartLabels.length + 1}`);
|
||||
}
|
||||
while (this.polarAreaChartData.length < maxLength) {
|
||||
this.polarAreaChartData.push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure labels and data arrays have the same length
|
||||
private syncLabelAndDataArrays(): void {
|
||||
if (this.polarAreaChartLabels && this.polarAreaChartData) {
|
||||
const labelCount = this.polarAreaChartLabels.length;
|
||||
const dataCount = this.polarAreaChartData.length;
|
||||
|
||||
if (labelCount > dataCount) {
|
||||
// Add zeros to data array
|
||||
while (this.polarAreaChartData.length < labelCount) {
|
||||
this.polarAreaChartData.push(0);
|
||||
}
|
||||
} else if (dataCount > labelCount) {
|
||||
// Add labels to label array
|
||||
while (this.polarAreaChartLabels.length < dataCount) {
|
||||
this.polarAreaChartLabels.push(`Item ${this.polarAreaChartLabels.length + 1}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// events
|
||||
public chartClicked(e: any): void {
|
||||
console.log('Polar chart clicked:', e);
|
||||
@@ -594,8 +493,4 @@ export class PolarChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
public chartHovered(e: any): void {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
// Clean up any subscriptions if needed
|
||||
}
|
||||
}
|
||||
@@ -298,32 +298,13 @@ export class RadarChartComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert drilldownFilters to filter parameters for drilldown level
|
||||
let drilldownFilterParams = '';
|
||||
if (this.drilldownFilters && this.drilldownFilters.length > 0) {
|
||||
const filterObj = {};
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (filter.field && filter.value) {
|
||||
filterObj[filter.field] = filter.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(filterObj).length > 0) {
|
||||
drilldownFilterParams = JSON.stringify(filterObj);
|
||||
}
|
||||
}
|
||||
console.log('Drilldown filter parameters:', drilldownFilterParams);
|
||||
|
||||
// Use drilldown filters if available, otherwise use layer filters
|
||||
const finalFilterParams = drilldownFilterParams || filterParams;
|
||||
console.log('Final filter parameters:', finalFilterParams);
|
||||
|
||||
// Log the URL that will be called
|
||||
const url = `chart/getdashjson/radar?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`;
|
||||
console.log('Drilldown data URL:', url);
|
||||
|
||||
// Fetch data from the dashboard service with parameter field and value
|
||||
// Backend handles filtering, we just pass the parameter field and value
|
||||
this.dashboardService.getChartData(actualApiUrl, 'radar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe(
|
||||
this.dashboardService.getChartData(actualApiUrl, 'radar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Received drilldown data:', data);
|
||||
if (data === null) {
|
||||
|
||||
Reference in New Issue
Block a user