Skip to content

Commit 399244d

Browse files
authored
Merge branch 'main' into add-cacheability-option
2 parents b576099 + ef8a9fb commit 399244d

File tree

121 files changed

+6731
-4442
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+6731
-4442
lines changed

package-lock.json

Lines changed: 4012 additions & 3701 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"build:components": "ng build components",
1616
"build:dashboards": "ng build dashboards",
1717
"build:ci": "node --max_old_space_size=3584 node_modules/@angular/cli/bin/ng build --configuration production --no-progress",
18-
"test": "ng test hypertrace-ui --cache",
18+
"test": "ng test hypertrace-ui --cache --maxWorkers=2",
1919
"lint": "ng lint hypertrace-ui",
2020
"lint:fix": "ng lint --fix hypertrace-ui",
2121
"prettier:check": "prettier --check '**'",
@@ -36,14 +36,14 @@
3636
"@angular/platform-browser": "^12.2.1",
3737
"@angular/platform-browser-dynamic": "^12.2.1",
3838
"@angular/router": "^12.2.1",
39-
"@apollo/client": "^3.4.15",
39+
"@apollo/client": "^3.5.6",
4040
"@fullstory/browser": "^1.4.9",
4141
"@hypertrace/hyperdash": "^1.2.1",
4242
"@hypertrace/hyperdash-angular": "^2.6.0",
4343
"@types/d3-hierarchy": "^2.0.2",
4444
"@types/d3-transition": "1.1.5",
4545
"apollo-angular": "^2.6.0",
46-
"core-js": "^3.19.0",
46+
"core-js": "^3.20.2",
4747
"d3-array": "^2.12.0",
4848
"d3-axis": "^2.1.0",
4949
"d3-brush": "^1.1.6",
@@ -59,11 +59,12 @@
5959
"d3-shape": "^1.3.5",
6060
"d3-transition": "^1.2.0",
6161
"d3-zoom": "^1.8.3",
62-
"graphql": "^15.6.1",
63-
"graphql-tag": "^2.12.5",
62+
"graphql": "^15.8.0",
63+
"graphql-tag": "^2.12.6",
6464
"iso8601-duration": "^1.3.0",
6565
"lodash-es": "^4.17.21",
66-
"mixpanel-browser": "^2.41.0",
66+
"mixpanel-browser": "^2.42.1",
67+
"ngx-color": "7.0.0",
6768
"rxjs": "~6.6.7",
6869
"tslib": "^2.3.1",
6970
"uuid": "^8.3.2",
@@ -75,42 +76,42 @@
7576
"@angular/cli": "12.2.1",
7677
"@angular/compiler-cli": "~12.2.1",
7778
"@angular/language-service": "~12.2.1",
78-
"@commitlint/cli": "^13.1.0",
79-
"@commitlint/config-conventional": "^13.1.0",
80-
"@compodoc/compodoc": "^1.1.15",
81-
"@ngneat/spectator": "^8.1.0",
79+
"@commitlint/cli": "^16.0.1",
80+
"@commitlint/config-conventional": "^16.0.0",
81+
"@compodoc/compodoc": "^1.1.16",
82+
"@ngneat/spectator": "^8.3.2",
8283
"@types/d3-array": "^2.9.0",
8384
"@types/d3-axis": "^2.0.0",
8485
"@types/d3-brush": "^2.1.0",
8586
"@types/d3-drag": "^1.2.3",
8687
"@types/d3-force": "^2.1.0",
8788
"@types/d3-path": "^2.0.0",
8889
"@types/d3-quadtree": "^1.0.7",
89-
"@types/d3-scale": "^2.1.1",
90+
"@types/d3-scale": "^2.2.6",
9091
"@types/d3-selection": "^1.4.2",
9192
"@types/d3-shape": "^2.1.0",
9293
"@types/d3-zoom": "^1.7.5",
93-
"@types/jest": "^26.0.24",
94+
"@types/jest": "^27.4.0",
9495
"@types/lodash-es": "^4.17.5",
95-
"@types/mixpanel-browser": "^2.35.7",
96-
"@types/node": "^16.7.10",
96+
"@types/mixpanel-browser": "^2.36.0",
97+
"@types/node": "^17.0.5",
9798
"@types/uuid": "^8.3.1",
9899
"@types/webpack-env": "^1.16.3",
99100
"codelyzer": "^6.0.2",
100101
"commitizen": "^4.2.4",
101102
"cz-conventional-changelog": "^3.3.0",
102-
"husky": "^7.0.0",
103+
"husky": "^7.0.4",
103104
"jest": "^26.6.3",
104-
"jest-config": "^27.3.1",
105-
"jest-html-reporter": "^3.4.1",
105+
"jest-config": "^27.4.7",
106+
"jest-html-reporter": "^3.4.2",
106107
"jest-junit": "^13.0.0",
107108
"jest-preset-angular": "^8.4.0",
108109
"lodash": "^4.17.21",
109-
"ng-mocks": "^12.5.0",
110+
"ng-mocks": "^12.5.1",
110111
"ng-packagr": "^12.2.5",
111112
"prettier": "^2.2.1",
112-
"pretty-quick": "^3.1.1",
113-
"ts-node": "~10.2.1",
113+
"pretty-quick": "^3.1.2",
114+
"ts-node": "~10.4.0",
114115
"tslint": "~6.1.3",
115116
"tslint-config-prettier": "^1.18.0",
116117
"typescript": "~4.3.5",

