Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
38b029a
SED-4450-working on loading spinners
lucian-baciu Dec 19, 2025
7850c11
SED-4450-working on refresh in dashboard view
lucian-baciu Dec 19, 2025
6e2a052
SED-4450-ts dashboard improvements
lucian-baciu Dec 23, 2025
a0cae89
SED-4450-analyics improvements
lucian-baciu Dec 24, 2025
dff75e3
Merge remote-tracking branch 'origin/master' into SED-4450-the-cross-…
lucian-baciu Dec 28, 2025
59a2e42
SED-4450-cleanup
lucian-baciu Dec 29, 2025
605a6b3
SED-4450-fixes on cross execution analytics
lucian-baciu Dec 31, 2025
98e1176
SED-4450-working on execution view
lucian-baciu Jan 1, 2026
e2965ed
SED-4450-loading fixes for compare mode & other features
lucian-baciu Jan 1, 2026
ac3cb9d
SED-4450-update the legacy execution page
lucian-baciu Jan 1, 2026
44d7d70
SED-4450-added table loading
lucian-baciu Jan 7, 2026
93af139
SED-4450-fix local data source loading
lucian-baciu Jan 7, 2026
d417be9
SED-4450-cross execution header animations
lucian-baciu Jan 8, 2026
6ace198
SED-4450-cleanup
lucian-baciu Jan 8, 2026
8678ed6
SED-4450-fix loading spinners
lucian-baciu Jan 8, 2026
27d4d6b
SED-4450-refactor
lucian-baciu Jan 20, 2026
6845068
SED-4450-fix loading + compare mode
lucian-baciu Jan 20, 2026
defef37
SED-4450-cleanup
lucian-baciu Jan 21, 2026
2e42d66
Merge branch 'master' into SED-4450-the-cross-execution-and-analytics…
neogucky Jan 25, 2026
353baae
Merge branch 'master' into SED-4450-the-cross-execution-and-analytics…
neogucky Feb 4, 2026
3d6d90d
SED-4450-fix merge
lucian-baciu Feb 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { inject, Injectable } from '@angular/core';
import { FetchBucketsRequest, TimeSeriesService } from '../../generated';
import { map, Observable, of, OperatorFunction, switchMap } from 'rxjs';
import { delay, map, Observable, of, OperatorFunction, switchMap } from 'rxjs';
import { TableApiWrapperService } from '../../table';
import { HttpOverrideResponseInterceptor } from '../shared/http-override-response-interceptor';
import { HttpOverrideResponseInterceptorService } from './http-override-response-interceptor.service';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<step-execution-dashboard
#dashboard
[execution]="execution!"
[timeRange]="(_state.timeRange$ | async)!"
[initialTimeRange]="(_state.timeRange$ | async)!"
(contextSettingsChanged)="handleDashboardSettingsChange($event)"
(contextSettingsInit)="handleDashboardSettingsInit($event)"
(fullRangeUpdateRequest)="handleFullRangeChangeRequest($event)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { ChangeDetectorRef, Component, DestroyRef, inject, OnDestroy, OnInit, viewChild } from '@angular/core';
import { ChangeDetectorRef, Component, DestroyRef, effect, inject, OnDestroy, OnInit, viewChild } from '@angular/core';
import { AltExecutionStateService } from '../../services/alt-execution-state.service';
import { TimeSeriesContext } from '../../../timeseries/modules/_common';
import { DashboardUrlParamsService } from '../../../timeseries/modules/_common/injectables/dashboard-url-params.service';
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
import { ExecutionDashboardComponent } from '../../../timeseries/components/execution-page/execution-dashboard.component';
import { filter, pairwise } from 'rxjs';
import { filter, map, Observable, pairwise, switchMap, withLatestFrom } from 'rxjs';
import { NavigationEnd, NavigationStart, Router } from '@angular/router';
import { TimeRange } from '@exense/step-core';
import { ActiveExecution } from '../../services/active-executions.service';
import { ActiveExecutionContextService } from '../../services/active-execution-context.service';
import { convertPickerSelectionToTimeRange } from '../../shared/convert-picker-selection';

