Browse Source

Resolve review comments 2

pull/4031/head
Amandee Ellawala 10 months ago
committed by Thomas Kaul
parent
commit
e81fc63d48
  1. 14
      apps/client/src/app/services/user/user.service.ts
  2. 2
      libs/common/src/lib/interfaces/user-settings.interface.ts
  3. 68
      libs/ui/src/lib/assistant/assistant.component.ts
  4. 6
      libs/ui/src/lib/assistant/assistant.html

14
apps/client/src/app/services/user/user.service.ts

@ -65,13 +65,6 @@ export class UserService extends ObservableStore<UserStoreState> {
}); });
} }
if (user?.settings['filters.tags']) {
filters.push({
id: user.settings['filters.tags'][0],
type: 'TAG'
});
}
if (user?.settings['filters.dataSource']) { if (user?.settings['filters.dataSource']) {
filters.push({ filters.push({
id: user.settings['filters.dataSource'], id: user.settings['filters.dataSource'],
@ -86,6 +79,13 @@ export class UserService extends ObservableStore<UserStoreState> {
}); });
} }
if (user?.settings['filters.tags']) {
filters.push({
id: user.settings['filters.tags'][0],
type: 'TAG'
});
}
return filters; return filters;
} }

2
libs/common/src/lib/interfaces/user-settings.interface.ts

