Skip to content

Commit b41272f

Browse files
authored
timeseries: second draft of TS promotion (#5291)
This change adds some messages and placeholders for the TimeSeries promotion. It also adds two buttons users can use to navigate to scalars, old experience, or dismiss the promotion.
1 parent 68105d6 commit b41272f

11 files changed

+197
-12
lines changed

tensorboard/webapp/metrics/actions/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,11 @@ export const selectTimeEnableToggled = createAction(
175175
export const useRangeSelectTimeToggled = createAction(
176176
'[Metrics] Use Range Select Time Toggle'
177177
);
178+
179+
export const metricsPromoDismissed = createAction(
180+
'[Metrics] Metrics Promo Dismissed'
181+
);
182+
183+
export const metricsPromoGoToScalars = createAction(
184+
'[Metrics] Metrics Promo Go To Scalars'
185+
);

tensorboard/webapp/metrics/views/BUILD

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,32 @@ tf_sass_binary(
1414
src = "metrics_container.scss",
1515
)
1616

17+
tf_sass_binary(
18+
name = "metrics_promo_styles",
19+
src = "metrics_promo_notice_component.scss",
20+
)
21+
1722
tf_ng_module(
1823
name = "views",
1924
srcs = [
2025
"metrics_container.ts",
2126
"metrics_promo_notice_component.ts",
2227
"metrics_promo_notice_container.ts",
28+
"metrics_promo_notice_types.ts",
2329
"metrics_views_module.ts",
2430
],
2531
assets = [
2632
":metrics_container_styles",
33+
":metrics_promo_styles",
2734
"metrics_promo_notice_component.ng.html",
2835
],
2936
deps = [
3037
"//tensorboard/webapp:app_state",
3138
"//tensorboard/webapp:selectors",
39+
"//tensorboard/webapp/angular:expect_angular_material_icon",
3240
"//tensorboard/webapp/core",
41+
"//tensorboard/webapp/customization",
42+
"//tensorboard/webapp/metrics/actions",
3343
"//tensorboard/webapp/metrics/views/main_view",
3444
"//tensorboard/webapp/metrics/views/right_pane",
3545
"//tensorboard/webapp/runs/views/runs_selector",
@@ -75,6 +85,7 @@ tf_ts_library(
7585
"//tensorboard/webapp/angular:expect_angular_core_testing",
7686
"//tensorboard/webapp/angular:expect_angular_platform_browser_animations",
7787
"//tensorboard/webapp/angular:expect_ngrx_store_testing",
88+
"//tensorboard/webapp/metrics/actions",
7889
"//tensorboard/webapp/metrics/data_source",
7990
"@npm//@angular/core",
8091
"@npm//@angular/platform-browser",

tensorboard/webapp/metrics/views/metrics_container.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@ limitations under the License.
1616

1717
:host {
1818
display: flex;
19-
height: 100%;
2019
flex-direction: column;
20+
height: 100%;
21+
justify-content: stretch;
2122
overflow: hidden;
2223
}
2324

2425
.notice {
26+
background-color: rgba(mat-color($mat-yellow, 200), 0.85);
27+
border-bottom: 1px solid mat-color($mat-yellow, 500);
28+
color: map-get($tb-foreground, text);
29+
display: block;
2530
flex: 0 0;
2631
}
2732

tensorboard/webapp/metrics/views/metrics_container.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ import {getIsTimeSeriesPromotionEnabled} from '../../selectors';
2222
@Component({
2323
selector: 'metrics-dashboard',
2424
template: `
25-
<div *ngIf="isButterBarEnabled$ | async" class="notice">
26-
Temporary butter bar content.
27-
</div>
25+
<metrics-promo-notice
26+
*ngIf="isButterBarEnabled$ | async"
27+
class="notice"
28+
></metrics-promo-notice>
2829
<tb-dashboard-layout>
2930
<runs-selector sidebar></runs-selector>
3031
<metrics-main-view main></metrics-main-view>

tensorboard/webapp/metrics/views/metrics_container_test.ts

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,18 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
See the License for the specific language governing permissions and
1313
limitations under the License.
1414
==============================================================================*/
15-
import {NO_ERRORS_SCHEMA} from '@angular/core';
15+
import {DebugElement, NO_ERRORS_SCHEMA} from '@angular/core';
1616
import {TestBed} from '@angular/core/testing';
1717
import {By} from '@angular/platform-browser';
1818
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
19-
import {Store} from '@ngrx/store';
19+
import {Action, Store} from '@ngrx/store';
2020
import {MockStore, provideMockStore} from '@ngrx/store/testing';
2121

2222
import {State} from '../../app_state';
2323
import {getIsTimeSeriesPromotionEnabled} from '../../selectors';
24+
import {metricsPromoDismissed, metricsPromoGoToScalars} from '../actions';
2425
import {MetricsDashboardContainer} from './metrics_container';
26+
import {MetricsPromoNoticeComponent} from './metrics_promo_notice_component';
2527
import {MetricsPromoNoticeContainer} from './metrics_promo_notice_container';
2628

2729
describe('metrics view', () => {
@@ -30,7 +32,11 @@ describe('metrics view', () => {
3032
beforeEach(async () => {
3133
await TestBed.configureTestingModule({
3234
imports: [NoopAnimationsModule],
33-
declarations: [MetricsDashboardContainer, MetricsPromoNoticeContainer],
35+
declarations: [
36+
MetricsDashboardContainer,
37+
MetricsPromoNoticeContainer,
38+
MetricsPromoNoticeComponent,
39+
],
3440
providers: [provideMockStore()],
3541
// Ignore errors from components that are out-of-scope for this test:
3642
// 'runs-selector'.
@@ -55,4 +61,33 @@ describe('metrics view', () => {
5561

5662
expect(fixture.debugElement.query(By.css('.notice'))).not.toBeNull();
5763
});
64+
65+
describe('promotion', () => {
66+
let actions: Action[];
67+
68+
function createComponent(): DebugElement {
69+
actions = [];
70+
spyOn(store, 'dispatch').and.callFake((action) => actions.push(action));
71+
72+
store.overrideSelector(getIsTimeSeriesPromotionEnabled, true);
73+
const fixture = TestBed.createComponent(MetricsDashboardContainer);
74+
fixture.detectChanges();
75+
76+
return fixture.debugElement.query(By.css('metrics-promo-notice'));
77+
}
78+
79+
it('dispatches action when clicking on dismiss', () => {
80+
const promoEl = createComponent();
81+
promoEl.query(By.css('.dismiss')).nativeElement.click();
82+
83+
expect(actions).toEqual([metricsPromoDismissed()]);
84+
});
85+
86+
it('dispatches action when clicking on "Go to scalars"', () => {
87+
const promoEl = createComponent();
88+
promoEl.query(By.css('.go-to-scalars')).nativeElement.click();
89+
90+
expect(actions).toEqual([metricsPromoGoToScalars()]);
91+
});
92+
});
5893
});

tensorboard/webapp/metrics/views/metrics_promo_notice_component.ng.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,14 @@
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17-
Temporary butter bar content.
17+
<tb-customization [customizableComponent]="customPromoMessage" class="message">
18+
Welcome to new default experience of TensorBoard. Time Series lets you view
19+
all visualizations at once, put them side-by-side with pins, and customize
20+
colors. Scalars and other plugins are still available.
21+
<button class="go-to-scalars" (click)="onGoToScalars.emit()">
22+
Go to Scalars plugin</button
23+
>.
24+
</tb-customization>
25+
<button class="dismiss" (click)="onDismiss.emit()">
26+
<mat-icon inline svgIcon="close_24px"></mat-icon>
27+
</button>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
==============================================================================*/
15+
@import 'tensorboard/webapp/theme/tb_theme';
16+
17+
:host {
18+
display: flex;
19+
font-size: 14px;
20+
gap: 5px;
21+
justify-content: space-between;
22+
line-height: 20px;
23+
padding: 5px 10px;
24+
}
25+
26+
button {
27+
background-color: transparent;
28+
border: 0;
29+
color: inherit;
30+
cursor: pointer;
31+
font: inherit;
32+
padding: 0;
33+
34+
&:hover {
35+
text-decoration: underline;
36+
}
37+
}
38+
39+
tb-customization button {
40+
color: map-get($tb-foreground, link);
41+
}
42+
43+
.dismiss {
44+
align-self: baseline;
45+
flex: none;
46+
height: 20px;
47+
width: 20px;
48+
}

tensorboard/webapp/metrics/views/metrics_promo_notice_component.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,33 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
See the License for the specific language governing permissions and
1313
limitations under the License.
1414
==============================================================================*/
15-
import {ChangeDetectionStrategy, Component} from '@angular/core';
15+
import {
16+
ChangeDetectionStrategy,
17+
Component,
18+
EventEmitter,
19+
Inject,
20+
Optional,
21+
Output,
22+
Type,
23+
} from '@angular/core';
24+
import {METRICS_PROMO_MESSAGE_COMPONENT} from './metrics_promo_notice_types';
1625

1726
@Component({
1827
selector: 'metrics-promo-notice-component',
1928
templateUrl: 'metrics_promo_notice_component.ng.html',
29+
styleUrls: ['metrics_promo_notice_component.css'],
2030
changeDetection: ChangeDetectionStrategy.OnPush,
2131
})
22-
export class MetricsPromoNoticeComponent {}
32+
export class MetricsPromoNoticeComponent {
33+
@Output()
34+
readonly onDismiss = new EventEmitter();
35+
36+
@Output()
37+
readonly onGoToScalars = new EventEmitter();
38+
39+
constructor(
40+
@Optional()
41+
@Inject(METRICS_PROMO_MESSAGE_COMPONENT)
42+
readonly customPromoMessage: Type<Component>
43+
) {}
44+
}

tensorboard/webapp/metrics/views/metrics_promo_notice_container.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,27 @@ See the License for the specific language governing permissions and
1313
limitations under the License.
1414
==============================================================================*/
1515
import {ChangeDetectionStrategy, Component} from '@angular/core';
16+
import {Store} from '@ngrx/store';
17+
18+
import {State} from '../../app_state';
19+
import {metricsPromoDismissed, metricsPromoGoToScalars} from '../actions';
1620

1721
@Component({
1822
selector: 'metrics-promo-notice',
19-
template: `<metrics-promo-notice-component></metrics-promo-notice-component>`,
23+
template: `<metrics-promo-notice-component
24+
(onDismiss)="onDismiss()"
25+
(onGoToScalars)="onGoToScalars()"
26+
></metrics-promo-notice-component>`,
2027
changeDetection: ChangeDetectionStrategy.OnPush,
2128
})
22-
export class MetricsPromoNoticeContainer {}
29+
export class MetricsPromoNoticeContainer {
30+
constructor(private readonly store: Store<State>) {}
31+
32+
onDismiss() {
33+
this.store.dispatch(metricsPromoDismissed());
34+
}
35+
36+
onGoToScalars() {
37+
this.store.dispatch(metricsPromoGoToScalars());
38+
}
39+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
==============================================================================*/
15+
16+
import {Component, InjectionToken, Type} from '@angular/core';
17+
18+
/**
19+
* When this token exists, it will replace Metrics promotion message by the
20+
* content of the provided component.
21+
*/
22+
export const METRICS_PROMO_MESSAGE_COMPONENT = new InjectionToken<
23+
Type<Component>
24+
>('[Metrics] METRICS_Promo Message Component');

0 commit comments

Comments
 (0)