Browse Source

Refactoring

pull/830/head
Thomas 3 years ago
parent
commit
40b76bdfcf
  1. 11
      apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts
  2. 75
      apps/client/src/app/pages/portfolio/transactions/transactions-page.component.ts
  3. 59
      apps/client/src/app/services/ics/ics.service.ts
  4. 26
      libs/common/src/lib/helper.ts

11
apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts

@ -211,15 +211,14 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
)
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((data) => {
downloadAsFile(
data,
`ghostfolio-export-${this.SymbolProfile?.symbol}-${format(
downloadAsFile({
content: data,
fileName: `ghostfolio-export-${this.SymbolProfile?.symbol}-${format(
parseISO(data.meta.date),
'yyyyMMddHHmm'
)}.json`,
'text/plain',
'json'
);
format: 'json'
});
});
}

75
apps/client/src/app/pages/portfolio/transactions/transactions-page.component.ts

@ -7,15 +7,16 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interf
import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
import { PositionDetailDialog } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.component';
import { DataService } from '@ghostfolio/client/services/data.service';
import { IcsService } from '@ghostfolio/client/services/ics/ics.service';
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
import { ImportTransactionsService } from '@ghostfolio/client/services/import-transactions.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { downloadAsFile } from '@ghostfolio/common/helper';
import { Export, User } from '@ghostfolio/common/interfaces';
import { User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { DataSource, Order as OrderModel, Type } from '@prisma/client';
import { DataSource, Order as OrderModel } from '@prisma/client';
import { format, parseISO } from 'date-fns';
import { capitalize, isArray } from 'lodash';
import { isArray } from 'lodash';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject, Subscription } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@ -50,6 +51,7 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
private dataService: DataService,
private deviceService: DeviceDetectorService,
private dialog: MatDialog,
private icsService: IcsService,
private impersonationStorageService: ImpersonationStorageService,
private importTransactionsService: ImportTransactionsService,
private route: ActivatedRoute,
@ -156,15 +158,14 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
delete activity.id;
}
downloadAsFile(
data,
`ghostfolio-export-${format(
downloadAsFile({
content: data,
fileName: `ghostfolio-export-${format(
parseISO(data.meta.date),
'yyyyMMddHHmm'
)}.json`,
'text/plain',
'json'
);
format: 'json'
});
});
}
@ -173,15 +174,16 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
.fetchExport(activityIds)
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((data) => {
downloadAsFile(
this.getIcsContent(data.activities),
`ghostfolio-drafts-${format(
downloadAsFile({
content: this.icsService.transformActivitiesToIcsContent(
data.activities
),
fileName: `ghostfolio-drafts-${format(
parseISO(data.meta.date),
'yyyyMMddHHmm'
)}.ics`,
'text/plain',
'string'
);
format: 'string'
});
});
}
@ -315,49 +317,6 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
this.unsubscribeSubject.complete();
}
private getIcsContent(aActivities: Export['activities']) {
const header = [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'PRODID:-//Ghostfolio//NONSGML v1.0//EN'
];
const events = aActivities.map((activity) => {
return this.getEvent({
date: parseISO(activity.date),
id: activity.id,
symbol: activity.symbol,
type: activity.type
});
});
const footer = ['END:VCALENDAR'];
return [...header, ...events, ...footer].join('\n');
}
private getEvent({
date,
id,
symbol,
type
}: {
date: Date;
id: string;
symbol: string;
type: Type;
}) {
const today = format(new Date(), 'yyyyMMdd');
return [
'BEGIN:VEVENT',
`UID:${id}`,
`DTSTAMP:${today}T000000`,
`DTSTART;VALUE=DATE:${format(date, 'yyyyMMdd')}`,
`DTEND;VALUE=DATE:${format(date, 'yyyyMMdd')}`,
`SUMMARY:${capitalize(type)} ${symbol}`,
'END:VEVENT'
].join('\n');
}
private handleImportError({
activities,
error

59
apps/client/src/app/services/ics/ics.service.ts

@ -0,0 +1,59 @@
import { Injectable } from '@angular/core';
import { capitalize } from '@ghostfolio/common/helper';
import { Export } from '@ghostfolio/common/interfaces';
import { Type } from '@prisma/client';
import { format, parseISO } from 'date-fns';
@Injectable({
providedIn: 'root'
})
export class IcsService {
private readonly ICS_DATE_FORMAT = 'yyyyMMdd';
public constructor() {}
public transformActivitiesToIcsContent(
aActivities: Export['activities']
): string {
const header = [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'PRODID:-//Ghostfolio//NONSGML v1.0//EN'
];
const events = aActivities.map((activity) => {
return this.getEvent({
date: parseISO(activity.date),
id: activity.id,
symbol: activity.symbol,
type: activity.type
});
});
const footer = ['END:VCALENDAR'];
return [...header, ...events, ...footer].join('\n');
}
private getEvent({
date,
id,
symbol,
type
}: {
date: Date;
id: string;
symbol: string;
type: Type;
}) {
const today = format(new Date(), this.ICS_DATE_FORMAT);
return [
'BEGIN:VEVENT',
`UID:${id}`,
`DTSTAMP:${today}T000000`,
`DTSTART;VALUE=DATE:${format(date, this.ICS_DATE_FORMAT)}`,
`DTEND;VALUE=DATE:${format(date, this.ICS_DATE_FORMAT)}`,
`SUMMARY:${capitalize(type)} ${symbol}`,
'END:VEVENT'
].join('\n');
}
}

26
libs/common/src/lib/helper.ts

@ -12,24 +12,28 @@ export function decodeDataSource(encodedDataSource: string) {
return Buffer.from(encodedDataSource, 'hex').toString();
}
export function downloadAsFile(
aContent: unknown,
aFileName: string,
aContentType: string,
aType: 'json' | 'string'
) {
export function downloadAsFile({
content,
contentType = 'text/plain',
fileName,
format
}: {
content: unknown;
contentType?: string;
fileName: string;
format: 'json' | 'string';
}) {
const a = document.createElement('a');
let content = aContent;
if (aType === 'json') {
content = JSON.stringify(aContent, undefined, ' ');
if (format === 'json') {
content = JSON.stringify(content, undefined, ' ');
}
const file = new Blob([<string>content], {
type: aContentType
type: contentType
});
a.href = URL.createObjectURL(file);
a.download = aFileName;
a.download = fileName;
a.click();
}

Loading…
Cancel
Save