Skip to content

Commit 36d9eb3

Browse files
committed
Fix choppiness when opening and showing organisation and system property filter controls
1 parent fb9e4f7 commit 36d9eb3

8 files changed

Lines changed: 59 additions & 7 deletions

File tree

gitb-ui/ui/src/app/components/base-conformance-item-display/base-conformance-item-display.component.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ export abstract class BaseConformanceItemDisplayComponent extends BaseComponent
9090
showExport = false
9191
updatePending = false
9292
exportPending = false
93+
/** Whether the list view's embedded filter is still loading its organisation/system custom
94+
* properties - bound to the external "Filter..." button's [pending] so the filter icon
95+
* turns into a spinner (the embedded filter's own header/pending icon isn't rendered). */
96+
filterLoading = false
9397
organisationId?: number
9498
communityId?: number
9599
listView = false
@@ -202,6 +206,12 @@ export abstract class BaseConformanceItemDisplayComponent extends BaseComponent
202206
})
203207
}
204208

209+
onFilterLoading(pending: boolean) {
210+
setTimeout(() => {
211+
this.filterLoading = pending
212+
})
213+
}
214+
205215
loadConformanceStatementsForListViewFactory() {
206216
return (this.loadConformanceStatementsForListView).bind(this)
207217
}

gitb-ui/ui/src/app/components/conformance-statement-table/conformance-statement-table.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
[organisationId]="organisationId"
66
[snapshotId]="snapshotId"
77
[initialFilters]="initialFilters"
8-
(onApply)="getConformanceStatements()"></app-test-filter>
8+
(onApply)="getConformanceStatements()"
9+
(loadingStatus)="filterLoading.emit($event)"></app-test-filter>
910
<div class="table-container rounded">
1011
<table class="table table-directive">
1112
<thead>

gitb-ui/ui/src/app/components/conformance-statement-table/conformance-statement-table.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ export class ConformanceStatementTableComponent extends BaseComponent implements
5151
@Output() exportChange = new EventEmitter<boolean>()
5252
@Output() searchChange = new EventEmitter<boolean>()
5353
@Output() communityChange = new EventEmitter<number|undefined>()
54+
/** Forwards the embedded test-filter's custom-property loading status, so the external
55+
* "Filter..." button can show loading feedback (the embedded filter's own header/pending
56+
* icon is not rendered). */
57+
@Output() filterLoading = new EventEmitter<boolean>()
5458
@Output() select = new EventEmitter<ConformanceResultFullWithTestSuites>
5559
@ViewChild("pagingControls") pagingControls?: PagingControlsApi
5660
@ViewChildren("testStatusDisplay") testStatusDisplay?: QueryList<TestStatusBaseApi>

