mysqlExporterDeno/static/index.html
2020-04-14 18:27:21 +02:00

330 lines
No EOL
13 KiB
HTML

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MySQL exporter</title>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
<div id="app">Loading...</div>
<style>
body {
margin: 30px auto;
max-width: 900px;
line-height: 1.6;
font-size: 18px;
color: #444;
padding: 0 10px;
}
* {
font-family: 'Noto Sans', sans-serif;
}
h1,
h2,
h3 {
font-family: Simplifica;
line-height: 1.2
}
a {
text-decoration: none;
color: rgb(0, 140, 255);
}
a:visited {
color: rgb(153, 0, 255);
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
word-break: normal;
text-align: center;
}
table {
width: 900px;
width: min(90vw, 900px);
table-layout: fixed;
}
th {
padding: 10px;
}
td {
padding: 5px;
word-break: break-all;
}
tr:hover {
background-color: rgb(214, 214, 214);
}
.privileges {
word-break: normal;
}
.null,
.key {
width: 30px;
}
.extra {
width: 35px;
}
.default {
width: 50px;
}
.head {
background-color: #444;
color: white;
}
</style>
<!--
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="24"
width="24" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<g transform="translate(0 -1028.4)">
<g transform="matrix(.70711 .70711 -.70711 .70711 740.06 298.16)">
<path
d="m10.541 1028.9c-3.3134 0-5.9997 2.6-5.9997 6 0 3.3 2.6863 6 5.9997 6 3.314 0 6-2.7 6-6 0-3.4-2.686-6-6-6zm0 2c1.105 0 2 0.9 2 2s-0.895 2-2 2c-1.1042 0-1.9997-0.9-1.9997-2s0.8955-2 1.9997-2z"
fill="#f39c12" />
<g fill="#f1c40f">
<path
d="m10 0c-3.3137 0-6 2.6863-6 6s2.6863 6 6 6c3.314 0 6-2.6863 6-6s-2.686-6-6-6zm0 2c1.105 0 2 0.8954 2 2s-0.895 2-2 2c-1.1046 0-2-0.8954-2-2s0.8954-2 2-2z"
transform="translate(0 1028.4)" />
<rect height="2" width="6" y="1039.4" x="7" />
<path d="m8 13v9l2 2 2-2v-1l-2-1 2-1v-1l-1-1 1-1v-3z" transform="translate(0 1028.4)" />
</g>
<path d="m11 1041.4v4l1-1v-3h-1zm0 4v2.5l1-0.5v-1l-1-1zm0 3.5v2.5l1-1v-1l-1-0.5z" fill="#f39c12" />
<path d="m9 1041.4v10l1 1v-4-7h-1z" fill="#f39c12" />
</g>
</g>
</svg> -->
<script>
function key(title, color, color2, color3) {
return `<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="24"
width="24" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<title>${title}</title>
<g transform="translate(0 -1028.4)">
<g transform="matrix(.70711 .70711 -.70711 .70711 740.06 298.16)">
<path
d="m10.541 1028.9c-3.3134 0-5.9997 2.6-5.9997 6 0 3.3 2.6863 6 5.9997 6 3.314 0 6-2.7 6-6 0-3.4-2.686-6-6-6zm0 2c1.105 0 2 0.9 2 2s-0.895 2-2 2c-1.1042 0-1.9997-0.9-1.9997-2s0.8955-2 1.9997-2z"
fill="${color}" />
<g fill="${color2}">
<path
d="m10 0c-3.3137 0-6 2.6863-6 6s2.6863 6 6 6c3.314 0 6-2.6863 6-6s-2.686-6-6-6zm0 2c1.105 0 2 0.8954 2 2s-0.895 2-2 2c-1.1046 0-2-0.8954-2-2s0.8954-2 2-2z"
transform="translate(0 1028.4)" />
<rect height="2" width="6" y="1039.4" x="7" />
<path d="m8 13v9l2 2 2-2v-1l-2-1 2-1v-1l-1-1 1-1v-3z" transform="translate(0 1028.4)" />
</g>
<path d="m11 1041.4v4l1-1v-3h-1zm0 4v2.5l1-0.5v-1l-1-1zm0 3.5v2.5l1-1v-1l-1-0.5z" fill="${color3}" />
<path d="m9 1041.4v10l1 1v-4-7h-1z" fill="${color3}" />
</g>
</g>
</svg>`;
}
const app = document.getElementById("app");
function htmlToElement(html) {
var template = document.createElement('template');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.firstChild;
}
(async () => {
if (window.location.hostname !== "localhost") {
console.warn("Fetching info supported only from localhost!");
return;
}
var dbRes = await fetch("/database");
var db = await dbRes.json();
if (!dbRes.ok) return console.warn("Couldn't fetch data");
app.innerText = "";
const appTitle = document.createElement("h1");
appTitle.innerText = "Data dictionary of " + db.name;
app.appendChild(appTitle);
const date = document.createElement("p");
date.innerText = "Loading table information...";
app.appendChild(date);
const tableList = document.createElement("ul");
app.appendChild(tableList);
var res = await fetch("/tables");
var tables = await res.json();
var re = await fetch("/fieldsIgnored");
var fieldsIgnored = await re.json();
fieldsIgnored = fieldsIgnored.map(el => el.toLowerCase());
date.innerText = "Generating data dictionary...";
for (var table in tables) {
var data = tables[table];
var tableEl = document.createElement("table");
var title = document.createElement("h2");
title.id = table.replace(/[\s]/g, "");
title.innerText = table;
app.appendChild(title);
if (!data.columns) {
console.error(data);
app.appendChild(htmlToElement(`<p>${data}<p>`));
continue;
}
var tableItem = document.createElement("li");
var tableLink = document.createElement("a");
tableItem.appendChild(tableLink);
tableLink.href = "#" + table.replace(/[\s]/g, "");
tableLink.innerText = table;
tableList.appendChild(tableItem);
try {
var comment = document.createElement("p");
comment.innerText = data.comment[0].table_comment;
app.appendChild(comment);
} catch (e) {}
function addField(fieldName, rename = fieldName) {
return fieldsIgnored.includes(fieldName.toLowerCase()) ? "" :
`<th class='${fieldName.toLowerCase()}'>${rename}</th>`;
}
var head = htmlToElement(`
<tr class="head">
${addField("Field")}
${addField("Type")}
${addField("Collation")}
${addField("Null", "NN")}
${addField("Key")}
${addField("Default")}
${addField("Extra")}
${addField("Privileges")}
${addField("Comment")}
</tr>
`);
tableEl.appendChild(head);
for (var column of data.columns) {
var el = document.createElement("tr");
for (var field in column) {
if (fieldsIgnored.includes(field.toLowerCase())) continue;
var td = document.createElement("td");
td.className = field.toLowerCase();
switch (field.toLowerCase()) {
case "privileges":
column[field] = column[field].split(",").join(", ");
break;
case "null":
let cb = document.createElement("input");
cb.type = "checkbox";
cb.checked = column[field] === "NO";
cb.disabled = true;
column[field] = cb;
break;
case "key":
switch(column[field]) {
case "PRI":
column[field] = htmlToElement(key("Primary key", "#f39c12", "#f1c40f", "#f39c12"));
break;
case "MUL":
column[field] = htmlToElement(`<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="22.000000pt" height="24.000000pt" viewBox="0 0 1113.000000 1280.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,1280.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<title>Multi key</title>
<path d="M3130 12789 c-1268 -111 -2354 -895 -2856 -2061 -328 -763 -361
-1656 -90 -2445 377 -1097 1288 -1932 2415 -2213 146 -37 372 -76 491 -85 140
-10 128 3 114 -122 -97 -823 340 -1627 1086 -1999 266 -132 520 -196 840 -211
l145 -6 113 -146 c62 -80 188 -237 280 -348 l167 -202 50 -6 c190 -26 347
-142 400 -295 39 -110 39 -273 1 -417 l-14 -51 47 -7 c243 -34 450 -220 517
-466 23 -83 23 -269 1 -359 -8 -36 -15 -66 -14 -66 1 -1 45 -16 97 -34 132
-43 213 -91 296 -174 124 -125 170 -252 161 -452 l-5 -121 242 -151 c320 -200
580 -354 583 -345 12 39 98 449 117 560 l25 142 -110 243 c-105 230 -455 1008
-796 1768 -191 425 -623 1377 -690 1521 l-50 105 73 97 c134 178 234 369 304
580 18 54 34 96 36 94 3 -2 -7 -41 -21 -87 -15 -45 -24 -84 -21 -87 3 -4 53 6
110 21 l105 27 173 -119 c95 -66 261 -177 367 -246 182 -118 197 -126 230
-119 20 4 74 7 121 7 186 -1 326 -87 404 -249 42 -86 65 -179 73 -291 5 -73 8
-84 22 -78 32 13 183 16 244 4 34 -6 98 -29 142 -49 215 -101 341 -287 376
-554 l12 -94 121 -6 c210 -10 343 -63 457 -185 69 -74 132 -196 150 -292 19
-106 14 -101 130 -131 412 -107 823 -209 826 -205 9 8 -18 420 -37 572 -17
136 -22 161 -43 183 -141 153 -741 829 -1763 1987 -243 274 -532 600 -643 724
-123 138 -200 231 -197 240 3 8 22 65 44 125 226 626 105 1343 -316 1884 -182
233 -441 439 -722 573 -158 75 -403 146 -593 173 -48 6 -49 7 -43 38 31 179
41 617 18 822 -70 615 -281 1173 -630 1660 -542 757 -1386 1271 -2297 1399
-249 35 -549 45 -775 25z m516 -559 c490 -39 946 -195 1354 -464 913 -602
1398 -1656 1264 -2746 -26 -210 -12 -187 -139 -220 -479 -122 -894 -417 -1168
-829 -62 -94 -197 -353 -197 -378 0 -5 -39 -20 -86 -31 -185 -47 -410 -148
-579 -259 -282 -186 -487 -412 -670 -737 l-27 -49 -122 7 c-579 33 -1110 227
-1581 580 -147 110 -420 381 -526 521 -336 443 -528 922 -584 1457 -136 1303
625 2523 1859 2982 366 137 804 197 1202 166z m2326 -4146 c7 -7 -67 -142
-139 -254 -46 -71 -182 -260 -187 -260 -16 0 -199 40 -203 44 -4 3 -1 38 6 77
34 185 171 334 354 384 52 14 159 20 169 9z m438 -466 c0 -72 -24 -167 -59
-236 -52 -101 -49 -99 -109 -62 -29 17 -52 34 -52 36 0 2 24 37 53 77 29 41
75 111 102 155 28 45 53 82 57 82 5 0 8 -24 8 -52z m-1507 -623 c26 -9 47 -20
47 -24 0 -8 -163 -103 -260 -151 -103 -52 -217 -99 -323 -136 -113 -38 -111
-41 -56 73 54 113 176 210 310 248 68 19 215 14 282 -10z m313 -562 c-4 -21
-22 -70 -41 -109 -58 -119 -189 -224 -316 -253 -105 -25 -266 -7 -341 37 -28
17 -37 32 -17 32 47 0 495 203 639 289 36 22 69 40 74 40 4 1 5 -16 2 -36z"/>
</g>
</svg>`);
break;
case "UNI":
column[field] = htmlToElement(key("Unique key", "#bfbfbf", "#dbdbdb", "#808080"));
break;
}
case "extra":
if (column[field] === "auto_increment") {
column[field] = "AI";
td.title = "Auto increment";
}
break;
}
if (column[field]) {
if (column[field] instanceof HTMLElement || column[field] instanceof SVGElement) {
td.appendChild(column[field]);
} else {
td.innerText = column[field];
}
} else if (field == "Default") {
td.innerText = "null";
}
el.appendChild(td);
}
tableEl.appendChild(el);
}
app.appendChild(tableEl);
}
var d = new Date();
date.innerHTML = `Generated ${d.toString()}.
<br>Number of tables: ${Object.keys(tables).length}
<br>Host: ${db.host}`;
})()
</script>
</body>
</html>