fix: replace change layout with safe change

This commit is contained in:
sashaqred 2020-04-15 12:03:52 +03:00 committed by Maksim Karatkevich
parent 448229bd7f
commit 0232d5edd6
11 changed files with 2147 additions and 0 deletions

View file

@ -0,0 +1,197 @@
import { delay, takeWhile } from 'rxjs/operators';
import { AfterViewInit, Component, Input, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { LayoutService } from '../../../../@core/utils';
import { ElectricityChart } from '../../../../@core/data/electricity';
@Component({
selector: 'ngx-electricity-chart',
styleUrls: ['./electricity-chart.component.scss'],
template: `
<div echarts
[options]="option"
class="echart"
(chartInit)="onChartInit($event)">
</div>
`,
})
export class ElectricityChartComponent implements AfterViewInit, OnDestroy {
private alive = true;
@Input() data: ElectricityChart[];
option: any;
echartsIntance: any;
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngAfterViewInit(): void {
this.theme.getJsTheme()
.pipe(
takeWhile(() => this.alive),
delay(1),
)
.subscribe(config => {
const eTheme: any = config.variables.electricity;
this.option = {
grid: {
left: 0,
top: 0,
right: 0,
bottom: 80,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
lineStyle: {
color: eTheme.tooltipLineColor,
width: eTheme.tooltipLineWidth,
},
},
textStyle: {
color: eTheme.tooltipTextColor,
fontSize: 20,
fontWeight: eTheme.tooltipFontWeight,
},
position: 'top',
backgroundColor: eTheme.tooltipBg,
borderColor: eTheme.tooltipBorderColor,
borderWidth: 1,
formatter: '{c0} kWh',
extraCssText: eTheme.tooltipExtraCss,
},
xAxis: {
type: 'category',
boundaryGap: false,
offset: 25,
data: this.data.map(i => i.label),
axisTick: {
show: false,
},
axisLabel: {
color: eTheme.xAxisTextColor,
fontSize: 18,
},
axisLine: {
lineStyle: {
color: eTheme.axisLineColor,
width: '2',
},
},
},
yAxis: {
boundaryGap: [0, '5%'],
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: eTheme.yAxisSplitLine,
width: '1',
},
},
},
series: [
{
type: 'line',
smooth: true,
symbolSize: 20,
itemStyle: {
normal: {
opacity: 0,
},
emphasis: {
color: '#ffffff',
borderColor: eTheme.itemBorderColor,
borderWidth: 2,
opacity: 1,
},
},
lineStyle: {
normal: {
width: eTheme.lineWidth,
type: eTheme.lineStyle,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.lineGradFrom,
}, {
offset: 1,
color: eTheme.lineGradTo,
}]),
shadowColor: eTheme.lineShadow,
shadowBlur: 6,
shadowOffsetY: 12,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.areaGradFrom,
}, {
offset: 1,
color: eTheme.areaGradTo,
}]),
},
},
data: this.data.map(i => i.value),
},
{
type: 'line',
smooth: true,
symbol: 'none',
lineStyle: {
normal: {
width: eTheme.lineWidth,
type: eTheme.lineStyle,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.lineGradFrom,
}, {
offset: 1,
color: eTheme.lineGradTo,
}]),
shadowColor: eTheme.shadowLineDarkBg,
shadowBlur: 14,
opacity: 1,
},
},
data: this.data.map(i => i.value),
},
],
};
});
}
onChartInit(echarts) {
this.echartsIntance = echarts;
}
resizeChart() {
if (this.echartsIntance) {
this.echartsIntance.resize();
}
}
ngOnDestroy() {
this.alive = false;
}
}

View file

