Change platform control from select to autocomplete in account dialog (#2429)

* Change platform control from select to autocomplete in account dialog

* Update changelog
pull/2454/head
Kevin 8 months ago committed by GitHub
parent 8236091477
commit 37ff7acf04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added support for notes in the activities import
- Added support to search in the platform selector of the create or update account dialog
- Added support for a search query in the portfolio position endpoint
- Added the application version to the endpoint `GET api/v1/admin`
- Introduced a carousel component for the testimonial section on the landing page

@ -55,12 +55,8 @@ export class InfoService {
public async get(): Promise<InfoItem> {
const info: Partial<InfoItem> = {};
let isReadOnlyMode: boolean;
const platforms = (
await this.platformService.getPlatforms({
orderBy: { name: 'asc' }
})
).map(({ id, name }) => {
return { id, name };
const platforms = await this.platformService.getPlatforms({
orderBy: { name: 'asc' }
});
let systemMessage: string;

@ -4,12 +4,20 @@ import {
Inject,
OnDestroy
} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import {
AbstractControl,
FormBuilder,
FormGroup,
ValidatorFn,
Validators
} from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto';
import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto';
import { DataService } from '@ghostfolio/client/services/data.service';
import { Subject } from 'rxjs';
import { Platform } from '@prisma/client';
import { Observable, Subject } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces';
@ -23,7 +31,8 @@ import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces';
export class CreateOrUpdateAccountDialog implements OnDestroy {
public accountForm: FormGroup;
public currencies: string[] = [];
public platforms: { id: string; name: string }[];
public filteredPlatforms: Observable<Platform[]>;
public platforms: Platform[];
private unsubscribeSubject = new Subject<void>();
@ -34,7 +43,7 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
private formBuilder: FormBuilder
) {}
ngOnInit() {
public ngOnInit() {
const { currencies, platforms } = this.dataService.fetchInfo();
this.currencies = currencies;
@ -47,8 +56,41 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
currency: [this.data.account.currency, Validators.required],
isExcluded: [this.data.account.isExcluded],
name: [this.data.account.name, Validators.required],
platformId: [this.data.account.platformId]
platformId: [
this.platforms.find(({ id }) => {
return id === this.data.account.platformId;
}),
this.autocompleteObjectValidator()
]
});
this.filteredPlatforms = this.accountForm
.get('platformId')
.valueChanges.pipe(
startWith(''),
map((value) => {
const name = typeof value === 'string' ? value : value?.name;
return name ? this.filter(name as string) : this.platforms.slice();
})
);
}
public autoCompleteCheck() {
const inputValue = this.accountForm.controls['platformId'].value;
if (typeof inputValue === 'string') {
const matchingEntry = this.platforms.find(({ name }) => {
return name === inputValue;
});
if (matchingEntry) {
this.accountForm.controls['platformId'].setValue(matchingEntry);
}
}
}
public displayFn(platform: Platform) {
return platform?.name ?? '';
}
public onCancel() {
@ -63,7 +105,7 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
id: this.accountForm.controls['accountId'].value,
isExcluded: this.accountForm.controls['isExcluded'].value,
name: this.accountForm.controls['name'].value,
platformId: this.accountForm.controls['platformId'].value
platformId: this.accountForm.controls['platformId'].value?.id ?? null
};
if (this.data.account.id) {
@ -79,4 +121,22 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private autocompleteObjectValidator(): ValidatorFn {
return (control: AbstractControl) => {
if (control.value && typeof control.value === 'string') {
return { invalidAutocompleteObject: { value: control.value } };
}
return null;
};
}
private filter(value: string): Platform[] {
const filterValue = value.toLowerCase();
return this.platforms.filter(({ name }) => {
return name.toLowerCase().startsWith(filterValue);
});
}
}

@ -42,12 +42,29 @@
<div [ngClass]="{ 'd-none': platforms?.length < 1 }">
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Platform</mat-label>
<mat-select formControlName="platformId">
<mat-option [value]="null"></mat-option>
<mat-option *ngFor="let platform of platforms" [value]="platform.id"
>{{ platform.name }}</mat-option
<input
formControlName="platformId"
matInput
type="text"
[matAutocomplete]="auto"
(blur)="autoCompleteCheck()"
(keydown.enter)="$event.stopPropagation()"
/>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
<mat-option
*ngFor="let platformEntry of filteredPlatforms | async"
[value]="platformEntry"
>
</mat-select>
<span class="d-flex">
<gf-symbol-icon
class="mr-1"
[tooltip]="platformEntry.name"
[url]="platformEntry.url"
></gf-symbol-icon>
<span>{{ platformEntry.name }}</span>
</span>
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
<div>

@ -7,6 +7,8 @@ import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { GfSymbolIconModule } from '@ghostfolio/client/components/symbol-icon/symbol-icon.module';
import { CreateOrUpdateAccountDialog } from './create-or-update-account-dialog.component';
@ -15,6 +17,8 @@ import { CreateOrUpdateAccountDialog } from './create-or-update-account-dialog.c
imports: [
CommonModule,
FormsModule,
GfSymbolIconModule,
MatAutocompleteModule,
MatButtonModule,
MatCheckboxModule,
MatDialogModule,

@ -1,5 +1,5 @@
import { SubscriptionOffer } from '@ghostfolio/common/types';
import { SymbolProfile, Tag } from '@prisma/client';
import { Platform, SymbolProfile, Tag } from '@prisma/client';
import { Statistics } from './statistics.interface';
import { Subscription } from './subscription.interface';
@ -13,7 +13,7 @@ export interface InfoItem {
fearAndGreedDataSource?: string;
globalPermissions: string[];
isReadOnlyMode?: boolean;
platforms: { id: string; name: string }[];
platforms: Platform[];
statistics: Statistics;
stripePublicKey?: string;
subscriptions: { [offer in SubscriptionOffer]: Subscription };

Loading…
Cancel
Save