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:
Nicolas Chevobbe 2019-06-27 13:13:32 +00:00
Родитель c2694625b5
Коммит 66150262ef
10 изменённых файлов: 285 добавлений и 32 удалений

Просмотреть файл

@ -396,4 +396,16 @@ webconsole.message.componentDidCatch.label=[DEVTOOLS ERROR] Were 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 wont 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 wont 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");
}