@ -0,0 +1,174 @@
import { delay, takeWhile } from 'rxjs/operators';
import { AfterViewInit, Component, Input, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { LayoutService } from '../../../@core/utils';
@Component({
selector: 'ngx-traffic-chart',
template: `
<div echarts
[options]="option"
class="echart"
(chartInit)="onChartInit($event)">
</div>
`,
})
export class TrafficChartComponent implements AfterViewInit, OnDestroy {
private alive = true;
@Input() points: number[];
type = 'month';
types = ['week', 'month', 'year'];
option: any = {};
echartsIntance: any;
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngAfterViewInit() {
this.theme.getJsTheme()
.pipe(
delay(1),
takeWhile(() => this.alive),
)
.subscribe(config => {
const trafficTheme: any = config.variables.traffic;
this.option = Object.assign({}, {
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
},
xAxis: {
type: 'category',
boundaryGap: false,
data: this.points,
},
yAxis: {
boundaryGap: [0, '5%'],
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: trafficTheme.yAxisSplitLine,
width: '1',
},
},
},
tooltip: {
axisPointer: {
type: 'shadow',
},
textStyle: {
color: trafficTheme.tooltipTextColor,
fontWeight: trafficTheme.tooltipFontWeight,
fontSize: 16,
},
position: 'top',
backgroundColor: trafficTheme.tooltipBg,
borderColor: trafficTheme.tooltipBorderColor,
borderWidth: 1,
formatter: '{c0} MB',
extraCssText: trafficTheme.tooltipExtraCss,
},
series: [
{
type: 'line',
symbol: 'circle',
symbolSize: 8,
sampling: 'average',
silent: true,
itemStyle: {
normal: {
color: trafficTheme.shadowLineDarkBg,
},
emphasis: {
color: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
borderWidth: 0,
},
},
lineStyle: {
normal: {
width: 2,
color: trafficTheme.shadowLineDarkBg,
},
},
data: this.points.map(p => p - 15),
},
{
type: 'line',
symbol: 'circle',
symbolSize: 6,
sampling: 'average',
itemStyle: {
normal: {
color: trafficTheme.itemColor,
borderColor: trafficTheme.itemBorderColor,
borderWidth: 2,
},
emphasis: {
color: 'white',
borderColor: trafficTheme.itemEmphasisBorderColor,
borderWidth: 2,
},
},
lineStyle: {
normal: {
width: 2,
color: trafficTheme.lineBg,
shadowColor: trafficTheme.lineBg,
shadowBlur: trafficTheme.lineShadowBlur,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: trafficTheme.gradFrom,
}, {
offset: 1,
color: trafficTheme.gradTo,
}]),
opacity: 1,
},
},
data: this.points,
},
],
});
});
}
onChartInit(echarts) {
this.echartsIntance = echarts;
}
resizeChart() {
if (this.echartsIntance) {
this.echartsIntance.resize();
}
}
ngOnDestroy() {
this.alive = false;
}
}

View file

@ -0,0 +1,307 @@
import { AfterViewInit, Component, Input, OnChanges, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { delay, takeWhile } from 'rxjs/operators';
import { OrdersChart } from '../../../../@core/data/orders-chart';
import { LayoutService } from '../../../../@core/utils/layout.service';
@Component({
selector: 'ngx-orders-chart',
styleUrls: ['./charts-common.component.scss'],
template: `
<div echarts
[options]="option"
class="echart"
(chartInit)="onChartInit($event)">
</div>
`,
})
export class OrdersChartComponent implements AfterViewInit, OnDestroy, OnChanges {
@Input()
ordersChartData: OrdersChart;
private alive = true;
echartsIntance: any;
option: any;
ngOnChanges(): void {
if (this.option) {
this.updateOrdersChartOptions(this.ordersChartData);
}
}
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngAfterViewInit(): void {
this.theme.getJsTheme()
.pipe(
takeWhile(() => this.alive),
delay(1),
)
.subscribe(config => {
const eTheme: any = config.variables.orders;
this.setOptions(eTheme);
this.updateOrdersChartOptions(this.ordersChartData);
});
}
setOptions(eTheme) {
this.option = {
grid: {
left: 40,
top: 20,
right: 0,
bottom: 40,
},
tooltip: {
trigger: 'item',
axisPointer: {
type: 'line',
lineStyle: {
color: eTheme.tooltipLineColor,
width: eTheme.tooltipLineWidth,
},
},
textStyle: {
color: eTheme.tooltipTextColor,
fontSize: eTheme.tooltipFontSize,
fontWeight: eTheme.tooltipFontWeight,
},
position: 'top',
backgroundColor: eTheme.tooltipBg,
borderColor: eTheme.tooltipBorderColor,
borderWidth: 1,
formatter: (params) => {
return Math.round(parseInt(params.value, 10));
},
extraCssText: eTheme.tooltipExtraCss,
},
xAxis: {
type: 'category',
boundaryGap: false,
offset: 5,
data: [],
axisTick: {
show: false,
},
axisLabel: {
color: eTheme.axisTextColor,
fontSize: eTheme.axisFontSize,
},
axisLine: {
lineStyle: {
color: eTheme.axisLineColor,
width: '2',
},
},
},
yAxis: {
type: 'value',
boundaryGap: false,
axisLine: {
lineStyle: {
color: eTheme.axisLineColor,
width: '1',
},
},
axisLabel: {
color: eTheme.axisTextColor,
fontSize: eTheme.axisFontSize,
},
axisTick: {
show: false,
},
splitLine: {
lineStyle: {
color: eTheme.yAxisSplitLine,
width: '1',
},
},
},
series: [
this.getFirstLine(eTheme),
this.getSecondLine(eTheme),
this.getThirdLine(eTheme),
],
};
}
getFirstLine(eTheme) {
return {
type: 'line',
smooth: true,
symbolSize: 20,
itemStyle: {
normal: {
opacity: 0,
},
emphasis: {
opacity: 0,
},
},
lineStyle: {
normal: {
width: 0,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.firstAreaGradFrom,
}, {
offset: 1,
color: eTheme.firstAreaGradTo,
}]),
opacity: 1,
},
},
data: [],
};
}
getSecondLine(eTheme) {
return {
type: 'line',
smooth: true,
symbolSize: 20,
itemStyle: {
normal: {
opacity: 0,
},
emphasis: {
color: '#ffffff',
borderColor: eTheme.itemBorderColor,
borderWidth: 2,
opacity: 1,
},
},
lineStyle: {
normal: {
width: eTheme.lineWidth,
type: eTheme.lineStyle,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.secondLineGradFrom,
}, {
offset: 1,
color: eTheme.secondLineGradTo,
}]),
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.secondAreaGradFrom,
}, {
offset: 1,
color: eTheme.secondAreaGradTo,
}]),
},
},
data: [],
};
}
getThirdLine(eTheme) {
return {
type: 'line',
smooth: true,
symbolSize: 20,
itemStyle: {
normal: {
opacity: 0,
},
emphasis: {
color: '#ffffff',
borderColor: eTheme.itemBorderColor,
borderWidth: 2,
opacity: 1,
},
},
lineStyle: {
normal: {
width: eTheme.lineWidth,
type: eTheme.lineStyle,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.thirdLineGradFrom,
}, {
offset: 1,
color: eTheme.thirdLineGradTo,
}]),
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.thirdAreaGradFrom,
}, {
offset: 1,
color: eTheme.thirdAreaGradTo,
}]),
},
},
data: [],
};
}
updateOrdersChartOptions(ordersChartData: OrdersChart) {
const options = this.option;
const series = this.getNewSeries(options.series, ordersChartData.linesData);
const xAxis = this.getNewXAxis(options.xAxis, ordersChartData.chartLabel);
this.option = {
...options,
xAxis,
series,
};
}
getNewSeries(series, linesData: number[][]) {
return series.map((line, index) => {
return {
...line,
data: linesData[index],
};
});
}
getNewXAxis(xAxis, chartLabel: string[]) {
return {
...xAxis,
data: chartLabel,
};
}
onChartInit(echarts) {
this.echartsIntance = echarts;
}
resizeChart() {
if (this.echartsIntance) {
// Fix recalculation chart size
// TODO: investigate more deeply
setTimeout(() => {
this.echartsIntance.resize();
}, 0);
}
}
ngOnDestroy() {
this.alive = false;
}
}

