diff options
Diffstat (limited to 'wwwroot')
| -rw-r--r-- | wwwroot/css/site.css | 28 | ||||
| -rw-r--r-- | wwwroot/favicon.ico | bin | 0 -> 3262 bytes | |||
| -rw-r--r-- | wwwroot/icon-192.png | bin | 0 -> 31523 bytes | |||
| -rw-r--r-- | wwwroot/icon-512.png | bin | 0 -> 136487 bytes | |||
| -rw-r--r-- | wwwroot/images/loginbg.webp | bin | 0 -> 2247672 bytes | |||
| -rw-r--r-- | wwwroot/js/dialog.js | 78 | ||||
| -rw-r--r-- | wwwroot/js/keyboard.js | 51 | ||||
| -rw-r--r-- | wwwroot/loginbg.webm | bin | 0 -> 390877 bytes | |||
| -rw-r--r-- | wwwroot/manifest.webmanifest | 6 | ||||
| -rw-r--r-- | wwwroot/styles/data-table.css | 21 | ||||
| -rw-r--r-- | wwwroot/styles/global.css | 169 |
11 files changed, 353 insertions, 0 deletions
diff --git a/wwwroot/css/site.css b/wwwroot/css/site.css new file mode 100644 index 0000000..21f9a94 --- /dev/null +++ b/wwwroot/css/site.css @@ -0,0 +1,28 @@ +#blazor-error-ui { + background: #555; + bottom: 0; + box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); + display: none; + left: 0; + padding: 0.6rem 1.25rem 0.7rem 1.25rem; + position: fixed; + width: 100%; + z-index: 1000; +} + +#blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 3.5rem; + top: 0.5rem; +} + +.blazor-error-boundary { + background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; + color: white; + padding: 1rem 1rem 1rem 3.7rem; +} + +.blazor-error-boundary::after { + content: "An error has occurred." +} diff --git a/wwwroot/favicon.ico b/wwwroot/favicon.ico Binary files differnew file mode 100644 index 0000000..a1be4cc --- /dev/null +++ b/wwwroot/favicon.ico diff --git a/wwwroot/icon-192.png b/wwwroot/icon-192.png Binary files differnew file mode 100644 index 0000000..28ce06d --- /dev/null +++ b/wwwroot/icon-192.png diff --git a/wwwroot/icon-512.png b/wwwroot/icon-512.png Binary files differnew file mode 100644 index 0000000..8c28696 --- /dev/null +++ b/wwwroot/icon-512.png diff --git a/wwwroot/images/loginbg.webp b/wwwroot/images/loginbg.webp Binary files differnew file mode 100644 index 0000000..759e666 --- /dev/null +++ b/wwwroot/images/loginbg.webp diff --git a/wwwroot/js/dialog.js b/wwwroot/js/dialog.js new file mode 100644 index 0000000..418962f --- /dev/null +++ b/wwwroot/js/dialog.js @@ -0,0 +1,78 @@ +function dialogMouseDown(e) { + bumpDialog(e.currentTarget); +} + +function dialogTitleMouseDown(e) { + e = e || window.event; + e.preventDefault(); + var element = e.currentTarget.parentElement; + var ds = element.dataset; + ds.lastX = e.clientX; + ds.lastY = e.clientY; + + window.dragDialog = element; + document.onmouseup = dragMouseUp; + document.onmousemove = dragMouseMove; +} + +function dragMouseUp() { + window.dragDialog = null; + document.onmouseup = null; + document.onmousemove = null; +} + +function dragMouseMove(e) { + e = e || window.event; + e.preventDefault(); + var element = window.dragDialog; + var ds = element.dataset; + deltaX = ds.lastX - e.clientX; + deltaY = ds.lastY - e.clientY; + ds.lastX = e.clientX; + ds.lastY = e.clientY; + element.style.left = (element.offsetLeft - deltaX) + 'px'; + element.style.top = (element.offsetTop - deltaY) + 'px'; +} + +function setDialogVisibility(element, visible) { + if(visible) { + element.style.left = null; + element.style.top = null; + element.style.opacity = 1; + element.style.visibility = 'visible'; + bumpDialog(element); + + var input = element.querySelector('input[type="text"]'); + if(input) { + setTimeout(() => input.focus(), 100); + } + } else { + element.style.opacity = 0; + element.style.visibility = 'hidden'; + } +} + +function bumpDialog(element) { + var dialogs = Array + .from(document.querySelectorAll('div.dialog')) + .map(e => ({ zIndex: parseInt(e.style.zIndex), element: e })) + .sort((a, b) => a.zIndex - b.zIndex) + .map(d => d.element) + .filter(e => e != element); + + dialogs.push(element); + + var z = 900; + for(var d of dialogs) + d.style.zIndex = z++; +} + +function dialogAddObjectReference(element, dialogObject) { + if(!window.dialogObjects) + window.dialogObjects = [] + + window.dialogObjects.push({ + element: element, + dialogObject: dialogObject + }); +} diff --git a/wwwroot/js/keyboard.js b/wwwroot/js/keyboard.js new file mode 100644 index 0000000..72ed3cb --- /dev/null +++ b/wwwroot/js/keyboard.js @@ -0,0 +1,51 @@ +async function keyDownHandler(e) { + function isDialogChild(e) { + while(e = e.parentElement) + if(e.tagName == 'DIV' && e.classList.contains('dialog')) + return true; + return false; + } + + var tag = document.activeElement.tagName; + if((tag == 'INPUT' || (tag == 'TEXTAREA' && e.ctrlKey)) && e.key == 'Enter') { + var element = document.activeElement; + while(element = element.parentElement) { + if(element.tagName == 'FORM') { + element.submit(); + e.preventDefault(); + return; + } + } + } + + if((tag == 'INPUT' || tag == 'TEXTAREA') && e.key != 'Escape') + return; + + var element = Array.from(document.querySelectorAll('div.dialog')) + .filter(e => e.style.visibility == 'visible') + .map(e => ({ element: e, zIndex: parseInt(e.style.zIndex) })) + .sort((a, b) => b.zIndex - a.zIndex) + .map(e => e.element)[0]; + + if(element) { + await window.dialogObjects + .find(d => d.element == element) + .dialogObject + .invokeMethodAsync('KeyHandler', e.key); + e.preventDefault(); + return; + } + + var button = Array.from(document.getElementsByTagName('button')) + .filter(b => typeof(b.dataset.keyboardShortcut) == 'string') + .filter(b => !isDialogChild(b)) + .find(b => b.dataset.keyboardShortcut == e.key); + + if(!e.ctrlKey && button) { + button.click(); + e.preventDefault(); + return; + } +} + +window.onload = () => document.onkeydown = keyDownHandler;
\ No newline at end of file diff --git a/wwwroot/loginbg.webm b/wwwroot/loginbg.webm Binary files differnew file mode 100644 index 0000000..139ed0d --- /dev/null +++ b/wwwroot/loginbg.webm diff --git a/wwwroot/manifest.webmanifest b/wwwroot/manifest.webmanifest new file mode 100644 index 0000000..f150f98 --- /dev/null +++ b/wwwroot/manifest.webmanifest @@ -0,0 +1,6 @@ +{ + "icons": [ + { "src": "/icon-192.png", "type": "images/png", "sizes": "192x192" }, + { "src": "/icon-512.png", "type": "images/png", "sizes": "512x512" } + ] +}
\ No newline at end of file diff --git a/wwwroot/styles/data-table.css b/wwwroot/styles/data-table.css new file mode 100644 index 0000000..994d625 --- /dev/null +++ b/wwwroot/styles/data-table.css @@ -0,0 +1,21 @@ +table.data-table { + border-collapse: collapse; + width: 100%; +} + +table.data-table > tr > th { + border-bottom: 1px solid white; + padding: 4px; +} + +table.data-table > tr > td { + padding: 4px; +} + +table.data-table > tr:nth-child(2n) { + background: rgba(255, 255, 255, 0.1); +} + +table.data-table > tr > td:not(:last-child) { + border-right: 1px solid white; +} diff --git a/wwwroot/styles/global.css b/wwwroot/styles/global.css new file mode 100644 index 0000000..ebcda47 --- /dev/null +++ b/wwwroot/styles/global.css @@ -0,0 +1,169 @@ +@import url('data-table.css'); + +:root { + --col-accent-pri: #0aa; + --col-accent-pri-hl: #0cc; + --col-error-pri: #ffaa00; + --col-checksum-verified-pri: #8dff76; + --col-bg: #222; + --col-dialog-bg: #333; + --col-navbar-bg: var(--col-accent-pri); + --col-button-pri: var(--col-accent-pri); + --col-button-pri-hl: var(--col-accent-pri-hl); + --col-button-disabled: #777; + --col-button-disabled-bg: #444; + --col-button-sec: #555; + --col-button-sec-hl: #777; + --col-button-sec-disabled: #555; + --col-button-sec-disabled-bg: #000; + --col-button-warning: #ff4848; + --col-button-warning-hl: #ff9999; + --col-scrollbar: #666666; + --col-scrollbar-hover: #aaaaaa; + --col-switch-bg: var(--col-bg); + --col-switch-fg: #fff; + --col-switch-bg-hl: var(--col-accent-pri); + + --size-default-gap: 30px; +} + +::selection { + background: var(--col-accent-pri); +} + +body { + background: var(--col-bg); + color: white; + display: flex; + flex-direction: column; + font-family: 'Trebuchet MS', 'Lucida Sans Unicode'; + margin: 0; + overflow: hidden; +} + +a { + color: var(--col-accent-pri); + text-decoration: none; +} + +a:hover { + filter: brightness(1.5); +} + +a::selection { + background: var(--col-accent-pri); + color: #fff; +} + +a.nondecorated { + color: #fff; +} + +a.nondecorated:hover { + color: #999; +} + +code { + background: #222; + border-radius: 10px; + box-sizing: border-box; + font-family: 'Lucida Console'; + font-size: 8pt; + overflow-y: auto; + padding: 20px; + white-space: pre-line; +} + +button, input[type=submit] { + background: var(--col-button-pri); + border-radius: 10px; + border: none; + box-sizing: border-box; + color: white; + cursor: pointer; + height: 30px; + margin: 10px 5px 0 5px; + padding: 0 9px 0 9px; + user-select: none; +} + +button:disabled { + color: var(--col-button-disabled) !important; + background: var(--col-button-disabled-bg) !important; +} + +button.warning { + background: var(--col-button-warning); +} + +button.warning:hover { + background: var(--col-button-warning-hl); +} + +button.warning:active { + color: var(--col-button-warning); + background: white; +} + +button.secondary { + background: var(--col-button-sec); +} + +button.secondary:hover { + background: var(--col-button-sec-hl); +} + +button.secondary:active { + background: white; + color: var(--col-button-sec); +} + +button.secondary:disabled { + color: var(--col-button-sec-disabled) !important; + background: var(--col-button-sec-disabled-bg) !important; +} + +button:hover, input[type=submit]:hover { + background: var(--col-button-pri-hl); +} + +button:active, input[type=submit]:active { + background: white; + color: var(--col-button-pri); +} + +input, textarea { + background: rgba(0, 0, 0, 0); + border-radius: 5px; + border: 1px solid #aaa; + box-sizing: border-box; + color: white; + margin-bottom: 10px; +} + +input { + height: 25px !important; +} + +/* necessary for use inside flex containers */ +hr { + width: 100%; +} + +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-thumb { + background: var(--col-scrollbar); + border-radius: 10px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--col-scrollbar-hover); +} + +::-webkit-scrollbar-corner { + opacity: 0; +} |
