Skip to content

Commit

Permalink
Merge pull request #233 from vector-im/bwindels/log-viewer
Browse files Browse the repository at this point in the history
Log viewer
  • Loading branch information
bwindels authored Feb 18, 2021
2 parents 7e05e4e + 69feb40 commit e9ce87e
Show file tree
Hide file tree
Showing 4 changed files with 502 additions and 0 deletions.
51 changes: 51 additions & 0 deletions scripts/logviewer/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

export function openFile(mimeType = null) {
const input = document.createElement("input");
input.setAttribute("type", "file");
input.className = "hidden";
if (mimeType) {
input.setAttribute("accept", mimeType);
}
const promise = new Promise((resolve, reject) => {
const checkFile = () => {
input.removeEventListener("change", checkFile, true);
const file = input.files[0];
document.body.removeChild(input);
if (file) {
resolve(file);
} else {
reject(new Error("no file picked"));
}
}
input.addEventListener("change", checkFile, true);
});
// IE11 needs the input to be attached to the document
document.body.appendChild(input);
input.click();
return promise;
}

export function readFileAsText(file) {
const reader = new FileReader();
const promise = new Promise((resolve, reject) => {
reader.addEventListener("load", evt => resolve(evt.target.result));
reader.addEventListener("error", evt => reject(evt.target.error));
});
reader.readAsText(file);
return promise;
}
110 changes: 110 additions & 0 deletions scripts/logviewer/html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
Copyright 2020 Bruno Windels <[email protected]>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// DOM helper functions

export function isChildren(children) {
// children should be an not-object (that's the attributes), or a domnode, or an array
return typeof children !== "object" || !!children.nodeType || Array.isArray(children);
}

export function classNames(obj, value) {
return Object.entries(obj).reduce((cn, [name, enabled]) => {
if (typeof enabled === "function") {
enabled = enabled(value);
}
if (enabled) {
return cn + (cn.length ? " " : "") + name;
} else {
return cn;
}
}, "");
}

export function setAttribute(el, name, value) {
if (name === "className") {
name = "class";
}
if (value === false) {
el.removeAttribute(name);
} else {
if (value === true) {
value = name;
}
el.setAttribute(name, value);
}
}

export function el(elementName, attributes, children) {
return elNS(HTML_NS, elementName, attributes, children);
}

export function elNS(ns, elementName, attributes, children) {
if (attributes && isChildren(attributes)) {
children = attributes;
attributes = null;
}

const e = document.createElementNS(ns, elementName);

if (attributes) {
for (let [name, value] of Object.entries(attributes)) {
if (name === "className" && typeof value === "object" && value !== null) {
value = classNames(value);
}
setAttribute(e, name, value);
}
}

if (children) {
if (!Array.isArray(children)) {
children = [children];
}
for (let c of children) {
if (!c.nodeType) {
c = text(c);
}
e.appendChild(c);
}
}
return e;
}

export function text(str) {
return document.createTextNode(str);
}

export const HTML_NS = "http://www.w3.org/1999/xhtml";
export const SVG_NS = "http://www.w3.org/2000/svg";

export const TAG_NAMES = {
[HTML_NS]: [
"br", "a", "ol", "ul", "li", "div", "h1", "h2", "h3", "h4", "h5", "h6",
"p", "strong", "em", "span", "img", "section", "main", "article", "aside",
"pre", "button", "time", "input", "textarea", "label", "form", "progress", "output"],
[SVG_NS]: ["svg", "circle"]
};

export const tag = {};


for (const [ns, tags] of Object.entries(TAG_NAMES)) {
for (const tagName of tags) {
tag[tagName] = function(attributes, children) {
return elNS(ns, tagName, attributes, children);
}
}
}
167 changes: 167 additions & 0 deletions scripts/logviewer/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style type="text/css">
html, body {
height: 100%;
}

body {
font-family: sans-serif;
font-size: 1rem;
margin: 0;
display: grid;
grid-template-areas: "nav nav" "items details";
grid-template-columns: 1fr 400px;
grid-template-rows: auto 1fr;
min-height: 0;
}

main {
grid-area: items;
min-width: 0;
min-height: 0;
overflow-y: auto;
padding: 8px;
}

main section h2 {
margin: 2px 14px;
font-size: 1rem;
}

aside {
grid-area: details;
padding: 8px;
}

aside h3 {
word-wrap: anywhere;
}

aside p {
margin: 2px 0;
}

aside .values li span {
word-wrap: ;
word-wrap: anywhere;
}

aside .values {
list-style: none;
padding: 0;
border: 1px solid lightgray;
}

aside .values span.key {
width: 30%;
display: block;
}

aside .values span.value {
width: 70%;
display: block;
padding-left: 10px;
}

aside .values li {
display: flex;
}

aside .values li:not(:first-child) {
border-top: 1px solid lightgray;
}

nav {
grid-area: nav;
}

.timeline li:not(.expanded) > ol {
display: none;
}

.timeline li > div {
display: flex;
}

.timeline .toggleExpanded {
border: none;
background: none;
width: 24px;
height: 24px;
margin-right: 4px;
cursor: pointer;
}

.timeline .toggleExpanded:before {
content: "▶";
}

.timeline li.expanded > div > .toggleExpanded:before {
content: "▼";
}

.timeline ol {
list-style: none;
padding: 0 0 0 20px;
margin: 0;
}

.timeline div.item {
--hue: 100deg;
--brightness: 80%;
background-color: hsl(var(--hue), 60%, var(--brightness));
border: 1px solid hsl(var(--hue), 60%, calc(var(--brightness) - 40%));
border-radius: 4px;
padding: 2px;
display: flex;
margin: 1px;
flex: 1;
min-width: 0;
cursor: pointer;
}


.timeline div.item:not(.has-children) {
margin-left: calc(24px + 4px + 1px);
}

.timeline div.item .caption {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
flex: 1;
}

.timeline div.item.level-3 {
--brightness: 90%;
}

.timeline div.item.level-6 {
--hue: 0deg !important;
}

.timeline div.item.type-network {
--hue: 30deg;
}

.timeline div.item.selected {
background-color: Highlight;
border-color: Highlight;
color: HighlightText;
}

.hidden {
display: none;
}
</style>
</head>
<body>
<nav><button id="openFile">Open log file</button></nav>
<main></main>
<aside></aside>
<script type="module" src="main.js"></script>
</body>
</html>
Loading

0 comments on commit e9ce87e

Please sign in to comment.