Migration tool UI improvements

- Update header text and buttons
- Add Roboto font
- Add Roboto Mono font
- Add Material icons font
- Update color scheme
- Move help button to header
- Change "Report a problem" button to "Send Feedback"
- Update button colors

Change-Id: Ia4d8b71ae8ec7a7c04ab8c238ffb0499becc9620
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151663
Commit-Queue: John Ryan <ryjohn@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
John Ryan 2020-06-22 18:19:16 +00:00 committed by commit-bot@chromium.org
parent ea7e6f29bf
commit 3c85ade7f9
14 changed files with 11244 additions and 4031 deletions

View file

@ -86,6 +86,15 @@ class MigrationInfo {
/// The path of the Dart logo displayed in the toolbar.
String get dartLogoPath => PreviewSite.dartLogoPath;
/// The path of the Material icons font.
String get materialIconsPath => PreviewSite.materialIconsPath;
/// The path of the Roboto font.
String get robotoFont => PreviewSite.robotoFontPath;
/// The path of the Roboto Mono font.
String get robotoMonoFont => PreviewSite.robotoMonoFontPath;
/// Return the path to [unit] from [includedRoot], to be used as a display
/// name for a library.
String computeName(UnitInfo unit) =>

View file

@ -21,16 +21,36 @@
<p class="root">{{ root }}</p>
<header class="elevation-z4">
<img src="{{ dartLogoPath }}" alt="DartPad Logo" class="logo"/>
<h1 class="before-apply">Proposed null safety changes</h1>
<h1 class="after-apply">&#10003; Null safety migration applied</h1>
<h2 id="unit-name">&nbsp;</h2>
<button class="apply-migration">&#9998; Apply Migration</button>
<button class="apply-migration" disabled>&#9998; Apply Migration</button>
<button class="rerun-migration before-apply">
<span class="optional">&#8635; Rerun From Sources</span>
<h1>Dart</h1>
<h2 class="before-apply">Proposed null safety changes</h2>
<h2 class="after-apply">&#10003; Null safety migration applied</h2>
<h3 id="unit-name">&nbsp;</h3>
<a target="_blank"
href="https://goo.gle/dart-null-safety-migration-tool">
<button class="action-button">
<i class="material-icons">launch</i>
<span>Help</span>
</button>
</a>
<button class="action-button apply-migration">
<i class="material-icons">edit</i>
<span class="label">
Apply Migration
</span>
</button>
<button class="action-button apply-migration" disabled>
<i class="material-icons">edit</i>
<span class="label">
Apply Migration
</span>
</button>
<button class="action-button rerun-migration before-apply">
<span class="optional">
<i class="material-icons">replay</i>
Rerun From Sources
</span>
<span class="required">
<span class="icon"
title="Disk contents have changed. Rerun to get an up-to-date migration.">!</span>
<i class="material-icons">warning</i>
Rerun With Changes
</span>
</button>
@ -68,12 +88,9 @@
</div><!-- /info-panel -->
</div><!-- /panels -->
<footer>
<a target="_blank"
href="https://goo.gle/dart-null-safety-migration-tool">Null safety
migration help</a>
<button class="report-problem">Send Feedback</button>
<span class="wide"> </span>
<div>Based on <span id="sdk-version">{{ sdkVersion }}</span></div>
<button class="report-problem">Report a Problem</button>
<div class="sdk-version">Based on <span id="sdk-version">{{ sdkVersion }}</span></div>
</footer>
</body>
</html>

View file

@ -2,6 +2,55 @@
/* for details. All rights reserved. Use of this source code is governed by a */
/* BSD-style license that can be found in the LICENSE file. */
/*
* Colors mentioned in this file, e.g. "$dark-text-color" are from DartPad:
* https://github.com/dart-lang/dart-pad/blob/master/lib/scss/colors.scss
*/
/* Text selection */
::selection {
background: #6e8eb1; /* $dark-selection-color */;
}
/* Material icons configuration */
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: local('Material Icons'),
local('MaterialIcons-Regular'),
url(/MaterialIconsRegular.ttf) format('truetype');
}
/*
* Required for Material Icons:
* https://google.github.io/material-design-icons/
*/
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px; /* Preferred icon size */
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
}
body {
background-color: #12202f;
color: #ccc;
@ -44,7 +93,8 @@ header {
}
header h1,
header h2 {
header h2,
header h3 {
display: inline-block;
font-family: "Google Sans","Roboto",sans-serif;
font-weight: 400;
@ -57,9 +107,20 @@ h1 {
header h2 {
font-size: 1.2em;
/* Shift text up */
position: relative;
top: -2px;
}
header .apply-migration, .rerun-migration {
header h3 {
/* Shift text up */
position: relative;
top: -2px;
}
header .action-button, header a {
right: 0px;
float: right;
margin: 10px;
@ -69,6 +130,8 @@ header img.logo {
height: 24px;
width: 24px;
margin-right: 8px;
position: relative;
top: 4px;
}
footer .report-problem {
@ -88,36 +151,6 @@ footer .report-problem {
display:none;
}
/* Red triangle */
.rerun-migration .required .icon::before {
transform: translate(-8px, -11px);
content: '\25B3';
font-size: 25px;
position: fixed;
color: #e82c2c;
text-shadow: 0px 0px 5px white;
z-index: -3;
}
/* Red triangle fill */
.rerun-migration .required .icon::after {
transform: translate(-9px, -10px);
content: '\25B4';
font-size: 25px;
position: fixed;
color: #b3ecff;
z-index: -1;
}
/* Red triangle exclamation */
.rerun-migration .required .icon {
display: inline-block;
margin-right: 8px;
transform: translate(0px, 2px);
margin-left: 2px;
color: #2b2b2b;
}
footer {
color: #ccc;
background-color: #27323a;
@ -131,6 +164,10 @@ footer .wide {
flex: 1;
}
footer .sdk-version {
margin-right: 32px;
}
.horizontal {
display: flex;
}
@ -142,7 +179,7 @@ footer .wide {
}
.panel-heading {
color: gray;
color: #676767;
margin: 8px;
}
@ -152,10 +189,11 @@ footer .wide {
}
.nav-panel {
background-color: #282b2e;
background-color: #12202f;
flex: 1 200px;
margin: 0;
overflow: scroll;
user-select: none;
}
.nav-inner {
@ -176,6 +214,14 @@ footer .wide {
padding-left: 6px;
}
.nav-tree .material-icons {
font-size: 20px;
position: relative;
top: 5px;
margin-right: 8px;
color: #676767;
}
.nav-inner ul {
padding-left: 12px;
margin: 0;
@ -220,9 +266,9 @@ footer .wide {
}
.edit-count {
background-color: #37aedc;
background-color: #676767;
border-radius: 10px;
color: #000000;
color: #fff;
display: inline-block;
font-size: 11px;
font-weight: 600;
@ -235,8 +281,8 @@ footer .wide {
.content {
flex: 4 300px;
background: #282b2e;
font-family: monospace;
background: #12202f;
font-family: "Roboto Mono", monospace;
margin: 0 6px;
position: relative;
white-space: pre;
@ -251,13 +297,6 @@ footer .wide {
margin-left: 56px;
}
.hljs {
background-color: #282b2e;
display: block;
overflow-x: auto;
padding: 0.5em;
}
.code .welcome {
font-family: "Google Sans","Roboto",sans-serif;
font-size: 18px;
@ -266,12 +305,12 @@ footer .wide {
}
.code .nav-link {
color: inherit;
color: #16adca;
text-decoration-line: none;
}
.code .nav-link:visited {
color: inherit;
color: #139bb5; /* #16adca darkened 10% */
text-decoration-line: none;
}
@ -311,7 +350,7 @@ footer .wide {
}
.regions td.line-no {
border-right: solid #282b2e 2px;
border-right: solid #12202f 2px;
color: #999999;
padding-right: 4px;
text-align: right;
@ -332,18 +371,17 @@ footer .wide {
}
.region.added-region {
background-color: #ccffcc;
color: #003300;
background-color: #263952; /* $dark-selection-color */
color: #c0c2c5; /* $dark-editor-text */
}
.region.removed-region {
background-color: #ff6666;
background-color: #FA557d; /* $dark-pink */
color: #001100;
}
.region.informative-region {
background-color: #404549; /* #282b2e, lightened 10% */
border-bottom: solid rgba(255, 255, 0, 0.7) 1px;
background-color: #178afd; /* $dark-selection-color */
display: inline-block;
height: 14px;
position: relative;
@ -366,7 +404,7 @@ footer .wide {
}
.info-panel .edit-panel {
background-color: #282b2e;
background-color: #12202f;
overflow: auto;
}
@ -392,11 +430,15 @@ footer .wide {
}
.info-panel a {
color: #33ccff;
color: #139bb5;
}
.info-panel a:hover {
color: #1ec7e7; /* #139bb5 lightened 20% */
}
.info-panel .edit-list {
background-color: #282b2e;
background-color: #12202f;
overflow: auto;
}
@ -456,7 +498,7 @@ footer .wide {
}
.popup-pane pre {
background: #282b2e;
background: #12202f;
padding: 20px;
bottom: 0px;
overflow: auto scroll;
@ -494,8 +536,8 @@ body.rerunning .rerunning-pane {
}
.edit-panel .type-description {
/* From HLJS's .hljs-keyword, .hljs-selector-tag, .hljs-deletion */
color: #cc7832;
/* From DartPad $dark-orange */
color: #ff916e;
font-family: monospace;
}
@ -510,8 +552,8 @@ ul.trace li {
}
ul.trace li .function {
/* From HLJS's .hljs-section, .hljs-title, .hljs-type */
color: #ffc66d;
/* from .hljs-variable */
color: #16adca;
font-family: monospace;
font-weight: 600;
}
@ -538,7 +580,7 @@ a {
}
a:hover {
color: #fff;
color: #dbdbdb; /* #ccc lightented 30%*/
fill: #fff;
}
@ -547,30 +589,79 @@ a:hover {
margin: 3px;
}
.add-hint-link:hover {
color: #fff;
}
header button {
text-transform: uppercase;
}
header a {
margin: 0;
}
/* Careful here. `a.button` is repetitive but required to get correct
* specificity */
button, .button, a.button {
background-color: #33ccff;
border: 2px solid #37aedc;
background-color: rgba(22, 138, 253, 0.15);
border: none;
border-radius: 3px;
padding: 6px 10px;
font-weight: bold;
color: #282828;
padding: 3px 10px;
font-weight: 500;
font-font: Roboto, sans-serif;
color: #fff;
}
button:hover, .button:hover {
background-color: #80dfff;
border: 2px solid #52b8e0;
background-color: rgba(22, 138, 253, 0.29);
cursor: pointer;
}
button[disabled] {
background-color: #7aa8b8;
color: #507177;
border: 2px solid #507177;
background-color: rgba(255,255,255,.12);
color: rgba(255,255,255,.37);
cursor: not-allowed;
}
/* Change edit panel button colors */
.edit-panel .button, .edit-panel button {
background-color: rgba(63, 104, 148, 0.6);
color: white;
}
.edit-panel .button:hover, .edit-panel button:hover {
background-color: rgba(101, 153, 208, 0.6);
color: white;
}
/*
* Adjustments to align material icons in the toolbar buttons.
*/
.action-button > span {
position:relative;
top: -3px;
}
.action-button .material-icons {
top: 4px;
}
/* Don't shift the icon when it's a direct child of the button */
.action-button > .material-icons {
top: 1px;
}
/* Shift the text to center with the icon. */
.action-button > span.label {
position:relative;
top: -4px;
}
.action-button .material-icons {
font-size: 20px;
position: relative;
}
.placeholder {
color: #777;
text-align: center;
@ -581,8 +672,57 @@ button[disabled] {
* HLJS Overrides
*/
.hljs {
background-color: #12202f; /* $dark-code-background-color */
color: #c0c2c5; /* $dark-editor-text */
display: block;
overflow-x: auto;
padding: 0.5em;
/**
* This allows the per-line highlights to show.
*/
background: none;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-deletion {
color: #51c686; /* cm-keyword */
}
.hljs-number {
color: #627978; /* cm-number */
}
.hljs-comment {
color: #9198b4; /* cm-comment */
}
.hljs-literal {
color: #ee8666; /* cm-atom */
}
.hljs-string {
color: #e55074; /* cm-string */
}
.hljs-variable {
color: #16adca; /* cm-variable */
}
.hljs-link {
color: #e55074; /* cm-string */
}
.hljs-section,
.hljs-type,
.hljs-built_in,
.hljs-title {
color: #ee8666; /* cm-variable-2 */
}
.hljs-addition {
color: #263952; /* $dark-selection-color */
}
.hljs-meta {
color: #627978;
}

File diff suppressed because it is too large Load diff

View file

@ -678,12 +678,12 @@ void writeNavigationSubtree(
arrow.innerHtml = '&#x25BC;';
Element icon = document.createElement('span');
li.append(icon);
icon.innerHtml = '&#x1F4C1;';
icon.innerHtml = '<span class="material-icons">folder_open</span>';
li.append(Text(entity.name));
writeNavigationSubtree(li, entity.subtree);
addArrowClickHandler(arrow);
} else {
li.innerHtml = '&#x1F4C4;';
li.innerHtml = '<span class="material-icons">insert_drive_file</span>';
Element a = document.createElement('a');
li.append(a);
a.classes.add('nav-link');

View file

@ -1,4 +1,4 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

View file

@ -0,0 +1,31 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:nnbd_migration/src/front_end/resources/resources.g.dart'
as resources;
import 'package:nnbd_migration/src/preview/preview_page.dart';
import 'package:nnbd_migration/src/preview/preview_site.dart';
/// The page that contains the CSS used to style the semantic highlighting
/// within a Dart file.
class MaterialIconsPage extends PreviewPage {
/// Initialize a newly created CSS page within the given [site].
MaterialIconsPage(PreviewSite site)
: super(site, PreviewSite.materialIconsPath.substring(1));
@override
bool get requiresAuth => false;
@override
void generateBody(Map<String, String> params) {
throw UnimplementedError();
}
@override
Future<void> generatePage(Map<String, String> params) async {
buf.write(resources.MaterialIconsRegular_ttf);
}
}

View file

@ -20,11 +20,14 @@ import 'package:nnbd_migration/src/preview/highlight_css_page.dart';
import 'package:nnbd_migration/src/preview/highlight_js_page.dart';
import 'package:nnbd_migration/src/preview/http_preview_server.dart';
import 'package:nnbd_migration/src/preview/index_file_page.dart';
import 'package:nnbd_migration/src/preview/material_icons_page.dart';
import 'package:nnbd_migration/src/preview/navigation_tree_page.dart';
import 'package:nnbd_migration/src/preview/not_found_page.dart';
import 'package:nnbd_migration/src/preview/pages.dart';
import 'package:nnbd_migration/src/preview/preview_page.dart';
import 'package:nnbd_migration/src/preview/region_page.dart';
import 'package:nnbd_migration/src/preview/roboto_mono_page.dart';
import 'package:nnbd_migration/src/preview/roboto_page.dart';
import 'package:nnbd_migration/src/preview/unauthorized_page.dart';
// The randomly generated auth token used to access the preview site.
@ -51,6 +54,15 @@ class PreviewSite extends Site
/// The path of the Dart logo displayed in the toolbar.
static const dartLogoPath = '/dart_192.png';
/// The path of the Material icons font.
static const materialIconsPath = '/MaterialIconsRegular.ttf';
/// The path of the Roboto font.
static const robotoFontPath = '/RobotoRegular.ttf';
/// The path of the Roboto Mono font.
static const robotoMonoFontPath = '/RobotoMonoRegular.ttf';
static const navigationTreePath = '/_preview/navigationTree.json';
static const applyHintPath = '/apply-hint';
@ -141,6 +153,18 @@ class PreviewSite extends Site
// Note: `return await` needed due to
// https://github.com/dart-lang/sdk/issues/39204
return await respond(request, DartLogoPage(this));
} else if (path == materialIconsPath) {
// Note: `return await` needed due to
// https://github.com/dart-lang/sdk/issues/39204
return await respond(request, MaterialIconsPage(this));
} else if (path == robotoFontPath) {
// Note: `return await` needed due to
// https://github.com/dart-lang/sdk/issues/39204
return await respond(request, RobotoPage(this));
} else if (path == robotoMonoFontPath) {
// Note: `return await` needed due to
// https://github.com/dart-lang/sdk/issues/39204
return await respond(request, RobotoMonoPage(this));
} else if (path == '/' ||
decodedPath == migrationInfo.includedRoot ||
decodedPath ==
@ -369,6 +393,10 @@ class PreviewSite extends Site
ContentType('application', 'javascript', charset: 'utf-8');
} else if (page is DartLogoPage) {
response.headers.contentType = ContentType('image', 'png');
} else if (page is MaterialIconsPage ||
page is RobotoPage ||
page is RobotoMonoPage) {
response.headers.contentType = ContentType('font', 'ttf');
} else {
response.headers.contentType = ContentType.html;
}

View file

@ -0,0 +1,31 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:nnbd_migration/src/front_end/resources/resources.g.dart'
as resources;
import 'package:nnbd_migration/src/preview/preview_page.dart';
import 'package:nnbd_migration/src/preview/preview_site.dart';
/// The page that contains the CSS used to style the semantic highlighting
/// within a Dart file.
class RobotoMonoPage extends PreviewPage {
/// Initialize a newly created CSS page within the given [site].
RobotoMonoPage(PreviewSite site)
: super(site, PreviewSite.robotoMonoFontPath.substring(1));
@override
bool get requiresAuth => false;
@override
void generateBody(Map<String, String> params) {
throw UnimplementedError();
}
@override
Future<void> generatePage(Map<String, String> params) async {
buf.write(resources.RobotoMonoRegular_ttf);
}
}

View file

@ -0,0 +1,31 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:nnbd_migration/src/front_end/resources/resources.g.dart'
as resources;
import 'package:nnbd_migration/src/preview/preview_page.dart';
import 'package:nnbd_migration/src/preview/preview_site.dart';
/// The page that contains the CSS used to style the semantic highlighting
/// within a Dart file.
class RobotoPage extends PreviewPage {
/// Initialize a newly created CSS page within the given [site].
RobotoPage(PreviewSite site)
: super(site, PreviewSite.robotoFontPath.substring(1));
@override
bool get requiresAuth => false;
@override
void generateBody(Map<String, String> params) {
throw UnimplementedError();
}
@override
Future<void> generatePage(Map<String, String> params) async {
buf.write(resources.RobotoRegular_ttf);
}
}

View file

@ -69,6 +69,7 @@ final List<String> resourceTypes = [
'.html',
'.js',
'.png',
'.ttf',
];
String base64Encode(List<int> bytes) {
@ -173,7 +174,8 @@ String _decode(String data) {
var name = path.basename(resource.path).replaceAll('.', '_');
String source;
if (path.extension(resource.path) == '.png') {
var extension = path.extension(resource.path);
if (extension == '.png' || extension == '.ttf') {
source = resource.readAsStringSync(encoding: latin1);
} else {
source = resource.readAsStringSync();
@ -240,7 +242,9 @@ void verifyResourcesGDartGenerated({
continue;
}
if (name == 'migration.js' || name == 'dart_192.png') {
if (name == 'migration.js' ||
name == 'dart_192.png' ||
path.extension(name) == '.ttf') {
// skip the compiled js and logo
continue;
}