chrome-devtools-frontend
Version:
Chrome DevTools UI
145 lines (125 loc) • 5.04 kB
text/typescript
// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* eslint-disable rulesdir/no-lit-render-outside-of-view */
import '../icon_button/icon_button.js';
import * as Common from '../../../core/common/common.js';
import type * as Host from '../../../core/host/host.js';
import * as i18n from '../../../core/i18n/i18n.js';
import {html, render} from '../../lit/lit.js';
import surveyLinkStyles from './surveyLink.css.js';
const UIStrings = {
/**
*@description Text shown when the link to open a survey is clicked but the survey has not yet appeared
*/
openingSurvey: 'Opening survey …',
/**
*@description Text displayed instead of the survey link after the survey link is clicked, if the survey was shown successfully
*/
thankYouForYourFeedback: 'Thank you for your feedback',
/**
*@description Text displayed instead of the survey link after the survey link is clicked, if the survey was not shown successfully
*/
anErrorOccurredWithTheSurvey: 'An error occurred with the survey',
} as const;
const str_ = i18n.i18n.registerUIStrings('ui/components/survey_link/SurveyLink.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
export type CanShowSurveyCallback = (result: Host.InspectorFrontendHostAPI.CanShowSurveyResult) => void;
export type ShowSurveyCallback = (result: Host.InspectorFrontendHostAPI.ShowSurveyResult) => void;
export interface SurveyLinkData {
trigger: string;
promptText: Common.UIString.LocalizedString;
canShowSurvey: (trigger: string, callback: CanShowSurveyCallback) => void;
showSurvey: (trigger: string, callback: ShowSurveyCallback) => void;
}
const enum State {
CHECKING = 'Checking', // (begin state) -> SHOW_LINK | DONT_SHOW_LINK
SHOW_LINK = 'ShowLink', // -> SENDING
SENDING = 'Sending', // -> SURVEY_SHOWN | FAILED
SURVEY_SHOWN = 'SurveyShown',
FAILED = 'Failed',
DONT_SHOW_LINK = 'DontShowLink',
}
// A link to a survey. The link is rendered aysnchronously because we need to first check if
// canShowSurvey succeeds.
export class SurveyLink extends HTMLElement {
readonly #shadow = this.attachShadow({mode: 'open'});
#trigger = '';
#promptText = Common.UIString.LocalizedEmptyString;
#canShowSurvey: (trigger: string, callback: CanShowSurveyCallback) => void = () => {};
#showSurvey: (trigger: string, callback: ShowSurveyCallback) => void = () => {};
#state: State = State.CHECKING;
// Re-setting data will cause the state to go back to 'Checking' which hides the link.
set data(data: SurveyLinkData) {
this.#trigger = data.trigger;
this.#promptText = data.promptText;
this.#canShowSurvey = data.canShowSurvey;
this.#showSurvey = data.showSurvey;
this.#checkSurvey();
}
#checkSurvey(): void {
this.#state = State.CHECKING;
this.#canShowSurvey(this.#trigger, ({canShowSurvey}) => {
if (!canShowSurvey) {
this.#state = State.DONT_SHOW_LINK;
} else {
this.#state = State.SHOW_LINK;
}
this.#render();
});
}
#sendSurvey(): void {
this.#state = State.SENDING;
this.#render();
this.#showSurvey(this.#trigger, ({surveyShown}) => {
if (!surveyShown) {
this.#state = State.FAILED;
} else {
this.#state = State.SURVEY_SHOWN;
}
this.#render();
});
}
#render(): void {
if (this.#state === State.CHECKING || this.#state === State.DONT_SHOW_LINK) {
return;
}
let linkText = this.#promptText;
if (this.#state === State.SENDING) {
linkText = i18nString(UIStrings.openingSurvey);
} else if (this.#state === State.SURVEY_SHOWN) {
linkText = i18nString(UIStrings.thankYouForYourFeedback);
} else if (this.#state === State.FAILED) {
linkText = i18nString(UIStrings.anErrorOccurredWithTheSurvey);
}
let linkState = '';
if (this.#state === State.SENDING) {
linkState = 'pending-link';
} else if (this.#state === State.FAILED || this.#state === State.SURVEY_SHOWN) {
linkState = 'disabled-link';
}
const ariaDisabled = this.#state !== State.SHOW_LINK;
// clang-format off
const output = html`
<style>${surveyLinkStyles}</style>
<button
class="link ${linkState}" tabindex=${ariaDisabled ? '-1' : '0'}
.disabled=${ariaDisabled} aria-disabled=${ariaDisabled} =${this.#sendSurvey}>
<devtools-icon class="link-icon" .data=${{
iconName: 'review',
color: 'var(--sys-color-primary)',
width: 'var(--issue-link-icon-size, 16px)',
height: 'var(--issue-link-icon-size, 16px)'}}>
</devtools-icon>
${linkText}
</button>`;
// clang-format on
render(output, this.#shadow, {host: this});
}
}
customElements.define('devtools-survey-link', SurveyLink);
declare global {
interface HTMLElementTagNameMap {
'devtools-survey-link': SurveyLink;
}
}