Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
"use strict";
loader.lazyRequireGetter(
this,
"PropTypes",
"resource://devtools/client/shared/vendor/react-prop-types.js"
);
loader.lazyRequireGetter(
this,
"HTMLTooltip",
"resource://devtools/client/shared/widgets/tooltip/HTMLTooltip.js",
true
);
loader.lazyRequireGetter(
this,
"createPortal",
"resource://devtools/client/shared/vendor/react-dom.js",
true
);
// React & Redux
const {
Component,
} = require("resource://devtools/client/shared/vendor/react.js");
const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
const {
connect,
} = require("resource://devtools/client/shared/vendor/react-redux.js");
const {
getAutocompleteState,
} = require("resource://devtools/client/webconsole/selectors/autocomplete.js");
const autocompleteActions = require("resource://devtools/client/webconsole/actions/autocomplete.js");
const {
l10n,
} = require("resource://devtools/client/webconsole/utils/messages.js");
const LEARN_MORE_URL = `https://firefox-source-docs.mozilla.org/devtools-user/web_console/invoke_getters_from_autocomplete/`;
class ConfirmDialog extends Component {
static get propTypes() {
return {
// Console object.
webConsoleUI: PropTypes.object.isRequired,
// Update autocomplete popup state.
autocompleteUpdate: PropTypes.func.isRequired,
autocompleteClear: PropTypes.func.isRequired,
// Data to be displayed in the confirm dialog.
getterPath: PropTypes.array,
serviceContainer: PropTypes.object.isRequired,
};
}
constructor(props) {
super(props);
const { webConsoleUI } = props;
webConsoleUI.confirmDialog = this;
this.cancel = this.cancel.bind(this);
this.confirm = this.confirm.bind(this);
this.onLearnMoreClick = this.onLearnMoreClick.bind(this);
}
componentDidMount() {
const doc = this.props.webConsoleUI.document;
const { toolbox } = this.props.webConsoleUI.wrapper;
const tooltipDoc = toolbox ? toolbox.doc : doc;
// The popup will be attached to the toolbox document or HUD document in the case
// such as the browser console which doesn't have a toolbox.
this.tooltip = new HTMLTooltip(tooltipDoc, {
className: "invoke-confirm",
});
}
componentDidUpdate() {
const { getterPath, serviceContainer } = this.props;
if (getterPath) {
this.tooltip.show(serviceContainer.getJsTermTooltipAnchor(), { y: 5 });
} else {
this.tooltip.hide();
this.props.webConsoleUI.jsterm.focus();
}
}
componentDidThrow(e) {
console.error("Error in ConfirmDialog", e);
this.setState(state => ({ ...state, hasError: true }));
}
onLearnMoreClick(e) {
this.props.serviceContainer.openLink(LEARN_MORE_URL, e);
}
cancel() {
this.tooltip.hide();
this.props.autocompleteClear();
}
confirm() {
this.tooltip.hide();
this.props.autocompleteUpdate(this.props.getterPath);
}
render() {
if (
(this.state && this.state.hasError) ||
!this.props ||
!this.props.getterPath
) {
return null;
}
const { getterPath } = this.props;
const getterName = getterPath.join(".");
// We deliberately use getStr, and not getFormatStr, because we want getterName to
// be wrapped in its own span.
const description = l10n.getStr("webconsole.confirmDialog.getter.label");
const [descriptionPrefix, descriptionSuffix] = description.split("%S");
const closeButtonTooltip = l10n.getFormatStr(
"webconsole.confirmDialog.getter.closeButton.tooltip",
["Esc"]
);
const invokeButtonLabel = l10n.getFormatStr(
"webconsole.confirmDialog.getter.invokeButtonLabelWithShortcut",
["Tab"]
);
const learnMoreElement = dom.a(
{
className: "learn-more-link",
key: "learn-more-link",
title: LEARN_MORE_URL.split("?")[0],
onClick: this.onLearnMoreClick,
},
l10n.getStr("webConsoleMoreInfoLabel")
);
return createPortal(
[
dom.div(
{
className: "confirm-label",
key: "confirm-label",
},
dom.p(
{},
dom.span({}, descriptionPrefix),
dom.span({ className: "emphasized" }, getterName),
dom.span({}, descriptionSuffix)
),
dom.button({
className: "devtools-button close-confirm-dialog-button",
key: "close-button",
title: closeButtonTooltip,
onClick: this.cancel,
})
),
dom.button(
{
className: "confirm-button",
key: "confirm-button",
onClick: this.confirm,
},
invokeButtonLabel
),
learnMoreElement,
],
this.tooltip.panel
);
}
}
// Redux connect
function mapStateToProps(state) {
const autocompleteData = getAutocompleteState(state);
return {
getterPath: autocompleteData.getterPath,
};
}
function mapDispatchToProps(dispatch) {
return {
autocompleteUpdate: getterPath =>
dispatch(autocompleteActions.autocompleteUpdate(true, getterPath)),
autocompleteClear: () => dispatch(autocompleteActions.autocompleteClear()),
};
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDialog);