Skip to content

Commit

Permalink
frontend: Implement executions list enhacements
Browse files Browse the repository at this point in the history
Executions list highlighting is in sync with duration
chart focus on event (execution).
Change label text on filter by period.
Added caret next to text from time period filter.
Implement synchronization between time period filter,
duration zoom, grid filters and grid sort criteria.
Whenever change occurs it is reflected on the other
components/charts and everything is sharable through URL.

Signed-off-by: Goran Kokinovski <[email protected]>
  • Loading branch information
gorankokin committed May 26, 2023
1 parent 460a133 commit ff2b724
Show file tree
Hide file tree
Showing 51 changed files with 2,310 additions and 482 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ describe(
pathSegment: `/manage/data-jobs/${longLivedFailingJobFixture.team}/${longLivedFailingJobFixture.job_name}/executions`,
queryParams: {
sort: '{"startTime":-1}',
filter: `{"startTimeFormatted":"${filterValue}"}`
filter: `{"startTime":"${filterValue}"}`
}
});
});
Expand Down Expand Up @@ -803,7 +803,7 @@ describe(
pathSegment: `/manage/data-jobs/${longLivedFailingJobFixture.team}/${longLivedFailingJobFixture.job_name}/executions`,
queryParams: {
sort: '{"startTime":-1}',
filter: `{"endTimeFormatted":"${filterValue}"}`
filter: `{"endTime":"${filterValue}"}`
}
});
});
Expand Down Expand Up @@ -1930,7 +1930,7 @@ describe(
})
.should('gt', 0);

// verify current URL has appended filters execution status: user_error, trigger type: manual, id: long_lived_job_name, startTimeFormatted: ${filterValue} and sort by id ascending
// verify current URL has appended filters execution status: user_error, trigger type: manual, id: long_lived_job_name, startTime: ${filterValue} and sort by id ascending
dataJobExecutionsPage
.getCurrentUrlNormalized({
includePathSegment: true,
Expand All @@ -1941,7 +1941,7 @@ describe(
pathSegment: `/manage/data-jobs/${longLivedFailingJobFixture.team}/${longLivedFailingJobFixture.job_name}/executions`,
queryParams: {
sort: '{"id":1}',
filter: `{"status":"user_error","type":"manual","id":"${longLivedFailingJobFixture.job_name}","startTimeFormatted":"${filterValue}"}`
filter: `{"status":"user_error","type":"manual","id":"${longLivedFailingJobFixture.job_name}","startTime":"${filterValue}"}`
}
});
});
Expand Down Expand Up @@ -1972,7 +1972,7 @@ describe(
})
.should('gt', 0);

