forked from TripwireTeam/tripwire
pushing unfinished work for the night
This commit is contained in:
parent
27f4047cf7
commit
7e089795c7
14 changed files with 760 additions and 156 deletions
15
web/index.html
Normal file
15
web/index.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>Tripwire Web Panel</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel='stylesheet' type='text/css' media='screen' href='./web/main.css'>
|
||||
<script src="https://unpkg.com/mithril/mithril.js"></script>
|
||||
<script src="https://unpkg.com/js-cookie"></script>
|
||||
<script src='./web/main.js' type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>JavaScript must be enabled to use this application.</noscript>
|
||||
</body>
|
||||
</html>
|
90
web/main.css
Normal file
90
web/main.css
Normal file
|
@ -0,0 +1,90 @@
|
|||
:root {
|
||||
background-color: #222;
|
||||
color: #CCC;
|
||||
font-family: Arial, sans-serif;
|
||||
|
||||
--border-radius: 6px;
|
||||
--header-height: 50px;
|
||||
--accent-color: #5f00aa;
|
||||
--accent-color-secondary: #4f0099;
|
||||
--error-color: #cc4444;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
header {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: var(--header-height);
|
||||
line-height: var(--header-height);
|
||||
background-color: #141414;
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
padding: 0px 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#header-spacer {
|
||||
padding-bottom: var(--header-height);
|
||||
}
|
||||
|
||||
#header-title {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
button, a.button {
|
||||
background-color: var(--accent-color);
|
||||
transition: background-color 0.3s;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-radius: var(--border-radius);
|
||||
padding: 8px 10px;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
}
|
||||
button:hover, a.button:hover {
|
||||
background-color: var(--accent-color-secondary);
|
||||
}
|
||||
|
||||
input {
|
||||
display: block;
|
||||
background-color: #141414;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-radius: var(--border-radius);
|
||||
padding: 8px 10px;
|
||||
color: white;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.center {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.errorText {
|
||||
color: var(--error-color);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.errorInput {
|
||||
outline: 1px solid var(--error-color);
|
||||
}
|
||||
|
||||
#playerHead {
|
||||
vertical-align: middle;
|
||||
margin-top: -4px;
|
||||
margin-right: 12px;
|
||||
}
|
200
web/main.js
Normal file
200
web/main.js
Normal file
|
@ -0,0 +1,200 @@
|
|||
import htm from 'https://unpkg.com/htm?module'
|
||||
const html = htm.bind(m);
|
||||
var root = document.body
|
||||
|
||||
var currentUser = null;
|
||||
try {
|
||||
currentUser = JSON.parse(Cookies.get("currentUser"))
|
||||
} catch {}
|
||||
var loggingIn = false;
|
||||
var logInError = ""
|
||||
|
||||
var PlayerHead = {
|
||||
oncreate: function (vnode) {
|
||||
const ctx = vnode.dom.getContext('2d');
|
||||
ctx.imageSmoothingEnabled = false
|
||||
|
||||
let img = new Image();
|
||||
img.src = `/getTexture/${currentUser.uuid}?type=skin`
|
||||
|
||||
img.onload = function(){
|
||||
ctx.drawImage(img, 8, 8, 8, 8, 0, 0, 32, 32);
|
||||
}
|
||||
},
|
||||
view: function(vnode) {
|
||||
return html `
|
||||
<canvas id="playerHead" width="32" height="32" />
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
var Header = {
|
||||
view: function() {
|
||||
return html`
|
||||
<header>
|
||||
<a href="#!/" id="header-title">Tripwire</span>
|
||||
<div class="align-right">
|
||||
${currentUser ?
|
||||
html`
|
||||
<${PlayerHead} />
|
||||
<span>Hello, ${currentUser.username}</span>
|
||||
` :
|
||||
html`<a class="button" href="#!/login">Log In</a>`
|
||||
}
|
||||
</div>
|
||||
</header>
|
||||
<div id="header-spacer"></div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
var ErrorText = {
|
||||
view: function(vnode) {
|
||||
return html`
|
||||
<span class="errorText">${vnode.attrs.error.errorMessage}</span>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
m.route(root, "/", {
|
||||
"/": {
|
||||
view: function() {
|
||||
return html`
|
||||
<${Header} />
|
||||
${currentUser ?
|
||||
html`
|
||||
<div class="center">
|
||||
<a class="button" href="#!/skinchanger">Change skin</a>
|
||||
</div>
|
||||
` :
|
||||
html`<span>Please log in to continue.</span>`
|
||||
}
|
||||
`
|
||||
}
|
||||
},
|
||||
"/skinchanger": function SkinChanger() {
|
||||
var pageError = null;
|
||||
var success = false;
|
||||
return {
|
||||
view: function() {
|
||||
if (!currentUser) {
|
||||
m.route.set("/login")
|
||||
}
|
||||
return html`
|
||||
<${Header} />
|
||||
${currentUser ?
|
||||
success ?
|
||||
html `
|
||||
<div class="center">
|
||||
<span style="font-size: 1.5em;">Texture successfully uploaded!</span><br/><br/>
|
||||
<a class="button" href="#!/">Go back</a>
|
||||
</div>
|
||||
` :
|
||||
html`
|
||||
<div class="center">
|
||||
<span style="font-size: 1.5em;">Select Skin/Cape </span>
|
||||
<span>(only .PNG supported)</span><br/><br/>
|
||||
<input style="display: inline;"
|
||||
type="radio"
|
||||
id="skinRadio"
|
||||
name="textureId"
|
||||
value="skin"
|
||||
checked
|
||||
/>
|
||||
<label for="skinRadio">Skin</label>
|
||||
<input style="display: inline;"
|
||||
type="radio"
|
||||
id="capeRadio"
|
||||
name="textureId"
|
||||
value="cape"
|
||||
/>
|
||||
<label for="capeRadio">Cape</label>
|
||||
<input id="textureFile"
|
||||
style="width: 100%"
|
||||
type="file"
|
||||
accept="image/png"
|
||||
onchange=${() => {
|
||||
pageError = null
|
||||
}}
|
||||
/>
|
||||
${pageError && html`<${ErrorText} error=${pageError}/>`}
|
||||
<button onclick=${() => {
|
||||
let input = document.getElementById("textureFile")
|
||||
if (input.files.length == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
let file = input.files[0]
|
||||
|
||||
let body = new FormData()
|
||||
body.append("file", file)
|
||||
body.append("token", currentUser.token)
|
||||
m.request({
|
||||
method: "POST",
|
||||
url: "/setTexture/"+currentUser.uuid+"?type=" +
|
||||
(document.getElementById("skinRadio").checked ? "skin" : "cape"),
|
||||
body: body,
|
||||
}).then((res) => {
|
||||
success = true
|
||||
}, (res) => {
|
||||
pageError = res.response
|
||||
})
|
||||
}}>Let it rip</button>
|
||||
</div>
|
||||
` :
|
||||
html`<span>Please log in to continue.</span>`
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
},
|
||||
"/login": {
|
||||
view: function() {
|
||||
if (currentUser) {
|
||||
m.route.set("/")
|
||||
}
|
||||
let oninput = () => {
|
||||
logInError = null
|
||||
}
|
||||
return html`
|
||||
<${Header} />
|
||||
<div class="center">
|
||||
<input id="usernameLogin"
|
||||
placeholder="Username"
|
||||
type="text"
|
||||
class=${logInError && "errorInput"}
|
||||
oninput=${oninput}
|
||||
/>
|
||||
<input id="passwordLogin"
|
||||
placeholder="Password"
|
||||
type="text"
|
||||
class=${logInError && "errorInput"}
|
||||
oninput=${oninput}
|
||||
/>
|
||||
${logInError && html`
|
||||
<${ErrorText} error=${logInError} />
|
||||
`}
|
||||
<button disabled=${loggingIn} onclick=${function() {
|
||||
loggingIn = true;
|
||||
m.request({
|
||||
method: "POST",
|
||||
url: "/webapi/logIn",
|
||||
body: {
|
||||
username: document.getElementById("usernameLogin").value,
|
||||
password: document.getElementById("passwordLogin").value,
|
||||
}
|
||||
})
|
||||
.then(function(result) {
|
||||
currentUser = result
|
||||
Cookies.set("currentUser", JSON.stringify(result))
|
||||
loggingIn = false
|
||||
}, function(result) {
|
||||
logInError = result.response
|
||||
loggingIn = false
|
||||
})
|
||||
}}>Log In</button>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue