import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { AdminService } from '@ghostfolio/client/services/admin.service'; import { CacheService } from '@ghostfolio/client/services/cache.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { DEFAULT_DATE_FORMAT } from '@ghostfolio/common/config'; import { AdminData, User } from '@ghostfolio/common/interfaces'; import { differenceInSeconds, formatDistanceToNowStrict, isValid, parseISO } from 'date-fns'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'mb-5' }, selector: 'gf-admin-page', styleUrls: ['./admin-page.scss'], templateUrl: './admin-page.html' }) export class AdminPageComponent implements OnDestroy, OnInit { public dataGatheringInProgress: boolean; public dataGatheringProgress: number; public defaultDateFormat = DEFAULT_DATE_FORMAT; public exchangeRates: { label1: string; label2: string; value: number }[]; public lastDataGathering: string; public transactionCount: number; public userCount: number; public user: User; public users: AdminData['users']; private unsubscribeSubject = new Subject(); /** * @constructor */ public constructor( private adminService: AdminService, private cacheService: CacheService, private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, private userService: UserService ) {} /** * Initializes the controller */ public ngOnInit() { this.fetchAdminData(); this.userService.stateChanged .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((state) => { if (state?.user) { this.user = state.user; } }); } public onFlushCache() { this.cacheService .flush() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { setTimeout(() => { window.location.reload(); }, 300); }); } public onGatherMax() { const confirmation = confirm( 'This action may take some time. Do you want to proceed?' ); if (confirmation === true) { this.adminService .gatherMax() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { setTimeout(() => { window.location.reload(); }, 300); }); } } public onGatherProfileData() { this.adminService .gatherProfileData() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => {}); } public formatDistanceToNow(aDateString: string) { if (aDateString) { const distanceString = formatDistanceToNowStrict(parseISO(aDateString), { addSuffix: true }); return Math.abs(differenceInSeconds(parseISO(aDateString), new Date())) < 60 ? 'just now' : distanceString; } return ''; } public onDeleteUser(aId: string) { const confirmation = confirm('Do you really want to delete this user?'); if (confirmation) { this.dataService .deleteUser(aId) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe({ next: () => { this.fetchAdminData(); } }); } } public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); } private fetchAdminData() { this.dataService .fetchAdminData() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe( ({ dataGatheringProgress, exchangeRates, lastDataGathering, transactionCount, userCount, users }) => { this.dataGatheringProgress = dataGatheringProgress; this.exchangeRates = exchangeRates; this.users = users; if (isValid(parseISO(lastDataGathering?.toString()))) { this.lastDataGathering = formatDistanceToNowStrict( new Date(lastDataGathering), { addSuffix: true } ); } else if (lastDataGathering === 'IN_PROGRESS') { this.dataGatheringInProgress = true; } else { this.lastDataGathering = 'Starting soon...'; } this.transactionCount = transactionCount; this.userCount = userCount; this.changeDetectorRef.markForCheck(); } ); } }