feat(web): initialize frontend

This commit is contained in:
Masahiko AMANO 2023-01-27 01:33:23 +03:00
parent 47ee5c4776
commit ebb3836930
40 changed files with 297 additions and 0 deletions

50
web/public/auth.html Normal file
View 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>

View 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
View 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

File diff suppressed because one or more lines are too long

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
web/public/images/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

33
web/public/index.html Normal file
View 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
View 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

File diff suppressed because one or more lines are too long

View 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
View 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
View File

@ -0,0 +1,2 @@
User-agent: *
Disallow: /

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