View file

@ -0,0 +1,200 @@
import { AfterViewInit, Component, Input, OnChanges, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { takeWhile } from 'rxjs/operators';
import { ProfitChart } from '../../../../@core/data/profit-chart';
import { LayoutService } from '../../../../@core/utils/layout.service';
@Component({
selector: 'ngx-profit-chart',
styleUrls: ['./charts-common.component.scss'],
template: `
<div echarts [options]="options" class="echart" (chartInit)="onChartInit($event)"></div>
`,
})
export class ProfitChartComponent implements AfterViewInit, OnDestroy, OnChanges {
@Input()
profitChartData: ProfitChart;
private alive = true;
echartsIntance: any;
options: any = {};
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngOnChanges(): void {
if (this.echartsIntance) {
this.updateProfitChartOptions(this.profitChartData);
}
}
ngAfterViewInit() {
this.theme.getJsTheme()
.pipe(takeWhile(() => this.alive))
.subscribe(config => {
const eTheme: any = config.variables.profit;
this.setOptions(eTheme);
});
}
setOptions(eTheme) {
this.options = {
backgroundColor: eTheme.bg,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
shadowStyle: {
color: 'rgba(0, 0, 0, 0.3)',
},
},
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: [
{
type: 'category',
data: this.profitChartData.chartLabel,
axisTick: {
alignWithLabel: true,
},
axisLine: {
lineStyle: {
color: eTheme.axisLineColor,
},
},
axisLabel: {
color: eTheme.axisTextColor,
fontSize: eTheme.axisFontSize,
},
},
],
yAxis: [
{
type: 'value',
axisLine: {
lineStyle: {
color: eTheme.axisLineColor,
},
},
splitLine: {
lineStyle: {
color: eTheme.splitLineColor,
},
},
axisLabel: {
color: eTheme.axisTextColor,
fontSize: eTheme.axisFontSize,
},
},
],
series: [
{
name: 'Canceled',
type: 'bar',
barGap: 0,
barWidth: '20%',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.firstLineGradFrom,
}, {
offset: 1,
color: eTheme.firstLineGradTo,
}]),
},
},
data: this.profitChartData.data[0],
},
{
name: 'Payment',
type: 'bar',
barWidth: '20%',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.secondLineGradFrom,
}, {
offset: 1,
color: eTheme.secondLineGradTo,
}]),
},
},
data: this.profitChartData.data[1],
},
{
name: 'All orders',
type: 'bar',
barWidth: '20%',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.thirdLineGradFrom,
}, {
offset: 1,
color: eTheme.thirdLineGradTo,
}]),
},
},
data: this.profitChartData.data[2],
},
],
};
}
updateProfitChartOptions(profitChartData: ProfitChart) {
const options = this.options;
const series = this.getNewSeries(options.series, profitChartData.data);
this.echartsIntance.setOption({
series: series,
xAxis: {
data: this.profitChartData.chartLabel,
},
});
}
getNewSeries(series, data: number[][]) {
return series.map((line, index) => {
return {
...line,
data: data[index],
};
});
}
onChartInit(echarts) {
this.echartsIntance = echarts;
}
resizeChart() {
if (this.echartsIntance) {
// Fix recalculation chart size
// TODO: investigate more deeply
setTimeout(() => {
this.echartsIntance.resize();
}, 0);
}
}
ngOnDestroy(): void {
this.alive = false;
}
}