@Component({
selector: 'step-alt-execution-analytics',
Expand All @@ -16,6 +19,7 @@ import { TimeRange } from '@exense/step-core';
})
export class AltExecutionAnalyticsComponent implements OnInit {
readonly _state = inject(AltExecutionStateService);
private _activeExecutionContext = inject(ActiveExecutionContextService);
private _urlParamsService = inject(DashboardUrlParamsService);
private _router = inject(Router);
private _destroyRef = inject(DestroyRef);
Expand All @@ -24,6 +28,34 @@ export class AltExecutionAnalyticsComponent implements OnInit {

activeTimeRangeSelection = toSignal(this._state.timeRangeSelection$);

readonly timeRangeChange = this._activeExecutionContext.activeExecution$
.pipe(
takeUntilDestroyed(),
switchMap((active) => active.timeRangeSelectionChange$.pipe(withLatestFrom(active.execution$))),
)
.subscribe(([tr, execution]) => {
if (!tr || !execution) {
return;
}
const timeRange = convertPickerSelectionToTimeRange(tr, execution);
this.dashboardComponent()?.updateFullTimeRange(timeRange!, { actionType: 'manual' });
});

readonly autoRefreshTriggered = this._activeExecutionContext.activeExecution$
.pipe(
takeUntilDestroyed(),
switchMap((active) =>
active.execution$.pipe(map((execution) => [execution, active.getTimeRangeSelection()] as const)),
),
)
.subscribe(([execution, timeRangeSelection]) => {
if (!timeRangeSelection || !execution) {
return;
}
const timeRange = convertPickerSelectionToTimeRange(timeRangeSelection, execution);
this.dashboardComponent()?.updateFullTimeRange(timeRange!, { actionType: 'auto' });
});

handleDashboardSettingsChange(context: TimeSeriesContext) {
this._urlParamsService.updateUrlParamsFromContext(context, this.activeTimeRangeSelection()!, undefined, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
matSortActive="count"
matSortDirection="desc"
[visibleColumns]="displayColumns()"
[indicatorMode]="TableIndicatorMode.SKELETON_ON_INITIAL_LOAD"
[indicatorMode]="TableIndicatorMode.SPINNER"
>
<ng-container matColumnDef="errorMessage" stepSearchCol>
<th mat-header-cell mat-sort-header *matHeaderCellDef>Error Message</th>
Expand All @@ -20,7 +20,9 @@
<mat-menu #menu="matMenu" class="error-wide-menu">
<ng-template matMenuContent>
@if (!element?.executionIds?.length) {
<div class="error-empty-executions"><step-icon name="alert-triangle" /> Current time range is too large to display details.</div>
<div class="error-empty-executions">
<step-icon name="alert-triangle" /> Current time range is too large to display details.
</div>
} @else {
<step-error-details-menu
[executionIds]="element.executionIds"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class AltReportPerformanceOverviewChartComponent {
zoomEnabled: true,
primaryAxesUnit: 'ms',
colorizationType: 'STROKE',
height: 238,
height: 340,
};

protected readonly metricKey = 'response-time';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
<div class="header">
<step-time-range-picker
[activeSelection]="activeTimeRangeSelection()!"
(selectionChange)="handleTimeRangeChange($event)"
(selectionChange)="handleTimeRangeSelectionChange($event)"
[activeTimeRange]="timeRange()"
[selectOptions]="timeRangeOptions"
/>
</div>

<step-execution-dashboard
#dashboardComponent
[execution]="execution()"
[timeRange]="timeRange()!"
[initialTimeRange]="timeRange()!"
(contextSettingsChanged)="handleDashboardSettingsChange($event)"
(contextSettingsInit)="handleDashboardSettingsInit($event)"
(fullRangeUpdateRequest)="handleFullRangeChangeRequest($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import {
Component,
computed,
DestroyRef,
effect,
inject,
input,
OnInit,
Signal,
signal,
untracked,
viewChild,
WritableSignal,
} from '@angular/core';
import { ActivatedRoute, NavigationEnd, NavigationStart, Router } from '@angular/router';
Expand All @@ -17,6 +20,9 @@ import { TimeSeriesConfig, TimeSeriesContext, TimeSeriesUtils } from '../../../.
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { filter, pairwise } from 'rxjs';
import { AuthService, DashboardsService, DashboardView, Execution, TimeRange } from '@exense/step-core';
import { DashboardComponent } from '../../../../timeseries/components/dashboard/dashboard.component';
import { convertPickerSelectionToTimeRange } from '../../../shared/convert-picker-selection';
import { ExecutionDashboardComponent } from '../../../../timeseries/components/execution-page/execution-dashboard.component';

@Component({
selector: 'step-legacy-execution-view',
Expand All @@ -25,15 +31,29 @@ import { AuthService, DashboardsService, DashboardView, Execution, TimeRange } f
standalone: false,
})
export class LegacyExecutionViewComponent implements OnInit {
execution = input.required<Execution>();

private _router: Router = inject(Router);
private _destroyRef = inject(DestroyRef);
private _changeDetectorRef = inject(ChangeDetectorRef);
private _dashboardService = inject(DashboardsService);
private _authService = inject(AuthService);
private _urlParamsService = inject(DashboardUrlParamsService);

private dashboardComponent = viewChild('dashboardComponent', { read: ExecutionDashboardComponent });

execution = input.required<Execution>();

executionChangeEffect = effect(() => {
// handle autorefresh
let execution = this.execution();
if (!execution) return;

untracked(() => {
let timeRangeSelection = this.activeTimeRangeSelection();
const timeRange = convertPickerSelectionToTimeRange(timeRangeSelection!, execution);
this.dashboardComponent()?.updateFullTimeRange(timeRange!, { actionType: 'auto' });
});
});

readonly timeRangeOptions: TimeRangePickerSelection[] = [
{ type: 'FULL' },
...TimeSeriesConfig.EXECUTION_PAGE_TIME_SELECTION_OPTIONS,
Expand All @@ -48,14 +68,9 @@ export class LegacyExecutionViewComponent implements OnInit {

timeRange: Signal<TimeRange | undefined> = computed(() => {
const pickerSelection = this.activeTimeRangeSelection();
if (pickerSelection) {
const execution = this.execution();
const end = execution.endTime || new Date().getTime();
if (pickerSelection.type === 'FULL') {
return { from: execution.startTime!, to: end };
} else {
return TimeSeriesUtils.convertSelectionToTimeRange(pickerSelection, end);
}
const execution = this.execution();
if (pickerSelection && execution) {
return convertPickerSelectionToTimeRange(pickerSelection, this.execution());
} else {
return undefined;
}
Expand Down Expand Up @@ -113,13 +128,10 @@ export class LegacyExecutionViewComponent implements OnInit {
);
}

handleTimeRangeChange(pickerSelection: TimeRangePickerSelection) {
handleTimeRangeSelectionChange(pickerSelection: TimeRangePickerSelection) {
this.activeTimeRangeSelection.set(pickerSelection);
}

triggerRefresh() {
let rangeSelection = this.activeTimeRangeSelection()!;
this.activeTimeRangeSelection.set({ ...rangeSelection });
let timeRange = convertPickerSelectionToTimeRange(pickerSelection, this.execution());
this.dashboardComponent()?.updateFullTimeRange(timeRange!, { actionType: 'manual' });
}

private subscribeToUrlNavigation() {
Expand Down
Loading