mirror of https://github.com/ghostfolio/ghostfolio
committed by
GitHub
11 changed files with 193 additions and 17 deletions
@ -0,0 +1,10 @@ |
|||||
|
<ngx-skeleton-loader |
||||
|
*ngIf="isLoading" |
||||
|
animation="pulse" |
||||
|
class="h-100" |
||||
|
[theme]="{ |
||||
|
width: '100%' |
||||
|
}" |
||||
|
></ngx-skeleton-loader> |
||||
|
|
||||
|
<div class="align-items-center d-flex h-100 w-100" id="svgMap"></div> |
@ -0,0 +1,24 @@ |
|||||
|
:host { |
||||
|
display: block; |
||||
|
height: 100%; |
||||
|
|
||||
|
::ng-deep { |
||||
|
.loader { |
||||
|
height: 100% !important; |
||||
|
} |
||||
|
|
||||
|
.svgMap-map-wrapper { |
||||
|
background: transparent; |
||||
|
|
||||
|
.svgMap-map-controls-wrapper { |
||||
|
display: none; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
:host-context(.is-dark-theme) { |
||||
|
.svgMap-tooltip { |
||||
|
background: var(--dark-background); |
||||
|
} |
||||
|
} |
@ -0,0 +1,79 @@ |
|||||
|
import { |
||||
|
ChangeDetectionStrategy, |
||||
|
ChangeDetectorRef, |
||||
|
Component, |
||||
|
Input, |
||||
|
OnChanges, |
||||
|
OnDestroy, |
||||
|
OnInit |
||||
|
} from '@angular/core'; |
||||
|
import { primaryColorHex } from '@ghostfolio/common/config'; |
||||
|
import { getCssVariable, getTextColor } from '@ghostfolio/common/helper'; |
||||
|
import { Currency } from '@prisma/client'; |
||||
|
import svgMap from 'svgmap'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'gf-world-map-chart', |
||||
|
changeDetection: ChangeDetectionStrategy.OnPush, |
||||
|
templateUrl: './world-map-chart.component.html', |
||||
|
styleUrls: ['./world-map-chart.component.scss'] |
||||
|
}) |
||||
|
export class WorldMapChartComponent implements OnChanges, OnDestroy, OnInit { |
||||
|
@Input() baseCurrency: Currency; |
||||
|
@Input() countries: { [code: string]: { name: string; value: number } }; |
||||
|
|
||||
|
public isLoading = true; |
||||
|
public svgMapElement; |
||||
|
|
||||
|
public constructor(private changeDetectorRef: ChangeDetectorRef) {} |
||||
|
|
||||
|
public ngOnInit() {} |
||||
|
|
||||
|
public ngOnChanges() { |
||||
|
if (this.countries) { |
||||
|
this.destroySvgMap(); |
||||
|
|
||||
|
this.initialize(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ngOnDestroy() { |
||||
|
this.destroySvgMap(); |
||||
|
} |
||||
|
|
||||
|
private initialize() { |
||||
|
this.svgMapElement = new svgMap({ |
||||
|
colorMax: primaryColorHex, |
||||
|
colorMin: '#d3f4f3', |
||||
|
colorNoData: `rgba(${getTextColor()}, ${getCssVariable( |
||||
|
'--palette-foreground-divider-alpha' |
||||
|
)})`,
|
||||
|
data: { |
||||
|
applyData: 'value', |
||||
|
data: { |
||||
|
value: { |
||||
|
format: `{0} ${this.baseCurrency}` |
||||
|
} |
||||
|
}, |
||||
|
values: this.countries |
||||
|
}, |
||||
|
hideFlag: true, |
||||
|
minZoom: 1.06, |
||||
|
maxZoom: 1.06, |
||||
|
targetElementID: 'svgMap' |
||||
|
}); |
||||
|
|
||||
|
setTimeout(() => { |
||||
|
this.isLoading = false; |
||||
|
|
||||
|
this.changeDetectorRef.markForCheck(); |
||||
|
}, 500); |
||||
|
} |
||||
|
|
||||
|
private destroySvgMap() { |
||||
|
this.svgMapElement?.mapWrapper?.remove(); |
||||
|
this.svgMapElement?.tooltip?.remove(); |
||||
|
|
||||
|
this.svgMapElement = null; |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
import { CommonModule } from '@angular/common'; |
||||
|
import { NgModule } from '@angular/core'; |
||||
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; |
||||
|
|
||||
|
import { WorldMapChartComponent } from './world-map-chart.component'; |
||||
|
|
||||
|
@NgModule({ |
||||
|
declarations: [WorldMapChartComponent], |
||||
|
exports: [WorldMapChartComponent], |
||||
|
imports: [CommonModule, NgxSkeletonLoaderModule], |
||||
|
providers: [] |
||||
|
}) |
||||
|
export class GfWorldMapChartModule {} |
Loading…
Reference in new issue