projects/common/src/navigation/navigation.service.test.ts

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import { Location } from '@angular/common';
22
import { Title } from '@angular/platform-browser';
33
import { Router, UrlSegment } from '@angular/router';
44
import { RouterTestingModule } from '@angular/router/testing';
5-
import { IconType } from '@hypertrace/assets-library';
65
import { APP_TITLE } from '@hypertrace/common';
7-
import { NavItemType } from '@hypertrace/components';
86
import { patchRouterNavigateForTest } from '@hypertrace/test-utils';
97
import { createServiceFactory, mockProvider, SpectatorService } from '@ngneat/spectator/jest';
108
import {
@@ -298,36 +296,6 @@ describe('Navigation Service', () => {
298296
}
299297
});
300298

301-
test('decorating navItem with features work as expected', () => {
302-
expect(
303-
spectator.service.decorateNavItem(
304-
{
305-
type: NavItemType.Header,
306-
label: 'Label'
307-
},
308-
spectator.service.getCurrentActivatedRoute()
309-
)
310-
).toEqual({ type: NavItemType.Header, label: 'Label' });
311-
312-
expect(
313-
spectator.service.decorateNavItem(
314-
{
315-
type: NavItemType.Link,
316-
label: 'Label',
317-
icon: IconType.None,
318-
matchPaths: ['root']
319-
},
320-
spectator.service.rootRoute()
321-
)
322-
).toEqual({
323-
type: NavItemType.Link,
324-
label: 'Label',
325-
icon: IconType.None,
326-
matchPaths: ['root'],
327-
features: ['test-feature']
328-
});
329-
});
330-
331299
test('setting title should work as expected', () => {
332300
router.navigate(['root', 'child']);
333301
expect(spectator.inject(Title).setTitle).toHaveBeenCalledWith('defaultAppTitle | child1');

projects/common/src/navigation/navigation.service.ts

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import {
1414
UrlSegment,
1515
UrlTree
1616
} from '@angular/router';
17-
import { NavItemConfig, NavItemType } from '@hypertrace/components';
18-
import { uniq } from 'lodash-es';
1917
import { from, Observable, of } from 'rxjs';
2018
import { distinctUntilChanged, filter, map, share, skip, startWith, switchMap, take, tap } from 'rxjs/operators';
2119
import { isEqualIgnoreFunctions, throwIfNil } from '../utilities/lang/lang-utils';
@@ -243,26 +241,6 @@ export class NavigationService {
243241
return this.findRouteConfig(path, childRoutes ? childRoutes : []);
244242
}
245243

246-
public decorateNavItem(navItem: NavItemConfig, activatedRoute: ActivatedRoute): NavItemConfig {
247-
if (navItem.type !== NavItemType.Link) {
248-
return { ...navItem };
249-
}
250-
const features = navItem.matchPaths
251-
.map(path => this.getRouteConfig([path], activatedRoute))
252-
.filter((maybeRoute): maybeRoute is HtRoute => maybeRoute !== undefined)
253-
.flatMap(route => this.getFeaturesForRoute(route))
254-
.concat(navItem.features || []);
255-
256-
return {
257-
...navItem,
258-
features: uniq(features)
259-
};
260-
}
261-
262-
private getFeaturesForRoute(route: HtRoute): string[] {
263-
return (route.data && route.data.features) || [];
264-
}
265-
266244
public rootRoute(): ActivatedRoute {
267245
return this.router.routerState.root;
268246
}
@@ -376,7 +354,7 @@ export class NavigationService {
376354
}
377355

378356
export interface QueryParamObject extends Params {
379-
[key: string]: string | string[] | number | number[] | undefined;
357+
[key: string]: string | string[] | boolean | boolean[] | number | number[] | undefined;
380358
}
381359

382360
export type NavigationPath = string | (string | Dictionary<string>)[];

projects/common/src/preference/preference.service.ts

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,61 @@
11
import { Injectable } from '@angular/core';
22
import { Observable, of, throwError } from 'rxjs';
33
import { map, switchMap } from 'rxjs/operators';
4+
import { AbstractStorage } from '../utilities/browser/storage/abstract-storage';
45
import { LocalStorage } from '../utilities/browser/storage/local-storage';
6+
import { SessionStorage } from '../utilities/browser/storage/session-storage';
57
import { BooleanCoercer } from '../utilities/coercers/boolean-coercer';
68
import { NumberCoercer } from '../utilities/coercers/number-coercer';
79

10+
export const enum StorageType {
11+
Local = 'local',
12+
Session = 'session'
13+
}
14+
815
@Injectable({
916
providedIn: 'root'
1017
})
1118
export class PreferenceService {
19+
private static readonly DEFAULT_STORAGE_TYPE: StorageType = StorageType.Local;
20+
1221
private static readonly PREFERENCE_STORAGE_NAMESPACE: string = 'preference';
1322
private static readonly SEPARATOR_CHAR: string = '.';
1423
private static readonly SEPARATOR_REGEX: RegExp = /\.(.+)/;
1524
private readonly numberCoercer: NumberCoercer = new NumberCoercer();
1625
private readonly booleanCoercer: BooleanCoercer = new BooleanCoercer();
1726

18-
public constructor(private readonly preferenceStorage: LocalStorage) {}
27+
public constructor(private readonly localStorage: LocalStorage, private readonly sessionStorage: SessionStorage) {}
1928

2029
/**
2130
* Returns the current storage value if defined, else the default value. The observable
2231
* will continue to emit as the preference is updated, reverting to default value if the
2332
* preference becomes unset. If default value is not provided, the observable will
2433
* throw in the case the preference is unset.
2534
*/
26-
public get<T extends PreferenceValue>(key: PreferenceKey, defaultValue?: T): Observable<T> {
27-
return this.preferenceStorage.watch(this.asStorageKey(key)).pipe(
28-
map(storedValue => this.fromStorageValue<T>(storedValue) ?? defaultValue),
29-
switchMap(value =>
30-
value === undefined
31-
? throwError(Error(`No value found or default provided for preferenceKey: ${key}`))
32-
: of(value)
33-
)
34-
);
35+
public get<T extends PreferenceValue>(
36+
key: PreferenceKey,
37+
defaultValue?: T,
38+
type: StorageType = PreferenceService.DEFAULT_STORAGE_TYPE
39+
): Observable<T> {
40+
return this.preferenceStorage(type)
41+
.watch(this.asStorageKey(key))
42+
.pipe(
43+
map(storedValue => this.fromStorageValue<T>(storedValue) ?? defaultValue),
44+
switchMap(value =>
45+
value === undefined
46+
? throwError(Error(`No value found or default provided for preferenceKey: ${key}`))
47+
: of(value)
48+
)
49+
);
3550
}
3651

37-
public set(key: PreferenceKey, value: PreferenceValue): void {
52+
public set(
53+
key: PreferenceKey,
54+
value: PreferenceValue,
55+
type: StorageType = PreferenceService.DEFAULT_STORAGE_TYPE
56+
): void {
3857
const val = this.asStorageValue(value);
39-
this.preferenceStorage.set(this.asStorageKey(key), val);
58+
this.preferenceStorage(type).set(this.asStorageKey(key), val);
4059
}
4160

4261
private asStorageKey(key: PreferenceKey): PreferenceStorageKey {
@@ -70,6 +89,16 @@ export class PreferenceService {
7089
return undefined;
7190
}
7291
}
92+
93+
private preferenceStorage(type: StorageType): AbstractStorage {
94+
switch (type) {
95+
case StorageType.Session:
96+
return this.sessionStorage;
97+
case StorageType.Local:
98+
default:
99+
return this.localStorage;
100+
}
101+
}
73102
}
74103

75104
type PreferenceStorageKey = string;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Time } from './time';
2+
3+
describe('Time', () => {
4+
const mockedTime = new Time(8, 30);
5+
6+
test('can get label', () => {
7+
expect(mockedTime.label).toBe('8:30 AM');
8+
});
9+
10+
test('can get date', () => {
11+
expect(mockedTime.date).toEqual(new Date(`${new Date().toDateString()} 08:30Z`));
12+
});
13+
14+
test('can get ISO String from time', () => {
15+
expect(mockedTime.toISOString()).toBe('08:30:00.000Z');
16+
});
17+
18+
test('can compare two times', () => {
19+
expect(mockedTime.equals(new Time(8, 30))).toBeTruthy();
20+
expect(mockedTime.equals(new Time(9, 30))).toBeFalsy();
21+
});
22+
});

projects/common/src/time/time.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,12 @@ export class Time {
3131
public get date(): Date {
3232
return this._date;
3333
}
34+
35+
public toISOString(): string {
36+
return this.date.toISOString().substring(11);
37+
}
38+
39+
public equals(other?: Time): boolean {
40+
return this.toISOString() === other?.toISOString();
41+
}
3442
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Injectable } from '@angular/core';
2+
import { AbstractStorage } from './abstract-storage';
3+
4+
@Injectable({ providedIn: 'root' })
5+
export class SessionStorage extends AbstractStorage {
6+
public constructor() {
7+
super(sessionStorage);
8+
}
9+
}

projects/components/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
"d3-axis": "^2.1.0",
2828
"d3-scale": "^3.3.0",
2929
"d3-selection": "^1.4.2",
30-
"d3-shape": "^1.3.5"
30+
"d3-shape": "^1.3.5",
31+
"ngx-color": "7.0.0"
3132
},
3233
"devDependencies": {
3334
"@hypertrace/test-utils": "^0.0.0"

projects/components/src/button/button.component.test.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { TrackDirective } from '@hypertrace/common';
44
import { createHostFactory, Spectator } from '@ngneat/spectator/jest';
55
import { MockDirective } from 'ng-mocks';
66
import { IconSize } from '../icon/icon-size';
7-
import { ButtonRole, ButtonSize, ButtonStyle } from './button';
7+
import { ButtonRole, ButtonSize, ButtonStyle, ButtonType } from './button';
88
import { ButtonComponent } from './button.component';
99
import { ButtonModule } from './button.module';
1010

@@ -26,7 +26,22 @@ describe('Button Component', () => {
2626
}
2727
});
2828

29-
expect(spectator.query('.button')).toHaveClass('button secondary small solid');
29+
const buttonEl = spectator.query('.button');
30+
expect(buttonEl).toHaveClass('button secondary small solid');
31+
expect(buttonEl).toHaveAttribute('type', 'button');
32+
});
33+
34+
test('should set correct button type', () => {
35+
spectator = createHost(`<ht-button [label]="label" [type]="type"></ht-button>`, {
36+
hostProps: {
37+
label: 'Button',
38+
type: ButtonType.Submit
39+
}
40+
});
41+
42+
const buttonEl = spectator.query('.button');
43+
expect(buttonEl).toHaveClass('button secondary small solid');
44+
expect(buttonEl).toHaveAttribute('type', 'submit');
3045
});
3146

3247
test('should have correct style class for selected role', () => {

0 commit comments

Comments
 (0)