feat(web): initialize frontend
50
web/public/auth.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Authentication | Tanabata</title>
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/images/apple-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/images/apple-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/images/apple-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/images/apple-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/images/apple-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/images/apple-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/images/apple-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/images/apple-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/images/android-icon-192x192.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/images/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
|
||||
<link rel="manifest" href="/tanabata.webmanifest">
|
||||
<meta name="msapplication-TileColor" content="#5c913b">
|
||||
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
|
||||
<meta name="theme-color" content="#5c913b">
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/general.css">
|
||||
<link rel="stylesheet" href="css/auth.css">
|
||||
<script src="js/jquery-3.6.0.min.js"></script>
|
||||
<script src="js/jquery.cookie.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Welcome to Tanabata!</h1>
|
||||
</header>
|
||||
<main>
|
||||
<form id="auth">
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" class="form-control" maxlength="32" placeholder="Password">
|
||||
<div class="invalid-feedback">Invalid password!</div>
|
||||
<div class="valid-feedback">Authorization success!</div>
|
||||
</div>
|
||||
<div class="form-group button-flex">
|
||||
<input type="submit" id="submit" class="btn btn-primary" value="Submit">
|
||||
<a href="/" class="btn btn-secondary">Back to home</a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
<script src="js/auth.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
2
web/public/browserconfig.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig><msapplication><tile><square70x70logo src="/images/ms-icon-70x70.png"/><square150x150logo src="/images/ms-icon-150x150.png"/><square310x310logo src="/images/ms-icon-310x310.png"/><TileColor>#5c913b</TileColor></tile></msapplication></browserconfig>
|
||||
18
web/public/css/auth.css
Normal file
@ -0,0 +1,18 @@
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
padding: 2vw 2vw;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.button-flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
display: none;
|
||||
}
|
||||
7
web/public/css/bootstrap.min.css
vendored
Normal file
77
web/public/css/general.css
Normal file
@ -0,0 +1,77 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Epilogue&family=Secular+One&display=swap');
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-image: url(/images/bg-1920x1440.webp);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
header {
|
||||
margin: 0;
|
||||
margin-top: 2vw;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: white;
|
||||
font-family: Epilogue, sans-serif;
|
||||
font-size: 48pt;
|
||||
text-shadow: 0 0 8px black;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
main {
|
||||
margin-top: 50px;
|
||||
background-color: #fff8;
|
||||
box-shadow: 0 0 0.5vw black;
|
||||
border-radius: 1.5vw;
|
||||
width: 80vw;
|
||||
max-width: 700px;
|
||||
transition: 0.3s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
main:hover {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 1vw black;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
padding: 0 2vw;
|
||||
height: 9vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: hsla(270, 80%, 80%, 0.6);
|
||||
border-bottom: 0;
|
||||
font-family: Secular One, sans-serif;
|
||||
font-size: 3vw;
|
||||
text-shadow: 2.5px 2px 0.5px white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
margin-top: 0.5vw;
|
||||
font-family: Secular One, sans-serif;
|
||||
font-size: 3vw;
|
||||
}
|
||||
BIN
web/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
web/public/images/android-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web/public/images/android-icon-192x192.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
web/public/images/android-icon-36x36.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
web/public/images/android-icon-48x48.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
web/public/images/android-icon-72x72.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
web/public/images/android-icon-96x96.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
web/public/images/apple-icon-114x114.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
web/public/images/apple-icon-120x120.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
web/public/images/apple-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web/public/images/apple-icon-152x152.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web/public/images/apple-icon-180x180.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/public/images/apple-icon-57x57.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
web/public/images/apple-icon-60x60.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
web/public/images/apple-icon-72x72.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
web/public/images/apple-icon-76x76.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
web/public/images/apple-icon-precomposed.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/public/images/apple-icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/public/images/bg-1920x1440.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
web/public/images/bg.png
Normal file
|
After Width: | Height: | Size: 421 KiB |
BIN
web/public/images/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
web/public/images/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
web/public/images/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
web/public/images/favicon.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
web/public/images/ms-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web/public/images/ms-icon-150x150.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web/public/images/ms-icon-310x310.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
web/public/images/ms-icon-70x70.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
33
web/public/index.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Home | Tanabata</title>
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/images/apple-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/images/apple-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/images/apple-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/images/apple-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/images/apple-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/images/apple-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/images/apple-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/images/apple-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/images/android-icon-192x192.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/images/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
|
||||
<link rel="manifest" href="/tanabata.webmanifest">
|
||||
<meta name="msapplication-TileColor" content="#5c913b">
|
||||
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
|
||||
<meta name="theme-color" content="#5c913b">
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/general.css">
|
||||
<script src="js/jquery-3.6.0.min.js"></script>
|
||||
<script src="js/jquery.cookie.js"></script>
|
||||
<script src="js/token.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome to Tanabata!</h1>
|
||||
</body>
|
||||
</html>
|
||||
27
web/public/js/auth.js
Normal file
@ -0,0 +1,27 @@
|
||||
$("#auth").on("submit", function submit(e) {
|
||||
e.preventDefault();
|
||||
var input_password = $("#password");
|
||||
let password = input_password.val();
|
||||
input_password.val("");
|
||||
$.ajax({
|
||||
url: "/AUTH",
|
||||
type: "POST",
|
||||
contentType: "text/plain",
|
||||
data: password,
|
||||
dataType: "json",
|
||||
success: function (resp) {
|
||||
if (resp.status) {
|
||||
$.cookie("token", resp.token, {expires: 7, path: '/'});
|
||||
input_password.removeClass("is-invalid");
|
||||
input_password.addClass("is-valid");
|
||||
$(".btn-secondary").css("display", "block");
|
||||
} else {
|
||||
input_password.removeClass("is-valid");
|
||||
input_password.addClass("is-invalid");
|
||||
}
|
||||
},
|
||||
failure: function (err) {
|
||||
alert(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
2
web/public/js/jquery-3.6.0.min.js
vendored
Normal file
8
web/public/js/jquery.cookie.js
Normal file
@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* jQuery Cookie Plugin v1.4.1
|
||||
* https://github.com/carhartl/jquery-cookie
|
||||
*
|
||||
* Copyright 2013 Klaus Hartl
|
||||
* Released under the MIT license
|
||||
*/
|
||||
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e("object"==typeof exports?require("jquery"):jQuery)}(function(e){var i=/\+/g;function o(e){return t.raw?e:encodeURIComponent(e)}function r(e){return t.raw?e:decodeURIComponent(e)}function n(o,r){var n=t.raw?o:function e(o){0===o.indexOf('"')&&(o=o.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return o=decodeURIComponent(o.replace(i," ")),t.json?JSON.parse(o):o}catch(r){}}(o);return e.isFunction(r)?r(n):n}var t=e.cookie=function(i,c,u){if(void 0!==c&&!e.isFunction(c)){if("number"==typeof(u=e.extend({},t.defaults,u)).expires){var a,s=u.expires,f=u.expires=new Date;f.setTime(+f+864e5*s)}return document.cookie=[o(i),"=",(a=c,o(t.json?JSON.stringify(a):String(a))),u.expires?"; expires="+u.expires.toUTCString():"",u.path?"; path="+u.path:"",u.domain?"; domain="+u.domain:"",u.secure?"; secure":""].join("")}for(var p=i?void 0:{},d=document.cookie?document.cookie.split("; "):[],v=0,x=d.length;v<x;v++){var k=d[v].split("="),l=r(k.shift()),j=k.join("=");if(i&&i===l){p=n(j,c);break}i||void 0===(j=n(j))||(p[l]=j)}return p};t.defaults={},e.removeCookie=function(i,o){return void 0!==e.cookie(i)&&(e.cookie(i,"",e.extend({},o,{expires:-1})),!e.cookie(i))}});
|
||||
24
web/public/js/token.js
Normal file
@ -0,0 +1,24 @@
|
||||
$(window).on("load", function () {
|
||||
let authorized = true;
|
||||
if ($.cookie("token") == null) {
|
||||
authorized = false;
|
||||
$.ajax({
|
||||
url: "/token",
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
data: `{"token":"${$.cookie("token")}"}`,
|
||||
dataType: "json",
|
||||
success: function (resp) {
|
||||
if (resp.status) {
|
||||
authorized = true;
|
||||
}
|
||||
},
|
||||
failure: function (err) {
|
||||
alert(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!authorized) {
|
||||
$(location).attr("href", "/auth");
|
||||
}
|
||||
});
|
||||
2
web/public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow: /
|
||||
47
web/public/tanabata.webmanifest
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "Tanabata",
|
||||
"lang": "en-US",
|
||||
"description": "Tanabata Project PWA",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"theme_color": "#5c913b",
|
||||
"icons": [
|
||||
{
|
||||
"src": "\/images\/android-icon-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "\/images\/android-icon-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "\/images\/android-icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "\/images\/android-icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "\/images\/android-icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "\/images\/android-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"density": "4.0"
|
||||
}
|
||||
]
|
||||
}
|
||||