View file

@ -0,0 +1,181 @@
import { AfterViewInit, Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { takeWhile } from 'rxjs/operators';
import { LayoutService } from '../../../../@core/utils/layout.service';
@Component({
selector: 'ngx-country-orders-chart',
styleUrls: ['./country-orders-chart.component.scss'],
template: `
<div class="header">
<span class="caption">Selected Country/Region</span>
<h2 class="h4">{{ countryName }}</h2>
</div>
<div echarts
[options]="option"
class="echart"
(chartInit)="onChartInit($event)">
</div>
`,
})
export class CountryOrdersChartComponent implements AfterViewInit, OnDestroy, OnChanges {
@Input() countryName: string;
@Input() data: number[];
@Input() maxValue: number;
@Input() labels: string[];
private alive = true;
option: any = {};
echartsInstance;
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.data && !changes.data.isFirstChange()) {
this.echartsInstance.setOption({
series: [
{
data: this.data.map(v => this.maxValue),
},
{
data: this.data,
},
{
data: this.data,
},
],
});
}
}
ngAfterViewInit() {
this.theme.getJsTheme()
.pipe(takeWhile(() => this.alive))
.subscribe(config => {
const countriesTheme: any = config.variables.countryOrders;
this.option = Object.assign({}, {
grid: {
left: '3%',
right: '3%',
bottom: '3%',
top: '3%',
containLabel: true,
},
xAxis: {
axisLabel: {
color: countriesTheme.chartAxisTextColor,
fontSize: countriesTheme.chartAxisFontSize,
},
axisLine: {
lineStyle: {
color: countriesTheme.chartAxisLineColor,
width: '2',
},
},
axisTick: {
show: false,
},
splitLine: {
lineStyle: {
color: countriesTheme.chartAxisSplitLine,
width: '1',
},
},
},
yAxis: {
data: this.labels,
axisLabel: {
color: countriesTheme.chartAxisTextColor,
fontSize: countriesTheme.chartAxisFontSize,
},
axisLine: {
lineStyle: {
color: countriesTheme.chartAxisLineColor,
width: '2',
},
},
axisTick: {
show: false,
},
},
series: [
{ // For shadow
type: 'bar',
data: this.data.map(v => this.maxValue),
cursor: 'default',
itemStyle: {
normal: {
color: countriesTheme.chartInnerLineColor,
},
opacity: 1,
},
barWidth: '40%',
barGap: '-100%',
barCategoryGap: '30%',
animation: false,
z: 1,
},
{ // For bottom line
type: 'bar',
data: this.data,
cursor: 'default',
itemStyle: {
normal: {
color: countriesTheme.chartLineBottomShadowColor,
},
opacity: 1,
},
barWidth: '40%',
barGap: '-100%',
barCategoryGap: '30%',
z: 2,
},
{
type: 'bar',
barWidth: '35%',
data: this.data,
cursor: 'default',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [{
offset: 0,
color: countriesTheme.chartGradientFrom,
}, {
offset: 1,
color: countriesTheme.chartGradientTo,
}]),
},
},
z: 3,
},
],
});
});
}
onChartInit(ec) {
this.echartsInstance = ec;
}
resizeChart() {
if (this.echartsInstance) {
this.echartsInstance.resize();
}
}
ngOnDestroy() {
this.alive = false;
}
}

View file

