Browse Source

Merge branch 'main' into feature/refactor-blog-articles-to-standalone-components

pull/2117/head
Thomas Kaul 2 years ago
committed by GitHub
parent
commit
a9cd4d34b0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      CHANGELOG.md
  2. 6
      apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html
  3. 11
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
  4. 7
      libs/ui/src/lib/symbol-autocomplete/abstract-mat-form-field.ts
  5. 30
      libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts
  6. 2
      package.json

6
CHANGELOG.md

@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Refactored the blog articles to standalone components - Refactored the blog articles to standalone components
## 1.286.0 - 2023-07-03
### Fixed
- Fixed the creation of (wealth) items and liabilities
## 1.285.0 - 2023-07-01 ## 1.285.0 - 2023-07-01
### Added ### Added

6
apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html

@ -79,7 +79,7 @@
FIRE grants individuals a higher level of autonomy and empowerment FIRE grants individuals a higher level of autonomy and empowerment
over their schedules and the activities they choose to pursue. over their schedules and the activities they choose to pursue.
Whether it involves exploring new career paths, starting a business, Whether it involves exploring new career paths, starting a business,
or embarking on extensive travel, FIRE provides the flexibility to or undertaking adventurous travels, FIRE provides the flexibility to
determine how time is spent and how life is shaped. determine how time is spent and how life is shaped.
</p> </p>
</section> </section>
@ -127,8 +127,8 @@
understanding of the advantages and disadvantages. understanding of the advantages and disadvantages.
</p> </p>
<p> <p>
Knowing your financial situation and tracking it diligently is vital Knowing your financial situation and consistently monitoring it is
on your journey to FIRE. This is where the power of vital on your journey to FIRE. This is where the strength of
<a href="https://ghostfol.io">Ghostfolio</a>, a comprehensive open <a href="https://ghostfol.io">Ghostfolio</a>, a comprehensive open
source wealth management software, comes into play. By leveraging source wealth management software, comes into play. By leveraging
Ghostfolio, you can gain deep insights into your financial health, Ghostfolio, you can gain deep insights into your financial health,

11
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts

@ -241,7 +241,11 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
this.activityForm.controls['searchSymbol'].valueChanges.subscribe(() => { this.activityForm.controls['searchSymbol'].valueChanges.subscribe(() => {
if (this.activityForm.controls['searchSymbol'].invalid) { if (this.activityForm.controls['searchSymbol'].invalid) {
this.data.activity.SymbolProfile = null; this.data.activity.SymbolProfile = null;
} else { } else if (
['BUY', 'DIVIDEND', 'SELL'].includes(
this.activityForm.controls['type'].value
)
) {
this.activityForm.controls['dataSource'].setValue( this.activityForm.controls['dataSource'].setValue(
this.activityForm.controls['searchSymbol'].value.dataSource this.activityForm.controls['searchSymbol'].value.dataSource
); );
@ -408,8 +412,9 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
fee: this.activityForm.controls['fee'].value, fee: this.activityForm.controls['fee'].value,
quantity: this.activityForm.controls['quantity'].value, quantity: this.activityForm.controls['quantity'].value,
symbol: symbol:
this.activityForm.controls['searchSymbol'].value.symbol === undefined || this.activityForm.controls['searchSymbol'].value?.symbol ===
isUUID(this.activityForm.controls['searchSymbol'].value.symbol) undefined ||
isUUID(this.activityForm.controls['searchSymbol'].value?.symbol)
? this.activityForm.controls['name'].value ? this.activityForm.controls['name'].value
: this.activityForm.controls['searchSymbol'].value.symbol, : this.activityForm.controls['searchSymbol'].value.symbol,
tags: this.activityForm.controls['tags'].value, tags: this.activityForm.controls['tags'].value,

7
libs/ui/src/lib/symbol-autocomplete/abstract-mat-form-field.ts

@ -9,7 +9,7 @@ import {
Input, Input,
OnDestroy OnDestroy
} from '@angular/core'; } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms'; import { ControlValueAccessor, NgControl, Validators } from '@angular/forms';
import { MatFormFieldControl } from '@angular/material/form-field'; import { MatFormFieldControl } from '@angular/material/form-field';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@ -96,7 +96,10 @@ export abstract class AbstractMatFormField<T>
public _required: boolean = false; public _required: boolean = false;
public get required() { public get required() {
return this._required; return (
this._required ||
this.ngControl.control?.hasValidator(Validators.required)
);
} }
@Input() @Input()

30
libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts

@ -9,7 +9,7 @@ import {
OnInit, OnInit,
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
import { FormControl, NgControl, Validators } from '@angular/forms'; import { FormControl, NgControl } from '@angular/forms';
import { import {
MatAutocomplete, MatAutocomplete,
MatAutocompleteSelectedEvent MatAutocompleteSelectedEvent
@ -25,7 +25,8 @@ import {
debounceTime, debounceTime,
distinctUntilChanged, distinctUntilChanged,
filter, filter,
switchMap switchMap,
takeUntil
} from 'rxjs/operators'; } from 'rxjs/operators';
import { AbstractMatFormField } from './abstract-mat-form-field'; import { AbstractMatFormField } from './abstract-mat-form-field';
@ -76,12 +77,18 @@ export class SymbolAutocompleteComponent
} }
public ngOnInit() { public ngOnInit() {
super.required = this.ngControl.control?.hasValidator(Validators.required);
if (this.disabled) { if (this.disabled) {
this.control.disable(); this.control.disable();
} }
this.control.valueChanges
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
if (super.value) {
super.value.dataSource = null;
}
});
this.control.valueChanges this.control.valueChanges
.pipe( .pipe(
debounceTime(400), debounceTime(400),
@ -89,6 +96,7 @@ export class SymbolAutocompleteComponent
filter((query) => { filter((query) => {
return isString(query) && query.length > 1; return isString(query) && query.length > 1;
}), }),
takeUntil(this.unsubscribeSubject),
tap(() => { tap(() => {
this.isLoading = true; this.isLoading = true;
@ -136,11 +144,6 @@ export class SymbolAutocompleteComponent
public ngDoCheck() { public ngDoCheck() {
if (this.ngControl) { if (this.ngControl) {
this.validateRequired(); this.validateRequired();
if (this.control.touched) {
this.validateSelection();
}
this.errorState = this.ngControl.invalid && this.ngControl.touched; this.errorState = this.ngControl.invalid && this.ngControl.touched;
this.stateChanges.next(); this.stateChanges.next();
} }
@ -173,13 +176,4 @@ export class SymbolAutocompleteComponent
this.ngControl.control.setErrors({ invalidData: true }); this.ngControl.control.setErrors({ invalidData: true });
} }
} }
private validateSelection() {
const error =
!this.isValueInOptions(this.input?.value) ||
this.input?.value !== super.value?.symbol;
if (error) {
this.ngControl.control.setErrors({ invalidData: true });
}
}
} }

2
package.json

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

Loading…
Cancel
Save