diff --git a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_component.ts b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_component.ts index c438efa607..c690bdb6b8 100644 --- a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_component.ts +++ b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_component.ts @@ -122,7 +122,8 @@ export class ScalarCardComponent { @ViewChild(LineChartComponent) lineChart?: LineChartComponent; sortingInfo: SortingInfo = { - header: ColumnHeaderType.RUN, + header: ColumnHeaderType.RUN, //This is no longer used but the type needs it or it will break sync. TODO(jameshollyer): remove this once internal code all uses name. + name: 'run', order: SortingOrder.ASCENDING, }; diff --git a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_data_table.ts b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_data_table.ts index 9e71487b99..e82a2733e3 100644 --- a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_data_table.ts +++ b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_data_table.ts @@ -131,8 +131,8 @@ export class ScalarCardDataTable { } const selectedStepData: SelectedStepRunData = { id: datum.id, + color: metadata.color, }; - selectedStepData.COLOR = metadata.color; for (const header of this.columnHeaders) { switch (header.type) { case ColumnHeaderType.RUN: @@ -140,51 +140,51 @@ export class ScalarCardDataTable { if (metadata.alias) { alias = `${metadata.alias.aliasNumber} ${metadata.alias.aliasText}/`; } - selectedStepData.RUN = `${alias}${metadata.displayName}`; + selectedStepData[header.name] = `${alias}${metadata.displayName}`; continue; case ColumnHeaderType.STEP: - selectedStepData.STEP = closestStartPoint.step; + selectedStepData[header.name] = closestStartPoint.step; continue; case ColumnHeaderType.VALUE: - selectedStepData.VALUE = closestStartPoint.value; + selectedStepData[header.name] = closestStartPoint.value; continue; case ColumnHeaderType.RELATIVE_TIME: - selectedStepData.RELATIVE_TIME = + selectedStepData[header.name] = closestStartPoint.relativeTimeInMs; continue; case ColumnHeaderType.SMOOTHED: - selectedStepData.SMOOTHED = closestStartPoint.y; + selectedStepData[header.name] = closestStartPoint.y; continue; case ColumnHeaderType.VALUE_CHANGE: if (!closestEndPoint) { continue; } - selectedStepData.VALUE_CHANGE = + selectedStepData[header.name] = closestEndPoint.y - closestStartPoint.y; continue; case ColumnHeaderType.START_STEP: - selectedStepData.START_STEP = closestStartPoint.step; + selectedStepData[header.name] = closestStartPoint.step; continue; case ColumnHeaderType.END_STEP: if (!closestEndPoint) { continue; } - selectedStepData.END_STEP = closestEndPoint.step; + selectedStepData[header.name] = closestEndPoint.step; continue; case ColumnHeaderType.START_VALUE: - selectedStepData.START_VALUE = closestStartPoint.y; + selectedStepData[header.name] = closestStartPoint.y; continue; case ColumnHeaderType.END_VALUE: if (!closestEndPoint) { continue; } - selectedStepData.END_VALUE = closestEndPoint.y; + selectedStepData[header.name] = closestEndPoint.y; continue; case ColumnHeaderType.MIN_VALUE: if (!closestEndPointIndex) { continue; } - selectedStepData.MIN_VALUE = this.getMinPointInRange( + selectedStepData[header.name] = this.getMinPointInRange( datum.points, closestStartPointIndex, closestEndPointIndex @@ -194,7 +194,7 @@ export class ScalarCardDataTable { if (!closestEndPointIndex) { continue; } - selectedStepData.MAX_VALUE = this.getMaxPointInRange( + selectedStepData[header.name] = this.getMaxPointInRange( datum.points, closestStartPointIndex, closestEndPointIndex @@ -204,14 +204,14 @@ export class ScalarCardDataTable { if (!closestEndPoint) { continue; } - selectedStepData.PERCENTAGE_CHANGE = + selectedStepData[header.name] = (closestEndPoint.y - closestStartPoint.y) / closestStartPoint.y; continue; case ColumnHeaderType.STEP_AT_MAX: if (!closestEndPointIndex) { continue; } - selectedStepData.STEP_AT_MAX = this.getMaxPointInRange( + selectedStepData[header.name] = this.getMaxPointInRange( datum.points, closestStartPointIndex, closestEndPointIndex @@ -221,7 +221,7 @@ export class ScalarCardDataTable { if (!closestEndPointIndex) { continue; } - selectedStepData.STEP_AT_MIN = this.getMinPointInRange( + selectedStepData[header.name] = this.getMinPointInRange( datum.points, closestStartPointIndex, closestEndPointIndex @@ -231,7 +231,7 @@ export class ScalarCardDataTable { if (!closestEndPointIndex) { continue; } - selectedStepData.MEAN = this.getMean( + selectedStepData[header.name] = this.getMean( datum.points, closestStartPointIndex, closestEndPointIndex @@ -241,7 +241,7 @@ export class ScalarCardDataTable { if (!closestEndPoint) { continue; } - selectedStepData.RAW_CHANGE = + selectedStepData[header.name] = closestEndPoint.value - closestStartPoint.value; continue; default: @@ -250,35 +250,39 @@ export class ScalarCardDataTable { } return selectedStepData; }); - dataTableData.sort( - (point1: SelectedStepRunData, point2: SelectedStepRunData) => { - const p1 = this.getSortableValue(point1, this.sortingInfo.header); - const p2 = this.getSortableValue(point2, this.sortingInfo.header); - if (p1 < p2) { - return this.sortingInfo.order === SortingOrder.ASCENDING ? -1 : 1; - } - if (p1 > p2) { - return this.sortingInfo.order === SortingOrder.ASCENDING ? 1 : -1; - } - - return 0; - } + const sortingHeader = this.columnHeaders.find( + (header) => header.name === this.sortingInfo.name ); + if (sortingHeader !== undefined) { + dataTableData.sort( + (point1: SelectedStepRunData, point2: SelectedStepRunData) => { + if (!sortingHeader) { + return 0; + } + const p1 = this.getSortableValue(point1, sortingHeader); + const p2 = this.getSortableValue(point2, sortingHeader); + if (p1 < p2) { + return this.sortingInfo.order === SortingOrder.ASCENDING ? -1 : 1; + } + if (p1 > p2) { + return this.sortingInfo.order === SortingOrder.ASCENDING ? 1 : -1; + } + + return 0; + } + ); + } return dataTableData; } - private getSortableValue( - point: SelectedStepRunData, - header: ColumnHeaderType - ) { - switch (header) { - // The value shown in the "RUN" column is a string concatenation of Alias Id + Alias + Run Name - // but we would actually prefer to sort by just the run name. - case ColumnHeaderType.RUN: - return makeValueSortable(this.chartMetadataMap[point.id].displayName); - default: - return makeValueSortable(point[header]); + private getSortableValue(point: SelectedStepRunData, header: ColumnHeader) { + // The value shown in the "RUN" column is a string concatenation of Alias Id + Alias + Run Name + // but we would actually prefer to sort by just the run name. + if (header.type === ColumnHeaderType.RUN) { + return makeValueSortable(this.chartMetadataMap[point.id].displayName); } + + return makeValueSortable(point[header.name]); } orderColumns(headers: ColumnHeader[]) { diff --git a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts index 94139cb618..d3bd65a5ce 100644 --- a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts +++ b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_test.ts @@ -2834,21 +2834,21 @@ describe('scalar card', () => { expect(data).toEqual([ { id: 'run1', - COLOR: '#fff', - RELATIVE_TIME: 1000, - RUN: 'run1', - STEP: 2, - VALUE: 10, - SMOOTHED: 10, + color: '#fff', + relativeTime: 1000, + run: 'run1', + step: 2, + value: 10, + smoothed: 10, }, { id: 'run2', - COLOR: '#fff', - RELATIVE_TIME: 1000, - RUN: 'run2', - STEP: 2, - VALUE: 10, - SMOOTHED: 10, + color: '#fff', + relativeTime: 1000, + run: 'run2', + step: 2, + value: 10, + smoothed: 10, }, ]); })); @@ -2899,37 +2899,37 @@ describe('scalar card', () => { expect(data).toEqual([ { id: 'run1', - COLOR: '#fff', - RUN: 'run1', - VALUE_CHANGE: 19, - START_STEP: 1, - END_STEP: 3, - START_VALUE: 1, - END_VALUE: 20, - MIN_VALUE: 1, - MAX_VALUE: 20, - PERCENTAGE_CHANGE: 19, // percentage change from 1 to 20 is 1900% - STEP_AT_MAX: 3, - STEP_AT_MIN: 1, - MEAN: 11, - RAW_CHANGE: 19, + color: '#fff', + run: 'run1', + valueChange: 19, + startStep: 1, + endStep: 3, + startValue: 1, + endValue: 20, + minValue: 1, + maxValue: 20, + percentageChange: 19, // percentage change from 1 to 20 is 1900% + stepAtMax: 3, + stepAtMin: 1, + mean: 11, + rawChange: 19, }, { id: 'run2', - COLOR: '#fff', - RUN: 'run2', - VALUE_CHANGE: 24, - START_STEP: 1, - END_STEP: 3, - START_VALUE: 1, - END_VALUE: 25, - MIN_VALUE: 1, - MAX_VALUE: 25, - PERCENTAGE_CHANGE: 24, // percentage change from 1 to 25 is 2400% - STEP_AT_MAX: 3, - STEP_AT_MIN: 1, - MEAN: 12, - RAW_CHANGE: 24, + color: '#fff', + run: 'run2', + valueChange: 24, + startStep: 1, + endStep: 3, + startValue: 1, + endValue: 25, + minValue: 1, + maxValue: 25, + percentageChange: 24, // percentage change from 1 to 25 is 2400% + stepAtMax: 3, + stepAtMin: 1, + mean: 12, + rawChange: 24, }, ]); })); @@ -2975,20 +2975,20 @@ describe('scalar card', () => { expect(data).toEqual([ { id: '["smoothed","run1"]', - COLOR: '#fff', - RUN: 'run1', - VALUE_CHANGE: 10.515172900494004, - START_STEP: 2, - END_STEP: 4, - START_VALUE: 8.46153846153846, - END_VALUE: 18.976711362032464, - MIN_VALUE: 4.532374100719424, - MAX_VALUE: 18.976711362032464, - PERCENTAGE_CHANGE: 1.2427022518765645, - STEP_AT_MAX: 4, - STEP_AT_MIN: 3, - MEAN: 12, - RAW_CHANGE: 17, + color: '#fff', + run: 'run1', + valueChange: 10.515172900494004, + startStep: 2, + endStep: 4, + startValue: 8.46153846153846, + endValue: 18.976711362032464, + minValue: 4.532374100719424, + maxValue: 18.976711362032464, + percentageChange: 1.2427022518765645, + stepAtMax: 4, + stepAtMin: 3, + mean: 12, + rawChange: 17, }, ]); })); @@ -3034,20 +3034,20 @@ describe('scalar card', () => { expect(data).toEqual([ { id: 'run1', - COLOR: '#fff', - RUN: 'run1', - VALUE_CHANGE: 10, - START_STEP: 2, - END_STEP: 5, - START_VALUE: 5, - END_VALUE: 15, - MIN_VALUE: 4, - MAX_VALUE: 20, - PERCENTAGE_CHANGE: 2, - STEP_AT_MAX: 4, - STEP_AT_MIN: 3, - MEAN: 11, - RAW_CHANGE: 10, + color: '#fff', + run: 'run1', + valueChange: 10, + startStep: 2, + endStep: 5, + startValue: 5, + endValue: 15, + minValue: 4, + maxValue: 20, + percentageChange: 2, + stepAtMax: 4, + stepAtMin: 3, + mean: 11, + rawChange: 10, }, ]); })); @@ -3094,8 +3094,8 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].STEP).toEqual(20); - expect(data[1].STEP).toEqual(15); + expect(data[0].step).toEqual(20); + expect(data[1].step).toEqual(15); })); it('selects closest start and end points to ranged time selection', fakeAsync(() => { @@ -3141,10 +3141,10 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].START_STEP).toEqual(1); - expect(data[1].START_STEP).toEqual(3); - expect(data[0].END_STEP).toEqual(20); - expect(data[1].END_STEP).toEqual(25); + expect(data[0].startStep).toEqual(1); + expect(data[1].startStep).toEqual(3); + expect(data[0].endStep).toEqual(20); + expect(data[1].endStep).toEqual(25); })); it('selects largest points when time selection startStep is greater than any points step', fakeAsync(() => { @@ -3189,8 +3189,8 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].STEP).toEqual(35); - expect(data[1].STEP).toEqual(50); + expect(data[0].step).toEqual(35); + expect(data[1].step).toEqual(50); })); it('selects smallest points when time selection startStep is less than any points step', fakeAsync(() => { @@ -3234,8 +3234,8 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].STEP).toEqual(10); - expect(data[1].STEP).toEqual(8); + expect(data[0].step).toEqual(10); + expect(data[1].step).toEqual(8); })); it('renders alias', fakeAsync(() => { @@ -3294,8 +3294,8 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].RUN).toEqual('100 test alias 1/Run1 name'); - expect(data[1].RUN).toEqual('200 test alias 2/Run2 name'); + expect(data[0].run).toEqual('100 test alias 1/Run1 name'); + expect(data[1].run).toEqual('200 test alias 2/Run2 name'); })); it('edits smoothed value when smoothed is enabled', fakeAsync(() => { @@ -3337,7 +3337,7 @@ describe('scalar card', () => { ).toBeGreaterThanOrEqual(0); expect( scalarCardDataTable.componentInstance.getTimeSelectionTableData()[0] - .SMOOTHED + .smoothed ).toBe(6.000000000000001); })); @@ -3373,7 +3373,7 @@ describe('scalar card', () => { By.directive(ScalarCardDataTable) ); scalarCardDataTable.componentInstance.sortingInfo = { - header: ColumnHeaderType.VALUE, + name: 'value', order: SortingOrder.ASCENDING, }; fixture.detectChanges(); @@ -3381,9 +3381,9 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].RUN).toEqual('run2'); - expect(data[1].RUN).toEqual('run1'); - expect(data[2].RUN).toEqual('run3'); + expect(data[0].run).toEqual('run2'); + expect(data[1].run).toEqual('run1'); + expect(data[2].run).toEqual('run3'); })); it('orders data descending', fakeAsync(() => { @@ -3418,7 +3418,7 @@ describe('scalar card', () => { By.directive(ScalarCardDataTable) ); scalarCardDataTable.componentInstance.sortingInfo = { - header: ColumnHeaderType.VALUE, + name: 'value', order: SortingOrder.DESCENDING, }; fixture.detectChanges(); @@ -3426,9 +3426,9 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].RUN).toEqual('run3'); - expect(data[1].RUN).toEqual('run1'); - expect(data[2].RUN).toEqual('run2'); + expect(data[0].run).toEqual('run3'); + expect(data[1].run).toEqual('run1'); + expect(data[2].run).toEqual('run2'); })); it('Correctly orders NaNs', fakeAsync(() => { @@ -3471,7 +3471,7 @@ describe('scalar card', () => { By.directive(ScalarCardDataTable) ); scalarCardDataTable.componentInstance.sortingInfo = { - header: ColumnHeaderType.VALUE, + name: 'value', order: SortingOrder.DESCENDING, }; fixture.detectChanges(); @@ -3479,13 +3479,13 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].RUN).toEqual('run3'); - expect(data[1].RUN).toEqual('run2'); - expect(data[2].RUN).toEqual('run1'); - expect(data[3].RUN).toEqual('run4'); - expect(data[4].RUN).toEqual('run5'); - expect(data[5].RUN).toEqual('run6'); - expect(data[6].RUN).toEqual('run7'); + expect(data[0].run).toEqual('run3'); + expect(data[1].run).toEqual('run2'); + expect(data[2].run).toEqual('run1'); + expect(data[3].run).toEqual('run4'); + expect(data[4].run).toEqual('run5'); + expect(data[5].run).toEqual('run6'); + expect(data[6].run).toEqual('run7'); })); it('Sorts RUNS column by displayName', fakeAsync(() => { @@ -3528,7 +3528,7 @@ describe('scalar card', () => { By.directive(ScalarCardDataTable) ); scalarCardDataTable.componentInstance.sortingInfo = { - header: ColumnHeaderType.RUN, + name: 'run', order: SortingOrder.ASCENDING, }; scalarCardDataTable.componentInstance.chartMetadataMap.run1.alias = { @@ -3564,13 +3564,13 @@ describe('scalar card', () => { const data = scalarCardDataTable.componentInstance.getTimeSelectionTableData(); - expect(data[0].RUN).toEqual('5 g/run1'); - expect(data[1].RUN).toEqual('6 f/run2'); - expect(data[2].RUN).toEqual('7 e/run3'); - expect(data[3].RUN).toEqual('4 d/run4'); - expect(data[4].RUN).toEqual('2 b/run5'); - expect(data[5].RUN).toEqual('3 c/run6'); - expect(data[6].RUN).toEqual('1 a/run7'); + expect(data[0].run).toEqual('5 g/run1'); + expect(data[1].run).toEqual('6 f/run2'); + expect(data[2].run).toEqual('7 e/run3'); + expect(data[3].run).toEqual('4 d/run4'); + expect(data[4].run).toEqual('2 b/run5'); + expect(data[5].run).toEqual('3 c/run6'); + expect(data[6].run).toEqual('1 a/run7'); })); }); diff --git a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_types.ts b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_types.ts index 7ac0ebeb43..29e0dba0e6 100644 --- a/tensorboard/webapp/metrics/views/card_renderer/scalar_card_types.ts +++ b/tensorboard/webapp/metrics/views/card_renderer/scalar_card_types.ts @@ -116,7 +116,12 @@ export enum SortingOrder { } export interface SortingInfo { + // Currently in the process of moving from header to name. + // Header is no longer used but is required as to not break sync + // TODO(jameshollyer): Remove header once all internal code is switched + // to using name and make name required. header: ColumnHeaderType; + name?: string; order: SortingOrder; } @@ -125,9 +130,9 @@ export interface SortingInfo { * DataTable. It will have a value for each required ColumnHeader for a given * run. */ -export type SelectedStepRunData = { - [key in ColumnHeaderType]?: string | number; -} & {id: string}; +export type SelectedStepRunData = Record & { + id: string; +}; /** * An object which is intended to hold the min and max step within each scalar diff --git a/tensorboard/webapp/widgets/data_table/data_table_component.ng.html b/tensorboard/webapp/widgets/data_table/data_table_component.ng.html index 4d67e35fd7..b50a93b7b8 100644 --- a/tensorboard/webapp/widgets/data_table/data_table_component.ng.html +++ b/tensorboard/webapp/widgets/data_table/data_table_component.ng.html @@ -20,26 +20,26 @@ - +
@@ -52,24 +52,27 @@ - +
- {{ getFormattedDataForColumn(header.type, runData) }} + {{ getFormattedDataForColumn(header.type, runData[header.name]) + }}
- {{ getFormattedDataForColumn(header.type, runData) }} + {{ getFormattedDataForColumn(header.type, runData[header.name]) + }}
- {{ getFormattedDataForColumn(header.type, runData) }} + {{ getFormattedDataForColumn(header.type, runData[header.name]) + }}
diff --git a/tensorboard/webapp/widgets/data_table/data_table_component.ts b/tensorboard/webapp/widgets/data_table/data_table_component.ts index deaa5691d1..ad14ad3b6f 100644 --- a/tensorboard/webapp/widgets/data_table/data_table_component.ts +++ b/tensorboard/webapp/widgets/data_table/data_table_component.ts @@ -65,8 +65,8 @@ export class DataTableComponent implements OnDestroy { readonly SortingOrder = SortingOrder; readonly Side = Side; - draggingHeaderType: ColumnHeaderType | undefined; - highlightedColumnType: ColumnHeaderType | undefined; + draggingHeaderName: string | undefined; + highlightedColumnName: string | undefined; highlightSide: Side = Side.RIGHT; ngOnDestroy() { @@ -75,186 +75,98 @@ export class DataTableComponent implements OnDestroy { getFormattedDataForColumn( columnHeader: ColumnHeaderType, - selectedStepRunData: SelectedStepRunData + datum: string | number | undefined ): string { + if (datum === undefined) { + return ''; + } switch (columnHeader) { case ColumnHeaderType.RUN: - if (selectedStepRunData.RUN === undefined) { - return ''; - } - return selectedStepRunData.RUN as string; + return datum as string; case ColumnHeaderType.VALUE: - if (selectedStepRunData.VALUE === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.VALUE as number - ); case ColumnHeaderType.STEP: - if (selectedStepRunData.STEP === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.STEP as number - ); - case ColumnHeaderType.TIME: - if (selectedStepRunData.TIME === undefined) { - return ''; - } - const time = new Date(selectedStepRunData.TIME!); - return time.toISOString(); - case ColumnHeaderType.RELATIVE_TIME: - if (selectedStepRunData.RELATIVE_TIME === undefined) { - return ''; - } - return relativeTimeFormatter.formatReadable( - selectedStepRunData.RELATIVE_TIME as number - ); case ColumnHeaderType.SMOOTHED: - if (selectedStepRunData.SMOOTHED === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.SMOOTHED as number - ); - case ColumnHeaderType.VALUE_CHANGE: - if (selectedStepRunData.VALUE_CHANGE === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - Math.abs(selectedStepRunData.VALUE_CHANGE as number) - ); case ColumnHeaderType.START_STEP: - if (selectedStepRunData.START_STEP === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.START_STEP as number - ); case ColumnHeaderType.END_STEP: - if (selectedStepRunData.END_STEP === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.END_STEP as number - ); case ColumnHeaderType.START_VALUE: - if (selectedStepRunData.START_VALUE === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.START_VALUE as number - ); case ColumnHeaderType.END_VALUE: - if (selectedStepRunData.END_VALUE === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.END_VALUE as number - ); case ColumnHeaderType.MIN_VALUE: - if (selectedStepRunData.MIN_VALUE === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.MIN_VALUE as number - ); case ColumnHeaderType.MAX_VALUE: - if (selectedStepRunData.MAX_VALUE === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.MAX_VALUE as number - ); - case ColumnHeaderType.PERCENTAGE_CHANGE: - if (selectedStepRunData.PERCENTAGE_CHANGE === undefined) { - return ''; - } - return ( - Math.round( - (selectedStepRunData.PERCENTAGE_CHANGE as number) * 100 - ).toString() + '%' - ); case ColumnHeaderType.STEP_AT_MAX: - if (selectedStepRunData.STEP_AT_MAX === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.STEP_AT_MAX as number - ); case ColumnHeaderType.STEP_AT_MIN: - if (selectedStepRunData.STEP_AT_MIN === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.STEP_AT_MIN as number - ); case ColumnHeaderType.MEAN: - if (selectedStepRunData.MEAN === undefined) { - return ''; - } - return intlNumberFormatter.formatShort( - selectedStepRunData.MEAN as number - ); + return intlNumberFormatter.formatShort(datum as number); + case ColumnHeaderType.TIME: + const time = new Date(datum!); + return time.toISOString(); + case ColumnHeaderType.RELATIVE_TIME: + return relativeTimeFormatter.formatReadable(datum as number); + case ColumnHeaderType.VALUE_CHANGE: + return intlNumberFormatter.formatShort(Math.abs(datum as number)); + case ColumnHeaderType.PERCENTAGE_CHANGE: + return Math.round((datum as number) * 100).toString() + '%'; case ColumnHeaderType.RAW_CHANGE: - if (selectedStepRunData.RAW_CHANGE === undefined) { - return ''; - } - return numberFormatter.formatShort( - Math.abs(selectedStepRunData.RAW_CHANGE as number) - ); + return numberFormatter.formatShort(Math.abs(datum as number)); default: return ''; } } - headerClicked(header: ColumnHeaderType) { + headerClicked(name: string) { if ( - this.sortingInfo.header === header && + this.sortingInfo.name === name && this.sortingInfo.order === SortingOrder.ASCENDING ) { - this.sortDataBy.emit({header, order: SortingOrder.DESCENDING}); + this.sortDataBy.emit({ + header: ColumnHeaderType.RUN, //This is no longer used but the sortingInfo interface needs it or it will break sync. TODO(jameshollyer): remove this once internal code all uses name. + name, + order: SortingOrder.DESCENDING, + }); return; } - this.sortDataBy.emit({header, order: SortingOrder.ASCENDING}); + this.sortDataBy.emit({ + header: ColumnHeaderType.RUN, //This is no longer used but the sortingInfo interface needs it or it will break sync. TODO(jameshollyer): remove this once internal code all uses name. + name, + order: SortingOrder.ASCENDING, + }); } dragStart(header: ColumnHeader) { - this.draggingHeaderType = header.type; + this.draggingHeaderName = header.name; // This stop the end drag animation document.addEventListener('dragover', preventDefault); } dragEnd() { - if (!this.draggingHeaderType || !this.highlightedColumnType) { + if (!this.draggingHeaderName || !this.highlightedColumnName) { return; } this.orderColumns.emit( this.moveHeader( - this.getIndexOfHeaderWithType(this.draggingHeaderType!), - this.getIndexOfHeaderWithType(this.highlightedColumnType!) + this.getIndexOfHeaderWithName(this.draggingHeaderName!), + this.getIndexOfHeaderWithName(this.highlightedColumnName!) ) ); - this.draggingHeaderType = undefined; - this.highlightedColumnType = undefined; + this.draggingHeaderName = undefined; + this.highlightedColumnName = undefined; document.removeEventListener('dragover', preventDefault); } dragEnter(header: ColumnHeader) { - if (!this.draggingHeaderType) { + if (!this.draggingHeaderName) { return; } if ( - this.getIndexOfHeaderWithType(header.type) < - this.getIndexOfHeaderWithType(this.draggingHeaderType!) + this.getIndexOfHeaderWithName(header.name) < + this.getIndexOfHeaderWithName(this.draggingHeaderName!) ) { this.highlightSide = Side.LEFT; } else { this.highlightSide = Side.RIGHT; } - this.highlightedColumnType = header.type; + this.highlightedColumnName = header.name; } // Move the item at sourceIndex to destinationIndex @@ -267,8 +179,8 @@ export class DataTableComponent implements OnDestroy { return newHeaders; } - getHeaderHighlightStyle(header: ColumnHeaderType) { - if (header !== this.highlightedColumnType) { + getHeaderHighlightStyle(name: string) { + if (name !== this.highlightedColumnName) { return {}; } @@ -286,9 +198,9 @@ export class DataTableComponent implements OnDestroy { ); } - getIndexOfHeaderWithType(type: ColumnHeaderType) { + getIndexOfHeaderWithName(name: string) { return this.headers.findIndex((element) => { - return type === element.type; + return name === element.name; }); } } diff --git a/tensorboard/webapp/widgets/data_table/data_table_test.ts b/tensorboard/webapp/widgets/data_table/data_table_test.ts index 2b764ee17b..eb441739f9 100644 --- a/tensorboard/webapp/widgets/data_table/data_table_test.ts +++ b/tensorboard/webapp/widgets/data_table/data_table_test.ts @@ -76,6 +76,7 @@ describe('data table', () => { fixture.componentInstance.data = input.data || []; fixture.componentInstance.sortingInfo = input.sortingInfo || { header: ColumnHeaderType.RUN, + name: 'run', order: SortingOrder.ASCENDING, }; @@ -184,7 +185,7 @@ describe('data table', () => { }, { type: ColumnHeaderType.VALUE_CHANGE, - name: 'valueChanged', + name: 'valueChange', displayName: 'Value', enabled: true, }, @@ -226,7 +227,7 @@ describe('data table', () => { }, { type: ColumnHeaderType.PERCENTAGE_CHANGE, - name: 'percentageChanged', + name: 'percentageChange', displayName: '%', enabled: true, }, @@ -240,19 +241,19 @@ describe('data table', () => { data: [ { id: 'someid', - RUN: 'run name', - VALUE: 31415926535, - STEP: 1, - RELATIVE_TIME: 123, - VALUE_CHANGE: -20, - START_STEP: 5, - END_STEP: 30, - START_VALUE: 13, - END_VALUE: 23, - MIN_VALUE: 0.12345, - MAX_VALUE: 89793238462, - PERCENTAGE_CHANGE: 0.3, - SMOOTHED: 3.14e10, + run: 'run name', + value: 31415926535, + step: 1, + relativeTime: 123, + valueChange: -20, + startStep: 5, + endStep: 30, + startValue: 13, + endValue: 23, + minValue: 0.12345, + maxValue: 89793238462, + percentageChange: 0.3, + smoothed: 3.14e10, }, ], }); @@ -313,9 +314,9 @@ describe('data table', () => { data: [ { id: 'someid', - RUN: 'run name', - VALUE: 3, - STEP: 1, + run: 'run name', + value: 3, + step: 1, }, ], }); @@ -409,7 +410,8 @@ describe('data table', () => { headerElements[3].triggerEventHandler('click', {}); expect(sortDataBySpy).toHaveBeenCalledOnceWith({ - header: ColumnHeaderType.STEP, + header: jasmine.any(String), // This attribute is no longer used but temporarily left here to no break internal syncs + name: 'step', order: SortingOrder.ASCENDING, }); }); @@ -444,6 +446,7 @@ describe('data table', () => { ], sortingInfo: { header: ColumnHeaderType.STEP, + name: 'step', order: SortingOrder.ASCENDING, }, }); @@ -452,7 +455,8 @@ describe('data table', () => { headerElements[3].triggerEventHandler('click', {}); expect(sortDataBySpy).toHaveBeenCalledOnceWith({ - header: ColumnHeaderType.STEP, + header: jasmine.any(String), // This attribute is no longer used but temporarily left here to no break internal syncs + name: 'step', order: SortingOrder.DESCENDING, }); }); @@ -481,6 +485,7 @@ describe('data table', () => { ], sortingInfo: { header: ColumnHeaderType.VALUE, + name: 'value', order: SortingOrder.ASCENDING, }, }); @@ -543,6 +548,7 @@ describe('data table', () => { ], sortingInfo: { header: ColumnHeaderType.STEP, + name: 'step', order: SortingOrder.DESCENDING, }, }); @@ -605,6 +611,7 @@ describe('data table', () => { ], sortingInfo: { header: ColumnHeaderType.STEP, + name: 'step', order: SortingOrder.DESCENDING, }, }); @@ -672,6 +679,7 @@ describe('data table', () => { ], sortingInfo: { header: ColumnHeaderType.STEP, + name: 'step', order: SortingOrder.DESCENDING, }, }); @@ -746,10 +754,10 @@ describe('data table', () => { data: [ { id: 'someid', - RUN: 'run name', - VALUE: 3, - STEP: 1, - SMOOTHED: 2, + run: 'run name', + value: 3, + step: 1, + smoothed: 2, }, ], smoothingEnabled: false,