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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||