mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-04-03 15:11:37 +00:00
435 lines
13 KiB
TypeScript
435 lines
13 KiB
TypeScript
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
|
import { Router } from '@angular/router';
|
|
import { Subject } from 'rxjs';
|
|
import { takeUntil } from 'rxjs/operators';
|
|
import { ApexOptions } from 'ng-apexcharts';
|
|
import { ProjectService } from 'app/modules/admin/dashboards/project/project.service';
|
|
|
|
@Component({
|
|
selector : 'project',
|
|
templateUrl : './project.component.html',
|
|
encapsulation : ViewEncapsulation.None,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
})
|
|
export class ProjectComponent implements OnInit, OnDestroy
|
|
{
|
|
chartGithubIssues: ApexOptions = {};
|
|
chartTaskDistribution: ApexOptions = {};
|
|
chartBudgetDistribution: ApexOptions = {};
|
|
chartWeeklyExpenses: ApexOptions = {};
|
|
chartMonthlyExpenses: ApexOptions = {};
|
|
chartYearlyExpenses: ApexOptions = {};
|
|
data: any;
|
|
selectedProject: string = 'ACME Corp. Backend App';
|
|
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
constructor(
|
|
private _projectService: ProjectService,
|
|
private _router: Router
|
|
)
|
|
{
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
// @ Lifecycle hooks
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* On init
|
|
*/
|
|
ngOnInit(): void
|
|
{
|
|
// Get the data
|
|
this._projectService.data$
|
|
.pipe(takeUntil(this._unsubscribeAll))
|
|
.subscribe((data) => {
|
|
|
|
// Store the data
|
|
this.data = data;
|
|
|
|
// Prepare the chart data
|
|
this._prepareChartData();
|
|
});
|
|
|
|
// Attach SVG fill fixer to all ApexCharts
|
|
window['Apex'] = {
|
|
chart: {
|
|
events: {
|
|
mounted: (chart: any, options?: any): void => {
|
|
this._fixSvgFill(chart.el);
|
|
},
|
|
updated: (chart: any, options?: any): void => {
|
|
this._fixSvgFill(chart.el);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* On destroy
|
|
*/
|
|
ngOnDestroy(): void
|
|
{
|
|
// Unsubscribe from all subscriptions
|
|
this._unsubscribeAll.next();
|
|
this._unsubscribeAll.complete();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
// @ Public methods
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Track by function for ngFor loops
|
|
*
|
|
* @param index
|
|
* @param item
|
|
*/
|
|
trackByFn(index: number, item: any): any
|
|
{
|
|
return item.id || index;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
// @ Private methods
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Fix the SVG fill references. This fix must be applied to all ApexCharts
|
|
* charts in order to fix 'black color on gradient fills on certain browsers'
|
|
* issue caused by the '<base>' tag.
|
|
*
|
|
* Fix based on https://gist.github.com/Kamshak/c84cdc175209d1a30f711abd6a81d472
|
|
*
|
|
* @param element
|
|
* @private
|
|
*/
|
|
private _fixSvgFill(element: Element): void
|
|
{
|
|
// Current URL
|
|
const currentURL = this._router.url;
|
|
|
|
// 1. Find all elements with 'fill' attribute within the element
|
|
// 2. Filter out the ones that doesn't have cross reference so we only left with the ones that use the 'url(#id)' syntax
|
|
// 3. Insert the 'currentURL' at the front of the 'fill' attribute value
|
|
Array.from(element.querySelectorAll('*[fill]'))
|
|
.filter(el => el.getAttribute('fill').indexOf('url(') !== -1)
|
|
.forEach((el) => {
|
|
const attrVal = el.getAttribute('fill');
|
|
el.setAttribute('fill', `url(${currentURL}${attrVal.slice(attrVal.indexOf('#'))}`);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Prepare the chart data from the data
|
|
*
|
|
* @private
|
|
*/
|
|
private _prepareChartData(): void
|
|
{
|
|
// Github issues
|
|
this.chartGithubIssues = {
|
|
chart : {
|
|
fontFamily: 'inherit',
|
|
foreColor : 'inherit',
|
|
height : '100%',
|
|
type : 'line',
|
|
toolbar : {
|
|
show: false
|
|
},
|
|
zoom : {
|
|
enabled: false
|
|
}
|
|
},
|
|
colors : ['#64748B', '#94A3B8'],
|
|
dataLabels : {
|
|
enabled : true,
|
|
enabledOnSeries: [0],
|
|
background : {
|
|
borderWidth: 0
|
|
}
|
|
},
|
|
grid : {
|
|
borderColor: 'var(--fuse-border)'
|
|
},
|
|
labels : this.data.githubIssues.labels,
|
|
legend : {
|
|
show: false
|
|
},
|
|
plotOptions: {
|
|
bar: {
|
|
columnWidth: '50%'
|
|
}
|
|
},
|
|
series : this.data.githubIssues.series,
|
|
states : {
|
|
hover: {
|
|
filter: {
|
|
type : 'darken',
|
|
value: 0.75
|
|
}
|
|
}
|
|
},
|
|
stroke : {
|
|
width: [3, 0]
|
|
},
|
|
tooltip : {
|
|
followCursor: true,
|
|
theme : 'dark'
|
|
},
|
|
xaxis : {
|
|
axisBorder: {
|
|
show: false
|
|
},
|
|
axisTicks : {
|
|
color: 'var(--fuse-border)'
|
|
},
|
|
labels : {
|
|
style: {
|
|
colors: 'var(--fuse-text-secondary)'
|
|
}
|
|
},
|
|
tooltip : {
|
|
enabled: false
|
|
}
|
|
},
|
|
yaxis : {
|
|
labels: {
|
|
offsetX: -16,
|
|
style : {
|
|
colors: 'var(--fuse-text-secondary)'
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Task distribution
|
|
this.chartTaskDistribution = {
|
|
chart : {
|
|
fontFamily: 'inherit',
|
|
foreColor : 'inherit',
|
|
height : '100%',
|
|
type : 'polarArea',
|
|
toolbar : {
|
|
show: false
|
|
},
|
|
zoom : {
|
|
enabled: false
|
|
}
|
|
},
|
|
labels : this.data.taskDistribution.labels,
|
|
legend : {
|
|
position: 'bottom'
|
|
},
|
|
plotOptions: {
|
|
polarArea: {
|
|
spokes: {
|
|
connectorColors: 'var(--fuse-border)'
|
|
},
|
|
rings : {
|
|
strokeColor: 'var(--fuse-border)'
|
|
}
|
|
}
|
|
},
|
|
series : this.data.taskDistribution.series,
|
|
states : {
|
|
hover: {
|
|
filter: {
|
|
type : 'darken',
|
|
value: 0.75
|
|
}
|
|
}
|
|
},
|
|
stroke : {
|
|
width: 2
|
|
},
|
|
theme : {
|
|
monochrome: {
|
|
enabled : true,
|
|
color : '#93C5FD',
|
|
shadeIntensity: 0.75,
|
|
shadeTo : 'dark'
|
|
}
|
|
},
|
|
tooltip : {
|
|
followCursor: true,
|
|
theme : 'dark'
|
|
},
|
|
yaxis : {
|
|
labels: {
|
|
style: {
|
|
colors: 'var(--fuse-text-secondary)'
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Budget distribution
|
|
this.chartBudgetDistribution = {
|
|
chart : {
|
|
fontFamily: 'inherit',
|
|
foreColor : 'inherit',
|
|
height : '100%',
|
|
type : 'radar',
|
|
sparkline : {
|
|
enabled: true
|
|
}
|
|
},
|
|
colors : ['#818CF8'],
|
|
dataLabels : {
|
|
enabled : true,
|
|
formatter : (val: number): string | number => `${val}%`,
|
|
textAnchor: 'start',
|
|
style : {
|
|
fontSize : '13px',
|
|
fontWeight: 500
|
|
},
|
|
background: {
|
|
borderWidth: 0,
|
|
padding : 4
|
|
},
|
|
offsetY : -15
|
|
},
|
|
markers : {
|
|
strokeColors: '#818CF8',
|
|
strokeWidth : 4
|
|
},
|
|
plotOptions: {
|
|
radar: {
|
|
polygons: {
|
|
strokeColors : 'var(--fuse-border)',
|
|
connectorColors: 'var(--fuse-border)'
|
|
}
|
|
}
|
|
},
|
|
series : this.data.budgetDistribution.series,
|
|
stroke : {
|
|
width: 2
|
|
},
|
|
tooltip : {
|
|
theme: 'dark',
|
|
y : {
|
|
formatter: (val: number): string => `${val}%`
|
|
}
|
|
},
|
|
xaxis : {
|
|
labels : {
|
|
show : true,
|
|
style: {
|
|
fontSize : '12px',
|
|
fontWeight: '500'
|
|
}
|
|
},
|
|
categories: this.data.budgetDistribution.categories
|
|
},
|
|
yaxis : {
|
|
max : (max: number): number => parseInt((max + 10).toFixed(0), 10),
|
|
tickAmount: 7
|
|
}
|
|
};
|
|
|
|
// Weekly expenses
|
|
this.chartWeeklyExpenses = {
|
|
chart : {
|
|
animations: {
|
|
enabled: false
|
|
},
|
|
fontFamily: 'inherit',
|
|
foreColor : 'inherit',
|
|
height : '100%',
|
|
type : 'line',
|
|
sparkline : {
|
|
enabled: true
|
|
}
|
|
},
|
|
colors : ['#22D3EE'],
|
|
series : this.data.weeklyExpenses.series,
|
|
stroke : {
|
|
curve: 'smooth'
|
|
},
|
|
tooltip: {
|
|
theme: 'dark'
|
|
},
|
|
xaxis : {
|
|
type : 'category',
|
|
categories: this.data.weeklyExpenses.labels
|
|
},
|
|
yaxis : {
|
|
labels: {
|
|
formatter: (val): string => `$${val}`
|
|
}
|
|
}
|
|
};
|
|
|
|
// Monthly expenses
|
|
this.chartMonthlyExpenses = {
|
|
chart : {
|
|
animations: {
|
|
enabled: false
|
|
},
|
|
fontFamily: 'inherit',
|
|
foreColor : 'inherit',
|
|
height : '100%',
|
|
type : 'line',
|
|
sparkline : {
|
|
enabled: true
|
|
}
|
|
},
|
|
colors : ['#4ADE80'],
|
|
series : this.data.monthlyExpenses.series,
|
|
stroke : {
|
|
curve: 'smooth'
|
|
},
|
|
tooltip: {
|
|
theme: 'dark'
|
|
},
|
|
xaxis : {
|
|
type : 'category',
|
|
categories: this.data.monthlyExpenses.labels
|
|
},
|
|
yaxis : {
|
|
labels: {
|
|
formatter: (val): string => `$${val}`
|
|
}
|
|
}
|
|
};
|
|
|
|
// Yearly expenses
|
|
this.chartYearlyExpenses = {
|
|
chart : {
|
|
animations: {
|
|
enabled: false
|
|
},
|
|
fontFamily: 'inherit',
|
|
foreColor : 'inherit',
|
|
height : '100%',
|
|
type : 'line',
|
|
sparkline : {
|
|
enabled: true
|
|
}
|
|
},
|
|
colors : ['#FB7185'],
|
|
series : this.data.yearlyExpenses.series,
|
|
stroke : {
|
|
curve: 'smooth'
|
|
},
|
|
tooltip: {
|
|
theme: 'dark'
|
|
},
|
|
xaxis : {
|
|
type : 'category',
|
|
categories: this.data.yearlyExpenses.labels
|
|
},
|
|
yaxis : {
|
|
labels: {
|
|
formatter: (val): string => `$${val}`
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|