Skip to content

Commit 97c2bc9

Browse files
author
Joel Griffith
authored
[Telemetry] Show opt-in changes for OSS users (#50831)
* WIP: Notice banner for OSS folks * Add telemetryNotifyUserAboutOptInDefault to injected vars * add userHasSeenNotice check * More WIP on banner notice component * Text changes on screens * make userHasSeenNotice flag work * Finalzed splash text + checking new flag * Consolidating banner calls and saving status of opt-in notice * Conditionally remove the banner and add some code docs * Fixing prior welcome tests * api integration test for user has seen opt in * change post method to put in ui * unit test for get_telemetry_notify_user_about_optin_default * Ignore TS woes * Adding new tests and snapshots for opt-in banner component * Notice banner test * Translation miss * More opt-in tests * increase types usage * roll back core server api change * update snapshot * Prop name change + snapshot updates
1 parent aaa3097 commit 97c2bc9

25 files changed

+682
-16
lines changed

src/legacy/core_plugins/kibana/public/home/components/__snapshots__/welcome.test.tsx.snap

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

src/legacy/core_plugins/kibana/public/home/components/home.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export class Home extends Component {
5151
getServices().getInjected('disableWelcomeScreen') ||
5252
props.localStorage.getItem(KEY_ENABLE_WELCOME) === 'false'
5353
);
54-
const showTelemetryDisclaimer = getServices().getInjected('allowChangingOptInStatus');
54+
const showTelemetryDisclaimer = getServices().getInjected('telemetryNotifyUserAboutOptInDefault');
5555

5656
this.state = {
5757
// If welcome is enabled, we wait for loading to complete
@@ -231,6 +231,7 @@ export class Home extends Component {
231231
onSkip={this.skipWelcome}
232232
urlBasePath={this.props.urlBasePath}
233233
showTelemetryDisclaimer={this.state.showTelemetryDisclaimer}
234+
onOptInSeen={this.props.onOptInSeen}
234235
/>
235236
);
236237
}
@@ -269,4 +270,5 @@ Home.propTypes = {
269270
localStorage: PropTypes.object.isRequired,
270271
urlBasePath: PropTypes.string.isRequired,
271272
mlEnabled: PropTypes.bool.isRequired,
273+
onOptInSeen: PropTypes.func.isRequired,
272274
};

src/legacy/core_plugins/kibana/public/home/components/home_app.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ export function HomeApp({ directories }) {
3535
savedObjectsClient,
3636
getBasePath,
3737
addBasePath,
38+
telemetryOptInProvider: {
39+
setOptInNoticeSeen,
40+
},
3841
} = getServices();
3942

4043
const isCloudEnabled = getInjected('isCloudEnabled', false);
@@ -83,6 +86,7 @@ export function HomeApp({ directories }) {
8386
find={savedObjectsClient.find}
8487
localStorage={localStorage}
8588
urlBasePath={getBasePath()}
89+
onOptInSeen={setOptInNoticeSeen}
8690
/>
8791
</Route>
8892
<Route path="/home">

src/legacy/core_plugins/kibana/public/home/components/welcome.test.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jest.mock('../kibana_services', () => ({
3535
test('should render a Welcome screen with the telemetry disclaimer', () => {
3636
const component = shallow(
3737
// @ts-ignore
38-
<Welcome urlBase="/" onSkip={() => {}} showTelemetryDisclaimer={true} />
38+
<Welcome urlBase="/" onSkip={() => {}} showTelemetryDisclaimer={true} onOptInSeen={() => {}} />
3939
);
4040

4141
expect(component).toMatchSnapshot();
@@ -45,8 +45,19 @@ test('should render a Welcome screen with no telemetry disclaimer', () => {
4545
// @ts-ignore
4646
const component = shallow(
4747
// @ts-ignore
48-
<Welcome urlBase="/" onSkip={() => {}} showTelemetryDisclaimer={false} />
48+
<Welcome urlBase="/" onSkip={() => {}} showTelemetryDisclaimer={false} onOptInSeen={() => {}} />
4949
);
5050

5151
expect(component).toMatchSnapshot();
5252
});
53+
54+
test('fires opt-in seen when mounted', () => {
55+
const seen = jest.fn();
56+
57+
shallow(
58+
// @ts-ignore
59+
<Welcome urlBase="/" onSkip={() => {}} showTelemetryDisclaimer={true} onOptInSeen={seen} />
60+
);
61+
62+
expect(seen).toHaveBeenCalled();
63+
});

src/legacy/core_plugins/kibana/public/home/components/welcome.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { SampleDataCard } from './sample_data';
4343
interface Props {
4444
urlBasePath: string;
4545
onSkip: () => void;
46+
onOptInSeen: () => any;
4647
showTelemetryDisclaimer: boolean;
4748
}
4849

@@ -75,6 +76,7 @@ export class Welcome extends React.Component<Props> {
7576

7677
componentDidMount() {
7778
this.services.trackUiMetric(this.services.METRIC_TYPE.LOADED, 'welcomeScreenMount');
79+
this.props.onOptInSeen();
7880
document.addEventListener('keydown', this.hideOnEsc);
7981
}
8082

@@ -132,17 +134,17 @@ export class Welcome extends React.Component<Props> {
132134
>
133135
<FormattedMessage
134136
id="kbn.home.dataManagementDisclaimerPrivacyLink"
135-
defaultMessage="Privacy Policy."
137+
defaultMessage="Privacy Statement."
136138
/>
137139
</EuiLink>
138140
<FormattedMessage
139141
id="kbn.home.dataManagementDisableCollection"
140-
defaultMessage=" To disable collection, "
142+
defaultMessage=" To stop collection, "
141143
/>
142144
<EuiLink href="#/management/kibana/settings">
143145
<FormattedMessage
144146
id="kbn.home.dataManagementDisableCollectionLink"
145-
defaultMessage="click here."
147+
defaultMessage="disable usage data here."
146148
/>
147149
</EuiLink>
148150
</EuiTextColor>

src/legacy/core_plugins/telemetry/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ const telemetry = (kibana: any) => {
112112
telemetryOptInStatusUrl: config.get('telemetry.optInStatusUrl'),
113113
allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'),
114114
telemetrySendUsageFrom: config.get('telemetry.sendUsageFrom'),
115+
telemetryNotifyUserAboutOptInDefault: false,
115116
};
116117
},
117118
hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'],

src/legacy/core_plugins/telemetry/mappings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
"lastVersionChecked": {
1515
"ignore_above": 256,
1616
"type": "keyword"
17+
},
18+
"userHasSeenNotice": {
19+
"type": "boolean"
1720
}
1821
}
1922
}

src/legacy/core_plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap

Lines changed: 51 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import React from 'react';
20+
import { EuiButton } from '@elastic/eui';
21+
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
22+
import { OptedInBanner } from './opted_in_notice_banner';
23+
24+
describe('OptInDetailsComponent', () => {
25+
it('renders as expected', () => {
26+
expect(shallowWithIntl(<OptedInBanner onSeenBanner={() => {}} />)).toMatchSnapshot();
27+
});
28+
29+
it('fires the "onSeenBanner" prop when a link is clicked', () => {
30+
const onLinkClick = jest.fn();
31+
const component = shallowWithIntl(<OptedInBanner onSeenBanner={onLinkClick} />);
32+
33+
const button = component.findWhere(n => n.type() === EuiButton);
34+
35+
if (!button) {
36+
throw new Error(`Couldn't find any buttons in opt-in notice`);
37+
}
38+
39+
button.simulate('click');
40+
41+
expect(onLinkClick).toHaveBeenCalled();
42+
});
43+
});
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
/* eslint @elastic/eui/href-or-on-click:0 */
21+
22+
import * as React from 'react';
23+
import { EuiButton, EuiLink, EuiCallOut, EuiSpacer } from '@elastic/eui';
24+
import { FormattedMessage } from '@kbn/i18n/react';
25+
26+
interface Props {
27+
onSeenBanner: () => any;
28+
}
29+
30+
/**
31+
* React component for displaying the Telemetry opt-in notice.
32+
*/
33+
export class OptedInBanner extends React.PureComponent<Props> {
34+
onLinkClick = () => {
35+
this.props.onSeenBanner();
36+
return;
37+
};
38+
39+
render() {
40+
return (
41+
<EuiCallOut title="Help us improve the Elastic Stack">
42+
<FormattedMessage
43+
id="telemetry.telemetryOptedInNoticeDescription"
44+
defaultMessage="To learn about how usage data helps us manage and improve our products and services, see our {privacyStatementLink}. To stop collection, {disableLink}."
45+
values={{
46+
privacyStatementLink: (
47+
<EuiLink
48+
onClick={this.onLinkClick}
49+
href="https://www.elastic.co/legal/privacy-statement"
50+
target="_blank"
51+
rel="noopener"
52+
>
53+
<FormattedMessage
54+
id="telemetry.telemetryOptedInPrivacyStatement"
55+
defaultMessage="Privacy Statement"
56+
/>
57+
</EuiLink>
58+
),
59+
disableLink: (
60+
<EuiLink href="#/management/kibana/settings" onClick={this.onLinkClick}>
61+
<FormattedMessage
62+
id="telemetry.telemetryOptedInDisableUsage"
63+
defaultMessage="disable usage data here"
64+
/>
65+
</EuiLink>
66+
),
67+
}}
68+
/>
69+
<EuiSpacer size="s" />
70+
<EuiButton size="s" onClick={this.props.onSeenBanner}>
71+
<FormattedMessage
72+
id="telemetry.telemetryOptedInDismissMessage"
73+
defaultMessage="Dismiss"
74+
/>
75+
</EuiButton>
76+
</EuiCallOut>
77+
);
78+
}
79+
}

0 commit comments

Comments
 (0)