Browse Source

Streamline filter actions and remove redundant code

pull/5618/head
Germán Martín 3 weeks ago
parent
commit
973063a5ed
  1. 16
      libs/ui/src/lib/assistant/assistant.component.ts
  2. 31
      libs/ui/src/lib/assistant/assistant.html
  3. 21
      libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.html
  4. 69
      libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.spec.ts
  5. 4
      libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.stories.ts
  6. 2
      libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.ts

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

@ -242,7 +242,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
);
}
// Accounts
const accounts$: Observable<Partial<ISearchResults>> =
this.searchAccounts(searchTerm).pipe(
map((accounts) => ({
@ -261,7 +260,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
})
);
// Asset profiles
const assetProfiles$: Observable<Partial<ISearchResults>> = this
.hasPermissionToAccessAdminControl
? this.searchAssetProfiles(searchTerm).pipe(
@ -290,7 +288,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
})
);
// Holdings
const holdings$: Observable<Partial<ISearchResults>> =
this.searchHoldings(searchTerm).pipe(
map((holdings) => ({
@ -309,7 +306,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
})
);
// Quick links
const quickLinks$: Observable<Partial<ISearchResults>> = of(
this.searchQuickLinks(searchTerm)
).pipe(
@ -325,7 +321,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
})
);
// Merge all results
return merge(accounts$, assetProfiles$, holdings$, quickLinks$).pipe(
scan(
(acc: ISearchResults, curr: Partial<ISearchResults>) => ({
@ -365,11 +360,9 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
}
public ngOnChanges() {
// Use accountsWithValue if provided, otherwise transform user.accounts as fallback
if (this.accountsWithValue?.length > 0) {
this.accounts = this.accountsWithValue;
} else {
// Transform basic accounts to AccountWithValue format for compatibility
this.accounts = (this.user?.accounts ?? []).map((account) => ({
...account,
allocationInPercentage: 0,
@ -379,7 +372,7 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
platform: account.platformId
? {
id: account.platformId,
name: account.platformId, // Fallback, ideally should be resolved
name: account.platformId,
url: ''
}
: undefined,
@ -566,12 +559,7 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
}
public onResetFilters() {
this.portfolioFilterFormControl.setValue({
account: null,
assetClass: null,
holding: null,
tag: null
});
this.portfolioFilterFormControl.reset();
this.filtersChanged.emit(
this.filterTypes.map((type) => {

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

@ -180,6 +180,7 @@
</div>
<div class="p-3">
<gf-portfolio-filter-form
#portfolioFilterForm
[accounts]="accounts"
[assetClasses]="assetClasses"
[disabled]="!hasPermissionToChangeFilters"
@ -188,7 +189,35 @@
[tags]="tags"
(applyFilters)="onApplyFilters()"
(resetFilters)="onResetFilters()"
/>
>
<div class="d-flex w-100" gfPortfolioFilterActions>
<button
i18n
mat-button
type="button"
[disabled]="
!portfolioFilterForm.hasFilters() || portfolioFilterForm.disabled
"
(click)="portfolioFilterForm.onResetFilters()"
>
Reset Filters
</button>
<span class="gf-spacer"></span>
<button
color="primary"
i18n
mat-flat-button
type="button"
[disabled]="
!portfolioFilterForm.filterForm.dirty ||
portfolioFilterForm.disabled
"
(click)="portfolioFilterForm.onApplyFilters()"
>
Apply Filters
</button>
</div>
</gf-portfolio-filter-form>
</div>
}
</div>

21
libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.html

@ -72,24 +72,5 @@
</mat-select>
</mat-form-field>
</div>
<div class="d-flex w-100">
<button
i18n
mat-button
[disabled]="!hasFilters() || disabled"
(click)="onResetFilters()"
>
Reset Filters
</button>
<span class="gf-spacer"></span>
<button
color="primary"
i18n
mat-flat-button
[disabled]="!filterForm.dirty || disabled"
(click)="onApplyFilters()"
>
Apply Filters
</button>
</div>
<ng-content select="[gfPortfolioFilterActions]"></ng-content>
</form>

69
libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.spec.ts

@ -1,69 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { GfPortfolioFilterFormComponent } from './portfolio-filter-form.component';
// Mock $localize for testing
(global as any).$localize = (template: any) => {
return template.raw ? template.raw.join('') : template;
};
describe('GfPortfolioFilterFormComponent', () => {
let component: GfPortfolioFilterFormComponent;
let fixture: ComponentFixture<GfPortfolioFilterFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
GfPortfolioFilterFormComponent,
MatButtonModule,
MatFormFieldModule,
MatSelectModule,
NoopAnimationsModule,
ReactiveFormsModule
]
}).compileComponents();
fixture = TestBed.createComponent(GfPortfolioFilterFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should initialize with empty form values', () => {
expect(component.filterForm.value).toEqual({
account: null,
assetClass: null,
holding: null,
tag: null
});
});
it('should detect when filters are applied', () => {
component.filterForm.patchValue({ account: 'test-account-id' });
expect(component.hasFilters()).toBeTruthy();
});
it('should detect when no filters are applied', () => {
expect(component.hasFilters()).toBeFalsy();
});
it('should emit resetFilters event when onResetFilters is called', () => {
jest.spyOn(component.resetFilters, 'emit');
component.onResetFilters();
expect(component.resetFilters.emit).toHaveBeenCalled();
});
it('should emit applyFilters event when onApplyFilters is called', () => {
jest.spyOn(component.applyFilters, 'emit');
component.onApplyFilters();
expect(component.applyFilters.emit).toHaveBeenCalled();
});
});

4
libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.stories.ts

@ -36,9 +36,9 @@ export const Default: Story = {
}
] as any,
assetClasses: [
{ id: 'COMMODITY', label: 'Commodity', type: 'ASSET_CLASS' },
{ id: 'EQUITY', label: 'Equity', type: 'ASSET_CLASS' },
{ id: 'FIXED_INCOME', label: 'Fixed Income', type: 'ASSET_CLASS' },
{ id: 'COMMODITY', label: 'Commodity', type: 'ASSET_CLASS' }
{ id: 'FIXED_INCOME', label: 'Fixed Income', type: 'ASSET_CLASS' }
] as any,
holdings: [
{

2
libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.ts

@ -25,7 +25,6 @@ import {
NG_VALUE_ACCESSOR,
ReactiveFormsModule
} from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { Subject, takeUntil } from 'rxjs';
@ -39,7 +38,6 @@ import { PortfolioFilterFormValue } from './interfaces';
FormsModule,
GfEntityLogoComponent,
GfSymbolPipe,
MatButtonModule,
MatFormFieldModule,
MatSelectModule,
ReactiveFormsModule

Loading…
Cancel
Save