Skip to content

Commit 6f156d8

Browse files
Patricio AlbizuPatricio Albizu
authored andcommitted
Merge branch 'main' of github.com:hypertrace/hypertrace-ui into DonutAlignment
2 parents a61016d + 2e8e867 commit 6f156d8

15 files changed

+220
-65
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Directive, TemplateRef } from '@angular/core';
2+
3+
@Directive({
4+
selector: '[htListViewValueRenderer]'
5+
})
6+
export class ListViewValueRendererDirective {
7+
public constructor(private readonly templateRef: TemplateRef<unknown>) {}
8+
9+
public getTemplateRef(): TemplateRef<unknown> {
10+
return this.templateRef;
11+
}
12+
}

projects/components/src/list-view/list-view.component.scss

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
@import 'font';
2-
@import 'color-palette';
1+
@import 'mixins';
32

43
$key-width: 40%;
5-
$value-width: 60%;
4+
$value-width: auto;
65
$horizontal-offset: 12px;
76

87
@mixin grid-view {

projects/components/src/list-view/list-view.component.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { CommonModule } from '@angular/common';
22
import { Component } from '@angular/core';
33
import { ComponentFixture, TestBed } from '@angular/core/testing';
4+
import { NavigationService } from '@hypertrace/common';
5+
import { mockProvider } from '@ngneat/spectator/jest';
46
import { ListViewComponent, ListViewHeader, ListViewRecord } from './list-view.component';
57

68
describe('List View Component', () => {
@@ -32,7 +34,8 @@ describe('List View Component', () => {
3234
beforeEach(() => {
3335
TestBed.configureTestingModule({
3436
declarations: [TestHostComponent, ListViewComponent],
35-
imports: [CommonModule]
37+
imports: [CommonModule],
38+
providers: [mockProvider(NavigationService)]
3639
});
3740

3841
fixture = TestBed.createComponent(TestHostComponent);

projects/components/src/list-view/list-view.component.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2-
1+
import { ChangeDetectionStrategy, Component, ContentChild, Input } from '@angular/core';
2+
import { ListViewValueRendererDirective } from './list-view-value-renderer.directive';
33
@Component({
44
selector: 'ht-list-view',
55
styleUrls: ['./list-view.component.scss'],
66
changeDetection: ChangeDetectionStrategy.OnPush,
77
template: `
8+
<ng-template #defaultValueRenderer let-record
9+
><span>{{ record.value }}</span></ng-template
10+
>
811
<div class="list-view">
912
<div *ngIf="this.header" class="header-row">
1013
<div class="header-key-label">
@@ -19,7 +22,12 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
1922
<span>{{ record.key }}</span>
2023
</div>
2124
<div class="value">
22-
<span>{{ record.value }}</span>
25+
<ng-container
26+
*ngTemplateOutlet="
27+
this.valueRenderer ? this.valueRenderer!.getTemplateRef() : defaultValueRenderer;
28+
context: { $implicit: record }
29+
"
30+
></ng-container>
2331
</div>
2432
</div>
2533
</div>
@@ -31,6 +39,9 @@ export class ListViewComponent {
3139

3240
@Input()
3341
public records?: ListViewRecord[];
42+
43+
@ContentChild(ListViewValueRendererDirective)
44+
public valueRenderer?: ListViewValueRendererDirective;
3445
}
3546

3647
export interface ListViewHeader {
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { CommonModule } from '@angular/common';
22
import { NgModule } from '@angular/core';
3+
import { ListViewValueRendererDirective } from './list-view-value-renderer.directive';
34
import { ListViewComponent } from './list-view.component';
45

56
@NgModule({
6-
declarations: [ListViewComponent],
7-
exports: [ListViewComponent],
7+
declarations: [ListViewComponent, ListViewValueRendererDirective],
8+
exports: [ListViewComponent, ListViewValueRendererDirective],
89
imports: [CommonModule]
910
})
1011
export class ListViewModule {}

projects/components/src/modal/modal-container.component.scss

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,6 @@
1111
display: flex;
1212
flex-direction: column;
1313

14-
&.modal-size-small {
15-
height: 365px;
16-
width: 420px;
17-
}
18-
19-
&.modal-size-medium {
20-
height: 530px;
21-
width: 456px;
22-
}
23-
24-
&.modal-size-large-short {
25-
height: 540px;
26-
width: 640px;
27-
}
28-
29-
&.modal-size-large {
30-
height: 720px;
31-
width: 640px;
32-
}
33-
34-
&.modal-size-large-tall {
35-
height: 800px;
36-
width: 640px;
37-
}
38-
39-
&.modal-size-medium-wide {
40-
height: 600px;
41-
width: 840px;
42-
}
43-
4414
.header {
4515
display: flex;
4616
flex-direction: column;

projects/components/src/modal/modal-container.component.test.ts

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ class TestComponent {
2222
describe('Modal Container component', () => {
2323
let spectator: Spectator<ModalContainerComponent>;
2424

25+
const checkSyles = (width: string, height: string): void => {
26+
const modalContainer = spectator.query('.modal-container') as HTMLElement;
27+
expect(modalContainer.style.height).toBe(height);
28+
expect(modalContainer.style.width).toBe(width);
29+
};
30+
2531
const createHost = createHostFactory({
2632
component: ModalContainerComponent,
2733
shallow: true,
@@ -77,14 +83,77 @@ describe('Modal Container component', () => {
7783
expect(spectator.query('.header')).toHaveText('Create User');
7884
});
7985

80-
test('uses the requested size', () => {
86+
test('uses the requested small size', () => {
8187
spectator = createConfiguredHost({
8288
showControls: true,
8389
title: 'Create User',
8490
content: TestComponent,
8591
size: ModalSize.Small
8692
});
87-
expect(spectator.query('.modal-container')).toHaveClass('modal-size-small');
93+
checkSyles('420px', '365px');
94+
});
95+
96+
test('uses the requested medium size', () => {
97+
spectator = createConfiguredHost({
98+
showControls: true,
99+
title: 'Create User',
100+
content: TestComponent,
101+
size: ModalSize.Medium
102+
});
103+
checkSyles('456px', '530px');
104+
});
105+
106+
test('uses the requested large-short size', () => {
107+
spectator = createConfiguredHost({
108+
showControls: true,
109+
title: 'Create User',
110+
content: TestComponent,
111+
size: ModalSize.LargeShort
112+
});
113+
checkSyles('640px', '540px');
114+
});
115+
116+
test('uses the requested large size', () => {
117+
spectator = createConfiguredHost({
118+
showControls: true,
119+
title: 'Create User',
120+
content: TestComponent,
121+
size: ModalSize.Large
122+
});
123+
checkSyles('640px', '720px');
124+
});
125+
126+
test('uses the requested large-tall size', () => {
127+
spectator = createConfiguredHost({
128+
showControls: true,
129+
title: 'Create User',
130+
content: TestComponent,
131+
size: ModalSize.LargeTall
132+
});
133+
checkSyles('640px', '800px');
134+
});
135+
136+
test('uses the requested medium-wide size', () => {
137+
spectator = createConfiguredHost({
138+
showControls: true,
139+
title: 'Create User',
140+
content: TestComponent,
141+
size: ModalSize.MediumWide
142+
});
143+
checkSyles('840px', '600px');
144+
});
145+
146+
test('custom size', () => {
147+
spectator = createConfiguredHost({
148+
showControls: true,
149+
title: 'Create User',
150+
content: TestComponent,
151+
size: {
152+
width: 100,
153+
height: 100
154+
}
155+
});
156+
checkSyles('100px', '100px');
88157
});
89158

90159
test('closes on close button click', () => {

projects/components/src/modal/modal-container.component.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import { LayoutChangeService } from '@hypertrace/common';
44
import { ButtonSize, ButtonStyle } from '../button/button';
55
import { POPOVER_DATA } from '../popover/popover';
66
import { PopoverRef } from '../popover/popover-ref';
7-
import { ModalConfig, ModalSize, MODAL_DATA } from './modal';
7+
import { getModalDimensions, ModalConfig, ModalDimension, MODAL_DATA } from './modal';
88

99
@Component({
1010
selector: 'ht-modal-container',
1111
styleUrls: ['./modal-container.component.scss'],
1212
changeDetection: ChangeDetectionStrategy.OnPush,
1313
template: `
14-
<div *ngIf="this.visible" class="modal-container" [ngClass]="'modal-size-' + this.size">
14+
<div *ngIf="this.visible" class="modal-container" [style.height]="this.size.height" [style.width]="this.size.width">
1515
<div class="header">
1616
<ht-button
1717
*ngIf="this.showControls"
@@ -41,7 +41,7 @@ import { ModalConfig, ModalSize, MODAL_DATA } from './modal';
4141
export class ModalContainerComponent {
4242
public readonly modalTitle: string;
4343
public readonly showControls: boolean;
44-
public readonly size: ModalSize;
44+
public readonly size: ModalDimension;
4545
public readonly isComponentModal: boolean;
4646
public readonly renderer: TemplateRef<unknown> | Type<unknown>;
4747
public readonly rendererInjector: Injector;
@@ -58,7 +58,9 @@ export class ModalContainerComponent {
5858
const config = constructionData.config;
5959
this.showControls = config.showControls ?? false;
6060
this.modalTitle = config.title ?? '';
61-
this.size = config.size;
61+
this.size = this.isModalDimension(config.size)
62+
? this.getDimensionsWithUnits(config.size)
63+
: this.getDimensionsWithUnits(getModalDimensions(config.size));
6264
this.isComponentModal = !(config.content instanceof TemplateRef);
6365
this.closeOnEscape = config.closeOnEscapeKey ?? true;
6466
this.renderer = config.content;
@@ -85,6 +87,24 @@ export class ModalContainerComponent {
8587
this.visible = false;
8688
this.popoverRef.close();
8789
}
90+
91+
private isModalDimension(size: unknown): size is ModalDimension {
92+
// tslint:disable-next-line:strict-type-predicates
93+
return typeof size === 'object' && size !== null && 'width' in (size as ModalDimension);
94+
}
95+
96+
private getDimensionsWithUnits(dims: ModalDimension): ModalDimension {
97+
const dimsWithUnits: ModalDimension = { ...dims };
98+
if (typeof dims.height === 'number') {
99+
dimsWithUnits.height = `${dims.height}px`;
100+
}
101+
102+
if (typeof dims.width === 'number') {
103+
dimsWithUnits.width = `${dims.width}px`;
104+
}
105+
106+
return dimsWithUnits;
107+
}
88108
}
89109

90110
export interface ModalConstructionData {

projects/components/src/modal/modal.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { InjectionToken, TemplateRef, Type } from '@angular/core';
22
import { Observable } from 'rxjs';
33

44
export interface ModalConfig<TData = unknown> {
5-
size: ModalSize;
65
content: TemplateRef<unknown> | Type<unknown>;
6+
size: ModalSize | ModalDimension;
77
showControls?: boolean;
88
title?: string;
99
data?: TData;
@@ -19,6 +19,33 @@ export const enum ModalSize {
1919
MediumWide = 'medium-wide'
2020
}
2121

22+
export interface ModalDimension {
23+
// Number => without unit (considered px) and String => with units (expression included)
24+
width: number | string;
25+
height: number | string;
26+
}
27+
28+
export const getModalDimensions = (modalSize: ModalSize): ModalDimension => {
29+
switch (modalSize) {
30+
case ModalSize.Small:
31+
return getModalDimensionObject(420, 365);
32+
case ModalSize.Medium:
33+
return getModalDimensionObject(456, 530);
34+
case ModalSize.LargeShort:
35+
return getModalDimensionObject(640, 540);
36+
case ModalSize.Large:
37+
return getModalDimensionObject(640, 720);
38+
case ModalSize.LargeTall:
39+
return getModalDimensionObject(640, 800);
40+
case ModalSize.MediumWide:
41+
return getModalDimensionObject(840, 600);
42+
default:
43+
return getModalDimensionObject(420, 365);
44+
}
45+
};
46+
47+
const getModalDimensionObject = (width: number, height: number): ModalDimension => ({ width: width, height: height });
48+
2249
export const MODAL_DATA = new InjectionToken<unknown>('MODAL_DATA');
2350

2451
export abstract class ModalRef<TResult> {

projects/components/src/public-api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ export * from './link/link.component';
167167
export * from './link/link.module';
168168

169169
// List View
170-
export { ListViewComponent, ListViewHeader, ListViewRecord } from './list-view/list-view.component';
171-
export { ListViewModule } from './list-view/list-view.module';
170+
export * from './list-view/list-view.component';
171+
export * from './list-view/list-view.module';
172172

173173
// Load Async
174174
export { LoadAsyncDirective } from './load-async/load-async.directive';

0 commit comments

Comments
 (0)