Feature/improve asset profile management (#1485)

* Improve asset profile management (Add note, fix filter)

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

@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
- Supported a note for asset profiles
### Fixed
- Fixed the filter by asset sub class for the asset profiles in the admin control
## 1.215.0 - 2022-11-27
### Changed
@ -538,7 +548,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Support a note for activities
- Supported a note for activities
### Todo

@ -116,6 +116,7 @@ export class AdminService {
},
assetClass: true,
assetSubClass: true,
comment: true,
countries: true,
dataSource: true,
Order: {
@ -150,6 +151,7 @@ export class AdminService {
activitiesCount: symbolProfile._count.Order,
assetClass: symbolProfile.assetClass,
assetSubClass: symbolProfile.assetSubClass,
comment: symbolProfile.comment,
dataSource: symbolProfile.dataSource,
date: symbolProfile.Order?.[0]?.date,
symbol: symbolProfile.symbol
@ -190,11 +192,13 @@ export class AdminService {
}
public async patchAssetProfileData({
comment,
dataSource,
symbol,
symbolMapping
}: Prisma.SymbolProfileUpdateInput & UniqueAsset) {
await this.symbolProfileService.updateSymbolProfile({
comment,
dataSource,
symbol,
symbolMapping

@ -1,6 +1,10 @@
import { IsObject, IsOptional } from 'class-validator';
import { IsObject, IsOptional, IsString } from 'class-validator';
export class UpdateAssetProfileDto {
@IsString()
@IsOptional()
comment?: string;
@IsObject()
@IsOptional()
symbolMapping?: {

@ -104,12 +104,13 @@ export class SymbolProfileService {
}
public updateSymbolProfile({
comment,
dataSource,
symbol,
symbolMapping
}: Prisma.SymbolProfileUpdateInput & UniqueAsset) {
return this.prismaService.symbolProfile.update({
data: { symbolMapping },
data: { comment, symbolMapping },
where: { dataSource_symbol: { dataSource, symbol } }
});
}

@ -16,6 +16,7 @@ import { UserService } from '@ghostfolio/client/services/user/user.service';
import { DATE_FORMAT, getDateFormatString } from '@ghostfolio/common/helper';
import { Filter, UniqueAsset, User } from '@ghostfolio/common/interfaces';
import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface';
import { translate } from '@ghostfolio/ui/i18n';
import { AssetSubClass, DataSource } from '@prisma/client';
import { format, parseISO } from 'date-fns';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -44,10 +45,10 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
AssetSubClass.PRECIOUS_METAL,
AssetSubClass.PRIVATE_EQUITY,
AssetSubClass.STOCK
].map((id) => {
].map((assetSubClass) => {
return {
id,
label: id,
id: assetSubClass,
label: translate(assetSubClass),
type: 'ASSET_SUB_CLASS'
};
});
@ -67,6 +68,7 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
'marketDataItemCount',
'sectorsCount',
'countriesCount',
'comment',
'actions'
];
public filters$ = new Subject<Filter[]>();

@ -100,6 +100,22 @@
</td>
</ng-container>
<ng-container matColumnDef="comment">
<th
*matHeaderCellDef
class="px-1"
mat-header-cell
mat-sort-header
></th>
<td *matCellDef="let element" class="px-1" mat-cell>
<ion-icon
*ngIf="element.comment"
class="d-block"
name="document-text-outline"
></ion-icon>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th *matHeaderCellDef class="px-1 text-center" mat-header-cell>
<button

@ -30,6 +30,7 @@ import { AssetProfileDialogParams } from './interfaces/interfaces';
export class AssetProfileDialog implements OnDestroy, OnInit {
public assetProfile: EnhancedSymbolProfile;
public assetProfileForm = this.formBuilder.group({
comment: '',
symbolMapping: ''
});
public countries: {
@ -86,6 +87,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
}
this.assetProfileForm.setValue({
comment: this.assetProfile?.comment,
symbolMapping: JSON.stringify(this.assetProfile?.symbolMapping)
});
@ -129,7 +131,8 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
} catch {}
const assetProfileData: UpdateAssetProfileDto = {
symbolMapping
symbolMapping,
comment: this.assetProfileForm.controls['comment'].value ?? null
};
this.adminService

@ -148,6 +148,18 @@
></textarea>
</mat-form-field>
</div>
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Note</mat-label>
<textarea
cdkAutosizeMinRows="2"
cdkTextareaAutosize
formControlName="comment"
matInput
(keyup.enter)="$event.stopPropagation()"
></textarea>
</mat-form-field>
</div>
</div>
<div class="d-flex justify-content-end" mat-dialog-actions>

@ -127,13 +127,14 @@ export class AdminService {
}
public patchAssetProfile({
comment,
dataSource,
symbol,
symbolMapping
}: UniqueAsset & UpdateAssetProfileDto) {
return this.http.patch<EnhancedSymbolProfile>(
`/api/v1/admin/profile-data/${dataSource}/${symbol}`,
{ symbolMapping }
{ comment, symbolMapping }
);
}

@ -360,6 +360,7 @@ export class DataService {
const {
ACCOUNT: filtersByAccount,
ASSET_CLASS: filtersByAssetClass,
ASSET_SUB_CLASS: filtersByAssetSubClass,
TAG: filtersByTag
} = groupBy(filters, (filter) => {
return filter.type;
@ -387,6 +388,17 @@ export class DataService {
);
}
if (filtersByAssetSubClass) {
params = params.append(
'assetSubClasses',
filtersByAssetSubClass
.map(({ id }) => {
return id;
})
.join(',')
);
}
if (filtersByTag) {
params = params.append(
'tags',

@ -8,6 +8,7 @@ export interface EnhancedSymbolProfile {
activitiesCount: number;
assetClass: AssetClass;
assetSubClass: AssetSubClass;
comment?: string;
countries: Country[];
createdAt: Date;
currency: string | null;

@ -299,6 +299,35 @@
<td *matFooterCellDef class="px-1" mat-footer-cell></td>
</ng-container>
<ng-container matColumnDef="comment">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell px-1"
mat-header-cell
mat-sort-header
></th>
<td
*matCellDef="let element"
class="d-none d-lg-table-cell px-1"
mat-cell
>
<button
*ngIf="element.comment"
class="mx-1 no-min-width px-2"
mat-button
title="Note"
(click)="onOpenComment(element.comment); $event.stopPropagation()"
>
<ion-icon name="document-text-outline"></ion-icon>
</button>
</td>
<td
*matFooterCellDef
class="d-none d-lg-table-cell px-1"
mat-footer-cell
></td>
</ng-container>
<ng-container matColumnDef="actions">
<th *matHeaderCellDef class="px-1 text-center" mat-header-cell>
<button
@ -345,15 +374,6 @@
</mat-menu>
</th>
<td *matCellDef="let element" class="px-1 text-center" mat-cell>
<button
*ngIf="element.comment && !this.showActions"
class="mx-1 no-min-width px-2"
mat-button
title="Note"
(click)="onOpenComment(element.comment)"
>
<ion-icon name="document-text-outline"></ion-icon>
</button>
<button
*ngIf="this.showActions"
class="mx-1 no-min-width px-2"

@ -94,6 +94,7 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
'currency',
'valueInBaseCurrency',
'account',
'comment',
'actions'
];

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "SymbolProfile" ADD COLUMN "comment" TEXT;

@ -112,6 +112,7 @@ model Settings {
model SymbolProfile {
assetClass AssetClass?
assetSubClass AssetSubClass?
comment String?
countries Json?
createdAt DateTime @default(now())
currency String

Loading…
Cancel
Save