[static assets] add them to git so we can forget to call "collectstatic" before we just serve
This commit is contained in:
parent
003baf931d
commit
77ae66b015
141 changed files with 34703 additions and 0 deletions
3
static/debug_toolbar/css/print.css
Normal file
3
static/debug_toolbar/css/print.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#djDebug {
|
||||
display: none !important;
|
||||
}
|
||||
772
static/debug_toolbar/css/toolbar.css
Normal file
772
static/debug_toolbar/css/toolbar.css
Normal file
|
|
@ -0,0 +1,772 @@
|
|||
/* Variable definitions */
|
||||
:root {
|
||||
/* Font families are the same as in Django admin/css/base.css */
|
||||
--djdt-font-family-primary: "Segoe UI", system-ui, Roboto, "Helvetica Neue",
|
||||
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol", "Noto Color Emoji";
|
||||
--djdt-font-family-monospace: ui-monospace, Menlo, Monaco, "Cascadia Mono",
|
||||
"Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace",
|
||||
"Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New",
|
||||
monospace, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
|
||||
"Noto Color Emoji";
|
||||
}
|
||||
|
||||
:root,
|
||||
#djDebug[data-theme="light"] {
|
||||
--djdt-font-color: black;
|
||||
--djdt-background-color: white;
|
||||
--djdt-panel-content-background-color: #eee;
|
||||
--djdt-panel-content-table-background-color: var(--djdt-background-color);
|
||||
--djdt-panel-title-background-color: #ffc;
|
||||
--djdt-djdt-panel-content-table-strip-background-color: #f5f5f5;
|
||||
--djdt--highlighted-background-color: lightgrey;
|
||||
--djdt-toggle-template-background-color: #bbb;
|
||||
|
||||
--djdt-sql-font-color: #333;
|
||||
--djdt-pre-text-color: #555;
|
||||
--djdt-path-and-locals: #777;
|
||||
--djdt-stack-span-color: black;
|
||||
--djdt-template-highlight-color: #333;
|
||||
|
||||
--djdt-table-border-color: #ccc;
|
||||
--djdt-button-border-color: var(--djdt-table-border-color);
|
||||
--djdt-pre-border-color: var(--djdt-table-border-color);
|
||||
--djdt-raw-border-color: var(--djdt-table-border-color);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--djdt-font-color: #8393a7;
|
||||
--djdt-background-color: #1e293bff;
|
||||
--djdt-panel-content-background-color: #0f1729ff;
|
||||
--djdt-panel-title-background-color: #242432;
|
||||
--djdt-djdt-panel-content-table-strip-background-color: #324154ff;
|
||||
--djdt--highlighted-background-color: #2c2a7dff;
|
||||
--djdt-toggle-template-background-color: #282755;
|
||||
|
||||
--djdt-sql-font-color: var(--djdt-font-color);
|
||||
--djdt-pre-text-color: var(--djdt-font-color);
|
||||
--djdt-path-and-locals: #65758cff;
|
||||
--djdt-stack-span-color: #7c8fa4;
|
||||
--djdt-template-highlight-color: var(--djdt-stack-span-color);
|
||||
|
||||
--djdt-table-border-color: #324154ff;
|
||||
--djdt-button-border-color: var(--djdt-table-border-color);
|
||||
--djdt-pre-border-color: var(--djdt-table-border-color);
|
||||
--djdt-raw-border-color: var(--djdt-table-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
#djDebug[data-theme="dark"] {
|
||||
--djdt-font-color: #8393a7;
|
||||
--djdt-background-color: #1e293bff;
|
||||
--djdt-panel-content-background-color: #0f1729ff;
|
||||
--djdt-panel-content-table-background-color: var(--djdt-background-color);
|
||||
--djdt-panel-title-background-color: #242432;
|
||||
--djdt-djdt-panel-content-table-strip-background-color: #324154ff;
|
||||
--djdt--highlighted-background-color: #2c2a7dff;
|
||||
--djdt-toggle-template-background-color: #282755;
|
||||
|
||||
--djdt-sql-font-color: var(--djdt-font-color);
|
||||
--djdt-pre-text-color: var(--djdt-font-color);
|
||||
--djdt-path-and-locals: #65758cff;
|
||||
--djdt-stack-span-color: #7c8fa4;
|
||||
--djdt-template-highlight-color: var(--djdt-stack-span-color);
|
||||
|
||||
--djdt-table-border-color: #324154ff;
|
||||
--djdt-button-border-color: var(--djdt-table-border-color);
|
||||
--djdt-pre-border-color: var(--djdt-table-border-color);
|
||||
--djdt-raw-border-color: var(--djdt-table-border-color);
|
||||
}
|
||||
|
||||
/* Debug Toolbar CSS Reset, adapted from Eric Meyer's CSS Reset */
|
||||
#djDebug {
|
||||
color: var(--djdt-font-color);
|
||||
background: var(--djdt-background-color);
|
||||
}
|
||||
#djDebug,
|
||||
#djDebug div,
|
||||
#djDebug span,
|
||||
#djDebug applet,
|
||||
#djDebug object,
|
||||
#djDebug iframe,
|
||||
#djDebug h1,
|
||||
#djDebug h2,
|
||||
#djDebug h3,
|
||||
#djDebug h4,
|
||||
#djDebug h5,
|
||||
#djDebug h6,
|
||||
#djDebug p,
|
||||
#djDebug blockquote,
|
||||
#djDebug pre,
|
||||
#djDebug a,
|
||||
#djDebug abbr,
|
||||
#djDebug acronym,
|
||||
#djDebug address,
|
||||
#djDebug big,
|
||||
#djDebug cite,
|
||||
#djDebug code,
|
||||
#djDebug del,
|
||||
#djDebug dfn,
|
||||
#djDebug em,
|
||||
#djDebug font,
|
||||
#djDebug img,
|
||||
#djDebug ins,
|
||||
#djDebug kbd,
|
||||
#djDebug q,
|
||||
#djDebug s,
|
||||
#djDebug samp,
|
||||
#djDebug small,
|
||||
#djDebug strike,
|
||||
#djDebug strong,
|
||||
#djDebug sub,
|
||||
#djDebug sup,
|
||||
#djDebug tt,
|
||||
#djDebug var,
|
||||
#djDebug b,
|
||||
#djDebug u,
|
||||
#djDebug i,
|
||||
#djDebug center,
|
||||
#djDebug dl,
|
||||
#djDebug dt,
|
||||
#djDebug dd,
|
||||
#djDebug ol,
|
||||
#djDebug ul,
|
||||
#djDebug li,
|
||||
#djDebug fieldset,
|
||||
#djDebug form,
|
||||
#djDebug label,
|
||||
#djDebug legend,
|
||||
#djDebug table,
|
||||
#djDebug caption,
|
||||
#djDebug tbody,
|
||||
#djDebug tfoot,
|
||||
#djDebug thead,
|
||||
#djDebug tr,
|
||||
#djDebug th,
|
||||
#djDebug td,
|
||||
#djDebug summary,
|
||||
#djDebug button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1.5em;
|
||||
color: var(--djdt-font-color);
|
||||
vertical-align: baseline;
|
||||
background-color: transparent;
|
||||
font-family: var(--djdt-font-family-primary);
|
||||
text-align: left;
|
||||
text-shadow: none;
|
||||
white-space: normal;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
#djDebug button {
|
||||
background-color: #eee;
|
||||
background-image: linear-gradient(to bottom, #eee, #cccccc);
|
||||
border: 1px solid var(--djdt-button-border-color);
|
||||
border-bottom: 1px solid #bbb;
|
||||
border-radius: 3px;
|
||||
color: #333;
|
||||
line-height: 1;
|
||||
padding: 0 8px;
|
||||
text-align: center;
|
||||
text-shadow: 0 1px 0 #eee;
|
||||
}
|
||||
|
||||
#djDebug button:hover {
|
||||
background-color: #ddd;
|
||||
background-image: linear-gradient(to bottom, #ddd, #bbb);
|
||||
border-color: #bbb;
|
||||
border-bottom-color: #999;
|
||||
cursor: pointer;
|
||||
text-shadow: 0 1px 0 #ddd;
|
||||
}
|
||||
|
||||
#djDebug button:active {
|
||||
border: 1px solid #aaa;
|
||||
border-bottom: 1px solid #888;
|
||||
box-shadow:
|
||||
inset 0 0 5px 2px #aaa,
|
||||
0 1px 0 0 #eee;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar {
|
||||
background-color: #111;
|
||||
width: 220px;
|
||||
z-index: 100000000;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
opacity: 0.9;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar small {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar li {
|
||||
border-bottom: 1px solid #222;
|
||||
color: #fff;
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
float: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar input[type="checkbox"] {
|
||||
float: right;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar li > a,
|
||||
#djDebug #djDebugToolbar li > div.djdt-contentless {
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
padding: 7px 10px 8px 25px;
|
||||
color: #fff;
|
||||
}
|
||||
#djDebug #djDebugToolbar li > div.djdt-disabled {
|
||||
font-style: italic;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar li a:hover {
|
||||
color: #111;
|
||||
background-color: #ffc;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar li.djdt-active {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar li.djdt-active:before {
|
||||
content: "▶";
|
||||
font-family: var(--djdt-font-family-primary);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #eee;
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar li.djdt-active a:hover {
|
||||
color: #b36a60;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar li small {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
font-style: normal;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbarHandle {
|
||||
position: fixed;
|
||||
transform: translateY(-100%) rotate(-90deg);
|
||||
transform-origin: right bottom;
|
||||
background-color: #fff;
|
||||
border: 1px solid #111;
|
||||
border-bottom: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 100000000;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
#djDebug #djShowToolBarButton {
|
||||
padding: 0 5px;
|
||||
border: 4px solid #fff;
|
||||
border-bottom-width: 0;
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
background: #000;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
#djDebug #djShowToolBarButton:hover {
|
||||
background-color: #111;
|
||||
border-color: #ffe761;
|
||||
cursor: move;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#djDebug #djShowToolBarD {
|
||||
color: #cf9;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
#djDebug #djShowToolBarJ {
|
||||
color: #cf9;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#djDebug pre,
|
||||
#djDebug code {
|
||||
display: block;
|
||||
font-family: var(--djdt-font-family-monospace);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#djDebug code {
|
||||
font-size: 12px;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#djDebug pre {
|
||||
white-space: pre-wrap;
|
||||
color: var(--djdt-pre-text-color);
|
||||
border: 1px solid var(--djdt-pre-border-color);
|
||||
border-collapse: collapse;
|
||||
background-color: var(--djdt-background-color);
|
||||
padding: 2px 3px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent {
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
top: 0;
|
||||
right: 220px;
|
||||
bottom: 0;
|
||||
left: 0px;
|
||||
background-color: var(--djdt-panel-content-background-color);
|
||||
color: #666;
|
||||
z-index: 100000000;
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent > div {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#djDebug .djDebugPanelTitle {
|
||||
position: absolute;
|
||||
background-color: var(--djdt-panel-title-background-color);
|
||||
color: #666;
|
||||
padding-left: 20px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
#djDebug .djDebugPanelTitle code {
|
||||
display: inline;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
#djDebug .djDebugPanelContent {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: auto;
|
||||
padding: 5px 0 0 20px;
|
||||
}
|
||||
|
||||
#djDebug .djDebugPanelContent .djdt-loader {
|
||||
margin: 80px auto;
|
||||
border: 6px solid white;
|
||||
border-radius: 50%;
|
||||
border-top: 6px solid #ffe761;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
#djDebug .djDebugPanelContent .djdt-scroll {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
display: block;
|
||||
padding: 0 10px 0 0;
|
||||
}
|
||||
|
||||
#djDebug h3 {
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
#djDebug h4 {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent table {
|
||||
border: 1px solid var(--djdt-table-border-color);
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
background-color: var(--djdt-panel-content-table-background-color);
|
||||
display: table;
|
||||
margin-top: 0.8em;
|
||||
overflow: auto;
|
||||
}
|
||||
#djDebug .djdt-panelContent tbody > tr:nth-child(odd):not(.djdt-highlighted) {
|
||||
background-color: var(--djdt-panel-content-table-strip-background-color);
|
||||
}
|
||||
#djDebug .djdt-panelContent tbody td,
|
||||
#djDebug .djdt-panelContent tbody th {
|
||||
vertical-align: top;
|
||||
padding: 2px 3px;
|
||||
}
|
||||
#djDebug .djdt-panelContent tbody td.djdt-time {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent thead th {
|
||||
padding: 1px 6px 1px 3px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#djDebug .djdt-panelContent tbody th {
|
||||
width: 12em;
|
||||
text-align: right;
|
||||
color: #666;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
#djDebug .djTemplateContext {
|
||||
background-color: var(--djdt-background-color);
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent .djDebugClose {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 15px;
|
||||
line-height: 16px;
|
||||
border: 6px solid #ddd;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
color: #ddd;
|
||||
font-weight: 900;
|
||||
font-size: 20px;
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
padding: 0 0 5px;
|
||||
box-sizing: border-box;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent .djDebugClose:hover {
|
||||
background: #c0695d;
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent dt,
|
||||
#djDebug .djdt-panelContent dd {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent dt {
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
|
||||
#djDebug .djdt-panelContent dd {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#djDebug a.toggleTemplate {
|
||||
padding: 4px;
|
||||
background-color: var(--djdt-toggle-template-background-color);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#djDebug a.toggleTemplate:hover {
|
||||
padding: 4px;
|
||||
background-color: #444;
|
||||
color: #ffe761;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#djDebug .djDebugCollapsed {
|
||||
color: var(--djdt-sql-font-color);
|
||||
}
|
||||
|
||||
#djDebug .djDebugUncollapsed {
|
||||
color: var(--djdt-sql-font-color);
|
||||
}
|
||||
|
||||
#djDebug .djUnselected {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#djDebug tr.djSelected {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
#djDebug .djDebugSql {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
#djDebug .djSQLDetailsDiv tbody th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#djDebug span.djDebugLineChart {
|
||||
background-color: #777;
|
||||
height: 3px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
z-index: 1000000001;
|
||||
}
|
||||
#djDebug span.djDebugLineChartWarning {
|
||||
background-color: #900;
|
||||
}
|
||||
|
||||
#djDebug .highlight {
|
||||
color: var(--djdt-font-color);
|
||||
}
|
||||
#djDebug .highlight .err {
|
||||
color: var(--djdt-font-color);
|
||||
} /* Error */
|
||||
|
||||
/*
|
||||
Styles for pygments HTMLFormatter
|
||||
|
||||
- This should match debug_toolbar/panels/templates/views.py::template_source
|
||||
- Each line needs to be prefixed with #djDebug .highlight as well.
|
||||
- The .w definition needs to include:
|
||||
white-space: pre-wrap
|
||||
|
||||
To regenerate:
|
||||
|
||||
from pygments.formatters import HtmlFormatter
|
||||
print(HtmlFormatter(wrapcode=True).get_style_defs())
|
||||
*/
|
||||
#djDebug .highlight pre { line-height: 125%; }
|
||||
#djDebug .highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
#djDebug .highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
#djDebug .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
#djDebug .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
#djDebug .highlight .hll { background-color: #ffffcc }
|
||||
#djDebug .highlight .c { color: #3D7B7B; font-style: italic } /* Comment */
|
||||
#djDebug .highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
#djDebug .highlight .k { color: #008000; font-weight: bold } /* Keyword */
|
||||
#djDebug .highlight .o { color: #666666 } /* Operator */
|
||||
#djDebug .highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
|
||||
#djDebug .highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
|
||||
#djDebug .highlight .cp { color: #9C6500 } /* Comment.Preproc */
|
||||
#djDebug .highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
|
||||
#djDebug .highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
|
||||
#djDebug .highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
|
||||
#djDebug .highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
#djDebug .highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
#djDebug .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
|
||||
#djDebug .highlight .gr { color: #E40000 } /* Generic.Error */
|
||||
#djDebug .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
#djDebug .highlight .gi { color: #008400 } /* Generic.Inserted */
|
||||
#djDebug .highlight .go { color: #717171 } /* Generic.Output */
|
||||
#djDebug .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
#djDebug .highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
#djDebug .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
#djDebug .highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
#djDebug .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
|
||||
#djDebug .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
|
||||
#djDebug .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
|
||||
#djDebug .highlight .kp { color: #008000 } /* Keyword.Pseudo */
|
||||
#djDebug .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
|
||||
#djDebug .highlight .kt { color: #B00040 } /* Keyword.Type */
|
||||
#djDebug .highlight .m { color: #666666 } /* Literal.Number */
|
||||
#djDebug .highlight .s { color: #BA2121 } /* Literal.String */
|
||||
#djDebug .highlight .na { color: #687822 } /* Name.Attribute */
|
||||
#djDebug .highlight .nb { color: #008000 } /* Name.Builtin */
|
||||
#djDebug .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
#djDebug .highlight .no { color: #880000 } /* Name.Constant */
|
||||
#djDebug .highlight .nd { color: #AA22FF } /* Name.Decorator */
|
||||
#djDebug .highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */
|
||||
#djDebug .highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
|
||||
#djDebug .highlight .nf { color: #0000FF } /* Name.Function */
|
||||
#djDebug .highlight .nl { color: #767600 } /* Name.Label */
|
||||
#djDebug .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
#djDebug .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
|
||||
#djDebug .highlight .nv { color: #19177C } /* Name.Variable */
|
||||
#djDebug .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
#djDebug .highlight .w { color: #bbbbbb; white-space: pre-wrap } /* Text.Whitespace */
|
||||
#djDebug .highlight .mb { color: #666666 } /* Literal.Number.Bin */
|
||||
#djDebug .highlight .mf { color: #666666 } /* Literal.Number.Float */
|
||||
#djDebug .highlight .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
#djDebug .highlight .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
#djDebug .highlight .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
#djDebug .highlight .sa { color: #BA2121 } /* Literal.String.Affix */
|
||||
#djDebug .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
|
||||
#djDebug .highlight .sc { color: #BA2121 } /* Literal.String.Char */
|
||||
#djDebug .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
|
||||
#djDebug .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
|
||||
#djDebug .highlight .s2 { color: #BA2121 } /* Literal.String.Double */
|
||||
#djDebug .highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
|
||||
#djDebug .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
|
||||
#djDebug .highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
|
||||
#djDebug .highlight .sx { color: #008000 } /* Literal.String.Other */
|
||||
#djDebug .highlight .sr { color: #A45A77 } /* Literal.String.Regex */
|
||||
#djDebug .highlight .s1 { color: #BA2121 } /* Literal.String.Single */
|
||||
#djDebug .highlight .ss { color: #19177C } /* Literal.String.Symbol */
|
||||
#djDebug .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
|
||||
#djDebug .highlight .fm { color: #0000FF } /* Name.Function.Magic */
|
||||
#djDebug .highlight .vc { color: #19177C } /* Name.Variable.Class */
|
||||
#djDebug .highlight .vg { color: #19177C } /* Name.Variable.Global */
|
||||
#djDebug .highlight .vi { color: #19177C } /* Name.Variable.Instance */
|
||||
#djDebug .highlight .vm { color: #19177C } /* Name.Variable.Magic */
|
||||
#djDebug .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
|
||||
|
||||
#djDebug svg.djDebugLineChart {
|
||||
width: 100%;
|
||||
height: 1.5em;
|
||||
}
|
||||
|
||||
#djDebug svg.djDebugLineChartWarning rect {
|
||||
fill: #900;
|
||||
}
|
||||
|
||||
#djDebug svg.djDebugLineChartInTransaction rect {
|
||||
fill: #d3ff82;
|
||||
}
|
||||
#djDebug svg.djDebugLineChart line {
|
||||
stroke: #94b24d;
|
||||
}
|
||||
|
||||
#djDebug .djDebugRowWarning .djdt-time {
|
||||
color: red;
|
||||
}
|
||||
#djDebug .djdt-panelContent table .djdt-toggle {
|
||||
width: 14px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
#djDebug .djdt-panelContent table .djdt-actions {
|
||||
min-width: 70px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#djDebug .djdt-color:after {
|
||||
content: "\00a0";
|
||||
}
|
||||
#djDebug .djToggleSwitch {
|
||||
box-sizing: content-box;
|
||||
padding: 0;
|
||||
border: 1px solid #999;
|
||||
border-radius: 0;
|
||||
width: 12px;
|
||||
color: #777;
|
||||
background: linear-gradient(to bottom, #fff, #dcdcdc);
|
||||
}
|
||||
#djDebug .djNoToggleSwitch {
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#djDebug .djSQLDetailsDiv {
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
|
||||
#djDebug .djdt-stack span {
|
||||
color: var(--djdt-stack-span-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
#djDebug .djdt-stack span.djdt-path,
|
||||
#djDebug .djdt-stack pre.djdt-locals,
|
||||
#djDebug .djdt-stack pre.djdt-locals span {
|
||||
color: var(--djdt-path-and-locals);
|
||||
font-weight: normal;
|
||||
}
|
||||
#djDebug .djdt-stack span.djdt-code {
|
||||
font-weight: normal;
|
||||
}
|
||||
#djDebug .djdt-stack pre.djdt-locals {
|
||||
margin: 0 27px 27px 27px;
|
||||
}
|
||||
#djDebug .djdt-raw {
|
||||
background-color: #fff;
|
||||
border: 1px solid var(--djdt-raw-border-color);
|
||||
margin-top: 0.8em;
|
||||
padding: 5px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
#djDebug .djdt-width-20 {
|
||||
width: 20%;
|
||||
}
|
||||
#djDebug .djdt-width-30 {
|
||||
width: 30%;
|
||||
}
|
||||
#djDebug .djdt-width-60 {
|
||||
width: 60%;
|
||||
}
|
||||
#djDebug .djdt-max-height-100 {
|
||||
max-height: 100%;
|
||||
}
|
||||
#djDebug .djdt-highlighted {
|
||||
background-color: var(--djdt--highlighted-background-color);
|
||||
}
|
||||
#djDebug tr.djdt-highlighted.djdt-profile-row {
|
||||
background-color: #ffc;
|
||||
}
|
||||
#djDebug tr.djdt-highlighted.djdt-profile-row:nth-child(2n + 1) {
|
||||
background-color: #dd9;
|
||||
}
|
||||
@keyframes djdt-flash-new {
|
||||
from {
|
||||
background-color: green;
|
||||
}
|
||||
to {
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
#djDebug .flash-new {
|
||||
animation: djdt-flash-new 1s;
|
||||
}
|
||||
|
||||
.djdt-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#djDebug #djDebugToolbar a#djToggleThemeButton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
#djToggleThemeButton > svg {
|
||||
margin-left: auto;
|
||||
}
|
||||
#djDebug[data-theme="light"] #djToggleThemeButton svg.theme-light,
|
||||
#djDebug[data-theme="dark"] #djToggleThemeButton svg.theme-dark,
|
||||
#djDebug[data-theme="auto"] #djToggleThemeButton svg.theme-auto {
|
||||
display: block;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
}
|
||||
109
static/debug_toolbar/js/history.js
Normal file
109
static/debug_toolbar/js/history.js
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { $$, ajaxForm, replaceToolbarState } from "./utils.js";
|
||||
|
||||
const djDebug = document.getElementById("djDebug");
|
||||
|
||||
function difference(setA, setB) {
|
||||
const _difference = new Set(setA);
|
||||
for (const elem of setB) {
|
||||
_difference.delete(elem);
|
||||
}
|
||||
return _difference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of dataset properties from a NodeList.
|
||||
*/
|
||||
function pluckData(nodes, key) {
|
||||
const data = [];
|
||||
nodes.forEach(function (obj) {
|
||||
data.push(obj.dataset[key]);
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
function refreshHistory() {
|
||||
const formTarget = djDebug.querySelector(".refreshHistory");
|
||||
const container = document.getElementById("djdtHistoryRequests");
|
||||
const oldIds = new Set(
|
||||
pluckData(container.querySelectorAll("tr[data-store-id]"), "storeId")
|
||||
);
|
||||
|
||||
ajaxForm(formTarget)
|
||||
.then(function (data) {
|
||||
// Remove existing rows first then re-populate with new data
|
||||
container
|
||||
.querySelectorAll("tr[data-store-id]")
|
||||
.forEach(function (node) {
|
||||
node.remove();
|
||||
});
|
||||
data.requests.forEach(function (request) {
|
||||
container.innerHTML = request.content + container.innerHTML;
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
const allIds = new Set(
|
||||
pluckData(
|
||||
container.querySelectorAll("tr[data-store-id]"),
|
||||
"storeId"
|
||||
)
|
||||
);
|
||||
const newIds = difference(allIds, oldIds);
|
||||
const lastRequestId = newIds.values().next().value;
|
||||
return {
|
||||
allIds,
|
||||
newIds,
|
||||
lastRequestId,
|
||||
};
|
||||
})
|
||||
.then(function (refreshInfo) {
|
||||
refreshInfo.newIds.forEach(function (newId) {
|
||||
const row = container.querySelector(
|
||||
`tr[data-store-id="${newId}"]`
|
||||
);
|
||||
row.classList.add("flash-new");
|
||||
});
|
||||
setTimeout(() => {
|
||||
container
|
||||
.querySelectorAll("tr[data-store-id]")
|
||||
.forEach((row) => {
|
||||
row.classList.remove("flash-new");
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
function switchHistory(newStoreId) {
|
||||
const formTarget = djDebug.querySelector(
|
||||
".switchHistory[data-store-id='" + newStoreId + "']"
|
||||
);
|
||||
const tbody = formTarget.closest("tbody");
|
||||
|
||||
const highlighted = tbody.querySelector(".djdt-highlighted");
|
||||
if (highlighted) {
|
||||
highlighted.classList.remove("djdt-highlighted");
|
||||
}
|
||||
formTarget.closest("tr").classList.add("djdt-highlighted");
|
||||
|
||||
ajaxForm(formTarget).then(function (data) {
|
||||
if (Object.keys(data).length === 0) {
|
||||
const container = document.getElementById("djdtHistoryRequests");
|
||||
container.querySelector(
|
||||
'button[data-store-id="' + newStoreId + '"]'
|
||||
).innerHTML = "Switch [EXPIRED]";
|
||||
}
|
||||
replaceToolbarState(newStoreId, data);
|
||||
});
|
||||
}
|
||||
|
||||
$$.on(djDebug, "click", ".switchHistory", function (event) {
|
||||
event.preventDefault();
|
||||
switchHistory(this.dataset.storeId);
|
||||
});
|
||||
|
||||
$$.on(djDebug, "click", ".refreshHistory", function (event) {
|
||||
event.preventDefault();
|
||||
refreshHistory();
|
||||
});
|
||||
// We don't refresh the whole toolbar each fetch or ajax request,
|
||||
// so we need to refresh the history when we open the panel
|
||||
$$.onPanelRender(djDebug, "HistoryPanel", refreshHistory);
|
||||
1
static/debug_toolbar/js/redirect.js
Normal file
1
static/debug_toolbar/js/redirect.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
document.getElementById("redirect_to").focus();
|
||||
88
static/debug_toolbar/js/timer.js
Normal file
88
static/debug_toolbar/js/timer.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import { $$ } from "./utils.js";
|
||||
|
||||
function insertBrowserTiming() {
|
||||
const timingOffset = performance.timing.navigationStart,
|
||||
timingEnd = performance.timing.loadEventEnd,
|
||||
totalTime = timingEnd - timingOffset;
|
||||
function getLeft(stat) {
|
||||
if (totalTime !== 0) {
|
||||
return (
|
||||
((performance.timing[stat] - timingOffset) / totalTime) * 100.0
|
||||
);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
function getCSSWidth(stat, endStat) {
|
||||
let width = 0;
|
||||
if (totalTime !== 0) {
|
||||
width =
|
||||
((performance.timing[endStat] - performance.timing[stat]) /
|
||||
totalTime) *
|
||||
100.0;
|
||||
}
|
||||
const denominator = 100.0 - getLeft(stat);
|
||||
if (denominator !== 0) {
|
||||
// Calculate relative percent (same as sql panel logic)
|
||||
width = (100.0 * width) / denominator;
|
||||
} else {
|
||||
width = 0;
|
||||
}
|
||||
return width < 1 ? "2px" : width + "%";
|
||||
}
|
||||
function addRow(tbody, stat, endStat) {
|
||||
const row = document.createElement("tr");
|
||||
if (endStat) {
|
||||
// Render a start through end bar
|
||||
row.innerHTML =
|
||||
"<td>" +
|
||||
stat.replace("Start", "") +
|
||||
"</td>" +
|
||||
'<td><svg class="djDebugLineChart" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 5" preserveAspectRatio="none"><rect y="0" height="5" fill="#ccc" /></svg></td>' +
|
||||
"<td>" +
|
||||
(performance.timing[stat] - timingOffset) +
|
||||
" (+" +
|
||||
(performance.timing[endStat] - performance.timing[stat]) +
|
||||
")</td>";
|
||||
row.querySelector("rect").setAttribute(
|
||||
"width",
|
||||
getCSSWidth(stat, endStat)
|
||||
);
|
||||
} else {
|
||||
// Render a point in time
|
||||
row.innerHTML =
|
||||
"<td>" +
|
||||
stat +
|
||||
"</td>" +
|
||||
'<td><svg class="djDebugLineChart" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 5" preserveAspectRatio="none"><rect y="0" height="5" fill="#ccc" /></svg></td>' +
|
||||
"<td>" +
|
||||
(performance.timing[stat] - timingOffset) +
|
||||
"</td>";
|
||||
row.querySelector("rect").setAttribute("width", 2);
|
||||
}
|
||||
row.querySelector("rect").setAttribute("x", getLeft(stat));
|
||||
tbody.appendChild(row);
|
||||
}
|
||||
|
||||
const browserTiming = document.getElementById("djDebugBrowserTiming");
|
||||
// Determine if the browser timing section has already been rendered.
|
||||
if (browserTiming.classList.contains("djdt-hidden")) {
|
||||
const tbody = document.getElementById("djDebugBrowserTimingTableBody");
|
||||
// This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param)
|
||||
addRow(tbody, "domainLookupStart", "domainLookupEnd");
|
||||
addRow(tbody, "connectStart", "connectEnd");
|
||||
addRow(tbody, "requestStart", "responseEnd"); // There is no requestEnd
|
||||
addRow(tbody, "responseStart", "responseEnd");
|
||||
addRow(tbody, "domLoading", "domComplete"); // Spans the events below
|
||||
addRow(tbody, "domInteractive");
|
||||
addRow(tbody, "domContentLoadedEventStart", "domContentLoadedEventEnd");
|
||||
addRow(tbody, "loadEventStart", "loadEventEnd");
|
||||
browserTiming.classList.remove("djdt-hidden");
|
||||
}
|
||||
}
|
||||
|
||||
const djDebug = document.getElementById("djDebug");
|
||||
// Insert the browser timing now since it's possible for this
|
||||
// script to miss the initial panel load event.
|
||||
insertBrowserTiming();
|
||||
$$.onPanelRender(djDebug, "TimerPanel", insertBrowserTiming);
|
||||
392
static/debug_toolbar/js/toolbar.js
Normal file
392
static/debug_toolbar/js/toolbar.js
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
import { $$, ajax, debounce, replaceToolbarState } from "./utils.js";
|
||||
|
||||
function onKeyDown(event) {
|
||||
if (event.keyCode === 27) {
|
||||
djdt.hideOneLevel();
|
||||
}
|
||||
}
|
||||
|
||||
function getDebugElement() {
|
||||
// Fetch the debug element from the DOM.
|
||||
// This is used to avoid writing the element's id
|
||||
// everywhere the element is being selected. A fixed reference
|
||||
// to the element should be avoided because the entire DOM could
|
||||
// be reloaded such as via HTMX boosting.
|
||||
return document.getElementById("djDebug");
|
||||
}
|
||||
|
||||
const djdt = {
|
||||
handleDragged: false,
|
||||
needUpdateOnFetch: false,
|
||||
init() {
|
||||
const djDebug = getDebugElement();
|
||||
djdt.needUpdateOnFetch = djDebug.dataset.updateOnFetch === "True";
|
||||
$$.on(djDebug, "click", "#djDebugPanelList li a", function (event) {
|
||||
event.preventDefault();
|
||||
if (!this.className) {
|
||||
return;
|
||||
}
|
||||
const panelId = this.className;
|
||||
const current = document.getElementById(panelId);
|
||||
if ($$.visible(current)) {
|
||||
djdt.hidePanels();
|
||||
} else {
|
||||
djdt.hidePanels();
|
||||
|
||||
$$.show(current);
|
||||
this.parentElement.classList.add("djdt-active");
|
||||
|
||||
const inner = current.querySelector(
|
||||
".djDebugPanelContent .djdt-scroll"
|
||||
),
|
||||
storeId = djDebug.dataset.storeId;
|
||||
if (storeId && inner.children.length === 0) {
|
||||
const url = new URL(
|
||||
djDebug.dataset.renderPanelUrl,
|
||||
window.location
|
||||
);
|
||||
url.searchParams.append("store_id", storeId);
|
||||
url.searchParams.append("panel_id", panelId);
|
||||
ajax(url).then(function (data) {
|
||||
inner.previousElementSibling.remove(); // Remove AJAX loader
|
||||
inner.innerHTML = data.content;
|
||||
$$.executeScripts(data.scripts);
|
||||
$$.applyStyles(inner);
|
||||
djDebug.dispatchEvent(
|
||||
new CustomEvent("djdt.panel.render", {
|
||||
detail: { panelId: panelId },
|
||||
})
|
||||
);
|
||||
});
|
||||
} else {
|
||||
djDebug.dispatchEvent(
|
||||
new CustomEvent("djdt.panel.render", {
|
||||
detail: { panelId: panelId },
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
$$.on(djDebug, "click", ".djDebugClose", function () {
|
||||
djdt.hideOneLevel();
|
||||
});
|
||||
$$.on(
|
||||
djDebug,
|
||||
"click",
|
||||
".djDebugPanelButton input[type=checkbox]",
|
||||
function () {
|
||||
djdt.cookie.set(
|
||||
this.dataset.cookie,
|
||||
this.checked ? "on" : "off",
|
||||
{
|
||||
path: "/",
|
||||
expires: 10,
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// Used by the SQL and template panels
|
||||
$$.on(djDebug, "click", ".remoteCall", function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
let url;
|
||||
const ajaxData = {};
|
||||
|
||||
if (this.tagName === "BUTTON") {
|
||||
const form = this.closest("form");
|
||||
url = this.formAction;
|
||||
ajaxData.method = form.method.toUpperCase();
|
||||
ajaxData.body = new FormData(form);
|
||||
} else if (this.tagName === "A") {
|
||||
url = this.href;
|
||||
}
|
||||
|
||||
ajax(url, ajaxData).then(function (data) {
|
||||
const win = document.getElementById("djDebugWindow");
|
||||
win.innerHTML = data.content;
|
||||
$$.show(win);
|
||||
});
|
||||
});
|
||||
|
||||
// Used by the cache, profiling and SQL panels
|
||||
$$.on(djDebug, "click", ".djToggleSwitch", function () {
|
||||
const id = this.dataset.toggleId;
|
||||
const toggleOpen = "+";
|
||||
const toggleClose = "-";
|
||||
const openMe = this.textContent === toggleOpen;
|
||||
const name = this.dataset.toggleName;
|
||||
const container = document.getElementById(name + "_" + id);
|
||||
container
|
||||
.querySelectorAll(".djDebugCollapsed")
|
||||
.forEach(function (e) {
|
||||
$$.toggle(e, openMe);
|
||||
});
|
||||
container
|
||||
.querySelectorAll(".djDebugUncollapsed")
|
||||
.forEach(function (e) {
|
||||
$$.toggle(e, !openMe);
|
||||
});
|
||||
const self = this;
|
||||
this.closest(".djDebugPanelContent")
|
||||
.querySelectorAll(".djToggleDetails_" + id)
|
||||
.forEach(function (e) {
|
||||
if (openMe) {
|
||||
e.classList.add("djSelected");
|
||||
e.classList.remove("djUnselected");
|
||||
self.textContent = toggleClose;
|
||||
} else {
|
||||
e.classList.remove("djSelected");
|
||||
e.classList.add("djUnselected");
|
||||
self.textContent = toggleOpen;
|
||||
}
|
||||
const switch_ = e.querySelector(".djToggleSwitch");
|
||||
if (switch_) {
|
||||
switch_.textContent = self.textContent;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$$.on(djDebug, "click", "#djHideToolBarButton", function (event) {
|
||||
event.preventDefault();
|
||||
djdt.hideToolbar();
|
||||
});
|
||||
|
||||
$$.on(djDebug, "click", "#djShowToolBarButton", function () {
|
||||
if (!djdt.handleDragged) {
|
||||
djdt.showToolbar();
|
||||
}
|
||||
});
|
||||
let startPageY, baseY;
|
||||
const handle = document.getElementById("djDebugToolbarHandle");
|
||||
function onHandleMove(event) {
|
||||
// Chrome can send spurious mousemove events, so don't do anything unless the
|
||||
// cursor really moved. Otherwise, it will be impossible to expand the toolbar
|
||||
// due to djdt.handleDragged being set to true.
|
||||
if (djdt.handleDragged || event.pageY !== startPageY) {
|
||||
let top = baseY + event.pageY;
|
||||
|
||||
if (top < 0) {
|
||||
top = 0;
|
||||
} else if (top + handle.offsetHeight > window.innerHeight) {
|
||||
top = window.innerHeight - handle.offsetHeight;
|
||||
}
|
||||
|
||||
handle.style.top = top + "px";
|
||||
djdt.handleDragged = true;
|
||||
}
|
||||
}
|
||||
$$.on(djDebug, "mousedown", "#djShowToolBarButton", function (event) {
|
||||
event.preventDefault();
|
||||
startPageY = event.pageY;
|
||||
baseY = handle.offsetTop - startPageY;
|
||||
document.addEventListener("mousemove", onHandleMove);
|
||||
|
||||
document.addEventListener(
|
||||
"mouseup",
|
||||
function (event) {
|
||||
document.removeEventListener("mousemove", onHandleMove);
|
||||
if (djdt.handleDragged) {
|
||||
event.preventDefault();
|
||||
localStorage.setItem("djdt.top", handle.offsetTop);
|
||||
requestAnimationFrame(function () {
|
||||
djdt.handleDragged = false;
|
||||
});
|
||||
djdt.ensureHandleVisibility();
|
||||
}
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
|
||||
// Make sure the debug element is rendered at least once.
|
||||
// showToolbar will continue to show it in the future if the
|
||||
// entire DOM is reloaded.
|
||||
$$.show(djDebug);
|
||||
const show =
|
||||
localStorage.getItem("djdt.show") || djDebug.dataset.defaultShow;
|
||||
if (show === "true") {
|
||||
djdt.showToolbar();
|
||||
} else {
|
||||
djdt.hideToolbar();
|
||||
}
|
||||
if (djDebug.dataset.sidebarUrl !== undefined) {
|
||||
djdt.updateOnAjax();
|
||||
}
|
||||
|
||||
// Updates the theme using user settings
|
||||
const userTheme = localStorage.getItem("djdt.user-theme");
|
||||
if (userTheme !== null) {
|
||||
djDebug.setAttribute("data-theme", userTheme);
|
||||
}
|
||||
// Adds the listener to the Theme Toggle Button
|
||||
$$.on(djDebug, "click", "#djToggleThemeButton", function () {
|
||||
switch (djDebug.getAttribute("data-theme")) {
|
||||
case "auto":
|
||||
djDebug.setAttribute("data-theme", "light");
|
||||
localStorage.setItem("djdt.user-theme", "light");
|
||||
break;
|
||||
case "light":
|
||||
djDebug.setAttribute("data-theme", "dark");
|
||||
localStorage.setItem("djdt.user-theme", "dark");
|
||||
break;
|
||||
default: /* dark is the default */
|
||||
djDebug.setAttribute("data-theme", "auto");
|
||||
localStorage.setItem("djdt.user-theme", "auto");
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
hidePanels() {
|
||||
const djDebug = getDebugElement();
|
||||
$$.hide(document.getElementById("djDebugWindow"));
|
||||
djDebug.querySelectorAll(".djdt-panelContent").forEach(function (e) {
|
||||
$$.hide(e);
|
||||
});
|
||||
document.querySelectorAll("#djDebugToolbar li").forEach(function (e) {
|
||||
e.classList.remove("djdt-active");
|
||||
});
|
||||
},
|
||||
ensureHandleVisibility() {
|
||||
const handle = document.getElementById("djDebugToolbarHandle");
|
||||
// set handle position
|
||||
const handleTop = Math.min(
|
||||
localStorage.getItem("djdt.top") || 265,
|
||||
window.innerHeight - handle.offsetWidth
|
||||
);
|
||||
handle.style.top = handleTop + "px";
|
||||
},
|
||||
hideToolbar() {
|
||||
djdt.hidePanels();
|
||||
|
||||
$$.hide(document.getElementById("djDebugToolbar"));
|
||||
|
||||
const handle = document.getElementById("djDebugToolbarHandle");
|
||||
$$.show(handle);
|
||||
djdt.ensureHandleVisibility();
|
||||
window.addEventListener("resize", djdt.ensureHandleVisibility);
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
|
||||
localStorage.setItem("djdt.show", "false");
|
||||
},
|
||||
hideOneLevel() {
|
||||
const win = document.getElementById("djDebugWindow");
|
||||
if ($$.visible(win)) {
|
||||
$$.hide(win);
|
||||
} else {
|
||||
const toolbar = document.getElementById("djDebugToolbar");
|
||||
if (toolbar.querySelector("li.djdt-active")) {
|
||||
djdt.hidePanels();
|
||||
} else {
|
||||
djdt.hideToolbar();
|
||||
}
|
||||
}
|
||||
},
|
||||
showToolbar() {
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
$$.show(document.getElementById("djDebug"));
|
||||
$$.hide(document.getElementById("djDebugToolbarHandle"));
|
||||
$$.show(document.getElementById("djDebugToolbar"));
|
||||
localStorage.setItem("djdt.show", "true");
|
||||
window.removeEventListener("resize", djdt.ensureHandleVisibility);
|
||||
},
|
||||
updateOnAjax() {
|
||||
const sidebarUrl =
|
||||
document.getElementById("djDebug").dataset.sidebarUrl;
|
||||
const slowjax = debounce(ajax, 200);
|
||||
|
||||
function handleAjaxResponse(storeId) {
|
||||
storeId = encodeURIComponent(storeId);
|
||||
const dest = `${sidebarUrl}?store_id=${storeId}`;
|
||||
slowjax(dest).then(function (data) {
|
||||
if (djdt.needUpdateOnFetch) {
|
||||
replaceToolbarState(storeId, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Patch XHR / traditional AJAX requests
|
||||
const origOpen = XMLHttpRequest.prototype.open;
|
||||
XMLHttpRequest.prototype.open = function () {
|
||||
this.addEventListener("load", function () {
|
||||
// Chromium emits a "Refused to get unsafe header" uncatchable warning
|
||||
// when the header can't be fetched. While it doesn't impede execution
|
||||
// it's worrisome to developers.
|
||||
if (
|
||||
this.getAllResponseHeaders().indexOf("djdt-store-id") >= 0
|
||||
) {
|
||||
handleAjaxResponse(this.getResponseHeader("djdt-store-id"));
|
||||
}
|
||||
});
|
||||
origOpen.apply(this, arguments);
|
||||
};
|
||||
|
||||
const origFetch = window.fetch;
|
||||
window.fetch = function () {
|
||||
const promise = origFetch.apply(this, arguments);
|
||||
promise.then(function (response) {
|
||||
if (response.headers.get("djdt-store-id") !== null) {
|
||||
handleAjaxResponse(response.headers.get("djdt-store-id"));
|
||||
}
|
||||
// Don't resolve the response via .json(). Instead
|
||||
// continue to return it to allow the caller to consume as needed.
|
||||
return response;
|
||||
});
|
||||
return promise;
|
||||
};
|
||||
},
|
||||
cookie: {
|
||||
get(key) {
|
||||
if (!document.cookie.includes(key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const cookieArray = document.cookie.split("; "),
|
||||
cookies = {};
|
||||
|
||||
cookieArray.forEach(function (e) {
|
||||
const parts = e.split("=");
|
||||
cookies[parts[0]] = parts[1];
|
||||
});
|
||||
|
||||
return cookies[key];
|
||||
},
|
||||
set(key, value, options) {
|
||||
options = options || {};
|
||||
|
||||
if (typeof options.expires === "number") {
|
||||
const days = options.expires,
|
||||
t = (options.expires = new Date());
|
||||
t.setDate(t.getDate() + days);
|
||||
}
|
||||
|
||||
document.cookie = [
|
||||
encodeURIComponent(key) + "=" + String(value),
|
||||
options.expires
|
||||
? "; expires=" + options.expires.toUTCString()
|
||||
: "",
|
||||
options.path ? "; path=" + options.path : "",
|
||||
options.domain ? "; domain=" + options.domain : "",
|
||||
options.secure ? "; secure" : "",
|
||||
"samesite" in options
|
||||
? "; samesite=" + options.samesite
|
||||
: "; samesite=lax",
|
||||
].join("");
|
||||
|
||||
return value;
|
||||
},
|
||||
},
|
||||
};
|
||||
window.djdt = {
|
||||
show_toolbar: djdt.showToolbar,
|
||||
hide_toolbar: djdt.hideToolbar,
|
||||
init: djdt.init,
|
||||
close: djdt.hideOneLevel,
|
||||
cookie: djdt.cookie,
|
||||
};
|
||||
|
||||
if (document.readyState !== "loading") {
|
||||
djdt.init();
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", djdt.init);
|
||||
}
|
||||
142
static/debug_toolbar/js/utils.js
Normal file
142
static/debug_toolbar/js/utils.js
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
const $$ = {
|
||||
on(root, eventName, selector, fn) {
|
||||
root.removeEventListener(eventName, fn);
|
||||
root.addEventListener(eventName, function (event) {
|
||||
const target = event.target.closest(selector);
|
||||
if (root.contains(target)) {
|
||||
fn.call(target, event);
|
||||
}
|
||||
});
|
||||
},
|
||||
onPanelRender(root, panelId, fn) {
|
||||
/*
|
||||
This is a helper function to attach a handler for a `djdt.panel.render`
|
||||
event of a specific panel.
|
||||
|
||||
root: The container element that the listener should be attached to.
|
||||
panelId: The Id of the panel.
|
||||
fn: A function to execute when the event is triggered.
|
||||
*/
|
||||
root.addEventListener("djdt.panel.render", function (event) {
|
||||
if (event.detail.panelId === panelId) {
|
||||
fn.call(event);
|
||||
}
|
||||
});
|
||||
},
|
||||
show(element) {
|
||||
element.classList.remove("djdt-hidden");
|
||||
},
|
||||
hide(element) {
|
||||
element.classList.add("djdt-hidden");
|
||||
},
|
||||
toggle(element, value) {
|
||||
if (value) {
|
||||
$$.show(element);
|
||||
} else {
|
||||
$$.hide(element);
|
||||
}
|
||||
},
|
||||
visible(element) {
|
||||
return !element.classList.contains("djdt-hidden");
|
||||
},
|
||||
executeScripts(scripts) {
|
||||
scripts.forEach(function (script) {
|
||||
const el = document.createElement("script");
|
||||
el.type = "module";
|
||||
el.src = script;
|
||||
el.async = true;
|
||||
document.head.appendChild(el);
|
||||
});
|
||||
},
|
||||
applyStyles(container) {
|
||||
/*
|
||||
* Given a container element, apply styles set via data-djdt-styles attribute.
|
||||
* The format is data-djdt-styles="styleName1:value;styleName2:value2"
|
||||
* The style names should use the CSSStyleDeclaration camel cased names.
|
||||
*/
|
||||
container
|
||||
.querySelectorAll("[data-djdt-styles]")
|
||||
.forEach(function (element) {
|
||||
const styles = element.dataset.djdtStyles || "";
|
||||
styles.split(";").forEach(function (styleText) {
|
||||
const styleKeyPair = styleText.split(":");
|
||||
if (styleKeyPair.length === 2) {
|
||||
const name = styleKeyPair[0].trim();
|
||||
const value = styleKeyPair[1].trim();
|
||||
element.style[name] = value;
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function ajax(url, init) {
|
||||
init = Object.assign({ credentials: "same-origin" }, init);
|
||||
return fetch(url, init)
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json().catch(function(error){
|
||||
return Promise.reject(
|
||||
new Error("The response is a invalid Json object : " + error)
|
||||
);
|
||||
});
|
||||
}
|
||||
return Promise.reject(
|
||||
new Error(response.status + ": " + response.statusText)
|
||||
);
|
||||
})
|
||||
.catch(function (error) {
|
||||
const win = document.getElementById("djDebugWindow");
|
||||
win.innerHTML =
|
||||
'<div class="djDebugPanelTitle"><button type="button" class="djDebugClose">»</button><h3>' +
|
||||
error.message +
|
||||
"</h3></div>";
|
||||
$$.show(win);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
function ajaxForm(element) {
|
||||
const form = element.closest("form");
|
||||
const url = new URL(form.action);
|
||||
const formData = new FormData(form);
|
||||
for (const [name, value] of formData.entries()) {
|
||||
url.searchParams.append(name, value);
|
||||
}
|
||||
const ajaxData = {
|
||||
method: form.method.toUpperCase(),
|
||||
};
|
||||
return ajax(url, ajaxData);
|
||||
}
|
||||
|
||||
function replaceToolbarState(newStoreId, data) {
|
||||
const djDebug = document.getElementById("djDebug");
|
||||
djDebug.setAttribute("data-store-id", newStoreId);
|
||||
// Check if response is empty, it could be due to an expired storeId.
|
||||
Object.keys(data).forEach(function (panelId) {
|
||||
const panel = document.getElementById(panelId);
|
||||
if (panel) {
|
||||
panel.outerHTML = data[panelId].content;
|
||||
document.getElementById("djdt-" + panelId).outerHTML =
|
||||
data[panelId].button;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function debounce(func, delay) {
|
||||
let timer = null;
|
||||
let resolves = [];
|
||||
|
||||
return function (...args) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
const result = func(...args);
|
||||
resolves.forEach((r) => r(result));
|
||||
resolves = [];
|
||||
}, delay);
|
||||
|
||||
return new Promise((r) => resolves.push(r));
|
||||
};
|
||||
}
|
||||
|
||||
export { $$, ajax, ajaxForm, replaceToolbarState, debounce };
|
||||
Loading…
Add table
Add a link
Reference in a new issue