gitb-ui/ui/src/app/components/filter-control/filter-control.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@if (showRefresh || showClear) {
22
<div class="btn-group" ngbDropdown>
3-
<button type="button" [labelIcon]="Constants.BUTTON_ICON.FILTER" class="btn btn-secondary" (click)="doToggle()">Filter...</button>
3+
<button type="button" [labelIcon]="Constants.BUTTON_ICON.FILTER" class="btn btn-secondary" [pending]="pending" (click)="doToggle()">Filter...</button>
44
<button id="button-filters" type="button" ngbDropdownToggle class="btn btn-secondary dropdown-toggle dropdown-toggle-split">
55
<span class="caret"></span>
66
<span class="sr-only visually-hidden">Search</span>

gitb-ui/ui/src/app/components/filter-control/filter-control.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export class FilterControlComponent implements FilterControlApi {
2626

2727
@Input() showRefresh = true
2828
@Input() showClear = true
29+
/** Whether the filter data backing the panel (e.g. custom properties) is still loading -
30+
* shows a spinner in place of the filter icon on the main toggle button, matching other
31+
* buttons' [pending] behaviour. */
32+
@Input() pending = false
2933
@Output() toggle = new EventEmitter<boolean>();
3034
@Output() refresh = new EventEmitter<void>();
3135
@Output() clear = new EventEmitter<void>();

gitb-ui/ui/src/app/components/test-filter/test-filter.component.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ export class TestFilterComponent implements OnInit, AfterViewInit {
8383
@Input() loadSystemPropertiesFn?: (_: number) => Observable<SystemParameter[]>
8484

8585
@Output() onApply = new EventEmitter<any>()
86+
/** Emitted while the organisation/system custom properties (needed before the panel can
87+
* expand) are being loaded - lets an embedding parent (e.g. the conformance dashboard's
88+
* external "Filter..." button) show its own loading feedback, given that in embedded mode
89+
* this component's own header (and pending icon) isn't rendered. */
90+
@Output() loadingStatus = new EventEmitter<boolean>()
8691

8792
@ViewChild("commentFilter") commentFilterComponent?: TextFilterComponentApi
8893

@@ -509,8 +514,9 @@ export class TestFilterComponent implements OnInit, AfterViewInit {
509514
} else {
510515
this.applicableCommunityId = undefined
511516
}
517+
this.loadingStatus.emit(true)
512518
this.resetCustomProperties().subscribe(() => {
513-
this.initialised = true
519+
this.completeInitialisation()
514520
})
515521
if (update.applyFilters) {
516522
this.applyFilters()
@@ -694,16 +700,41 @@ export class TestFilterComponent implements OnInit, AfterViewInit {
694700

695701
clickedHeader() {
696702
this.showFiltering = !this.showFiltering
697-
if (this.showFiltering) {
703+
if (this.showFiltering && this.initialised) {
704+
// Already loaded - the panel expands right away, so drop the header's "collapsed"
705+
// (rounded-corner) styling in step with it. If not yet initialised, this is instead
706+
// done from completeInitialisation() once the panel is actually about to expand -
707+
// see the comment there for why this must not happen earlier.
698708
this.toggleFilterCollapsedFinished(false)
699709
}
700710
if (!this.initialised) {
711+
this.loadingStatus.emit(true)
701712
this.resetCustomProperties().subscribe(() => {
702-
this.initialised = true
713+
this.completeInitialisation()
703714
})
704715
}
705716
}
706717

718+
/** Marks the panel as ready to expand, deferred to a follow-up macrotask so that the
719+
* organisation/system property fields (whose visibility is set by resetCustomProperties(),
720+
* just completed) have already rendered into the still-collapsed panel on this tick.
721+
* Flipping "initialised" (and so [ngbCollapse]) in the same cycle as their first render
722+
* makes ngbCollapse measure a stale (too short) target height, so the fields pop in
723+
* mid-animation instead of the panel expanding in one smooth motion. The header's
724+
* "collapsed" styling (filterCollapsedFinished) must flip in this same step rather than
725+
* immediately on click - otherwise the header's rounded corners change well before the
726+
* panel actually starts expanding, which is its own visible pop disconnected from the
727+
* expand animation. */
728+
private completeInitialisation() {
729+
setTimeout(() => {
730+
this.initialised = true
731+
this.loadingStatus.emit(false)
732+
if (this.showFiltering) {
733+
this.toggleFilterCollapsedFinished(false)
734+
}
735+
})
736+
}
737+
707738
private resetCustomProperties(): Observable<boolean> {
708739
if (this.applicableCommunityId != undefined && this.filterDefined(Constants.FILTER_TYPE.ORGANISATION_PROPERTY) && this.filterDefined(Constants.FILTER_TYPE.SYSTEM_PROPERTY)) {
709740
const obs1 = this.loadOrganisationProperties(this.applicableCommunityId)

gitb-ui/ui/src/app/pages/admin/conformance-dashboard/conformance-dashboard.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div class="card-title">Conformance statements</div>
55
<div class="btn-toolbar allStatementControls">
66
@if (listView) {
7-
<app-filter-control #filterControl (toggle)="toggleFilters()" (refresh)="refreshFilters()" (clear)="clearFilters()"></app-filter-control>
7+
<app-filter-control #filterControl [pending]="filterLoading" (toggle)="toggleFilters()" (refresh)="refreshFilters()" (clear)="clearFilters()"></app-filter-control>
88
@if (showExport) {
99
<button type="button" [labelIcon]="Constants.BUTTON_ICON.REPORT_CSV" class="btn btn-secondary" (click)="onExportConformanceStatementsAsCsv()" [pending]="exportPending">Export CSV</button>
1010
}
@@ -175,6 +175,7 @@
175175
(communityChange)="listViewCommunityChange($event)"
176176
(searchChange)="listViewSearching($event)"
177177
(exportChange)="listViewExportChange($event)"
178+
(filterLoading)="onFilterLoading($event)"
178179
(select)="onStatementSelectFromListView($event)"></app-conformance-statement-table>
179180
}
180181
</div>

gitb-ui/ui/src/app/pages/organisation/conformance-statements/conformance-statements.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div class="card-title">Conformance statements</div>
55
<div class="btn-toolbar">
66
@if (listView) {
7-
<app-filter-control #filterControl (toggle)="toggleFilters()" (refresh)="refreshFilters()" (clear)="clearFilters()"></app-filter-control>
7+
<app-filter-control #filterControl [pending]="filterLoading" (toggle)="toggleFilters()" (refresh)="refreshFilters()" (clear)="clearFilters()"></app-filter-control>
88
@if (showExport) {
99
<button type="button" [labelIcon]="Constants.BUTTON_ICON.REPORT_CSV" class="btn btn-secondary" (click)="onExportConformanceStatementsAsCsv()" [pending]="exportPending">Export CSV</button>
1010
}
@@ -156,6 +156,7 @@
156156
[initialPaging]="restoredListViewPaging"
157157
(searchChange)="listViewSearching($event)"
158158
(exportChange)="listViewExportChange($event)"
159+
(filterLoading)="onFilterLoading($event)"
159160
(select)="onStatementSelectFromListView($event)"></app-conformance-statement-table>
160161
}
161162
@if (showBack) {

0 commit comments

Comments
 (0)