@ -0,0 +1,164 @@
import { delay, takeWhile } from 'rxjs/operators';
import { AfterViewInit, Component, Input, OnChanges, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { LayoutService } from '../../../../@core/utils/layout.service';
@Component({
selector: 'ngx-earning-live-update-chart',
styleUrls: ['earning-card-front.component.scss'],
template: `
<div echarts
class="echart"
[options]="option"
(chartInit)="onChartInit($event)"></div>
`,
})
export class EarningLiveUpdateChartComponent implements AfterViewInit, OnDestroy, OnChanges {
private alive = true;
@Input() liveUpdateChartData: { value: [string, number] }[];
option: any;
echartsInstance;
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngOnChanges(): void {
if (this.option) {
this.updateChartOptions(this.liveUpdateChartData);
}
}
ngAfterViewInit() {
this.theme.getJsTheme()
.pipe(
delay(1),
takeWhile(() => this.alive),
)
.subscribe(config => {
const earningLineTheme: any = config.variables.earningLine;
this.setChartOption(earningLineTheme);
});
}
setChartOption(earningLineTheme) {
this.option = {
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
},
xAxis: {
type: 'time',
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
},
yAxis: {
boundaryGap: [0, '5%'],
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
},
tooltip: {
axisPointer: {
type: 'shadow',
},
textStyle: {
color: earningLineTheme.tooltipTextColor,
fontWeight: earningLineTheme.tooltipFontWeight,
fontSize: earningLineTheme.tooltipFontSize,
},
position: 'top',
backgroundColor: earningLineTheme.tooltipBg,
borderColor: earningLineTheme.tooltipBorderColor,
borderWidth: earningLineTheme.tooltipBorderWidth,
formatter: params => `$ ${Math.round(parseInt(params.value[1], 10))}`,
extraCssText: earningLineTheme.tooltipExtraCss,
},
series: [
{
type: 'line',
symbol: 'circle',
sampling: 'average',
itemStyle: {
normal: {
opacity: 0,
},
emphasis: {
opacity: 0,
},
},
lineStyle: {
normal: {
width: 0,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: earningLineTheme.gradFrom,
}, {
offset: 1,
color: earningLineTheme.gradTo,
}]),
opacity: 1,
},
},
data: this.liveUpdateChartData,
},
],
animation: true,
};
}
updateChartOptions(chartData: { value: [string, number] }[]) {
this.echartsInstance.setOption({
series: [{
data: chartData,
}],
});
}
onChartInit(ec) {
this.echartsInstance = ec;
}
resizeChart() {
if (this.echartsInstance) {
this.echartsInstance.resize();
}
}
ngOnDestroy() {
this.alive = false;
}
}

View file

@ -0,0 +1,172 @@
import { delay, takeWhile } from 'rxjs/operators';
import { AfterViewInit, Component, Input, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { LayoutService } from '../../../../@core/utils';
@Component({
selector: 'ngx-stats-ares-chart',
styleUrls: ['stats-card-back.component.scss'],
template: `
<div echarts [options]="option"
class="echart"
(chartInit)="onChartInit($event)">
</div>
`,
})
export class StatsAreaChartComponent implements AfterViewInit, OnDestroy {
private alive = true;
@Input() points: number[];
echartsIntance: any;
option: any = {};
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngAfterViewInit() {
this.theme.getJsTheme()
.pipe(
delay(1),
takeWhile(() => this.alive),
)
.subscribe(config => {
const trafficTheme: any = config.variables.traffic;
this.option = Object.assign({}, {
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
},
xAxis: {
type: 'category',
boundaryGap: false,
data: this.points,
},
yAxis: {
boundaryGap: [0, '5%'],
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: trafficTheme.yAxisSplitLine,
width: '1',
},
},
},
tooltip: {
axisPointer: {
type: 'shadow',
},
textStyle: {
color: trafficTheme.tooltipTextColor,
fontWeight: trafficTheme.tooltipFontWeight,
fontSize: 16,
},
position: 'top',
backgroundColor: trafficTheme.tooltipBg,
borderColor: trafficTheme.tooltipBorderColor,
borderWidth: 1,
formatter: '$ {c0}',
extraCssText: trafficTheme.tooltipExtraCss,
},
series: [
{
type: 'line',
symbol: 'circle',
symbolSize: 8,
sampling: 'average',
silent: true,
itemStyle: {
normal: {
color: trafficTheme.shadowLineDarkBg,
},
emphasis: {
color: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
borderWidth: 0,
},
},
lineStyle: {
normal: {
width: 2,
color: trafficTheme.shadowLineDarkBg,
},
},
data: this.points.map(p => p - 15),
},
{
type: 'line',
symbol: 'circle',
symbolSize: 6,
sampling: 'average',
itemStyle: {
normal: {
color: trafficTheme.itemColor,
borderColor: trafficTheme.itemBorderColor,
borderWidth: 2,
},
emphasis: {
color: 'white',
borderColor: trafficTheme.itemEmphasisBorderColor,
borderWidth: 2,
},
},
lineStyle: {
normal: {
width: 2,
color: trafficTheme.lineBg,
shadowColor: trafficTheme.lineBg,
shadowBlur: trafficTheme.lineShadowBlur,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: trafficTheme.gradFrom,
}, {
offset: 1,
color: trafficTheme.gradTo,
}]),
opacity: 1,
},
},
data: this.points,
},
],
});
});
}
onChartInit(echarts) {
this.echartsIntance = echarts;
}
resizeChart() {
if (this.echartsIntance) {
this.echartsIntance.resize();
}
}
ngOnDestroy() {
this.alive = false;
}
}