// verify current URL has appended filters execution status: user_error, trigger type: manual, id: long_lived_job_name, startTimeFormatted: ${filterValue}, endTimeFormatted: ${filterValue} and sort by id ascending
// verify current URL has appended filters execution status: user_error, trigger type: manual, id: long_lived_job_name, startTime: ${filterValue}, endTime: ${filterValue} and sort by id ascending
dataJobExecutionsPage
.getCurrentUrlNormalized({
includePathSegment: true,
Expand All @@ -1983,7 +1983,7 @@ describe(
pathSegment: `/manage/data-jobs/${longLivedFailingJobFixture.team}/${longLivedFailingJobFixture.job_name}/executions`,
queryParams: {
sort: '{"id":1}',
filter: `{"status":"user_error","type":"manual","id":"${longLivedFailingJobFixture.job_name}","startTimeFormatted":"${filterValue}","endTimeFormatted":"${filterValue}"}`
filter: `{"status":"user_error","type":"manual","id":"${longLivedFailingJobFixture.job_name}","startTime":"${filterValue}","endTime":"${filterValue}"}`
}
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1495,7 +1495,6 @@ describe('FiltersSortManager', () => {
// Given
const filterValue1 = 'f1v,f11v';
const filterValue3 = 'f3v';
const filterValue4 = 'f4v,f44v,f444v';
const sortValue1 = 's1v';
const sortValue2 = '-1';
const sortValue3 = 's3v';
Expand Down Expand Up @@ -1744,8 +1743,6 @@ describe('FiltersSortManager', () => {
// Given
const filterValue1 = 'f1v,f11v';
const filterValue3 = 'f3v';
const filterValue4 = 'f4v,f44v,f444v';
const sortValue1 = 's1v';
const sortValue2 = '-1';
const sortValue3 = 's3v';
const sortValue4 = 's4v';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,8 @@ export class FiltersSortManager<
// debouncing for update URL, to avoid multiple updates when there are multiple serial near close update events
this._updateTimeoutRef = setTimeout(() => {
this._doUpdateBrowserUrl(strategy);

this._updateTimeoutRef = null;
}, this._debouncingTime);
}

Expand All @@ -355,6 +357,8 @@ export class FiltersSortManager<
cancelScheduledBrowserUrlUpdate(): void {
if (CollectionsUtil.isNumber(this._updateTimeoutRef)) {
clearTimeout(this._updateTimeoutRef);

this._updateTimeoutRef = null;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { Component, HostListener, Input } from '@angular/core';
import { Component, Input } from '@angular/core';

import { DataJobExecutionStatus } from '../../../../../model';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright 2021-2023 VMware, Inc.
* SPDX-License-Identifier: Apache-2.0
*/

import { DatePipe } from '@angular/common';

import { TestBed } from '@angular/core/testing';

import { DATA_PIPELINES_DATE_TIME_FORMAT } from '../../../../../../../model';

import { GridDataJobExecution } from '../../../model';

import { ExecutionDefaultComparator } from './execution-default.comparator';

describe('ExecutionDefaultComparator', () => {
let datePipe: DatePipe;
let dataJobExecutions: GridDataJobExecution[];

beforeEach(() => {
TestBed.configureTestingModule({
providers: [DatePipe]
});

datePipe = TestBed.inject(DatePipe);

const aStartTime = new Date();
const aEndTime = new Date(aStartTime.getTime() + 100);
const bStartTime = new Date();
const bEndTime = new Date(bStartTime.getTime() + 110);

dataJobExecutions = [
{
id: 'aJob',
startTimeFormatted: datePipe.transform(aStartTime, DATA_PIPELINES_DATE_TIME_FORMAT),
startTime: aStartTime.toISOString(),
endTimeFormatted: datePipe.transform(aEndTime, DATA_PIPELINES_DATE_TIME_FORMAT),
endTime: aEndTime.toISOString(),
duration: '100',
jobVersion: 'version-10'
},
{
id: 'bJob',
startTimeFormatted: datePipe.transform(bStartTime, DATA_PIPELINES_DATE_TIME_FORMAT),
startTime: bStartTime.toISOString(),
endTimeFormatted: datePipe.transform(bEndTime, DATA_PIPELINES_DATE_TIME_FORMAT),
endTime: bEndTime.toISOString(),
duration: '110',
jobVersion: 'version-11'
}
];
});

describe('Properties::', () => {
describe('|direction|', () => {
it('should verify value', () => {
// Given
const instance = new ExecutionDefaultComparator('jobVersion', 'ASC');

// Then
expect(instance.property).toEqual('jobVersion');
expect(instance.direction).toEqual('ASC');
});
});
});

describe('Methods::', () => {
describe('|compare|', () => {
it('should verify will return -1 because of ascending sort', () => {
// Given
const instance = new ExecutionDefaultComparator('jobVersion', 'ASC');

// When
const res = instance.compare(dataJobExecutions[0], dataJobExecutions[1]);

// Then
expect(res).toEqual(-1);
});

it('should verify will return 1 because of ascending sort', () => {
// Given
const instance = new ExecutionDefaultComparator('endTime', 'ASC');

// When
const res = instance.compare(dataJobExecutions[1], dataJobExecutions[0]);

// Then
expect(res).toEqual(1);
});

it('should verify will return 1 because of descending sort', () => {
// Given
const instance = new ExecutionDefaultComparator('jobVersion', 'DESC');

// When
const res = instance.compare(dataJobExecutions[0], dataJobExecutions[1]);

// Then
expect(res).toEqual(1);
});

it('should verify will return -1 because of descending sort', () => {
// Given
const instance = new ExecutionDefaultComparator('endTime', 'DESC');

// When
const res = instance.compare(dataJobExecutions[1], dataJobExecutions[0]);

// Then
expect(res).toEqual(-1);
});

it('should verify will return 0 because of ascending sort', () => {
// Given
const instance = new ExecutionDefaultComparator('startTime', 'ASC');

// When
const res = instance.compare(dataJobExecutions[0], dataJobExecutions[1]);

// Then
expect(res).toEqual(-0);
});

it('should verify will return 0 because of descending sort', () => {
// Given
const instance = new ExecutionDefaultComparator('startTime', 'DESC');

// When
const res = instance.compare(dataJobExecutions[0], dataJobExecutions[1]);

// Then
expect(res).toEqual(0);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2021-2023 VMware, Inc.
* SPDX-License-Identifier: Apache-2.0
*/

import { get } from 'lodash';

import { Comparator } from '@versatiledatakit/shared';

import { GridDataJobExecution } from '../../../model/data-job-execution';

/**
* ** Execution default comparator.
*/
export class ExecutionDefaultComparator implements Comparator<GridDataJobExecution> {
/**
* ** Property path to value from GridDataJobExecution object.
*/
public readonly property: keyof GridDataJobExecution;

/**
* ** Sort direction.
*/
public readonly direction: 'ASC' | 'DESC';

/**
* ** Constructor.
*/
constructor(property: keyof GridDataJobExecution, direction: 'ASC' | 'DESC') {
this.property = property;
this.direction = direction;
}

/**
* @inheritDoc
*/
compare(exec1: GridDataJobExecution, exec2: GridDataJobExecution) {
const value1 = get<GridDataJobExecution, keyof GridDataJobExecution>(exec1, this.property);
const value2 = get<GridDataJobExecution, keyof GridDataJobExecution>(exec2, this.property);
const directionModifier = this.direction === 'DESC' ? 1 : -1;

return (value1 > value2 ? -1 : value2 > value1 ? 1 : 0) * directionModifier;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright 2023 VMware, Inc.
* SPDX-License-Identifier: Apache-2.0
*/

export * from './execution-default.comparator';
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright 2021-2023 VMware, Inc.
* SPDX-License-Identifier: Apache-2.0
*/

import { DatePipe } from '@angular/common';

import { TestBed } from '@angular/core/testing';

import { DATA_PIPELINES_DATE_TIME_FORMAT } from '../../../../../../../model';

import { GridDataJobExecution } from '../../../model';

import { ExecutionDurationComparator } from './execution-duration.comparator';

describe('ExecutionDurationComparator', () => {
let datePipe: DatePipe;
let dataJobExecutions: GridDataJobExecution[];

beforeEach(() => {
TestBed.configureTestingModule({
providers: [DatePipe]
});

datePipe = TestBed.inject(DatePipe);

const aStartTime = new Date();
const aEndTime = new Date(aStartTime.getTime() + 100);
const bStartTime = new Date();
const bEndTime = new Date(bStartTime.getTime() + 110);

dataJobExecutions = [
{
id: 'aJob',
startTimeFormatted: datePipe.transform(aStartTime, DATA_PIPELINES_DATE_TIME_FORMAT),
startTime: aStartTime.toISOString(),
endTimeFormatted: datePipe.transform(aEndTime, DATA_PIPELINES_DATE_TIME_FORMAT),
endTime: aEndTime.toISOString(),
duration: '100',
jobVersion: ''
},
{
id: 'bJob',
startTimeFormatted: datePipe.transform(bStartTime, DATA_PIPELINES_DATE_TIME_FORMAT),
startTime: bStartTime.toISOString(),
endTimeFormatted: datePipe.transform(bEndTime, DATA_PIPELINES_DATE_TIME_FORMAT),
endTime: bEndTime.toISOString(),
duration: '110',
jobVersion: ''
}
];
});

describe('Properties::', () => {
describe('|direction|', () => {
it('should verify value', () => {
// Given
const instance = new ExecutionDurationComparator('ASC');

// Then
expect(instance.direction).toEqual('ASC');
});
});
});

describe('Methods::', () => {
describe('|compare|', () => {
it('should verify will return -10 because of ascending sort', () => {
// Given
const instance = new ExecutionDurationComparator('ASC');

// When
const res = instance.compare(dataJobExecutions[0], dataJobExecutions[1]);

// Then
expect(res).toEqual(-10);
});

it('should verify will return 10 because of descending sort', () => {
// Given
const instance = new ExecutionDurationComparator('DESC');

// When
const res = instance.compare(dataJobExecutions[0], dataJobExecutions[1]);

// Then
expect(res).toEqual(10);
});
});
});
});
Loading

0 comments on commit ff2b724

Please sign in to comment.