@ -14,9 +14,9 @@ export interface UserSettings {
dateRange?: DateRange; dateRange?: DateRange;
emergencyFund?: number; emergencyFund?: number;
'filters.accounts'?: string[]; 'filters.accounts'?: string[];
'filters.tags'?: string[];
'filters.dataSource'?: string; 'filters.dataSource'?: string;
'filters.symbol'?: string; 'filters.symbol'?: string;
'filters.tags'?: string[];
holdingsViewMode?: HoldingsViewMode; holdingsViewMode?: HoldingsViewMode;
isExperimentalFeatures?: boolean; isExperimentalFeatures?: boolean;
isRestrictedView?: boolean; isRestrictedView?: boolean;

68
libs/ui/src/lib/assistant/assistant.component.ts

@ -2,7 +2,13 @@ import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
import { AdminService } from '@ghostfolio/client/services/admin.service'; import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
import { Filter, PortfolioPosition, User } from '@ghostfolio/common/interfaces'; import { getAssetProfileIdentifier } from '@ghostfolio/common/helper';
import {
AssetProfileIdentifier,
Filter,
PortfolioPosition,
User
} from '@ghostfolio/common/interfaces';
import { DateRange } from '@ghostfolio/common/types'; import { DateRange } from '@ghostfolio/common/types';
import { translate } from '@ghostfolio/ui/i18n'; import { translate } from '@ghostfolio/ui/i18n';
@ -36,8 +42,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatMenuTrigger } from '@angular/material/menu'; import { MatMenuTrigger } from '@angular/material/menu';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { Account, AssetClass } from '@prisma/client'; import { Account, AssetClass, DataSource } from '@prisma/client';
import { sortBy } from 'lodash';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { EMPTY, Observable, Subject, lastValueFrom } from 'rxjs'; import { EMPTY, Observable, Subject, lastValueFrom } from 'rxjs';
import { import {
@ -135,9 +140,10 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
public filterForm = this.formBuilder.group({ public filterForm = this.formBuilder.group({
account: new FormControl<string>(undefined), account: new FormControl<string>(undefined),
assetClass: new FormControl<string>(undefined), assetClass: new FormControl<string>(undefined),
holdings: new FormControl<PortfolioPosition>(undefined), holding: new FormControl<PortfolioPosition>(undefined),
tag: new FormControl<string>(undefined) tag: new FormControl<string>(undefined)
}); });
public holdings: PortfolioPosition[] = [];
public isLoading = false; public isLoading = false;
public isOpen = false; public isOpen = false;
public placeholder = $localize`Find holding...`; public placeholder = $localize`Find holding...`;
@ -147,7 +153,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
holdings: [] holdings: []
}; };
public tags: Filter[] = []; public tags: Filter[] = [];
public holdings: PortfolioPosition[] = [];
private filterTypes: Filter['type'][] = [ private filterTypes: Filter['type'][] = [
'ACCOUNT', 'ACCOUNT',
@ -167,7 +172,7 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
) {} ) {}
public ngOnInit() { public ngOnInit() {
this.loadPortfolioHoldings(); this.initializeFilterForm();
this.assetClasses = Object.keys(AssetClass).map((assetClass) => { this.assetClasses = Object.keys(AssetClass).map((assetClass) => {
return { return {
@ -276,7 +281,7 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
this.filterForm.enable({ emitEvent: false }); this.filterForm.enable({ emitEvent: false });
} }
this.loadPortfolioHoldings(); this.initializeFilterForm();
this.tags = this.tags =
this.user?.tags this.user?.tags
@ -336,11 +341,11 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
type: 'ASSET_CLASS' type: 'ASSET_CLASS'
}, },
{ {
id: this.filterForm.get('holdings').value?.dataSource, id: this.filterForm.get('holding').value?.dataSource,
type: 'DATA_SOURCE' type: 'DATA_SOURCE'
}, },
{ {
id: this.filterForm.get('holdings').value?.symbol, id: this.filterForm.get('holding').value?.symbol,
type: 'SYMBOL' type: 'SYMBOL'
}, },
{ {
@ -486,40 +491,53 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
); );
} }
public holdingComparisonFunction(option, value): boolean { public holdingComparisonFunction(
option: AssetProfileIdentifier,
value: AssetProfileIdentifier
): boolean {
if (value === null) {
return false;
}
return ( return (
option.dataSource === value?.dataSource && option.symbol === value?.symbol getAssetProfileIdentifier(option) === getAssetProfileIdentifier(value)
); );
} }
private loadPortfolioHoldings() { private initializeFilterForm() {
this.dataService this.dataService
.fetchPortfolioHoldings({ .fetchPortfolioHoldings({
range: 'max' range: 'max'
}) })
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ holdings }) => { .subscribe(({ holdings }) => {
this.holdings = sortBy(holdings, ({ name }) => { this.holdings = holdings
return name.toLowerCase(); .filter(({ assetSubClass }) => {
}); return assetSubClass !== 'CASH';
this.setFormValues(); })
.sort((a, b) => {
return a.name?.localeCompare(b.name);
});
this.setFilterFormValues();
}); });
} }
private setFormValues() { private setFilterFormValues() {
const dataSource = this.user?.settings?.['filters.dataSource'] ?? null; const dataSource = this.user?.settings?.[
const symbol = this.user?.settings?.['filters.symbol'] ?? null; 'filters.dataSource'
const selectedHolding = this.holdings.find( ] as DataSource;
(holding) => const symbol = this.user?.settings?.['filters.symbol'];
(holding.dataSource ?? null) === dataSource && const selectedHolding = this.holdings.find((holding) => {
(holding.symbol ?? null) === symbol return (
); getAssetProfileIdentifier(holding) ===
getAssetProfileIdentifier({ dataSource, symbol })
);
});
this.filterForm.setValue( this.filterForm.setValue(
{ {
account: this.user?.settings?.['filters.accounts']?.[0] ?? null, account: this.user?.settings?.['filters.accounts']?.[0] ?? null,
assetClass: this.user?.settings?.['filters.assetClasses']?.[0] ?? null, assetClass: this.user?.settings?.['filters.assetClasses']?.[0] ?? null,
holdings: selectedHolding ?? null, holding: selectedHolding ?? null,
tag: this.user?.settings?.['filters.tags']?.[0] ?? null tag: this.user?.settings?.['filters.tags']?.[0] ?? null
}, },
{ {

6
libs/ui/src/lib/assistant/assistant.html

@ -126,16 +126,16 @@
<mat-form-field appearance="outline" class="w-100 without-hint"> <mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Holding</mat-label> <mat-label i18n>Holding</mat-label>
<mat-select <mat-select
formControlName="holdings" formControlName="holding"
[compareWith]="holdingComparisonFunction" [compareWith]="holdingComparisonFunction"
> >
<mat-select-trigger>{{ <mat-select-trigger>{{
filterForm.get('holdings')?.value?.name filterForm.get('holding')?.value?.name
}}</mat-select-trigger> }}</mat-select-trigger>
<mat-option [value]="null" /> <mat-option [value]="null" />
@for (holding of holdings; track holding.name) { @for (holding of holdings; track holding.name) {
<mat-option class="line-height-1" [value]="holding"> <mat-option class="line-height-1" [value]="holding">
<span <span class="text-truncate"
><b>{{ holding.name }}</b></span ><b>{{ holding.name }}</b></span
> >
<br /> <br />

Loading…
Cancel
Save