View file

@ -0,0 +1,153 @@
import { AfterViewInit, Component, Input, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { takeWhile } from 'rxjs/operators';
import { LayoutService } from '../../../../@core/utils/layout.service';
@Component({
selector: 'ngx-stats-bar-animation-chart',
template: `
<div echarts
[options]="options"
class="echart"
(chartInit)="onChartInit($event)">
</div>
`,
})
export class StatsBarAnimationChartComponent implements AfterViewInit, OnDestroy {
private alive = true;
@Input() linesData: { firstLine: number[]; secondLine: number[] } = {
firstLine: [],
secondLine: [],
};
echartsIntance: any;
options: any = {};
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngAfterViewInit() {
this.theme.getJsTheme()
.pipe(takeWhile(() => this.alive))
.subscribe(config => {
const profitBarAnimationEchart: any = config.variables.profitBarAnimationEchart;
this.setChartOption(profitBarAnimationEchart);
});
}
setChartOption(chartVariables) {
this.options = {
color: [
chartVariables.firstAnimationBarColor,
chartVariables.secondAnimationBarColor,
],
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
},
legend: {
data: ['transactions', 'orders'],
borderWidth: 0,
borderRadius: 0,
itemWidth: 15,
itemHeight: 15,
textStyle: {
color: chartVariables.textColor,
},
},
tooltip: {
axisPointer: {
type: 'shadow',
},
textStyle: {
color: chartVariables.tooltipTextColor,
fontWeight: chartVariables.tooltipFontWeight,
fontSize: chartVariables.tooltipFontSize,
},
position: 'top',
backgroundColor: chartVariables.tooltipBg,
borderColor: chartVariables.tooltipBorderColor,
borderWidth: chartVariables.tooltipBorderWidth,
formatter: params => `$ ${Math.round(parseInt(params.value, 10))}`,
extraCssText: chartVariables.tooltipExtraCss,
},
xAxis: [
{
data: this.linesData.firstLine.map((_, index) => index),
silent: false,
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
},
],
yAxis: [
{
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: chartVariables.splitLineStyleColor,
opacity: chartVariables.splitLineStyleOpacity,
width: chartVariables.splitLineStyleWidth,
},
},
},
],
series: [
{
name: 'transactions',
type: 'bar',
data: this.linesData.firstLine,
animationDelay: idx => idx * 10,
},
{
name: 'orders',
type: 'bar',
data: this.linesData.secondLine,
animationDelay: idx => idx * 10 + 100,
},
],
animationEasing: 'elasticOut',
animationDelayUpdate: idx => idx * 5,
};
}
onChartInit(echarts) {
this.echartsIntance = echarts;
}
resizeChart() {
if (this.echartsIntance) {
this.echartsIntance.resize();
}
}
ngOnDestroy(): void {
this.alive = false;
}
}

View file

