Feature/render tags in dialogs (#864)

* Render tags

* Update changelog
pull/866/head^2
Thomas Kaul 2 years ago committed by GitHub
parent c61a415fb2
commit b7bbc029ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- Added the tags to the create or edit transaction dialog
- Added the tags to the position detail dialog
### Changed
- Changed the date to UTC in the data gathering service

@ -202,7 +202,8 @@ export class OrderService {
}
},
// eslint-disable-next-line @typescript-eslint/naming-convention
SymbolProfile: true
SymbolProfile: true,
tags: true
},
orderBy: { date: 'asc' }
})

@ -1,5 +1,6 @@
import { EnhancedSymbolProfile } from '@ghostfolio/api/services/interfaces/symbol-profile.interface';
import { OrderWithAccount } from '@ghostfolio/common/types';
import { Tag } from '@prisma/client';
export interface PortfolioPositionDetail {
averagePrice: number;
@ -16,6 +17,7 @@ export interface PortfolioPositionDetail {
orders: OrderWithAccount[];
quantity: number;
SymbolProfile: EnhancedSymbolProfile;
tags: Tag[];
transactionCount: number;
value: number;
}

@ -46,7 +46,12 @@ import type {
} from '@ghostfolio/common/types';
import { Inject, Injectable } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { AssetClass, DataSource, Type as TypeOfOrder } from '@prisma/client';
import {
AssetClass,
DataSource,
Tag,
Type as TypeOfOrder
} from '@prisma/client';
import Big from 'big.js';
import {
differenceInDays,
@ -62,7 +67,7 @@ import {
subDays,
subYears
} from 'date-fns';
import { isEmpty, sortBy } from 'lodash';
import { isEmpty, sortBy, uniqBy } from 'lodash';
import {
HistoricalDataContainer,
@ -476,8 +481,11 @@ export class PortfolioService {
);
});
let tags: Tag[] = [];
if (orders.length <= 0) {
return {
tags,
averagePrice: undefined,
firstBuyDate: undefined,
grossPerformance: undefined,
@ -504,6 +512,8 @@ export class PortfolioService {
const portfolioOrders: PortfolioOrder[] = orders
.filter((order) => {
tags = tags.concat(order.tags);
return order.type === 'BUY' || order.type === 'SELL';
})
.map((order) => ({
@ -518,6 +528,8 @@ export class PortfolioService {
unitPrice: new Big(order.unitPrice)
}));
tags = uniqBy(tags, 'id');
const portfolioCalculator = new PortfolioCalculator({
currency: positionCurrency,
currentRateService: this.currentRateService,
@ -626,6 +638,7 @@ export class PortfolioService {
netPerformance,
orders,
SymbolProfile,
tags,
transactionCount,
averagePrice: averagePrice.toNumber(),
grossPerformancePercent:
@ -682,6 +695,7 @@ export class PortfolioService {
minPrice,
orders,
SymbolProfile,
tags,
averagePrice: 0,
firstBuyDate: undefined,
grossPerformance: undefined,

@ -11,7 +11,7 @@ import { DataService } from '@ghostfolio/client/services/data.service';
import { DATE_FORMAT, downloadAsFile } from '@ghostfolio/common/helper';
import { OrderWithAccount } from '@ghostfolio/common/types';
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
import { SymbolProfile } from '@prisma/client';
import { SymbolProfile, Tag } from '@prisma/client';
import { format, isSameMonth, isToday, parseISO } from 'date-fns';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@ -48,6 +48,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
[name: string]: { name: string; value: number };
};
public SymbolProfile: SymbolProfile;
public tags: Tag[];
public transactionCount: number;
public value: number;
@ -83,6 +84,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
orders,
quantity,
SymbolProfile,
tags,
transactionCount,
value
}) => {
@ -115,6 +117,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
this.quantity = quantity;
this.sectors = {};
this.SymbolProfile = SymbolProfile;
this.tags = tags;
this.transactionCount = transactionCount;
this.value = value;

@ -194,21 +194,31 @@
</div>
</div>
<gf-activities-table
*ngIf="orders?.length > 0"
[activities]="orders"
[baseCurrency]="data.baseCurrency"
[deviceType]="data.deviceType"
[hasPermissionToCreateActivity]="false"
[hasPermissionToExportActivities]="!hasImpersonationId"
[hasPermissionToFilter]="false"
[hasPermissionToImportActivities]="false"
[hasPermissionToOpenDetails]="false"
[locale]="data.locale"
[showActions]="false"
[showSymbolColumn]="false"
(export)="onExport()"
></gf-activities-table>
<div class="mb-3">
<div class="h4 mb-0" i18n>Activities</div>
<gf-activities-table
*ngIf="orders?.length > 0"
[activities]="orders"
[baseCurrency]="data.baseCurrency"
[deviceType]="data.deviceType"
[hasPermissionToCreateActivity]="false"
[hasPermissionToExportActivities]="!hasImpersonationId"
[hasPermissionToFilter]="false"
[hasPermissionToImportActivities]="false"
[hasPermissionToOpenDetails]="false"
[locale]="data.locale"
[showActions]="false"
[showSymbolColumn]="false"
(export)="onExport()"
></gf-activities-table>
</div>
<div *ngIf="tags?.length > 0">
<div class="h4" i18n>Tags</div>
<mat-chip-list>
<mat-chip *ngFor="let tag of tags">{{ tag.name }}</mat-chip>
</mat-chip-list>
</div>
</div>
<gf-dialog-footer

@ -1,6 +1,7 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatChipsModule } from '@angular/material/chips';
import { MatDialogModule } from '@angular/material/dialog';
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
@ -24,6 +25,7 @@ import { PositionDetailDialog } from './position-detail-dialog.component';
GfPortfolioProportionChartModule,
GfValueModule,
MatButtonModule,
MatChipsModule,
MatDialogModule,
NgxSkeletonLoaderModule
],

@ -86,6 +86,7 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
},
Validators.required
],
tags: [this.data.activity?.tags],
type: [undefined, Validators.required], // Set after value changes subscription
unitPrice: [this.data.activity?.unitPrice, Validators.required]
});

@ -134,6 +134,18 @@
>
</mat-form-field>
</div>
<div
[ngClass]="{ 'd-none': activityForm.controls['tags']?.value?.length <= 0 }"
>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Tags</mat-label>
<mat-chip-list>
<mat-chip *ngFor="let tag of activityForm.controls['tags']?.value">
{{ tag.name }}
</mat-chip>
</mat-chip-list>
</mat-form-field>
</div>
</div>
<div class="d-flex" mat-dialog-actions>
<gf-value

@ -3,6 +3,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatChipsModule } from '@angular/material/chips';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
@ -24,6 +25,7 @@ import { CreateOrUpdateTransactionDialog } from './create-or-update-transaction-
FormsModule,
MatAutocompleteModule,
MatButtonModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,
MatFormFieldModule,

@ -1,8 +1,9 @@
import { Account, Order, Platform, SymbolProfile } from '@prisma/client';
import { Account, Order, Platform, SymbolProfile, Tag } from '@prisma/client';
type AccountWithPlatform = Account & { Platform?: Platform };
export type OrderWithAccount = Order & {
Account?: AccountWithPlatform;
SymbolProfile?: SymbolProfile;
tags?: Tag[];
};

Loading…
Cancel
Save