зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1519312 - Render the console input to the left of the panel when editor preference is true; r=Honza.
When the editor preference is true, a CSS class is added to the panel that allow us to shift the layout to a CSS Grid, where the input panel is on the left and the output on the right. A toolbar is added to be able to execute an expression when in editor mode. Differential Revision: https://phabricator.services.mozilla.com/D17096 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
c2694625b5
Коммит
66150262ef
|
@ -396,4 +396,16 @@ webconsole.message.componentDidCatch.label=[DEVTOOLS ERROR] We’re sorry, we co
|
|||
# LOCALIZATION NOTE (webconsole.message.componentDidCatch.copyButton.label)
|
||||
# Label displayed on the button next to the message we display when the webconsole
|
||||
# couldn't handle a given packet (See webconsole.message.componentDidCatch.label).
|
||||
webconsole.message.componentDidCatch.copyButton.label=Copy message metadata to clipboard
|
||||
webconsole.message.componentDidCatch.copyButton.label=Copy message metadata to clipboard
|
||||
|
||||
|
||||
# LOCALIZATION NOTE (webconsole.editor.toolbar.executeButton.label)
|
||||
# Label used for the text of the execute button, in the editor toolbar, which is
|
||||
# displayed when the editor mode is enabled (devtools.webconsole.input.editor=true).
|
||||
webconsole.editor.toolbar.executeButton.label=Run
|
||||
|
||||
# LOCALIZATION NOTE (webconsole.editor.toolbar.executeButton.tooltip)
|
||||
# Label used for the tooltip on the execute button, in the editor toolbar, which is
|
||||
# displayed when the editor mode is enabled (devtools.webconsole.input.editor=true).
|
||||
# Parameters: %S is the keyboard shortcut.
|
||||
webconsole.editor.toolbar.executeButton.tooltip=Run expression (%S). This won’t clear the input.
|
||||
|
|
|
@ -132,7 +132,7 @@ a {
|
|||
|
||||
/* We already paint a top border on jsterm-input-container (and we need to keep
|
||||
* it when scrolling console content), so remove the last item's border. */
|
||||
.message:last-child {
|
||||
.webconsole-app:not(.jsterm-editor) .message:last-child {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
|
@ -603,35 +603,33 @@ a.learn-more-link.webconsole-learn-more-link {
|
|||
|
||||
/*
|
||||
This element contains the different toolbars in the console
|
||||
- primary, containing the clear messages button and the text search input.
|
||||
It can expand as much as it need.
|
||||
- filtered messages, containing the "X items hidden by filters" and the reset filters button.
|
||||
It should be on the same row than the primary bar if it fits there, or on its own 100% row if it is wrapped.
|
||||
- close button, close the split console panel. This button will be displayed on righ-top of tool bar always.
|
||||
- secondary, containing the filter buttons (Error, Warning, …).
|
||||
It should be on its own 100% row.
|
||||
- primary, containing the clear messages button and the text search input, and a
|
||||
checkbox (Persist logs or Show Content Messages).
|
||||
It can expand as much as it needs.
|
||||
- close button, close the split console panel. This button will always be displayed on
|
||||
righ-top of the toolbar.
|
||||
- secondary, containing the filter buttons (Error, Warning, …). It's placed inside the
|
||||
primary toolbar if there's enought space.
|
||||
|
||||
Basically here's what we can have :
|
||||
We have 2 different layout:
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------
|
||||
| Clear button - Open filter bar button - Filter Input | X items hidden by filters - Reset Filters button | Close button |
|
||||
--------------------------------------------------------------------------------------------------------------------------
|
||||
| Error - Warning - Log - Info - Debug - CSS - Network - XHR |
|
||||
--------------------------------------------------------------------------------------------------------------------------
|
||||
Narrow:
|
||||
|
||||
or
|
||||
--------------------------------------------------------------
|
||||
| 🗑 - Filter Input | ✕ |
|
||||
--------------------------------------------------------------
|
||||
| Error - Warning - Log - Info - Debug - CSS - Network - XHR |
|
||||
--------------------------------------------------------------
|
||||
|
||||
---------------------------------------------------------------------------------------------------
|
||||
| Clear button - Open filter bar button - Filter Input | Close button |
|
||||
---------------------------------------------------------------------------------------------------
|
||||
| X items hidden by filters - Reset Filters button |
|
||||
---------------------------------------------------------------------------------------------------
|
||||
| Error - Warning - Log - Info - Debug - CSS - Network - XHR |
|
||||
---------------------------------------------------------------------------------------------------
|
||||
And wide:
|
||||
|
||||
--------------------------------------------------------------------------------------
|
||||
| 🗑 - Filter Input | Error - Warning - Log - Info - Debug - CSS - Network - XHR | ✕ |
|
||||
--------------------------------------------------------------------------------------
|
||||
*/
|
||||
.webconsole-filteringbar-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr max-content auto auto;
|
||||
grid-template-columns: 1fr auto;
|
||||
--primary-toolbar-height: 29px;
|
||||
}
|
||||
|
||||
|
@ -909,7 +907,7 @@ body {
|
|||
*
|
||||
* +------------------------------+--------------+
|
||||
* | | |
|
||||
* | WEBCONSOLE FLEX WRAPPER | SIDEBAR |
|
||||
* | WEBCONSOLE WRAPPER | SIDEBAR |
|
||||
* | | |
|
||||
* +------------------------------+--------------+
|
||||
*/
|
||||
|
@ -927,7 +925,7 @@ body {
|
|||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
.webconsole-flex-wrapper {
|
||||
.webconsole-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
|
@ -935,17 +933,17 @@ body {
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.webconsole-flex-wrapper .webconsole-filteringbar-wrapper {
|
||||
.webconsole-wrapper .webconsole-filteringbar-wrapper {
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.webconsole-flex-wrapper .webconsole-output {
|
||||
.webconsole-wrapper .webconsole-output {
|
||||
flex-shrink: 100000;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.webconsole-flex-wrapper > .webconsole-output:not(:empty) {
|
||||
.webconsole-wrapper > .webconsole-output:not(:empty) {
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
|
@ -964,7 +962,7 @@ body {
|
|||
padding-block-start: 2px;
|
||||
}
|
||||
|
||||
.webconsole-flex-wrapper > .webconsole-output:empty ~ .jsterm-input-container {
|
||||
.webconsole-wrapper > .webconsole-output:empty ~ .jsterm-input-container {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
|
@ -1122,6 +1120,88 @@ body {
|
|||
min-width: 100%;
|
||||
}
|
||||
|
||||
|
||||
/** EDITOR MODE */
|
||||
.jsterm-editor .webconsole-wrapper {
|
||||
display: grid;
|
||||
/*
|
||||
* Here's the design we want in editor mode
|
||||
* +----------------------------------------------------+
|
||||
* | Editor Toolbar | Filter bar primary |
|
||||
* +----------------------------------------------------+
|
||||
* | | (Filter bar secondary) |
|
||||
* | +-------------------------+
|
||||
* | Editor | |
|
||||
* | | |
|
||||
* | | |
|
||||
* | | output |
|
||||
* | | |
|
||||
* | | |
|
||||
* +--------------------------+ |
|
||||
* | (Reverse search input) | |
|
||||
* +----------------------------------------------------+
|
||||
*
|
||||
* Elements in parens may not be visible, so we set some rows to be auto to make them
|
||||
* have no height when the element they contain is hidden.
|
||||
*/
|
||||
grid-template-rows: var(--primary-toolbar-height) auto 1fr auto;
|
||||
/* The first column is set to auto so we can resize it */
|
||||
grid-template-columns: auto 1fr;
|
||||
}
|
||||
|
||||
.jsterm-editor .webconsole-filteringbar-wrapper {
|
||||
grid-column: 2 / 3;
|
||||
grid-row: 1 / 3;
|
||||
grid-template-rows: subgrid;
|
||||
}
|
||||
|
||||
.jsterm-editor .webconsole-filterbar-primary {
|
||||
grid-row: 1 / 2;
|
||||
}
|
||||
|
||||
/* Only put the filter buttons toolbar on its own row in narrow filterbar layout */
|
||||
.jsterm-editor .narrow .devtools-toolbar.webconsole-filterbar-secondary {
|
||||
grid-row: 2 / 3;
|
||||
}
|
||||
|
||||
.jsterm-editor .webconsole-editor-toolbar {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: 1 / 2;
|
||||
border-inline-end: 1px solid var(--theme-splitter-color);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: start;
|
||||
height: unset;
|
||||
}
|
||||
|
||||
.jsterm-editor .webconsole-output {
|
||||
grid-column: 2 / 3;
|
||||
grid-row: 3 / -1;
|
||||
}
|
||||
|
||||
.jsterm-editor .jsterm-input-container {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: 2 / 4;
|
||||
width: 50vw;
|
||||
border-inline-end: 1px solid var(--theme-splitter-color);
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.jsterm-editor #webconsole-notificationbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jsterm-cm.jsterm-editor .jsterm-input-container > .CodeMirror {
|
||||
padding-inline-start: 0;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.jsterm-editor .reverse-search {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: -1 / -2;
|
||||
border-top: 1px solid var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
/** Utils **/
|
||||
.clipboard-only {
|
||||
position: absolute;
|
||||
|
|
|
@ -17,6 +17,7 @@ const ConsoleOutput = createFactory(require("devtools/client/webconsole/componen
|
|||
const FilterBar = createFactory(require("devtools/client/webconsole/components/FilterBar/FilterBar"));
|
||||
const SideBar = createFactory(require("devtools/client/webconsole/components/SideBar"));
|
||||
const ReverseSearchInput = createFactory(require("devtools/client/webconsole/components/Input/ReverseSearchInput"));
|
||||
const EditorToolbar = createFactory(require("devtools/client/webconsole/components/Input/EditorToolbar"));
|
||||
const JSTerm = createFactory(require("devtools/client/webconsole/components/Input/JSTerm"));
|
||||
const ConfirmDialog = createFactory(require("devtools/client/webconsole/components/Input/ConfirmDialog"));
|
||||
const NotificationBox = createFactory(require("devtools/client/shared/components/NotificationBox").NotificationBox);
|
||||
|
@ -238,7 +239,7 @@ class App extends Component {
|
|||
ref: node => {
|
||||
this.node = node;
|
||||
}},
|
||||
div({className: "webconsole-flex-wrapper"},
|
||||
div({className: "webconsole-wrapper"},
|
||||
FilterBar({
|
||||
hidePersistLogsCheckbox: webConsoleUI.isBrowserConsole,
|
||||
hideShowContentMessagesCheckbox,
|
||||
|
@ -254,6 +255,10 @@ class App extends Component {
|
|||
wrapping: true,
|
||||
notifications,
|
||||
}),
|
||||
EditorToolbar({
|
||||
editorMode,
|
||||
webConsoleUI,
|
||||
}),
|
||||
JSTerm({
|
||||
webConsoleUI,
|
||||
serviceContainer,
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* 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";
|
||||
|
||||
// React & Redux
|
||||
const { Component } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
const { l10n } = require("devtools/client/webconsole/utils/messages");
|
||||
const Services = require("Services");
|
||||
const isMacOS = Services.appinfo.OS === "Darwin";
|
||||
|
||||
class EditorToolbar extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
webConsoleUI: PropTypes.object.isRequired,
|
||||
editorMode: PropTypes.bool,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
editorMode,
|
||||
webConsoleUI,
|
||||
} = this.props;
|
||||
|
||||
if (!editorMode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return dom.div({
|
||||
className: "devtools-toolbar devtools-input-toolbar webconsole-editor-toolbar",
|
||||
},
|
||||
dom.button({
|
||||
className: "devtools-button webconsole-editor-toolbar-executeButton",
|
||||
title: l10n.getFormatStr("webconsole.editor.toolbar.executeButton.tooltip",
|
||||
[isMacOS ? "Cmd + Enter" : "Ctrl + Enter"]),
|
||||
onClick: () => webConsoleUI.jsterm.execute(),
|
||||
}, l10n.getStr("webconsole.editor.toolbar.executeButton.label")));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EditorToolbar;
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
DevToolsModules(
|
||||
'ConfirmDialog.js',
|
||||
'EditorToolbar.js',
|
||||
'JSTerm.js',
|
||||
'ReverseSearchInput.css',
|
||||
'ReverseSearchInput.js',
|
||||
|
|
|
@ -209,8 +209,10 @@ skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1
|
|||
[browser_jsterm_ctrl_key_nav.js]
|
||||
skip-if = os != 'mac' # The tested ctrl+key shortcuts are OSX only
|
||||
[browser_jsterm_document_no_xray.js]
|
||||
[browser_jsterm_editor.js]
|
||||
[browser_jsterm_editor_enter.js]
|
||||
[browser_jsterm_editor_execute.js]
|
||||
[browser_jsterm_editor_toolbar.js]
|
||||
[browser_jsterm_error_docs.js]
|
||||
[browser_jsterm_error_outside_valid_range.js]
|
||||
[browser_jsterm_focus_reload.js]
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Check that the editor is displayed as expected.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf8,<p>Test editor";
|
||||
|
||||
add_task(async function() {
|
||||
// Run test with legacy JsTerm
|
||||
await pushPref("devtools.webconsole.jsterm.codeMirror", false);
|
||||
await performTests();
|
||||
|
||||
// And then run it with the CodeMirror-powered one.
|
||||
await pushPref("devtools.webconsole.jsterm.codeMirror", true);
|
||||
await performTests();
|
||||
});
|
||||
|
||||
async function performTests() {
|
||||
await pushPref("devtools.webconsole.input.editor", false);
|
||||
|
||||
const tab = await addTab(TEST_URI);
|
||||
let hud = await openConsole(tab);
|
||||
|
||||
info("Test that the editor mode is disabled when the pref is set to false");
|
||||
is(isEditorModeEnabled(hud), false, "Editor is disabled when pref is set to false");
|
||||
|
||||
await closeConsole();
|
||||
|
||||
info("Test that wrapper does have the jsterm-editor class when editor is enabled");
|
||||
await pushPref("devtools.webconsole.input.editor", true);
|
||||
hud = await openConsole(tab);
|
||||
is(isEditorModeEnabled(hud), true, "Editor is enabled when pref is set to true");
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Check that the editor toolbar works as expected when in editor mode.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf8,<p>Test editor toolbar";
|
||||
|
||||
add_task(async function() {
|
||||
// Run test with legacy JsTerm
|
||||
await pushPref("devtools.webconsole.jsterm.codeMirror", false);
|
||||
await performTests();
|
||||
|
||||
// And then run it with the CodeMirror-powered one.
|
||||
await pushPref("devtools.webconsole.jsterm.codeMirror", true);
|
||||
await performTests();
|
||||
});
|
||||
|
||||
async function performTests() {
|
||||
await pushPref("devtools.webconsole.input.editor", false);
|
||||
|
||||
const tab = await addTab(TEST_URI);
|
||||
let hud = await openConsole(tab);
|
||||
|
||||
info("Test that the toolbar is not displayed when in editor mode");
|
||||
let toolbar = getEditorToolbar(hud);
|
||||
is(toolbar, null, "The toolbar isn't displayed when not in editor mode");
|
||||
await closeToolbox();
|
||||
|
||||
await pushPref("devtools.webconsole.input.editor", true);
|
||||
hud = await openConsole(tab);
|
||||
|
||||
info("Test that the toolbar is displayed when in editor mode");
|
||||
toolbar = getEditorToolbar(hud);
|
||||
ok(toolbar, "The toolbar is displayed when in editor mode");
|
||||
|
||||
info("Test that the toolbar has the expected items");
|
||||
const runButton = toolbar.querySelector(".webconsole-editor-toolbar-executeButton");
|
||||
is(runButton.textContent, "Run", "The button has the expected text");
|
||||
const keyShortcut = (Services.appinfo.OS === "Darwin" ? "Cmd" : "Ctrl") + " + Enter";
|
||||
is(runButton.getAttribute("title"),
|
||||
`Run expression (${keyShortcut}). This won’t clear the input.`);
|
||||
|
||||
info("Test that clicking on the Run button works as expected");
|
||||
// Setting the input value.
|
||||
const input = "`${1 + 1} = 2`";
|
||||
setInputValue(hud, input);
|
||||
|
||||
runButton.click();
|
||||
await waitFor(() => findMessage(hud, input));
|
||||
await waitFor(() => findMessage(hud, "2 = 2", ".message.result"));
|
||||
ok(true, "The expression and its result are displayed in the output");
|
||||
ok(isInputFocused(hud), "input is still focused after clicking the Run button");
|
||||
}
|
||||
|
||||
function getEditorToolbar(hud) {
|
||||
return hud.ui.outputNode.querySelector(".webconsole-editor-toolbar");
|
||||
}
|
|
@ -32,7 +32,7 @@ async function performTests() {
|
|||
outputNode,
|
||||
,
|
||||
inputNode,
|
||||
] = appNode.querySelector(".webconsole-flex-wrapper").childNodes;
|
||||
] = appNode.querySelector(".webconsole-wrapper").childNodes;
|
||||
|
||||
testLayout(appNode);
|
||||
|
||||
|
|
|
@ -1390,3 +1390,16 @@ function reloadPage() {
|
|||
});
|
||||
return onLoad;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the editor mode is enabled (i.e. .webconsole-app has the expected class).
|
||||
*
|
||||
* @param {WebConsole} hud
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
function isEditorModeEnabled(hud) {
|
||||
const {outputNode} = hud.ui;
|
||||
const appNode = outputNode.querySelector(".webconsole-app");
|
||||
return appNode.classList.contains("jsterm-editor");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче