feature #27678 Allow to configure some options of the profiler interface (javiereguiluz)

This PR was squashed before being merged into the 4.2-dev branch (closes #27678).

Discussion
----------

Allow to configure some options of the profiler interface

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yno
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

This PR adds some configurable options for the interface of the Symfony profiler.

First, you can configure the theme. The current one remains as the default light theme, but there's a new dark theme. A quick comparison:

![theme-light](https://user-images.githubusercontent.com/73419/41765883-ad2f9e6a-7605-11e8-87fb-881afbffc788.png)

![theme-dark](https://user-images.githubusercontent.com/73419/41765888-af597800-7605-11e8-9097-eb9667b82136.png)

The second option is the width of the profiler pages. The current normal width remains as the default, but there's a new dynamic width that is as width as the browser window. The "Performance" panel is the one where this option makes more sense. A quick comparison when using a 2560 x 1440 resolution:

![settings-width-normal](https://user-images.githubusercontent.com/73419/41765890-b4affe14-7605-11e8-80b9-99ca54b07b83.png)

![settings-width-wide](https://user-images.githubusercontent.com/73419/41765891-b6506876-7605-11e8-95c4-664b1fb0f3dd.png)

All settings are managed by JavaScript and persisted in localStorage, so everything is fast and simple:

![settings-in-action](https://user-images.githubusercontent.com/73419/41765926-ce04f31a-7605-11e8-93f4-a7f810f034a5.gif)

-----

Note to reviewers:

* This is the first draft of the PR.
* I expect: approval/rejection of this idea and general comments of the proposed solution.

Once this is accepted, I will finish the feature tweaking/fixing the design and the HTML/CSS/JS/Twig code. Don't comment on those details for now. Thanks!

Commits
-------

944c53fb0e Allow to configure some options of the profiler interface
This commit is contained in:
Fabien Potencier 2018-07-18 14:37:32 +02:00
commit ce73293532
5 changed files with 379 additions and 118 deletions

View File

@ -4,8 +4,8 @@
{% if colors is not defined %} {% if colors is not defined %}
{% set colors = { {% set colors = {
'default': '#999', 'default': '#777',
'section': '#444', 'section': '#999',
'event_listener': '#00B8F5', 'event_listener': '#00B8F5',
'template': '#66CC00', 'template': '#66CC00',
'doctrine': '#FF6633', 'doctrine': '#FF6633',
@ -220,6 +220,11 @@
return query('#collector-content h2').clientWidth; return query('#collector-content h2').clientWidth;
} }
function getCssVarValue(varName)
{
return getComputedStyle(document.querySelector('body')).getPropertyValue(varName);
}
/** /**
* Draw one canvas. * Draw one canvas.
* *
@ -272,7 +277,11 @@
ctx.lineWidth = 0; ctx.lineWidth = 0;
// For each event, draw a line. // For each event, draw a line.
ctx.strokeStyle = "#CCC"; ctx.strokeStyle = getCssVarValue('--table-border');
// set the background color of the canvas
ctx.fillStyle = getCssVarValue('--table-background');
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawableEvents.forEach(function(event) { drawableEvents.forEach(function(event) {
event.periods.forEach(function(period) { event.periods.forEach(function(period) {
@ -379,31 +388,31 @@
// For each event, draw the label. // For each event, draw the label.
mainEvents.forEach(function(event) { mainEvents.forEach(function(event) {
ctx.fillStyle = "#444"; ctx.fillStyle = getCssVarValue('--color-text');
ctx.font = "12px sans-serif"; ctx.font = "12px sans-serif";
text = event.name; text = event.name;
ms = " " + (event.duration < 1 ? event.duration : parseInt(event.duration, 10)) + " ms / " + event.memory + " MB"; ms = " " + (event.duration < 1 ? event.duration : parseInt(event.duration, 10)) + " ms / " + event.memory + " MB";
if (x + event.starttime * ratio + ctx.measureText(text + ms).width > width) { if (x + event.starttime * ratio + ctx.measureText(text + ms).width > width) {
ctx.textAlign = "end"; ctx.textAlign = "end";
ctx.font = "10px sans-serif"; ctx.font = "10px sans-serif";
ctx.fillStyle = "#777"; ctx.fillStyle = getCssVarValue('--color-muted');
xc = x + event.endtime * ratio - 1; xc = x + event.endtime * ratio - 1;
ctx.fillText(ms, xc, h); ctx.fillText(ms, xc, h);
xc -= ctx.measureText(ms).width; xc -= ctx.measureText(ms).width;
ctx.font = "12px sans-serif"; ctx.font = "12px sans-serif";
ctx.fillStyle = "#222"; ctx.fillStyle = getCssVarValue('--color-text');
ctx.fillText(text, xc, h); ctx.fillText(text, xc, h);
} else { } else {
ctx.textAlign = "start"; ctx.textAlign = "start";
ctx.font = "13px sans-serif"; ctx.font = "13px sans-serif";
ctx.fillStyle = "#222"; ctx.fillStyle = getCssVarValue('--color-text');
xc = x + event.starttime * ratio + 1; xc = x + event.starttime * ratio + 1;
ctx.fillText(text, xc, h); ctx.fillText(text, xc, h);
xc += ctx.measureText(text).width; xc += ctx.measureText(text).width;
ctx.font = "11px sans-serif"; ctx.font = "11px sans-serif";
ctx.fillStyle = "#777"; ctx.fillStyle = getCssVarValue('--color-muted');
ctx.fillText(ms, xc, h); ctx.fillText(ms, xc, h);
} }

View File

@ -14,6 +14,10 @@
{% endblock %} {% endblock %}
</head> </head>
<body> <body>
<script async>
document.body.classList.add(localStorage.getItem('symfony/profiler/theme'), localStorage.getItem('symfony/profiler/width'));
</script>
{% block body '' %} {% block body '' %}
</body> </body>
</html> </html>

View File

@ -126,6 +126,8 @@
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
{{ include('@WebProfiler/Profiler/settings.html.twig') }}
</div> </div>
<div id="collector-wrapper"> <div id="collector-wrapper">
@ -142,6 +144,6 @@
event.preventDefault(); event.preventDefault();
Sfjs.toggleClass(document.getElementById('sidebar'), 'expanded'); Sfjs.toggleClass(document.getElementById('sidebar'), 'expanded');
}) })
}()) }());
</script> </script>
{% endblock %} {% endblock %}

View File

@ -1,19 +1,72 @@
{# Mixins
========================================================================= #}
{% set mixins = {
'break_long_words': '-ms-word-break: break-all; word-break: break-all; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto;',
'monospace_font': 'font-family: monospace; font-size: 13px; font-size-adjust: 0.5;',
'sans_serif_font': 'font-family: Helvetica, Arial, sans-serif;',
'subtle_border_and_shadow': 'background: #FFF; border: 1px solid #E0E0E0; box-shadow: 0px 0px 1px rgba(128, 128, 128, .2);'
} %}
{# when updating any of these colors, do the same in toolbar.css.twig #}
{% set colors = { 'success': '#4F805D', 'warning': '#A46A1F', 'error': '#B0413E' } %}
{# Normalization {# Normalization
(normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css) (normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css)
========================================================================= #} ========================================================================= #}
html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0} *{-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}
:root {
--font-sans-serif: 'Helvetica, Arial, sans-serif';
--page-background: #f9f9f9;
--color-text: #222;
--color-muted: #777;
/* when updating any of these colors, do the same in toolbar.css.twig */
--color-success: #4f805d;
--color-warning: #a46a1f;
--color-error: #b0413e;
--tab-background: #fff;
--tab-color: #444;
--tab-active-background: #666;
--tab-active-color: #fafafa;
--tab-disabled-background: #f5f5f5;
--tab-disabled-color: #999;
--metric-value-background: #fff;
--metric-value-color: inherit;
--metric-unit-color: #999;
--metric-label-background: #e0e0e0;
--metric-label-color: inherit;
--table-border: #e0e0e0;
--table-background: #fff;
--table-header: #e0e0e0;
--shadow: 0px 0px 1px rgba(128, 128, 128, .2);
--border: 1px solid #e0e0e0;
--color-muted: #999;
--base-0: #fff;
--base-1: #f5f5f5;
--base-2: #e0e0e0;
--base-3: #ccc;
--base-4: #666;
--base-5: #444;
--base-6: #222;
}
.theme-dark {
--page-background: #36393e;
--color-text: #e0e0e0;
--color-muted: #999;
--tab-background: #555;
--tab-color: #ccc;
--tab-active-background: #888;
--tab-active-color: #fafafa;
--tab-disabled-background: var(--page-background);
--tab-disabled-color: #777;
--metric-value-background: #555;
--metric-value-color: inherit;
--metric-unit-color: #999;
--metric-label-background: #777;
--metric-label-color: #e0e0e0;
--table-border: #444;
--table-background: #333;
--table-header: #555;
--shadow: 0px 0px 1px rgba(32, 32, 32, .2);
--border: 1px solid #666;
--color-muted: #777;
--base-0: #2e3136;
--base-1: #444;
--base-2: #666;
--base-3: #666;
--base-4: #666;
--base-5: #e0e0e0;
--base-6: #f5f5f5;
}
{# Basic styles {# Basic styles
========================================================================= #} ========================================================================= #}
@ -22,11 +75,11 @@ html, body {
width: 100%; width: 100%;
} }
body { body {
background-color: #F9F9F9; background-color: var(--page-background);
color: #222; color: var(--base-6);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
{{ mixins.sans_serif_font|raw }} font_family: var(--font-sans-serif);
font-size: 14px; font-size: 14px;
line-height: 1.4; line-height: 1.4;
} }
@ -50,7 +103,7 @@ h4 {
} }
h2 span, h3 span, h4 span, h2 span, h3 span, h4 span,
h2 small, h3 small, h4 small { h2 small, h3 small, h4 small {
color: #999; color: var(--color-muted);
} }
li { li {
@ -91,24 +144,25 @@ h4 a:hover {
} }
abbr { abbr {
border-bottom: 1px dotted #444; border-bottom: 1px dotted var(--base-5);
cursor: help; cursor: help;
} }
code, pre { code, pre {
{{ mixins.monospace_font|raw }} font-family: monospace;
font-size: 13px;
} }
{# Buttons {# Buttons (the colors of this element don't change based on the selected theme)
------------------------------------------------------------------------- #} ------------------------------------------------------------------------- #}
button { button {
{{ mixins.sans_serif_font|raw }} font_family: var(--font-sans-serif);
} }
.btn { .btn {
background: #777; background: #777;
border-radius: 2px; border-radius: 2px;
border: 0; border: 0;
color: #F5F5F5; color: #f5f5f5;
display: inline-block; display: inline-block;
padding: .5em .75em; padding: .5em .75em;
} }
@ -141,13 +195,15 @@ button {
{# Tables {# Tables
------------------------------------------------------------------------- #} ------------------------------------------------------------------------- #}
table, tr, th, td { table, tr, th, td {
background: #FFF; background: var(--table-background);
border-collapse: collapse; border-collapse: collapse;
line-height: 1.5; line-height: 1.5;
vertical-align: top; vertical-align: top;
} }
table { table {
{{ mixins.subtle_border_and_shadow|raw }}; background: var(--base-0);
border: var(--border);
box-shadow: var(--shadow);
margin: 1em 0; margin: 1em 0;
width: 100%; width: 100%;
} }
@ -161,7 +217,7 @@ table th {
text-align: left; text-align: left;
} }
table thead th { table thead th {
background-color: #E0E0E0; background-color: var(--table-header);
} }
table thead th.key { table thead th.key {
width: 19%; width: 19%;
@ -173,9 +229,10 @@ table thead.small th {
table tbody th, table tbody th,
table tbody td { table tbody td {
{{ mixins.monospace_font|raw }} border: 1px solid var(--base-2);
border: 1px solid #E0E0E0;
border-width: 1px 0; border-width: 1px 0;
font-family: monospace;
font-size: 13px;
} }
table tbody div { table tbody div {
@ -212,16 +269,21 @@ table tbody td.num-col {
display: block; display: block;
} }
.break-long-words { .break-long-words {
{{ mixins.break_long_words|raw }} -ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
} }
.text-small { .text-small {
font-size: 12px !important; font-size: 12px !important;
} }
.text-muted { .text-muted {
color: #999; color: var(--color-muted);
} }
.text-danger { .text-danger {
color: {{ colors.error|raw }}; color: var(--color-error);
} }
.text-bold { .text-bold {
font-weight: bold; font-weight: bold;
@ -233,23 +295,23 @@ table tbody td.num-col {
text-align: center; text-align: center;
} }
.font-normal { .font-normal {
{{ mixins.sans_serif_font|raw }} font_family: var(--font-sans-serif);
font-size: 14px; font-size: 14px;
} }
.help { .help {
color: #999; color: var(--color-muted);
font-size: 14px; font-size: 14px;
margin-bottom: .5em; margin-bottom: .5em;
} }
.empty { .empty {
border: 4px dashed #E0E0E0; border: 4px dashed var(--base-2);
color: #999; color: var(--color-muted);
margin: 1em 0; margin: 1em 0;
padding: .5em 2em; padding: .5em 2em;
} }
.label { .label {
background-color: #666; background-color: var(--base-4);
color: #FAFAFA; color: #FAFAFA;
display: inline-block; display: inline-block;
font-size: 12px; font-size: 12px;
@ -261,9 +323,9 @@ table tbody td.num-col {
min-width: 70px; min-width: 70px;
text-align: center; text-align: center;
} }
.label.status-success { background: {{ colors.success|raw }}; color: #FFF; } .label.status-success { background: var(--color-success); color: #FFF; }
.label.status-warning { background: {{ colors.warning|raw }}; color: #FFF; } .label.status-warning { background: var(--color-warning); color: #FFF; }
.label.status-error { background: {{ colors.error|raw }}; color: #FFF; } .label.status-error { background: var(--color-error); color: #FFF; }
{# Metrics {# Metrics
------------------------------------------------------------------------- #} ------------------------------------------------------------------------- #}
@ -277,7 +339,10 @@ table tbody td.num-col {
} }
.metric { .metric {
{{ mixins.subtle_border_and_shadow|raw }}; background: var(--metric-value-background);
border: 1px solid var(--table-border);
box-shadow: var(--shadow);
color: var(--metric-value-color);
min-width: 100px; min-width: 100px;
min-height: 70px; min-height: 70px;
} }
@ -291,13 +356,13 @@ table tbody td.num-col {
margin: 5px 0 -5px; margin: 5px 0 -5px;
} }
.metric .unit { .metric .unit {
color: #999; color: var(--metric-unit-color);
font-size: 18px; font-size: 18px;
margin-left: -4px; margin-left: -4px;
} }
.metric .label { .metric .label {
background: #E0E0E0; background: var(--metric-label-background);
color: #222; color: var(--metric-label-color);
display: block; display: block;
font-size: 12px; font-size: 12px;
padding: 5px; padding: 5px;
@ -337,12 +402,14 @@ table tbody td.num-col {
{# Cards {# Cards
------------------------------------------------------------------------- #} ------------------------------------------------------------------------- #}
.card { .card {
{{ mixins.subtle_border_and_shadow|raw }}; background: var(--base-0);
border: var(--border);
box-shadow: var(--shadow);
margin: 1em 0; margin: 1em 0;
padding: 10px; padding: 10px;
} }
.card-block + .card-block { .card-block + .card-block {
border-top: 1px solid #E0E0E0; border-top: 1px solid var(--base-2);
padding-top: 10px; padding-top: 10px;
} }
.card *:first-child, .card *:first-child,
@ -351,7 +418,7 @@ table tbody td.num-col {
} }
.card .label { .card .label {
background-color: #EEE; background-color: #EEE;
color: #222; color: var(--base-6);
} }
{# Status {# Status
@ -377,10 +444,10 @@ tr.status-warning td {
} }
.status-warning .colored { .status-warning .colored {
color: {{ colors.warning|raw }}; color: var(--color-warning);
} }
.status-error .colored { .status-error .colored {
color: {{ colors.error|raw }}; color: var(--color-error);
} }
{# Syntax highlighting {# Syntax highlighting
@ -467,14 +534,14 @@ tr.status-warning td {
margin-top: 0; margin-top: 0;
} }
{# Header {# Header (the colors of this element don't change based on the selected theme)
========================================================================= #} ========================================================================= #}
#header { #header {
background-color: #222; background-color: #222;
overflow: hidden; overflow: hidden;
} }
#header h1 { #header h1 {
color: #FFF; color: #fff;
flex: 1; flex: 1;
font-weight: normal; font-weight: normal;
font-size: 21px; font-size: 21px;
@ -482,7 +549,7 @@ tr.status-warning td {
padding: 10px 10px 8px; padding: 10px 10px 8px;
} }
#header h1 span { #header h1 span {
color: #CCC; color: #ccc;
} }
#header h1 svg { #header h1 svg {
height: 40px; height: 40px;
@ -492,13 +559,13 @@ tr.status-warning td {
} }
#header h1 svg path, #header h1 svg path,
#header h1 svg .sf-svg-path { #header h1 svg .sf-svg-path {
fill: #FFF; fill: #fff;
} }
#header .search { #header .search {
padding-top: 11px; padding-top: 11px;
} }
#header .search input { #header .search input {
border: 1px solid #DDD; border: 1px solid #ddd;
margin-right: 4px; margin-right: 4px;
padding: 7px 8px; padding: 7px 8px;
width: 200px; width: 200px;
@ -507,14 +574,14 @@ tr.status-warning td {
{# Summary {# Summary
========================================================================= #} ========================================================================= #}
#summary .status { #summary .status {
background: #E0E0E0; background: var(--base-2);
border: solid rgba(0, 0, 0, 0.1); border: solid rgba(0, 0, 0, 0.1);
border-width: 2px 0; border-width: 2px 0;
padding: 10px; padding: 10px;
} }
#summary h2, #summary h2,
#summary h2 a { #summary h2 a {
color: #222; color: var(--base-6);
font-size: 21px; font-size: 21px;
margin: 0; margin: 0;
text-decoration: none; text-decoration: none;
@ -523,9 +590,9 @@ tr.status-warning td {
text-decoration: underline; text-decoration: underline;
} }
#summary .status-success { background: {{ colors.success|raw }}; } #summary .status-success { background: var(--color-success); }
#summary .status-warning { background: {{ colors.warning|raw }}; } #summary .status-warning { background: var(--color-warning); }
#summary .status-error { background: {{ colors.error|raw }}; } #summary .status-error { background: var(--color-error); }
#summary .status-success h2, #summary .status-success h2,
#summary .status-success a, #summary .status-success a,
@ -564,7 +631,7 @@ tr.status-warning td {
========================================================================= #} ========================================================================= #}
#sidebar { #sidebar {
background: #444; background: #444;
color: #CCC; color: #ccc;
padding-bottom: 30px; padding-bottom: 30px;
position: relative; position: relative;
width: 220px; width: 220px;
@ -593,7 +660,7 @@ tr.status-warning td {
text-align: center; text-align: center;
} }
#sidebar #sidebar-shortcuts .btn { #sidebar #sidebar-shortcuts .btn {
color: #F5F5F5; color: #f5f5f5;
} }
#sidebar #sidebar-shortcuts .btn + .btn { #sidebar #sidebar-shortcuts .btn + .btn {
margin-left: 5px; margin-left: 5px;
@ -602,7 +669,7 @@ tr.status-warning td {
padding: .5em; padding: .5em;
} }
{# Sidebar Search {# Sidebar Search (the colors of this element don't change based on the selected theme)
------------------------------------------------------------------------- #} ------------------------------------------------------------------------- #}
#sidebar-search .form-group:first-of-type { #sidebar-search .form-group:first-of-type {
padding-top: 20px; padding-top: 20px;
@ -625,7 +692,7 @@ tr.status-warning td {
padding: 3px 6px; padding: 3px 6px;
} }
#sidebar-search .form-group input { #sidebar-search .form-group input {
background: #CCC; background: #ccc;
border: 1px solid #999; border: 1px solid #999;
color: #222; color: #222;
width: 120px; width: 120px;
@ -638,7 +705,7 @@ tr.status-warning td {
margin-right: 10px; margin-right: 10px;
} }
{# Sidebar Menu {# Sidebar Menu (the colors of this element don't change based on the selected theme)
------------------------------------------------------------------------- #} ------------------------------------------------------------------------- #}
#menu-profiler { #menu-profiler {
margin: 0; margin: 0;
@ -652,7 +719,7 @@ tr.status-warning td {
#menu-profiler li a { #menu-profiler li a {
border: solid transparent; border: solid transparent;
border-width: 2px 0; border-width: 2px 0;
color: #CCC; color: var(--base-3);
display: block; display: block;
} }
#menu-profiler li a:hover { #menu-profiler li a:hover {
@ -710,12 +777,12 @@ tr.status-warning td {
#menu-profiler li.selected a .icon svg .sf-svg-path, #menu-profiler li.selected a .icon svg .sf-svg-path,
#menu-profiler li a:hover .icon svg path, #menu-profiler li a:hover .icon svg path,
#menu-profiler li a:hover .icon svg .sf-svg-path { #menu-profiler li a:hover .icon svg .sf-svg-path {
fill: #FFF; fill: #fff;
} }
#menu-profiler li a .count { #menu-profiler li a .count {
background-color: #666; background-color: #666;
color: #FFF; color: #fff;
display: inline-block; display: inline-block;
font-weight: bold; font-weight: bold;
min-width: 10px; min-width: 10px;
@ -736,16 +803,17 @@ tr.status-warning td {
} }
#menu-profiler .label-status-warning .count { #menu-profiler .label-status-warning .count {
background: {{ colors.warning|raw }}; background: var(--color-warning);
} }
#menu-profiler .label-status-error .count { #menu-profiler .label-status-error .count {
background: {{ colors.error|raw }}; background: var(--color-error);
} }
{# Timeline panel {# Timeline panel
========================================================================= #} ========================================================================= #}
#timeline-control { #timeline-control {
background: #FFF; background: var(--table-background);
box-shadow: var(--shadow);
margin: 1em 0; margin: 1em 0;
padding: 10px; padding: 10px;
} }
@ -754,6 +822,8 @@ tr.status-warning td {
margin-right: 1em; margin-right: 1em;
} }
#timeline-control input { #timeline-control input {
background: var(--metric-value-background);
border: 1px solid var(--table-border);
font-size: 16px; font-size: 16px;
padding: 4px; padding: 4px;
text-align: right; text-align: right;
@ -772,8 +842,8 @@ tr.status-warning td {
padding: 0 10px 0 5px; padding: 0 10px 0 5px;
} }
.sf-profiler-timeline canvas { .sf-profiler-timeline canvas {
border: 1px solid #DDD; border: 1px solid var(--table-border);
background: #FFF; background: var(--page-background);
margin: .5em 0; margin: .5em 0;
} }
.sf-profiler-timeline + p.help { .sf-profiler-timeline + p.help {
@ -787,9 +857,9 @@ tr.status-warning td {
padding: 0; padding: 0;
} }
.tab-navigation li { .tab-navigation li {
background: #FFF; background: var(--tab-background);
border: 1px solid #DDD; border: 1px solid var(--table-border);
color: #444; color: var(--tab-color);
cursor: pointer; cursor: pointer;
display: inline-block; display: inline-block;
font-size: 16px; font-size: 16px;
@ -797,12 +867,9 @@ tr.status-warning td {
padding: .5em .75em; padding: .5em .75em;
z-index: 1; z-index: 1;
} }
.tab-navigation li:hover {
background: #EEE;
}
.tab-navigation li .badge { .tab-navigation li .badge {
background-color: #F5F5F5; background-color: var(--base-1);
color: #777; color: var(--base-4);
display: inline-block; display: inline-block;
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
@ -812,29 +879,24 @@ tr.status-warning td {
text-align: center; text-align: center;
white-space: nowrap; white-space: nowrap;
} }
.tab-navigation li:hover .badge {
background: #FAFAFA;
color: #777;
}
.tab-navigation li.disabled { .tab-navigation li.disabled {
background: #F5F5F5; background: var(--tab-disabled-background);
color: #999; color: var(--tab-disabled-color);
} }
.tab-navigation li.active { .tab-navigation li.active {
background: #666; background: var(--tab-active-background);
border-color: #666; color: var(--tab-active-color);
color: #FAFAFA;
z-index: 1100; z-index: 1100;
} }
.tab-navigation li.active .badge { .tab-navigation li.active .badge {
background-color: #444; background-color: var(--base-5);
color: #FFF; color: var(--base-2);
} }
.tab-content > *:first-child { .tab-content > *:first-child {
margin-top: 0; margin-top: 0;
} }
.tab-navigation li .badge.status-warning { background: {{ colors.warning|raw }}; color: #FFF; } .tab-navigation li .badge.status-warning { background: var(--color-warning); color: #FFF; }
.tab-navigation li .badge.status-error { background: {{ colors.error|raw }}; color: #FFF; } .tab-navigation li .badge.status-error { background: var(--color-error); color: #FFF; }
.sf-tabs .tab:not(:first-child) { display: none; } .sf-tabs .tab:not(:first-child) { display: none; }
@ -897,7 +959,7 @@ table.logs .metadata {
{# Doctrine panel {# Doctrine panel
========================================================================= #} ========================================================================= #}
.sql-runnable { .sql-runnable {
background: #F5F5F5; background: var(--base-1);
margin: .5em 0; margin: .5em 0;
padding: 1em; padding: 1em;
} }
@ -909,9 +971,14 @@ table.logs .metadata {
word-break: normal; word-break: normal;
} }
.queries-table pre { .queries-table pre {
{{ mixins.break_long_words|raw }}
margin: 0; margin: 0;
white-space: pre-wrap; white-space: pre-wrap;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
} }
{# Validator panel {# Validator panel
@ -963,13 +1030,18 @@ table.logs .metadata {
{# Dump panel {# Dump panel
========================================================================= #} ========================================================================= #}
pre.sf-dump, pre.sf-dump .sf-dump-default {
z-index: 1000 !important;
}
#collector-content .sf-dump { #collector-content .sf-dump {
margin-bottom: 2em; margin-bottom: 2em;
} }
#collector-content pre.sf-dump, #collector-content pre.sf-dump,
#collector-content .sf-dump code, #collector-content .sf-dump code,
#collector-content .sf-dump samp { #collector-content .sf-dump samp {
{{ mixins.monospace_font|raw }} font-family: monospace;
font-size: 13px;
} }
#collector-content .sf-dump a { #collector-content .sf-dump a {
cursor: pointer; cursor: pointer;
@ -977,7 +1049,6 @@ table.logs .metadata {
#collector-content .sf-dump pre.sf-dump, #collector-content .sf-dump pre.sf-dump,
#collector-content .sf-dump .trace { #collector-content .sf-dump .trace {
border: 1px solid #DDD; border: 1px solid #DDD;
background: #FFF;
padding: 10px; padding: 10px;
margin: 0.5em 0; margin: 0.5em 0;
overflow: auto; overflow: auto;
@ -985,18 +1056,9 @@ table.logs .metadata {
#collector-content pre.sf-dump, #collector-content pre.sf-dump,
#collector-content .sf-dump-default { #collector-content .sf-dump-default {
color: #CC7832;
background: none; background: none;
} }
#collector-content .sf-dump-str { color: #629755; } #collector-content .sf-dump-ellipsis { max-width: 100em; }
#collector-content .sf-dump-private,
#collector-content .sf-dump-protected,
#collector-content .sf-dump-public { color: #262626; }
#collector-content .sf-dump-note { color: #6897BB; }
#collector-content .sf-dump-key { color: #789339; }
#collector-content .sf-dump-ref { color: #6E6E6E; }
#collector-content .sf-dump-ellipsis { color: #CC7832; max-width: 100em; }
#collector-content .sf-dump-ellipsis-path { max-width: 5em; }
#collector-content .sf-dump { #collector-content .sf-dump {
margin: 0; margin: 0;
@ -1021,14 +1083,11 @@ table.logs .metadata {
margin-bottom: 0; margin-bottom: 0;
padding: 0; padding: 0;
} }
#collector-content .sf-dump .trace li.selected {
background: rgba(255, 255, 153, 0.5);
}
{# Search Results page {# Search Results page
========================================================================= #} ========================================================================= #}
#search-results td { #search-results td {
{{ mixins.sans_serif_font|raw }} font_family: var(--font-sans-serif);
vertical-align: middle; vertical-align: middle;
} }
@ -1097,3 +1156,30 @@ table.logs .metadata {
margin-left: 2px; margin-left: 2px;
} }
} }
{# Config Options
========================================================================= #}
body.width-full .container {
max-width: 100%;
}
body.theme-light #collector-content .sf-dump pre.sf-dump,
body.theme-light #collector-content .sf-dump .trace {
background: #FFF;
}
body.theme-light #collector-content pre.sf-dump,
body.theme-light #collector-content .sf-dump-default {
color: #CC7832;
}
body.theme-light #collector-content .sf-dump-str { color: #629755; }
body.theme-light #collector-content .sf-dump-private,
body.theme-light #collector-content .sf-dump-protected,
body.theme-light #collector-content .sf-dump-public { color: #262626; }
body.theme-light #collector-content .sf-dump-note { color: #6897BB; }
body.theme-light #collector-content .sf-dump-key { color: #789339; }
body.theme-light #collector-content .sf-dump-ref { color: #6E6E6E; }
body.theme-light #collector-content .sf-dump-ellipsis { color: #CC7832; max-width: 100em; }
body.theme-light #collector-content .sf-dump-ellipsis-path { max-width: 5em; }
body.theme-light #collector-content .sf-dump .trace li.selected {
background: rgba(255, 255, 153, 0.5);
}

View File

@ -0,0 +1,160 @@
<style>
#open-settings {
color: var(--text-muted);
display: block;
margin: 15px 15px 5px;
}
.modal-wrap {
-webkit-transition: all 0.3s ease-in-out;
align-items: center;
background: rgba(0, 0, 0, 0.8);
display: flex;
height: 100%;
justify-content: center;
left: 0;
opacity: 1;
overflow: auto;
position: fixed;
top: 0;
transition: all 0.3s ease-in-out;
visibility: hidden;
width: 100%;
z-index: 100000;
}
.modal-wrap.visible {
opacity: 1;
visibility: visible;
}
.modal-wrap .modal-container {
box-shadow: 5px 5px 10px 0px rgba(0, 0, 0, 0.5);
color: var(--base-6);
margin: 1em;
max-width: 94%;
width: 600px;
}
.modal-wrap .modal-header {
align-items: center;
background: var(--table-header);
display: flex;
justify-content: space-between;
padding: 15px 30px;
}
.modal-wrap .modal-header h3 {
color: var(--base-6);
margin: 0;
}
.modal-wrap .modal-header .close-modal {
background: transparent;
border: 0;
color: var(--base-4);
cursor: pointer;
font-size: 28px;
line-height: 1;
}
.modal-wrap .modal-header .close-modal:hover { opacity: 1; }
.modal-wrap .modal-content {
background: var(--base-1);
margin: 0;
padding: 15px 30px;
width: 100%;
z-index: 100000;
}
.modal-content h4 {
border-bottom: var(--border);
margin: 0 0 15px;
padding: 0 0 5px;
}
.modal-content input, .modal-content .form-help {
margin-left: 15px;
}
.modal-content label {
cursor: pointer;
font-size: 16px;
margin-left: 3px;
}
.modal-content .form-help {
color: var(--color-muted);
font-size: 14px;
margin: 5px 0 15px 33px;
}
.modal-content .form-help + h4 {
margin-top: 45px;
}
</style>
<a href="#" id="open-settings" data-triger="profiler-settings">Settings</a>
<div class="modal-wrap" id="profiler-settings">
<div class="modal-container">
<div class="modal-header">
<h3>Configuration Settings</h3>
<button class="close-modal">&times;</button>
</div>
<div class="modal-content">
<h4>Theme</h4>
<input class="config-option" type="radio" name="theme" value="light" id="settings-theme-light">
<label for="settings-theme-light">Light</label>
<p class="form-help">Default theme. Improves readability.</p>
<input class="config-option" type="radio" name="theme" value="dark" id="settings-theme-dark">
<label for="settings-theme-dark">Dark</label>
<p class="form-help">Reduces eye fatigue. Ideal for low light conditions.</p>
<h4>Page Width</h4>
<input class="config-option" type="radio" name="width" value="light" id="settings-width-normal">
<label for="settings-width-normal">Normal</label>
<p class="form-help">Fixed page width. Improves readability.</p>
<input class="config-option" type="radio" name="width" value="dark" id="settings-width-full">
<label for="settings-width-full">Full-page</label>
<p class="form-help">Dynamic page width. As wide as the browser window.</p>
</div>
</div>
</div>
<script>
(function() {
let configOptions = document.querySelectorAll('.config-option');
let oppositeValues = { 'light': 'dark', 'dark': 'light', 'normal': 'full', 'full': 'normal' };
[...configOptions].forEach(option => {
option.addEventListener('click', function (event) {
let optionParts = option.id.split('-');
let optionName = optionParts[1];
let optionValue = optionParts[2];
document.body.classList.remove(optionName + '-' + oppositeValues[optionValue]);
document.body.classList.add(optionName + '-' + optionValue);
localStorage.setItem('symfony/profiler/' + optionName, optionName + '-' + optionValue);
});
});
let openModalButton = document.getElementById('open-settings');
let modalWindow = document.getElementById('profiler-settings');
let closeModalButton = document.getElementsByClassName('close-modal')[0];
let modalWrapper = document.getElementsByClassName('modal-wrap')[0]
openModalButton.addEventListener('click', function(event) {
document.getElementById('settings-' + localStorage.getItem('symfony/profiler/theme')).checked = 'checked';
document.getElementById('settings-' + localStorage.getItem('symfony/profiler/width')).checked = 'checked';
modalWindow.classList.toggle('visible');
event.preventDefault();
});
closeModalButton.addEventListener('click', function() {
modalWindow.classList.remove('visible');
});
modalWrapper.addEventListener('click', function(event) {
if (event.target == event.currentTarget) {
modalWindow.classList.remove('visible');
}
});
})();
</script>