Bug 1350233 - Add [learn more] MDN link for statistics panel
MozReview-Commit-ID: BeRrGFD7c1D
--- a/devtools/client/netmonitor/src/assets/styles/netmonitor.css
+++ b/devtools/client/netmonitor/src/assets/styles/netmonitor.css
@@ -93,16 +93,27 @@ body,
overflow: auto;
}
.cropped-textbox .textbox-input {
/* workaround for textbox not supporting the @crop attribute */
text-overflow: ellipsis;
}
+.learn-more-link {
+ color: var(--theme-highlight-blue);
+ cursor: pointer;
+ margin: 0 5px;
+ white-space: nowrap;
+}
+
+.learn-more-link:hover {
+ text-decoration: underline;
+}
+
/* Status bar */
.status-bar-label {
display: inline-flex;
align-content: stretch;
margin-inline-end: 10px;
/* Status bar has just one line so, don't wrap labels */
@@ -142,16 +153,18 @@ body,
padding: 12px;
font-size: 120%;
flex: 1;
overflow: auto;
}
.notice-perf-message {
margin-top: 2px;
+ display: flex;
+ align-items: center;
}
.requests-list-perf-notice-button {
min-width: 30px;
min-height: 26px;
margin: 0 5px;
vertical-align: middle;
}
@@ -855,28 +868,16 @@ body,
color: inherit;
padding-inline-start: 3px;
}
.theme-dark .tabpanel-summary-value {
color: var(--theme-selection-color);
}
-.learn-more-link {
- color: var(--theme-highlight-blue);
- cursor: pointer;
- margin: 0 5px;
- white-space: nowrap;
- flex-grow: 1;
-}
-
-.learn-more-link:hover {
- text-decoration: underline;
-}
-
/* Headers tabpanel */
.headers-overview {
background: var(--theme-toolbar-background);
}
.headers-summary,
.response-summary {
@@ -917,16 +918,20 @@ body,
.headers-summary .textbox-input {
margin-inline-end: 2px;
}
.headers-summary .status-text {
width: auto!important;
}
+.headers-summary .learn-more-link {
+ flex-grow: 1;
+}
+
/* Response tabpanel */
.response-error-header {
margin: 0;
padding: 3px 8px;
background-color: var(--theme-highlight-red);
color: var(--theme-selection-color);
}
@@ -1150,16 +1155,24 @@ body,
}
.statistics-panel .charts,
.statistics-panel .pie-table-chart-container {
width: 100%;
height: 100%;
}
+.statistics-panel .learn-more-link {
+ font-weight: 400;
+}
+
+.statistics-panel .table-chart-title {
+ display: flex;
+}
+
.pie-table-chart-container {
display: flex;
justify-content: center;
align-items: center;
}
.statistics-panel .pie-chart-container {
margin-inline-start: 3vw;
--- a/devtools/client/netmonitor/src/components/request-list-empty-notice.js
+++ b/devtools/client/netmonitor/src/components/request-list-empty-notice.js
@@ -1,24 +1,29 @@
/* 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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
createClass,
+ createFactory,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const Actions = require("../actions/index");
const { ACTIVITY_TYPE } = require("../constants");
const { NetMonitorController } = require("../netmonitor-controller");
const { L10N } = require("../utils/l10n");
+const { getPerformanceAnalysisURL } = require("../utils/mdn-utils");
+
+// Components
+const MDNLink = createFactory(require("./mdn-link"));
const { button, div, span } = DOM;
/**
* UI displayed when the request list is empty. Contains instructions on reloading
* the page and on triggering performance analysis of the page.
*/
const RequestListEmptyNotice = createClass({
@@ -49,17 +54,18 @@ const RequestListEmptyNotice = createCla
div({ className: "notice-perf-message" },
span(null, L10N.getStr("netmonitor.perfNotice1")),
button({
title: L10N.getStr("netmonitor.perfNotice3"),
className: "devtools-button requests-list-perf-notice-button",
"data-standalone": true,
onClick: this.props.onPerfClick,
}),
- span(null, L10N.getStr("netmonitor.perfNotice2"))
+ span(null, L10N.getStr("netmonitor.perfNotice2")),
+ MDNLink({ url: getPerformanceAnalysisURL() })
)
);
}
});
module.exports = connect(
undefined,
dispatch => ({
--- a/devtools/client/netmonitor/src/components/statistics-panel.js
+++ b/devtools/client/netmonitor/src/components/statistics-panel.js
@@ -1,29 +1,35 @@
/* 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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
+const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const {
createClass,
+ createFactory,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { Chart } = require("devtools/client/shared/widgets/Chart");
const { PluralForm } = require("devtools/shared/plural-form");
const Actions = require("../actions/index");
const { Filters } = require("../utils/filter-predicates");
const {
getSizeWithDecimals,
getTimeWithDecimals
} = require("../utils/format-utils");
const { L10N } = require("../utils/l10n");
+const { getPerformanceAnalysisURL } = require("../utils/mdn-utils");
+
+// Components
+const MDNLink = createFactory(require("./mdn-link"));
const { button, div } = DOM;
const MediaQueryList = window.matchMedia("(min-width: 700px)");
const NETWORK_ANALYSIS_PIE_CHART_DIAMETER = 200;
const BACK_BUTTON = L10N.getStr("netmonitor.backButton");
const CHARTS_CACHE_ENABLED = L10N.getStr("charts.cacheEnabled");
const CHARTS_CACHE_DISABLED = L10N.getStr("charts.cacheDisabled");
@@ -43,16 +49,20 @@ const StatisticsPanel = createClass({
},
getInitialState() {
return {
isVerticalSpliter: MediaQueryList.matches,
};
},
+ componentWillMount() {
+ this.mdnLinkContainerNodes = new Map();
+ },
+
componentDidUpdate(prevProps) {
MediaQueryList.addListener(this.onLayoutChange);
const { requests } = this.props;
let ready = requests && !requests.isEmpty() && requests.every((req) =>
req.contentSize !== undefined && req.mimeType && req.responseHeaders &&
req.status !== undefined && req.totalTime !== undefined
);
@@ -63,20 +73,45 @@ const StatisticsPanel = createClass({
data: ready ? this.sanitizeChartDataSource(requests, false) : null,
});
this.createChart({
id: "emptyCacheChart",
title: CHARTS_CACHE_DISABLED,
data: ready ? this.sanitizeChartDataSource(requests, true) : null,
});
+
+ this.createMDNLink("primedCacheChart", getPerformanceAnalysisURL());
+ this.createMDNLink("emptyCacheChart", getPerformanceAnalysisURL());
},
componentWillUnmount() {
MediaQueryList.removeListener(this.onLayoutChange);
+ this.unmountMDNLinkContainers();
+ },
+
+ createMDNLink(chartId, url) {
+ if (this.mdnLinkContainerNodes.has(chartId)) {
+ ReactDOM.unmountComponentAtNode(this.mdnLinkContainerNodes.get(chartId));
+ }
+
+ // MDNLink is a React component but Chart isn't. To get the link
+ // into the chart we mount a new ReactDOM at the appropriate
+ // location after the chart has been created.
+ let title = this.refs[chartId].querySelector(".table-chart-title");
+ let containerNode = document.createElement("span");
+ title.appendChild(containerNode);
+ ReactDOM.render(MDNLink({ url }), containerNode);
+ this.mdnLinkContainerNodes.set(chartId, containerNode);
+ },
+
+ unmountMDNLinkContainers() {
+ for (let [, node] of this.mdnLinkContainerNodes) {
+ ReactDOM.unmountComponentAtNode(node);
+ }
},
createChart({ id, title, data }) {
// Create a new chart.
let chart = Chart.PieTable(document, {
diameter: NETWORK_ANALYSIS_PIE_CHART_DIAMETER,
title,
header: {
--- a/devtools/client/netmonitor/src/utils/mdn-utils.js
+++ b/devtools/client/netmonitor/src/utils/mdn-utils.js
@@ -135,55 +135,64 @@ const SUPPORTED_HTTP_CODES = [
"501",
"502",
"503",
"504",
"505",
"511"
];
+const MDN_URL = "https://developer.mozilla.org/docs/";
const GA_PARAMS =
"?utm_source=mozilla&utm_medium=devtools-netmonitor&utm_campaign=default";
-const NETWORK_MONITOR_TIMINGS_MDN_URL =
- "https://developer.mozilla.org/docs/Tools/Network_Monitor#Timings";
-
/**
* Get the MDN URL for the specified header.
*
* @param {string} header Name of the header for the baseURL to use.
*
* @return {string} The MDN URL for the header, or null if not available.
*/
function getHeadersURL(header) {
const lowerCaseHeader = header.toLowerCase();
let idx = SUPPORTED_HEADERS.findIndex(item =>
item.toLowerCase() === lowerCaseHeader);
return idx > -1 ?
- `https://developer.mozilla.org/docs/Web/HTTP/Headers/${SUPPORTED_HEADERS[idx] + GA_PARAMS}` : null;
+ `${MDN_URL}Web/HTTP/Headers/${SUPPORTED_HEADERS[idx] + GA_PARAMS}` : null;
}
/**
* Get the MDN URL for the specified HTTP status code.
*
* @param {string} HTTP status code for the baseURL to use.
*
* @return {string} The MDN URL for the HTTP status code, or null if not available.
*/
function getHTTPStatusCodeURL(statusCode) {
let idx = SUPPORTED_HTTP_CODES.indexOf(statusCode);
- return idx > -1 ? `https://developer.mozilla.org/docs/Web/HTTP/Status/${SUPPORTED_HTTP_CODES[idx] + GA_PARAMS}` : null;
+ return idx > -1 ?
+ `${MDN_URL}Web/HTTP/Status/${SUPPORTED_HTTP_CODES[idx] + GA_PARAMS}` : null;
}
/**
* Get the MDN URL of the Timings tag for Network Monitor.
*
* @return {string} the MDN URL of the Timings tag for Network Monitor.
*/
function getNetMonitorTimingsURL() {
- return NETWORK_MONITOR_TIMINGS_MDN_URL;
+ return `${MDN_URL}Tools/Network_Monitor${GA_PARAMS}#Timings`;
+}
+
+/**
+ * Get the MDN URL for Performance Analysis
+ *
+ * @return {string} The MDN URL for the documentation of Performance Analysis.
+ */
+function getPerformanceAnalysisURL() {
+ return `${MDN_URL}Tools/Network_Monitor${GA_PARAMS}#Performance_analysis`;
}
module.exports = {
getHeadersURL,
getHTTPStatusCodeURL,
getNetMonitorTimingsURL,
+ getPerformanceAnalysisURL,
};