@ -0,0 +1,150 @@
import { AfterViewInit, Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { takeWhile } from 'rxjs/operators';
import { LayoutService } from '../../../../@core/utils/layout.service';
declare const echarts: any;
@Component({
selector: 'ngx-traffic-bar-chart',
template: `
<div echarts
[options]="option"
class="echart"
(chartInit)="onChartInit($event)">
</div>
`,
})
export class TrafficBarChartComponent implements AfterViewInit, OnDestroy, OnChanges {
@Input() data: number[];
@Input() labels: string[];
@Input() formatter: string;
private alive = true;
option: any = {};
echartsInstance: any;
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
onChartInit(ec) {
this.echartsInstance = ec;
}
resizeChart() {
if (this.echartsInstance) {
this.echartsInstance.resize();
}
}
ngOnChanges(changes: SimpleChanges): void {
if (!changes.data.isFirstChange() && !changes.labels.isFirstChange()) {
this.echartsInstance.setOption({
series: [{
data: this.data,
}],
xAxis: {
data: this.labels,
},
tooltip: {
formatter: this.formatter,
},
});
}
}
ngAfterViewInit() {
this.theme.getJsTheme()
.pipe(takeWhile(() => this.alive))
.subscribe(config => {
const trafficTheme: any = config.variables.trafficBarEchart;
this.option = Object.assign({}, {
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
containLabel: true,
},
xAxis: {
type : 'category',
data : this.labels,
axisLabel: {
color: trafficTheme.axisTextColor,
fontSize: trafficTheme.axisFontSize,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
yAxis: {
show: false,
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
boundaryGap: [0, '5%'],
},
tooltip: {
axisPointer: {
type: 'shadow',
},
textStyle: {
color: trafficTheme.tooltipTextColor,
fontWeight: trafficTheme.tooltipFontWeight,
fontSize: 16,
},
position: 'top',
backgroundColor: trafficTheme.tooltipBg,
borderColor: trafficTheme.tooltipBorderColor,
borderWidth: 1,
formatter: this.formatter,
extraCssText: trafficTheme.tooltipExtraCss,
},
series: [
{
type: 'bar',
barWidth: '40%',
data: this.data,
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: trafficTheme.gradientFrom,
}, {
offset: 1,
color: trafficTheme.gradientTo,
}]),
opacity: 1,
shadowColor: trafficTheme.gradientFrom,
shadowBlur: trafficTheme.shadowBlur,
},
},
},
],
});
});
}
ngOnDestroy() {
this.alive = false;
}
}

View file

@ -0,0 +1,234 @@
import { delay, takeWhile } from 'rxjs/operators';
import { AfterViewInit, Component, Input, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { LayoutService } from '../../../../@core/utils';
import { OutlineData } from '../../../../@core/data/visitors-analytics';
@Component({
selector: 'ngx-visitors-analytics-chart',
styleUrls: ['./visitors-analytics-chart.component.scss'],
template: `
<div echarts
[options]="option"
class="echart"
(chartInit)="onChartInit($event)">
</div>
`,
})
export class ECommerceVisitorsAnalyticsChartComponent implements AfterViewInit, OnDestroy {
private alive = true;
@Input() chartData: {
innerLine: number[];
outerLine: OutlineData[];
};
option: any;
themeSubscription: any;
echartsIntance: any;
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngAfterViewInit(): void {
this.theme.getJsTheme()
.pipe(
delay(1),
takeWhile(() => this.alive),
)
.subscribe(config => {
const eTheme: any = config.variables.visitors;
this.setOptions(eTheme);
});
}
setOptions(eTheme) {
this.option = {
grid: {
left: 40,
top: 20,
right: 0,
bottom: 60,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
lineStyle: {
color: eTheme.tooltipLineColor,
width: eTheme.tooltipLineWidth,
},
},
textStyle: {
color: eTheme.tooltipTextColor,
fontSize: 20,
fontWeight: eTheme.tooltipFontWeight,
},
position: 'top',
backgroundColor: eTheme.tooltipBg,
borderColor: eTheme.tooltipBorderColor,
borderWidth: 1,
formatter: (params) => {
return Math.round(parseInt(params[0].value, 10));
},
extraCssText: eTheme.tooltipExtraCss,
},
xAxis: {
type: 'category',
boundaryGap: false,
offset: 25,
data: this.chartData.outerLine.map(i => i.label),
axisTick: {
show: false,
},
axisLabel: {
color: eTheme.axisTextColor,
fontSize: eTheme.axisFontSize,
},
axisLine: {
lineStyle: {
color: eTheme.axisLineColor,
width: '2',
},
},
},
yAxis: {
type: 'value',
boundaryGap: false,
axisLine: {
lineStyle: {
color: eTheme.axisLineColor,
width: '1',
},
},
axisLabel: {
color: eTheme.axisTextColor,
fontSize: eTheme.axisFontSize,
},
axisTick: {
show: false,
},
splitLine: {
lineStyle: {
color: eTheme.yAxisSplitLine,
width: '1',
},
},
},
series: [
this.getInnerLine(eTheme),
this.getOuterLine(eTheme),
],
};
}
getOuterLine(eTheme) {
return {
type: 'line',
smooth: true,
symbolSize: 20,
itemStyle: {
normal: {
opacity: 0,
},
emphasis: {
color: '#ffffff',
borderColor: eTheme.itemBorderColor,
borderWidth: 2,
opacity: 1,
},
},
lineStyle: {
normal: {
width: eTheme.lineWidth,
type: eTheme.lineStyle,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.lineGradFrom,
}, {
offset: 1,
color: eTheme.lineGradTo,
}]),
shadowColor: eTheme.lineShadow,
shadowBlur: 6,
shadowOffsetY: 12,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.areaGradFrom,
}, {
offset: 1,
color: eTheme.areaGradTo,
}]),
},
},
data: this.chartData.outerLine.map(i => i.value),
};
}
getInnerLine(eTheme) {
return {
type: 'line',
smooth: true,
symbolSize: 20,
tooltip: {
show: false,
extraCssText: '',
},
itemStyle: {
normal: {
opacity: 0,
},
emphasis: {
opacity: 0,
},
},
lineStyle: {
normal: {
width: eTheme.innerLineWidth,
type: eTheme.innerLineStyle,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1),
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: eTheme.innerAreaGradFrom,
}, {
offset: 1,
color: eTheme.innerAreaGradTo,
}]),
opacity: 1,
},
},
data: this.chartData.innerLine,
};
}
onChartInit(echarts) {
this.echartsIntance = echarts;
}
resizeChart() {
if (this.echartsIntance) {
this.echartsIntance.resize();
}
}
ngOnDestroy() {
this.alive = false;
}
}

