Release/1.143.0 (#871)

* Release 1.143.0
  * Improve filtering by tags
pull/873/head 1.143.0
Thomas Kaul 3 years ago committed by GitHub
parent b4bc72c6f9
commit b6cd007ad4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,6 +5,12 @@ 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/), 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). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 1.143.0 - 26.04.2022
### Changed
- Improved the filtering by tags
## 1.142.0 - 25.04.2022 ## 1.142.0 - 25.04.2022
### Added ### Added

@ -17,7 +17,7 @@ import { Market, ToggleOption } from '@ghostfolio/common/types';
import { Account, AssetClass, DataSource } from '@prisma/client'; import { Account, AssetClass, DataSource } from '@prisma/client';
import { DeviceDetectorService } from 'ngx-device-detector'; import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject, Subscription } from 'rxjs'; import { Subject, Subscription } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
@Component({ @Component({
host: { class: 'page' }, host: { class: 'page' },
@ -39,7 +39,9 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
[code: string]: { name: string; value: number }; [code: string]: { name: string; value: number };
}; };
public deviceType: string; public deviceType: string;
public filters$ = new Subject<string[]>();
public hasImpersonationId: boolean; public hasImpersonationId: boolean;
public isLoading = false;
public markets: { public markets: {
[key in Market]: { name: string; value: number }; [key in Market]: { name: string; value: number };
}; };
@ -122,6 +124,26 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
this.hasImpersonationId = !!aId; this.hasImpersonationId = !!aId;
}); });
this.filters$
.pipe(
distinctUntilChanged(),
switchMap((tags) => {
this.isLoading = true;
return this.dataService.fetchPortfolioDetails({ tags });
}),
takeUntil(this.unsubscribeSubject)
)
.subscribe((portfolioDetails) => {
this.portfolioDetails = portfolioDetails;
this.initializeAnalysisData(this.period);
this.isLoading = false;
this.changeDetectorRef.markForCheck();
});
this.userService.stateChanged this.userService.stateChanged
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe((state) => { .subscribe((state) => {
@ -341,25 +363,6 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
} }
} }
public onUpdateFilters(tags: string[] = []) {
this.update(tags);
}
public update(tags?: string[]) {
this.initialize();
this.dataService
.fetchPortfolioDetails({ tags })
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((portfolioDetails) => {
this.portfolioDetails = portfolioDetails;
this.initializeAnalysisData(this.period);
this.changeDetectorRef.markForCheck();
});
}
public ngOnDestroy() { public ngOnDestroy() {
this.unsubscribeSubject.next(); this.unsubscribeSubject.next();
this.unsubscribeSubject.complete(); this.unsubscribeSubject.complete();

@ -4,9 +4,10 @@
<h3 class="d-flex justify-content-center mb-3" i18n>Allocations</h3> <h3 class="d-flex justify-content-center mb-3" i18n>Allocations</h3>
<gf-activities-filter <gf-activities-filter
[allFilters]="tags" [allFilters]="tags"
[isLoading]="isLoading"
[ngClass]="{ 'd-none': tags.length <= 0 }" [ngClass]="{ 'd-none': tags.length <= 0 }"
[placeholder]="placeholder" [placeholder]="placeholder"
(valueChanged)="onUpdateFilters($event)" (valueChanged)="filters$.next($event)"
></gf-activities-filter> ></gf-activities-filter>
</div> </div>
</div> </div>

@ -30,4 +30,9 @@
{{ filter | gfSymbol }} {{ filter | gfSymbol }}
</mat-option> </mat-option>
</mat-autocomplete> </mat-autocomplete>
<mat-spinner
matSuffix
[diameter]="20"
[ngClass]="{ 'd-none': !isLoading }"
></mat-spinner>
</mat-form-field> </mat-form-field>

@ -7,6 +7,10 @@
.mat-form-field-infix { .mat-form-field-infix {
border-top: 0 solid transparent !important; border-top: 0 solid transparent !important;
} }
.mat-spinner circle {
stroke: rgba(var(--dark-dividers));
}
} }
.mat-chip { .mat-chip {
@ -19,4 +23,8 @@
.mat-form-field { .mat-form-field {
color: rgba(var(--light-primary-text)); color: rgba(var(--light-primary-text));
} }
.mat-spinner circle {
stroke: rgba(var(--light-dividers));
}
} }

@ -8,6 +8,7 @@ import {
OnChanges, OnChanges,
OnDestroy, OnDestroy,
Output, Output,
SimpleChanges,
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
@ -27,6 +28,7 @@ import { takeUntil } from 'rxjs/operators';
}) })
export class ActivitiesFilterComponent implements OnChanges, OnDestroy { export class ActivitiesFilterComponent implements OnChanges, OnDestroy {
@Input() allFilters: string[]; @Input() allFilters: string[];
@Input() isLoading: boolean;
@Input() placeholder: string; @Input() placeholder: string;
@Output() valueChanged = new EventEmitter<string[]>(); @Output() valueChanged = new EventEmitter<string[]>();
@ -59,8 +61,8 @@ export class ActivitiesFilterComponent implements OnChanges, OnDestroy {
}); });
} }
public ngOnChanges() { public ngOnChanges(changes: SimpleChanges) {
if (this.allFilters) { if (changes.allFilters?.currentValue) {
this.updateFilter(); this.updateFilter();
} }
} }
@ -103,6 +105,7 @@ export class ActivitiesFilterComponent implements OnChanges, OnDestroy {
private updateFilter() { private updateFilter() {
this.filters$.next(this.allFilters); this.filters$.next(this.allFilters);
this.valueChanged.emit(this.searchKeywords); // Emit an array with a new reference
this.valueChanged.emit([...this.searchKeywords]);
} }
} }

@ -4,6 +4,7 @@ import { ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatChipsModule } from '@angular/material/chips'; import { MatChipsModule } from '@angular/material/chips';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
import { ActivitiesFilterComponent } from './activities-filter.component'; import { ActivitiesFilterComponent } from './activities-filter.component';
@ -17,6 +18,7 @@ import { ActivitiesFilterComponent } from './activities-filter.component';
MatAutocompleteModule, MatAutocompleteModule,
MatChipsModule, MatChipsModule,
MatInputModule, MatInputModule,
MatProgressSpinnerModule,
ReactiveFormsModule ReactiveFormsModule
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA]

@ -192,13 +192,8 @@ export class PortfolioProportionChartComponent
// Reuse color // Reuse color
item.color = this.colorMap[symbol]; item.color = this.colorMap[symbol];
} else { } else {
const color = item.color =
this.getColorPalette()[index % this.getColorPalette().length]; this.getColorPalette()[index % this.getColorPalette().length];
// Store color for reuse
this.colorMap[symbol] = color;
item.color = color;
} }
}); });
@ -265,6 +260,7 @@ export class PortfolioProportionChartComponent
this.chart = new Chart(this.chartCanvas.nativeElement, { this.chart = new Chart(this.chartCanvas.nativeElement, {
data, data,
options: <unknown>{ options: <unknown>{
animation: false,
cutout: '70%', cutout: '70%',
layout: { layout: {
padding: this.showLabels === true ? 100 : 0 padding: this.showLabels === true ? 100 : 0

@ -1,6 +1,6 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "1.142.0", "version": "1.143.0",
"homepage": "https://ghostfol.io", "homepage": "https://ghostfol.io",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"scripts": { "scripts": {

Loading…
Cancel
Save