diff --git a/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.scss b/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.scss new file mode 100644 index 000000000..f80b3d83f --- /dev/null +++ b/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.scss @@ -0,0 +1,19 @@ +@import 'font'; +@import 'color-palette'; + +.string-array-cell { + display: flex; + flex-direction: row; + align-items: center; + + .first-item { + @include ellipsis-overflow(); + padding-right: 8px; + } + + .summary-text { + padding: 0 6px; + background-color: $gray-2; + border-radius: 4px; + } +} diff --git a/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.test.ts b/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.test.ts new file mode 100644 index 000000000..678a6b0ae --- /dev/null +++ b/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.test.ts @@ -0,0 +1,47 @@ +import { TableCellNoOpParser } from '@hypertrace/components'; +import { createComponentFactory } from '@ngneat/spectator/jest'; +import { tableCellDataProvider, tableCellProviders } from '../../test/cell-providers'; +import { StringArrayTableCellRendererComponent } from './string-array-table-cell-renderer.component'; + +describe('String array table cell renderer component', () => { + const buildComponent = createComponentFactory({ + component: StringArrayTableCellRendererComponent, + providers: [ + tableCellProviders( + { + id: 'test' + }, + new TableCellNoOpParser(undefined!) + ) + ], + + shallow: true + }); + + test('should render an array with one item as expected', () => { + const spectator = buildComponent({ + providers: [tableCellDataProvider(['first-item'])] + }); + + expect(spectator.query('.first-item')).toHaveText('first-item'); + expect(spectator.query('.summary-text')).toHaveText(''); + }); + + test('should render an empty array as expected', () => { + const spectator = buildComponent({ + providers: [tableCellDataProvider([])] + }); + + expect(spectator.query('.first-item')).toHaveText('-'); + expect(spectator.query('.summary-text')).toHaveText(''); + }); + + test('should render array with multiple items as expected', () => { + const spectator = buildComponent({ + providers: [tableCellDataProvider(['first-item', 'second-item', 'third-item'])] + }); + + expect(spectator.query('.first-item')).toHaveText('first-item'); + expect(spectator.query('.summary-text')).toHaveText('+2'); + }); +}); diff --git a/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.ts b/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.ts new file mode 100644 index 000000000..2116c7f72 --- /dev/null +++ b/projects/components/src/table/cells/data-renderers/string-array/string-array-table-cell-renderer.component.ts @@ -0,0 +1,57 @@ +import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core'; +import { TableColumnConfig, TableRow } from '../../../table-api'; +import { + TABLE_CELL_DATA, + TABLE_COLUMN_CONFIG, + TABLE_COLUMN_INDEX, + TABLE_DATA_PARSER, + TABLE_ROW_DATA +} from '../../table-cell-injection'; +import { TableCellParserBase } from '../../table-cell-parser-base'; +import { TableCellRenderer } from '../../table-cell-renderer'; +import { TableCellRendererBase } from '../../table-cell-renderer-base'; +import { CoreTableCellParserType } from '../../types/core-table-cell-parser-type'; +import { CoreTableCellRendererType } from '../../types/core-table-cell-renderer-type'; +import { TableCellAlignmentType } from '../../types/table-cell-alignment-type'; + +@Component({ + selector: 'ht-string-array-table-cell-renderer', + styleUrls: ['./string-array-table-cell-renderer.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` +
+ {{ this.firstItem }} + {{ this.summaryText }} + + +
{{ value }}
+
+
+ ` +}) +@TableCellRenderer({ + type: CoreTableCellRendererType.StringArray, + alignment: TableCellAlignmentType.Left, + parser: CoreTableCellParserType.NoOp +}) +export class StringArrayTableCellRendererComponent extends TableCellRendererBase implements OnInit { + public firstItem!: string; + public summaryText!: string; + + public constructor( + @Inject(TABLE_COLUMN_CONFIG) columnConfig: TableColumnConfig, + @Inject(TABLE_COLUMN_INDEX) index: number, + @Inject(TABLE_DATA_PARSER) parser: TableCellParserBase, + @Inject(TABLE_CELL_DATA) cellData: string[], + @Inject(TABLE_ROW_DATA) rowData: TableRow + ) { + super(columnConfig, index, parser, cellData, rowData); + } + + public ngOnInit(): void { + super.ngOnInit(); + + this.firstItem = this.value[0] ?? '-'; + this.summaryText = this.value.length > 1 ? `+${this.value.length - 1}` : ''; + } +} diff --git a/projects/components/src/table/cells/table-cells.module.ts b/projects/components/src/table/cells/table-cells.module.ts index 0a87f9300..2169f6693 100644 --- a/projects/components/src/table/cells/table-cells.module.ts +++ b/projects/components/src/table/cells/table-cells.module.ts @@ -19,6 +19,7 @@ import { TableCellTimestampParser } from './data-parsers/table-cell-timestamp-pa import { CodeTableCellRendererComponent } from './data-renderers/code/code-table-cell-renderer.component'; import { IconTableCellRendererComponent } from './data-renderers/icon/icon-table-cell-renderer.component'; import { NumericTableCellRendererComponent } from './data-renderers/numeric/numeric-table-cell-renderer.component'; +import { StringArrayTableCellRendererComponent } from './data-renderers/string-array/string-array-table-cell-renderer.component'; import { TableDataCellRendererComponent } from './data-renderers/table-data-cell-renderer.component'; import { TextTableCellRendererComponent } from './data-renderers/text/text-table-cell-renderer.component'; import { TimeAgoTableCellRendererComponent } from './data-renderers/time-ago/time-ago-table-cell-renderer.component'; @@ -64,7 +65,8 @@ export const TABLE_CELL_PARSERS = new InjectionToken('TABLE_CELL_PA TextTableCellRendererComponent, TimestampTableCellRendererComponent, TimeAgoTableCellRendererComponent, - CodeTableCellRendererComponent + CodeTableCellRendererComponent, + StringArrayTableCellRendererComponent ], providers: [ { @@ -77,7 +79,8 @@ export const TABLE_CELL_PARSERS = new InjectionToken('TABLE_CELL_PA TextTableCellRendererComponent, TimestampTableCellRendererComponent, TimeAgoTableCellRendererComponent, - CodeTableCellRendererComponent + CodeTableCellRendererComponent, + StringArrayTableCellRendererComponent ], multi: true }, diff --git a/projects/components/src/table/cells/types/core-table-cell-renderer-type.ts b/projects/components/src/table/cells/types/core-table-cell-renderer-type.ts index 8be4d8506..b52550bc9 100644 --- a/projects/components/src/table/cells/types/core-table-cell-renderer-type.ts +++ b/projects/components/src/table/cells/types/core-table-cell-renderer-type.ts @@ -4,6 +4,7 @@ export const enum CoreTableCellRendererType { Icon = 'icon', Number = 'number', RowExpander = 'row-expander', + StringArray = 'string-array', Text = 'text', Timestamp = 'timestamp', TimeAgo = 'time-ago'