mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Add analytics integration (#8695)
Co-authored-by: Bram Kragten <mail@bramkragten.nl> Co-authored-by: Philip Allgaier <mail@spacegaier.de>
This commit is contained in:
parent
62f685bac2
commit
742028b691
@ -8,6 +8,7 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { atLeastVersion } from "../../../src/common/config/version";
|
||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||
import "../../../src/components/buttons/ha-progress-button";
|
||||
import "../../../src/components/ha-card";
|
||||
@ -150,30 +151,32 @@ class HassioSupervisorInfo extends LitElement {
|
||||
</ha-settings-row>
|
||||
|
||||
${this.supervisor.supervisor.supported
|
||||
? html` <ha-settings-row three-line>
|
||||
<span slot="heading">
|
||||
${this.supervisor.localize(
|
||||
"system.supervisor.share_diagnostics"
|
||||
)}
|
||||
</span>
|
||||
<div slot="description" class="diagnostics-description">
|
||||
${this.supervisor.localize(
|
||||
"system.supervisor.share_diagnostics_description"
|
||||
)}
|
||||
<button
|
||||
class="link"
|
||||
.title=${this.supervisor.localize("common.show_more")}
|
||||
@click=${this._diagnosticsInformationDialog}
|
||||
>
|
||||
${this.supervisor.localize("common.learn_more")}
|
||||
</button>
|
||||
</div>
|
||||
<ha-switch
|
||||
haptic
|
||||
.checked=${this.supervisor.supervisor.diagnostics}
|
||||
@change=${this._toggleDiagnostics}
|
||||
></ha-switch>
|
||||
</ha-settings-row>`
|
||||
? !atLeastVersion(this.hass.config.version, 2021, 4)
|
||||
? html` <ha-settings-row three-line>
|
||||
<span slot="heading">
|
||||
${this.supervisor.localize(
|
||||
"system.supervisor.share_diagnostics"
|
||||
)}
|
||||
</span>
|
||||
<div slot="description" class="diagnostics-description">
|
||||
${this.supervisor.localize(
|
||||
"system.supervisor.share_diagnostics_description"
|
||||
)}
|
||||
<button
|
||||
class="link"
|
||||
.title=${this.supervisor.localize("common.show_more")}
|
||||
@click=${this._diagnosticsInformationDialog}
|
||||
>
|
||||
${this.supervisor.localize("common.learn_more")}
|
||||
</button>
|
||||
</div>
|
||||
<ha-switch
|
||||
haptic
|
||||
.checked=${this.supervisor.supervisor.diagnostics}
|
||||
@change=${this._toggleDiagnostics}
|
||||
></ha-switch>
|
||||
</ha-settings-row>`
|
||||
: ""
|
||||
: html`<div class="error">
|
||||
${this.supervisor.localize(
|
||||
"system.supervisor.unsupported_title"
|
||||
|
188
src/components/ha-analytics.ts
Normal file
188
src/components/ha-analytics.ts
Normal file
@ -0,0 +1,188 @@
|
||||
import "@polymer/paper-tooltip/paper-tooltip";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { Analytics, AnalyticsPreferences } from "../data/analytics";
|
||||
import { haStyle } from "../resources/styles";
|
||||
import { HomeAssistant } from "../types";
|
||||
import { documentationUrl } from "../util/documentation-url";
|
||||
import "./ha-checkbox";
|
||||
import type { HaCheckbox } from "./ha-checkbox";
|
||||
import "./ha-settings-row";
|
||||
|
||||
const ADDITIONAL_PREFERENCES = ["usage", "statistics"];
|
||||
|
||||
declare global {
|
||||
interface HASSDomEvents {
|
||||
"analytics-preferences-changed": { preferences: AnalyticsPreferences };
|
||||
}
|
||||
}
|
||||
|
||||
@customElement("ha-analytics")
|
||||
export class HaAnalytics extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public analytics!: Analytics;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.analytics.huuid) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
const enabled = this.analytics.preferences.base;
|
||||
|
||||
return html`
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.core.section.core.analytics.instance_id",
|
||||
"huuid",
|
||||
this.analytics.huuid
|
||||
)}
|
||||
</p>
|
||||
<ha-settings-row>
|
||||
<span slot="prefix">
|
||||
<ha-checkbox
|
||||
@change=${this._handleRowCheckboxClick}
|
||||
.checked=${enabled}
|
||||
.preference=${"base"}
|
||||
>
|
||||
</ha-checkbox>
|
||||
</span>
|
||||
<span slot="heading">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.base.title`
|
||||
)}
|
||||
</span>
|
||||
<span slot="description">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.base.description`
|
||||
)}
|
||||
</span>
|
||||
</ha-settings-row>
|
||||
${ADDITIONAL_PREFERENCES.map(
|
||||
(preference) =>
|
||||
html`<ha-settings-row>
|
||||
<span slot="prefix">
|
||||
<ha-checkbox
|
||||
@change=${this._handleRowCheckboxClick}
|
||||
.checked=${this.analytics.preferences[preference]}
|
||||
.preference=${preference}
|
||||
.disabled=${!enabled}
|
||||
>
|
||||
</ha-checkbox>
|
||||
${!enabled
|
||||
? html`<paper-tooltip animation-delay="0" position="right"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.core.section.core.analytics.needs_base"
|
||||
)}
|
||||
</paper-tooltip>`
|
||||
: ""}
|
||||
</span>
|
||||
<span slot="heading">
|
||||
${preference === "usage"
|
||||
? isComponentLoaded(this.hass, "hassio")
|
||||
? this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.usage_supervisor.title`
|
||||
)
|
||||
: this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.usage.title`
|
||||
)
|
||||
: this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.${preference}.title`
|
||||
)}
|
||||
</span>
|
||||
<span slot="description">
|
||||
${preference === "usage"
|
||||
? isComponentLoaded(this.hass, "hassio")
|
||||
? this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.usage_supervisor.description`
|
||||
)
|
||||
: this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.usage.description`
|
||||
)
|
||||
: this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.${preference}.description`
|
||||
)}
|
||||
</span>
|
||||
</ha-settings-row>`
|
||||
)}
|
||||
<ha-settings-row>
|
||||
<span slot="prefix">
|
||||
<ha-checkbox
|
||||
@change=${this._handleRowCheckboxClick}
|
||||
.checked=${this.analytics.preferences.diagnostics}
|
||||
.preference=${"diagnostics"}
|
||||
>
|
||||
</ha-checkbox>
|
||||
</span>
|
||||
<span slot="heading">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.diagnostics.title`
|
||||
)}
|
||||
</span>
|
||||
<span slot="description">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.core.section.core.analytics.preference.diagnostics.description`
|
||||
)}
|
||||
</span>
|
||||
</ha-settings-row>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.core.section.core.analytics.documentation",
|
||||
"link",
|
||||
html`<a
|
||||
.href=${documentationUrl(this.hass, "/integrations/analytics/")}
|
||||
>
|
||||
${documentationUrl(this.hass, "/integrations/analytics/")}
|
||||
</a>`
|
||||
)}
|
||||
</p>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleRowCheckboxClick(ev: Event) {
|
||||
const checkbox = ev.currentTarget as HaCheckbox;
|
||||
const preference = (checkbox as any).preference;
|
||||
const preferences = { ...this.analytics.preferences };
|
||||
|
||||
if (checkbox.checked) {
|
||||
if (preferences[preference]) {
|
||||
return;
|
||||
}
|
||||
preferences[preference] = true;
|
||||
} else {
|
||||
preferences[preference] = false;
|
||||
}
|
||||
|
||||
fireEvent(this, "analytics-preferences-changed", { preferences });
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.error {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
ha-settings-row {
|
||||
padding: 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-analytics": HaAnalytics;
|
||||
}
|
||||
}
|
27
src/data/analytics.ts
Normal file
27
src/data/analytics.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
export interface AnalyticsPreferences {
|
||||
base?: boolean;
|
||||
diagnostics?: boolean;
|
||||
usage?: boolean;
|
||||
statistics?: boolean;
|
||||
}
|
||||
|
||||
export interface Analytics {
|
||||
preferences: AnalyticsPreferences;
|
||||
huuid: string;
|
||||
}
|
||||
|
||||
export const getAnalyticsDetails = (hass: HomeAssistant) =>
|
||||
hass.callWS<Analytics>({
|
||||
type: "analytics",
|
||||
});
|
||||
|
||||
export const setAnalyticsPreferences = (
|
||||
hass: HomeAssistant,
|
||||
preferences: AnalyticsPreferences
|
||||
) =>
|
||||
hass.callWS<AnalyticsPreferences>({
|
||||
type: "analytics/preferences",
|
||||
preferences,
|
||||
});
|
@ -12,10 +12,14 @@ export interface OnboardingIntegrationStepResponse {
|
||||
auth_code: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface OnboardingAnalyticsStepResponse {}
|
||||
|
||||
export interface OnboardingResponses {
|
||||
user: OnboardingUserStepResponse;
|
||||
core_config: OnboardingCoreConfigStepResponse;
|
||||
integration: OnboardingIntegrationStepResponse;
|
||||
analytics: OnboardingAnalyticsStepResponse;
|
||||
}
|
||||
|
||||
export type ValidOnboardingStep = keyof OnboardingResponses;
|
||||
@ -49,6 +53,9 @@ export const onboardCoreConfigStep = (hass: HomeAssistant) =>
|
||||
"onboarding/core_config"
|
||||
);
|
||||
|
||||
export const onboardAnalyticsStep = (hass: HomeAssistant) =>
|
||||
hass.callApi<OnboardingAnalyticsStepResponse>("POST", "onboarding/analytics");
|
||||
|
||||
export const onboardIntegrationStep = (
|
||||
hass: HomeAssistant,
|
||||
params: { client_id: string; redirect_uri: string }
|
||||
|
@ -31,6 +31,7 @@ import { HomeAssistant } from "../types";
|
||||
import { registerServiceWorker } from "../util/register-service-worker";
|
||||
import "./onboarding-create-user";
|
||||
import "./onboarding-loading";
|
||||
import "./onboarding-analytics";
|
||||
|
||||
type OnboardingEvent =
|
||||
| {
|
||||
@ -43,6 +44,9 @@ type OnboardingEvent =
|
||||
}
|
||||
| {
|
||||
type: "integration";
|
||||
}
|
||||
| {
|
||||
type: "analytics";
|
||||
};
|
||||
|
||||
declare global {
|
||||
@ -102,6 +106,15 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
|
||||
></onboarding-core-config>
|
||||
`;
|
||||
}
|
||||
if (step.step === "analytics") {
|
||||
return html`
|
||||
<onboarding-analytics
|
||||
.hass=${this.hass}
|
||||
.localize=${this.localize}
|
||||
></onboarding-analytics>
|
||||
`;
|
||||
}
|
||||
|
||||
if (step.step === "integration") {
|
||||
return html`
|
||||
<onboarding-integrations
|
||||
|
124
src/onboarding/onboarding-analytics.ts
Normal file
124
src/onboarding/onboarding-analytics.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { LocalizeFunc } from "../common/translations/localize";
|
||||
import "../components/ha-analytics";
|
||||
import {
|
||||
Analytics,
|
||||
getAnalyticsDetails,
|
||||
setAnalyticsPreferences,
|
||||
} from "../data/analytics";
|
||||
import { onboardAnalyticsStep } from "../data/onboarding";
|
||||
import type { HomeAssistant } from "../types";
|
||||
|
||||
@customElement("onboarding-analytics")
|
||||
class OnboardingAnalytics extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public localize!: LocalizeFunc;
|
||||
|
||||
@internalProperty() private _error?: string;
|
||||
|
||||
@internalProperty() private _analyticsDetails?: Analytics;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._analyticsDetails?.huuid) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<p>
|
||||
${this.localize(
|
||||
"ui.panel.page-onboarding.analytics.intro",
|
||||
"link",
|
||||
html`<a href="https://analytics.home-assistant.io" target="_blank"
|
||||
>https://analytics.home-assistant.io</a
|
||||
>`
|
||||
)}
|
||||
</p>
|
||||
<ha-analytics
|
||||
@analytics-preferences-changed=${this._preferencesChanged}
|
||||
.hass=${this.hass}
|
||||
.analytics=${this._analyticsDetails}
|
||||
>
|
||||
</ha-analytics>
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : ""}
|
||||
<div class="footer">
|
||||
<mwc-button @click=${this._save}>
|
||||
${this.localize("ui.panel.page-onboarding.analytics.finish")}
|
||||
</mwc-button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
this.addEventListener("keypress", (ev) => {
|
||||
if (ev.keyCode === 13) {
|
||||
this._save(ev);
|
||||
}
|
||||
});
|
||||
this._load();
|
||||
}
|
||||
|
||||
private _preferencesChanged(event: CustomEvent): void {
|
||||
this._analyticsDetails = {
|
||||
...this._analyticsDetails!,
|
||||
preferences: event.detail.preferences,
|
||||
};
|
||||
}
|
||||
|
||||
private async _save(ev) {
|
||||
ev.preventDefault();
|
||||
try {
|
||||
await setAnalyticsPreferences(
|
||||
this.hass,
|
||||
this._analyticsDetails!.preferences
|
||||
);
|
||||
|
||||
await onboardAnalyticsStep(this.hass);
|
||||
fireEvent(this, "onboarding-step", {
|
||||
type: "analytics",
|
||||
});
|
||||
} catch (err) {
|
||||
alert(`Failed to save: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async _load() {
|
||||
this._error = undefined;
|
||||
try {
|
||||
this._analyticsDetails = await getAnalyticsDetails(this.hass);
|
||||
} catch (err) {
|
||||
this._error = err.message || err;
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
.error {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 16px;
|
||||
text-align: right;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"onboarding-analytics": OnboardingAnalytics;
|
||||
}
|
||||
}
|
132
src/panels/config/core/ha-config-analytics.ts
Normal file
132
src/panels/config/core/ha-config-analytics.ts
Normal file
@ -0,0 +1,132 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||
import "../../../components/ha-analytics";
|
||||
import "../../../components/ha-card";
|
||||
import "../../../components/ha-checkbox";
|
||||
import "../../../components/ha-settings-row";
|
||||
import {
|
||||
Analytics,
|
||||
getAnalyticsDetails,
|
||||
setAnalyticsPreferences,
|
||||
} from "../../../data/analytics";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
|
||||
@customElement("ha-config-analytics")
|
||||
class ConfigAnalytics extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@internalProperty() private _analyticsDetails?: Analytics;
|
||||
|
||||
@internalProperty() private _error?: string;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (
|
||||
!isComponentLoaded(this.hass, "analytics") ||
|
||||
!this.hass.user?.is_owner ||
|
||||
!this._analyticsDetails?.huuid
|
||||
) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-card
|
||||
.header=${this.hass.localize(
|
||||
"ui.panel.config.core.section.core.analytics.header"
|
||||
)}
|
||||
>
|
||||
<div class="card-content">
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : ""}
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.core.section.core.analytics.introduction",
|
||||
"link",
|
||||
html`<a href="https://analytics.home-assistant.io" target="_blank"
|
||||
>https://analytics.home-assistant.io</a
|
||||
>`
|
||||
)}
|
||||
</p>
|
||||
<ha-analytics
|
||||
@analytics-preferences-changed=${this._preferencesChanged}
|
||||
.hass=${this.hass}
|
||||
.analytics=${this._analyticsDetails}
|
||||
></ha-analytics>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<mwc-button @click=${this._save}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.core.section.core.core_config.save_button"
|
||||
)}
|
||||
</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
super.firstUpdated(changedProps);
|
||||
if (isComponentLoaded(this.hass, "analytics")) {
|
||||
this._load();
|
||||
}
|
||||
}
|
||||
|
||||
private async _load() {
|
||||
this._error = undefined;
|
||||
try {
|
||||
this._analyticsDetails = await getAnalyticsDetails(this.hass);
|
||||
} catch (err) {
|
||||
this._error = err.message || err;
|
||||
}
|
||||
}
|
||||
|
||||
private async _save() {
|
||||
this._error = undefined;
|
||||
try {
|
||||
await setAnalyticsPreferences(
|
||||
this.hass,
|
||||
this._analyticsDetails?.preferences || {}
|
||||
);
|
||||
} catch (err) {
|
||||
this._error = err.message || err;
|
||||
}
|
||||
}
|
||||
|
||||
private _preferencesChanged(event: CustomEvent): void {
|
||||
this._analyticsDetails = {
|
||||
...this._analyticsDetails!,
|
||||
preferences: event.detail.preferences,
|
||||
};
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.error {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
ha-settings-row {
|
||||
padding: 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-config-analytics": ConfigAnalytics;
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import "../../../components/ha-card";
|
||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
import "../../../styles/polymer-ha-style";
|
||||
import "../ha-config-section";
|
||||
import "./ha-config-analytics";
|
||||
import "./ha-config-core-form";
|
||||
import "./ha-config-name-form";
|
||||
import "./ha-config-url-form";
|
||||
@ -29,6 +30,7 @@ class HaConfigSectionCore extends LocalizeMixin(PolymerElement) {
|
||||
<ha-config-name-form hass="[[hass]]"></ha-config-name-form>
|
||||
<ha-config-core-form hass="[[hass]]"></ha-config-core-form>
|
||||
<ha-config-url-form hass="[[hass]]"></ha-config-url-form>
|
||||
<ha-config-analytics hass="[[hass]]"></ha-config-analytics>
|
||||
</ha-config-section>
|
||||
`;
|
||||
}
|
||||
|
@ -977,6 +977,35 @@
|
||||
"save_button": "Save",
|
||||
"external_url": "External URL",
|
||||
"internal_url": "Internal URL"
|
||||
},
|
||||
"analytics": {
|
||||
"header": "Analytics",
|
||||
"introduction": "Share analytics from your instance. This data will be publiclly available at {link}",
|
||||
"instance_id": "Instance ID: {huuid}",
|
||||
"needs_base": "You need to enable base analytics for this option to be available",
|
||||
"preference": {
|
||||
"base": {
|
||||
"title": "Basic analytics",
|
||||
"description": "This includes the instance ID, the version and the installation type"
|
||||
},
|
||||
"diagnostics": {
|
||||
"title": "Diagnostics",
|
||||
"description": "Share crash reports and diagnostic information"
|
||||
},
|
||||
"usage": {
|
||||
"title": "Used integrations",
|
||||
"description": "This includes the names of your integrations"
|
||||
},
|
||||
"usage_supervisor": {
|
||||
"title": "Used integrations and add-ons",
|
||||
"description": "This includes the names and capabilities of your integrations and add-ons"
|
||||
},
|
||||
"statistics": {
|
||||
"title": "Usage statistics",
|
||||
"description": "This includes a count of elements in your installation, for a full list look at the documentation"
|
||||
}
|
||||
},
|
||||
"documentation": "Before you enable this make sure you visit the analytics documentation page {link} to understand what you are sending and how it's stored."
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3420,6 +3449,8 @@
|
||||
},
|
||||
"page-onboarding": {
|
||||
"intro": "Are you ready to awaken your home, reclaim your privacy and join a worldwide community of tinkerers?",
|
||||
"next": "Next",
|
||||
"finish": "Finish",
|
||||
"user": {
|
||||
"intro": "Let's get started by creating a user account.",
|
||||
"required_field": "Required",
|
||||
@ -3449,6 +3480,10 @@
|
||||
"more_integrations": "More",
|
||||
"finish": "Finish"
|
||||
},
|
||||
"analytics": {
|
||||
"intro": "Share analytics from your instance. This data will be publiclly available at {link}",
|
||||
"finish": "Next"
|
||||
},
|
||||
"restore": {
|
||||
"description": "Alternatively you can restore from a previous snapshot.",
|
||||
"in_progress": "Restore in progress",
|
||||
|
Loading…
x
Reference in New Issue
Block a user