View file

@ -0,0 +1,215 @@
import { AfterViewInit, Component, Input, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { delay, takeWhile } from 'rxjs/operators';
import { LayoutService } from '../../../../@core/utils/layout.service';
@Component({
selector: 'ngx-visitors-statistics',
styleUrls: ['./visitors-statistics.component.scss'],
templateUrl: './visitors-statistics.component.html',
})
export class ECommerceVisitorsStatisticsComponent implements AfterViewInit, OnDestroy {
private alive = true;
@Input() value: number;
option: any = {};
chartLegend: { iconColor: string; title: string }[];
echartsIntance: any;
constructor(private theme: NbThemeService,
private layoutService: LayoutService) {
this.layoutService.onSafeChangeLayoutSize()
.pipe(
takeWhile(() => this.alive),
)
.subscribe(() => this.resizeChart());
}
ngAfterViewInit() {
this.theme.getJsTheme()
.pipe(
takeWhile(() => this.alive),
delay(1),
)
.subscribe(config => {
const variables: any = config.variables;
const visitorsPieLegend: any = config.variables.visitorsPieLegend;
this.setOptions(variables);
this.setLegendItems(visitorsPieLegend);
});
}
setLegendItems(visitorsPieLegend) {
this.chartLegend = [
{
iconColor: visitorsPieLegend.firstSection,
title: 'New Visitors',
},
{
iconColor: visitorsPieLegend.secondSection,
title: 'Return Visitors',
},
];
}
setOptions(variables) {
const visitorsPie: any = variables.visitorsPie;
this.option = {
tooltip: {
trigger: 'item',
formatter: '',
},
series: [
{
name: ' ',
clockWise: true,
hoverAnimation: false,
type: 'pie',
center: ['50%', '50%'],
radius: visitorsPie.firstPieRadius,
data: [
{
value: this.value,
name: ' ',
label: {
normal: {
position: 'center',
formatter: '',
textStyle: {
fontSize: '22',
fontFamily: variables.fontSecondary,
fontWeight: '600',
color: variables.fgHeading,
},
},
},
tooltip: {
show: false,
},
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: visitorsPie.firstPieGradientLeft,
},
{
offset: 1,
color: visitorsPie.firstPieGradientRight,
},
]),
shadowColor: visitorsPie.firstPieShadowColor,
shadowBlur: 0,
shadowOffsetX: 0,
shadowOffsetY: 3,
},
},
hoverAnimation: false,
},
{
value: 100 - this.value,
name: ' ',
tooltip: {
show: false,
},
label: {
normal: {
position: 'inner',
},
},
itemStyle: {
normal: {
color: variables.layoutBg,
},
},
},
],
},
{
name: ' ',
clockWise: true,
hoverAnimation: false,
type: 'pie',
center: ['50%', '50%'],
radius: visitorsPie.secondPieRadius,
data: [
{
value: this.value,
name: ' ',
label: {
normal: {
position: 'center',
formatter: '',
textStyle: {
fontSize: '22',
fontFamily: variables.fontSecondary,
fontWeight: '600',
color: variables.fgHeading,
},
},
},
tooltip: {
show: false,
},
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1),
},
},
hoverAnimation: false,
},
{
value: 100 - this.value,
name: ' ',
tooltip: {
show: false,
},
label: {
normal: {
position: 'inner',
},
},
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: visitorsPie.secondPieGradientLeft,
},
{
offset: 1,
color: visitorsPie.secondPieGradientRight,
},
]),
shadowColor: visitorsPie.secondPieShadowColor,
shadowBlur: 0,
shadowOffsetX: visitorsPie.shadowOffsetX,
shadowOffsetY: visitorsPie.shadowOffsetY,
},
},
},
],
},
],
};
}
onChartInit(echarts) {
this.echartsIntance = echarts;
}
resizeChart() {
if (this.echartsIntance) {
this.echartsIntance.resize();
}
}
ngOnDestroy() {
this.alive = false;
}
}