PA 10 complete.
|
@ -8,9 +8,12 @@ const publishers = require('./model/publishers');
|
||||||
const {request, response} = require("express");
|
const {request, response} = require("express");
|
||||||
const {check, checkSchema, validationResult} = require("express-validator");
|
const {check, checkSchema, validationResult} = require("express-validator");
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const cors = require('cors');
|
||||||
|
|
||||||
//Setup defaults for script
|
//Setup defaults for script
|
||||||
const app = express();
|
const app = express();
|
||||||
|
app.use(cors());
|
||||||
|
app.use(express.static('public'));
|
||||||
const storage = multer.diskStorage({
|
const storage = multer.diskStorage({
|
||||||
//Logic where to upload files
|
//Logic where to upload files
|
||||||
destination: function (request, file, callback) {
|
destination: function (request, file, callback) {
|
||||||
|
@ -31,8 +34,6 @@ const upload = multer({
|
||||||
});
|
});
|
||||||
const port = 8787;
|
const port = 8787;
|
||||||
|
|
||||||
app.use(express.static('public'));
|
|
||||||
|
|
||||||
//The * in app.* needs to match the method type of the request
|
//The * in app.* needs to match the method type of the request
|
||||||
app.get('/games', upload.none(),
|
app.get('/games', upload.none(),
|
||||||
async (request, response) => {
|
async (request, response) => {
|
||||||
|
|
|
@ -112,8 +112,8 @@ async function getGame(id) {
|
||||||
queryParameters = [];
|
queryParameters = [];
|
||||||
|
|
||||||
if (typeof id !== 'undefined' && id.length > 0) {
|
if (typeof id !== 'undefined' && id.length > 0) {
|
||||||
whereStatements.push("m.id LIKE ?");
|
whereStatements.push("m.id = ?");
|
||||||
queryParameters.push('%' + id + '%');
|
queryParameters.push(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Dynamically add WHERE expressions to SELECT statements if needed
|
//Dynamically add WHERE expressions to SELECT statements if needed
|
||||||
|
|
62
server/public/404.html
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Page Not Found</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
line-height: 1.2;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
color: #888;
|
||||||
|
display: table;
|
||||||
|
font-family: sans-serif;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 2em auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #555;
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 280px) {
|
||||||
|
|
||||||
|
body,
|
||||||
|
p {
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: 0 0 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Page Not Found</h1>
|
||||||
|
<p>Sorry, but the page you were trying to view does not exist.</p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
<!-- IE needs 512+ bytes: https://docs.microsoft.com/archive/blogs/ieinternals/friendly-http-error-pages -->
|
19
server/public/LICENSE.txt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) HTML5 Boilerplate
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
BIN
server/public/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 43 KiB |
12
server/public/browserconfig.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Please read: https://msdn.microsoft.com/en-us/library/ie/dn455106.aspx -->
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square70x70logo src="icons/tile.png"/>
|
||||||
|
<square150x150logo src="icons/tile.png"/>
|
||||||
|
<wide310x150logo src="icons/tile-wide.png"/>
|
||||||
|
<square310x310logo src="icons/tile.png"/>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
433
server/public/css/main.css
Normal file
|
@ -0,0 +1,433 @@
|
||||||
|
/*! HTML5 Boilerplate v8.0.0 | MIT License | https://html5boilerplate.com/ */
|
||||||
|
|
||||||
|
/* main.css 2.1.0 | MIT License | https://github.com/h5bp/main.css#readme */
|
||||||
|
/*
|
||||||
|
* What follows is the result of much research on cross-browser styling.
|
||||||
|
* Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
|
||||||
|
* Kroc Camen, and the H5BP dev community and team.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Base styles: opinionated defaults
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
html {
|
||||||
|
color: #222;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove text-shadow in selection highlight:
|
||||||
|
* https://twitter.com/miketaylr/status/12228805301
|
||||||
|
*
|
||||||
|
* Vendor-prefixed and regular ::selection selectors cannot be combined:
|
||||||
|
* https://stackoverflow.com/a/16982510/7133471
|
||||||
|
*
|
||||||
|
* Customize the background color to match your design.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-moz-selection {
|
||||||
|
background: #b3d4fc;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::selection {
|
||||||
|
background: #b3d4fc;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A better looking default horizontal rule
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
display: block;
|
||||||
|
height: 1px;
|
||||||
|
border: 0;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
margin: 1em 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove the gap between audio, canvas, iframes,
|
||||||
|
* images, videos and the bottom of their containers:
|
||||||
|
* https://github.com/h5bp/html5-boilerplate/issues/440
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio,
|
||||||
|
canvas,
|
||||||
|
iframe,
|
||||||
|
img,
|
||||||
|
svg,
|
||||||
|
video {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove default fieldset styles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow only vertical resizing of textareas.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Author's custom styles
|
||||||
|
========================================================================== */
|
||||||
|
#header {
|
||||||
|
background-color: #171a21;
|
||||||
|
color: #c6d4df;
|
||||||
|
}
|
||||||
|
|
||||||
|
#form {
|
||||||
|
background-image: linear-gradient(180deg, #171a21, #1b2838);
|
||||||
|
min-height: 750px;
|
||||||
|
color: #c6d4df;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
width: 100%;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #171a21;
|
||||||
|
color: lightsteelblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr{
|
||||||
|
border-top: 3px solid #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
body, html {
|
||||||
|
margin: 0px;
|
||||||
|
background-color: #171a21;
|
||||||
|
transition: all 0.4s ease 0s;
|
||||||
|
color: #d3dade;
|
||||||
|
}
|
||||||
|
|
||||||
|
p{
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select, textarea {
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #316282;
|
||||||
|
color: #d3dade;
|
||||||
|
border: 1px solid #22445b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#submitButton {
|
||||||
|
border-radius: 5px;
|
||||||
|
border:0;
|
||||||
|
min-width: 150px;
|
||||||
|
min-height: 50px;
|
||||||
|
background-image: linear-gradient(#5c7e10, #4c6b22);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#submitButton:hover {
|
||||||
|
background-image: linear-gradient(#92c91a, #84b83b);
|
||||||
|
box-shadow: #000000 3px 3px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#backButton {
|
||||||
|
border-radius: 5px;
|
||||||
|
border:0;
|
||||||
|
min-width: 150px;
|
||||||
|
min-height: 50px;
|
||||||
|
background-image: linear-gradient(#316282, #22445b);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#backButton:hover {
|
||||||
|
background-image: linear-gradient(#b3d4fc, #a1c1ec);
|
||||||
|
box-shadow: #000000 3px 3px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#deleteButton {
|
||||||
|
border-radius: 5px;
|
||||||
|
border:0;
|
||||||
|
min-width: 150px;
|
||||||
|
min-height: 50px;
|
||||||
|
background-image: linear-gradient(#c51210, #5c1210);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#deleteButton:hover {
|
||||||
|
background-image: linear-gradient(#e53333, #d51210);
|
||||||
|
box-shadow: #000000 3px 3px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#successMessage {
|
||||||
|
background-color: #4c6b22;
|
||||||
|
color: #b3d4fc;
|
||||||
|
min-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#errorMessage {
|
||||||
|
background-color: darkred;
|
||||||
|
color: #b3d4fc;
|
||||||
|
min-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
background-color: darkred;
|
||||||
|
color: #b3d4fc;
|
||||||
|
min-height: 30px;
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 22px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tableCoverArt {
|
||||||
|
max-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table{
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table, th, td {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th{
|
||||||
|
background-color: #5c7e10;
|
||||||
|
border: 1px solid #4c6b22;
|
||||||
|
color: #ffffff;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
border-left: 1px solid #5c7e10;
|
||||||
|
border-right: 1px solid #5c7e10;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(even) {
|
||||||
|
background-color: #1b2838;
|
||||||
|
color: #d3dade;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(odd) {
|
||||||
|
background-color: #171a21;
|
||||||
|
color: #d3dade;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overflow{
|
||||||
|
overflow-x:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: VT323;
|
||||||
|
font-display: swap;
|
||||||
|
src: url("../fonts/VT323-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Oswald, "DejaVu Sans";
|
||||||
|
font-display: swap;
|
||||||
|
src: url("../fonts/Oswald-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'IBM Plex Mono';
|
||||||
|
font-display: swap;
|
||||||
|
src: url("../fonts/IBMPlexMono-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'IBM Plex Sans';
|
||||||
|
font-display: swap;
|
||||||
|
src: url("../fonts/IBMPlexSans-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Helper classes
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hide visually and from screen readers
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hidden,
|
||||||
|
[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hide only visually, but have it available for screen readers:
|
||||||
|
* https://snook.ca/archives/html_and_css/hiding-content-for-accessibility
|
||||||
|
*
|
||||||
|
* 1. For long content, line feeds are not interpreted as spaces and small width
|
||||||
|
* causes content to wrap 1 word per line:
|
||||||
|
* https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe
|
||||||
|
*/
|
||||||
|
|
||||||
|
.sr-only {
|
||||||
|
border: 0;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
height: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 1px;
|
||||||
|
/* 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extends the .sr-only class to allow the element
|
||||||
|
* to be focusable when navigated to via the keyboard:
|
||||||
|
* https://www.drupal.org/node/897638
|
||||||
|
*/
|
||||||
|
|
||||||
|
.sr-only.focusable:active,
|
||||||
|
.sr-only.focusable:focus {
|
||||||
|
clip: auto;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
overflow: visible;
|
||||||
|
position: static;
|
||||||
|
white-space: inherit;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hide visually and from screen readers, but maintain layout
|
||||||
|
*/
|
||||||
|
|
||||||
|
.invisible {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clearfix: contain floats
|
||||||
|
*
|
||||||
|
* For modern browsers
|
||||||
|
* 1. The space content is one way to avoid an Opera bug when the
|
||||||
|
* `contenteditable` attribute is included anywhere else in the document.
|
||||||
|
* Otherwise it causes space to appear at the top and bottom of elements
|
||||||
|
* that receive the `clearfix` class.
|
||||||
|
* 2. The use of `table` rather than `block` is only necessary if using
|
||||||
|
* `:before` to contain the top-margins of child elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.clearfix::before,
|
||||||
|
.clearfix::after {
|
||||||
|
content: " ";
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix::after {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
EXAMPLE Media Queries for Responsive Design.
|
||||||
|
These examples override the primary ('mobile first') styles.
|
||||||
|
Modify as content requires.
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
@media only screen and (min-width: 35em) {
|
||||||
|
/* Style adjustments for viewports that meet the condition */
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print,
|
||||||
|
(-webkit-min-device-pixel-ratio: 1.25),
|
||||||
|
(min-resolution: 1.25dppx),
|
||||||
|
(min-resolution: 120dpi) {
|
||||||
|
/* Style adjustments for high resolution devices */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Print styles.
|
||||||
|
Inlined to avoid the additional HTTP request:
|
||||||
|
https://www.phpied.com/delay-loading-your-print-css/
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
background: #fff !important;
|
||||||
|
color: #000 !important;
|
||||||
|
/* Black prints faster */
|
||||||
|
box-shadow: none !important;
|
||||||
|
text-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:visited {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[href]::after {
|
||||||
|
content: " (" attr(href) ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr[title]::after {
|
||||||
|
content: " (" attr(title) ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't show links that are fragment identifiers,
|
||||||
|
* or use the `javascript:` pseudo protocol
|
||||||
|
*/
|
||||||
|
a[href^="#"]::after,
|
||||||
|
a[href^="javascript:"]::after {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
white-space: pre-wrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre,
|
||||||
|
blockquote {
|
||||||
|
border: 1px solid #999;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Printing Tables:
|
||||||
|
* https://web.archive.org/web/20180815150934/http://css-discuss.incutio.com/wiki/Printing_Tables
|
||||||
|
*/
|
||||||
|
thead {
|
||||||
|
display: table-header-group;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr,
|
||||||
|
img {
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
|
orphans: 3;
|
||||||
|
widows: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
|
page-break-after: avoid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
349
server/public/css/normalize.css
vendored
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||||
|
|
||||||
|
/* Document
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the line height in all browsers.
|
||||||
|
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the margin in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the `main` element consistently in IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the font size and margin on `h1` elements within `section` and
|
||||||
|
* `article` contexts in Chrome, Firefox, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grouping content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in Firefox.
|
||||||
|
* 2. Show the overflow in Edge and IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box; /* 1 */
|
||||||
|
height: 0; /* 1 */
|
||||||
|
overflow: visible; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text-level semantics
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the gray background on active links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Remove the bottom border in Chrome 57-
|
||||||
|
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: none; /* 1 */
|
||||||
|
text-decoration: underline; /* 2 */
|
||||||
|
text-decoration: underline dotted; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||||
|
* all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the border on images inside links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Change the font styles in all browsers.
|
||||||
|
* 2. Remove the margin in Firefox and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit; /* 1 */
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the overflow in IE.
|
||||||
|
* 1. Show the overflow in Edge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input { /* 1 */
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||||
|
* 1. Remove the inheritance of text transform in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select { /* 1 */
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type="button"],
|
||||||
|
[type="reset"],
|
||||||
|
[type="submit"] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner border and padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
|
[type="reset"]::-moz-focus-inner,
|
||||||
|
[type="submit"]::-moz-focus-inner {
|
||||||
|
border-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the focus styles unset by the previous rule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button:-moz-focusring,
|
||||||
|
[type="button"]:-moz-focusring,
|
||||||
|
[type="reset"]:-moz-focusring,
|
||||||
|
[type="submit"]:-moz-focusring {
|
||||||
|
outline: 1px dotted ButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
padding: 0.35em 0.75em 0.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the text wrapping in Edge and IE.
|
||||||
|
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||||
|
* 3. Remove the padding so developers are not caught out when they zero out
|
||||||
|
* `fieldset` elements in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
color: inherit; /* 2 */
|
||||||
|
display: table; /* 1 */
|
||||||
|
max-width: 100%; /* 1 */
|
||||||
|
padding: 0; /* 3 */
|
||||||
|
white-space: normal; /* 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the default vertical scrollbar in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in IE 10.
|
||||||
|
* 2. Remove the padding in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="checkbox"],
|
||||||
|
[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the odd appearance in Chrome and Safari.
|
||||||
|
* 2. Correct the outline style in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
outline-offset: -2px; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner padding in Chrome and Safari on macOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
* 2. Change font properties to `inherit` in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interactive
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
details {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
314
server/public/delete.html
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Delete Game</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="manifest" href="site.webmanifest">
|
||||||
|
<link rel="apple-touch-icon" href="icon.png">
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#488ea7">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="header" class="container">
|
||||||
|
<h1>Edit Game</h1>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card" id="successMessage"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card" id="errorMessage"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card warning">
|
||||||
|
<p>Are you SURE you want to delete this game?</p>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="form">
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Title</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="title" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>
|
||||||
|
Developer
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<select id="developer">
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>
|
||||||
|
Publisher
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<select id="publisher">
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Release Date</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="releaseDate" type="date"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Supported OSes</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<span>Windows</span>
|
||||||
|
<input id="win" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span>MacOS</span>
|
||||||
|
<input id="mac" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span>Linux</span>
|
||||||
|
<input id="linux" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Cover Art</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div id="currentArt"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Short Description</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textarea id="shortDescription" rows="5" cols="40" maxlength="300"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Long Description</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textarea id="longDescription" rows="15" cols="40"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-2 align-content-center">
|
||||||
|
<button id="deleteButton" type="submit">Delete</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 align-content-center">
|
||||||
|
<button id="backButton">Back</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-8"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer id="footer">
|
||||||
|
<p>Page created by <a href="https://lunarpenguin.net/">Kaj Forney</a>, as work for class (GIMM 285).</p>
|
||||||
|
<p>All example data used is originally from <a href="https://store.steampowered.com/">Steam</a>.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
||||||
|
crossorigin="anonymous" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const isEmpty = (obj) => Object.keys(obj).length === 0;
|
||||||
|
|
||||||
|
document.getElementById("successMessage").hidden = true;
|
||||||
|
document.getElementById("errorMessage").hidden = true;
|
||||||
|
|
||||||
|
document.getElementById('backButton').addEventListener('click', (event) => {
|
||||||
|
history.back();
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch("http://localhost:8787/developers", { method: 'GET' })
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({ status, json }) => {
|
||||||
|
if (200 === status) {
|
||||||
|
const developerSelect = document.getElementById('developer');
|
||||||
|
for (dev of json.data) {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.value = dev.id;
|
||||||
|
option.text = dev.name;
|
||||||
|
developerSelect.add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch("http://localhost:8787/publishers", { method: 'GET' })
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({ status, json }) => {
|
||||||
|
if (200 === status) {
|
||||||
|
const publisherSelect = document.getElementById('publisher');
|
||||||
|
for (publisher of json.data) {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.value = publisher.id;
|
||||||
|
option.text = publisher.name;
|
||||||
|
publisherSelect.add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
let urlParams = new URLSearchParams(window.location.search)
|
||||||
|
fetch("http://localhost:8787/games/" + urlParams.get("id"), {method: 'GET'})
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({ status, json }) => {
|
||||||
|
if (200 === status) {
|
||||||
|
let gameData = json.data[0];
|
||||||
|
|
||||||
|
if(gameData !== undefined) {
|
||||||
|
document.getElementById("title").value = gameData.title;
|
||||||
|
|
||||||
|
let releaseDate = new Date(gameData.releaseDate);
|
||||||
|
document.getElementById("releaseDate").value = releaseDate.toISOString().split("T", 1);
|
||||||
|
|
||||||
|
document.getElementById("win").checked = Boolean(gameData.win);
|
||||||
|
document.getElementById("mac").checked = Boolean(gameData.mac);
|
||||||
|
document.getElementById("linux").checked = Boolean(gameData.linux);
|
||||||
|
|
||||||
|
let coverImg = document.createElement('img');
|
||||||
|
coverImg.src = "http://localhost:8787/images/" + gameData.coverArt;
|
||||||
|
document.getElementById("currentArt").appendChild(coverImg);
|
||||||
|
|
||||||
|
document.getElementById("shortDescription").value = gameData.shortDescription;
|
||||||
|
document.getElementById("longDescription").value = gameData.longDescription;
|
||||||
|
} else {
|
||||||
|
document.getElementById("errorMessage").innerHTML = "Invalid App ID!";
|
||||||
|
document.getElementById("errorMessage").hidden = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('deleteButton').addEventListener('click', (event) => {
|
||||||
|
const parameters = {};
|
||||||
|
|
||||||
|
if(urlParams.get("id") !== undefined) {
|
||||||
|
parameters.id = urlParams.get("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Settings for FETCH API request
|
||||||
|
let fetchSettings = {
|
||||||
|
method: 'DELETE'
|
||||||
|
};
|
||||||
|
|
||||||
|
//Send FETCH API request
|
||||||
|
fetch("http://localhost:8787/games/" + urlParams.get("id") + (!isEmpty(parameters) ? '?' + new URLSearchParams(parameters) : ''), fetchSettings)
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({status, json}) => {
|
||||||
|
if (status === 200) {
|
||||||
|
let message = "Game deletion successful!"
|
||||||
|
document.getElementById('successMessage').hidden = false;
|
||||||
|
document.getElementById('successMessage').innerHTML = message;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
362
server/public/edit.html
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Edit Game</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="manifest" href="site.webmanifest">
|
||||||
|
<link rel="apple-touch-icon" href="icon.png">
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#488ea7">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="header" class="container">
|
||||||
|
<h1>Edit Game</h1>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card" id="successMessage"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card" id="errorMessage"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="form">
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Title</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="title" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>
|
||||||
|
Developer
|
||||||
|
<br/>
|
||||||
|
(<a href="insertDeveloper.html">Add New Developer</a>)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<select id="developer">
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>
|
||||||
|
Publisher
|
||||||
|
<br/>
|
||||||
|
(<a href="insertPublisher.html">Add New Publisher</a>)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<select id="publisher">
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Release Date</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="releaseDate" type="date"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Supported OSes</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<span>Windows</span>
|
||||||
|
<input id="win" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span>MacOS</span>
|
||||||
|
<input id="mac" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span>Linux</span>
|
||||||
|
<input id="linux" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Cover Art</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div id="currentArt"></div>
|
||||||
|
<input id="coverArt" type="file"
|
||||||
|
accept="image/jpeg, image/png"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Short Description</label>
|
||||||
|
<p>(maximum 300 characters)</p>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textarea id="shortDescription" rows="5" cols="40" maxlength="300"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Long Description</label>
|
||||||
|
<p>(supports <a href="https://www.markdownguide.org/">Markdown</a>) </p>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textarea id="longDescription" rows="15" cols="40"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-2 align-content-center">
|
||||||
|
<button id="submitButton" type="submit">Submit</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 align-content-center">
|
||||||
|
<button id="backButton">Back</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-8"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer id="footer">
|
||||||
|
<p>Page created by <a href="https://lunarpenguin.net/">Kaj Forney</a>, as work for class (GIMM 285).</p>
|
||||||
|
<p>All example data used is originally from <a href="https://store.steampowered.com/">Steam</a>.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
||||||
|
crossorigin="anonymous" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const isEmpty = (obj) => Object.keys(obj).length === 0;
|
||||||
|
|
||||||
|
document.getElementById("successMessage").hidden = true;
|
||||||
|
document.getElementById("errorMessage").hidden = true;
|
||||||
|
|
||||||
|
document.getElementById('backButton').addEventListener('click', (event) => {
|
||||||
|
history.back();
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch("http://localhost:8787/developers", { method: 'GET' })
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({ status, json }) => {
|
||||||
|
if (200 === status) {
|
||||||
|
const developerSelect = document.getElementById('developer');
|
||||||
|
for (dev of json.data) {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.value = dev.id;
|
||||||
|
option.text = dev.name;
|
||||||
|
developerSelect.add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch("http://localhost:8787/publishers", { method: 'GET' })
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({ status, json }) => {
|
||||||
|
if (200 === status) {
|
||||||
|
const publisherSelect = document.getElementById('publisher');
|
||||||
|
for (publisher of json.data) {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.value = publisher.id;
|
||||||
|
option.text = publisher.name;
|
||||||
|
publisherSelect.add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
let urlParams = new URLSearchParams(window.location.search)
|
||||||
|
fetch("http://localhost:8787/games/" + urlParams.get("id"), {method: 'GET'})
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({ status, json }) => {
|
||||||
|
if (200 === status) {
|
||||||
|
let gameData = json.data[0];
|
||||||
|
|
||||||
|
if(gameData !== undefined) {
|
||||||
|
document.getElementById("title").value = gameData.title;
|
||||||
|
|
||||||
|
let releaseDate = new Date(gameData.releaseDate);
|
||||||
|
document.getElementById("releaseDate").value = releaseDate.toISOString().split("T", 1);
|
||||||
|
|
||||||
|
document.getElementById("win").checked = Boolean(gameData.win);
|
||||||
|
document.getElementById("mac").checked = Boolean(gameData.mac);
|
||||||
|
document.getElementById("linux").checked = Boolean(gameData.linux);
|
||||||
|
|
||||||
|
let coverImg = document.createElement('img');
|
||||||
|
coverImg.src = "http://localhost:8787/images/" + gameData.coverArt;
|
||||||
|
document.getElementById("currentArt").appendChild(coverImg);
|
||||||
|
|
||||||
|
document.getElementById("shortDescription").value = gameData.shortDescription;
|
||||||
|
document.getElementById("longDescription").value = gameData.longDescription;
|
||||||
|
} else {
|
||||||
|
document.getElementById("errorMessage").innerHTML = "Invalid App ID!";
|
||||||
|
document.getElementById("errorMessage").hidden = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('submitButton').addEventListener('click', (event) => {
|
||||||
|
const parameters = {};
|
||||||
|
|
||||||
|
if(urlParams.get("id") !== undefined) {
|
||||||
|
parameters.id = urlParams.get("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById('title').value.length !== 0) {
|
||||||
|
//formData.append('title', document.getElementById('title').value);
|
||||||
|
parameters.title = document.getElementById('title').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('developer').value.length !== 0) {
|
||||||
|
//formData.append('developer', document.getElementById('developer').value);
|
||||||
|
parameters.developerID = document.getElementById('developer').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('publisher').value.length !== 0) {
|
||||||
|
//formData.append('publisher', document.getElementById('publisher').value);
|
||||||
|
parameters.publisherID = document.getElementById('publisher').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('releaseDate').value.length !== 0) {
|
||||||
|
//formData.append('releaseDate', document.getElementById('releaseDate').value);
|
||||||
|
parameters.releaseDate = document.getElementById('releaseDate').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById('win').checked) {
|
||||||
|
parameters.win = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parameters.win = 0;
|
||||||
|
}
|
||||||
|
if (document.getElementById('mac').checked) {
|
||||||
|
parameters.mac = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parameters.mac = 0;
|
||||||
|
}
|
||||||
|
if (document.getElementById('linux').checked) {
|
||||||
|
parameters.linux = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parameters.linux = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById('shortDescription').value.length !== 0) {
|
||||||
|
parameters.shortDescription = document.getElementById('shortDescription').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('longDescription').value.length !== 0) {
|
||||||
|
parameters.longDescription = document.getElementById('longDescription').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
const coverField = document.querySelector('input[type="file"]');
|
||||||
|
formData.append("coverArt", coverField.files[0]);
|
||||||
|
|
||||||
|
|
||||||
|
//Settings for FETCH API request
|
||||||
|
let fetchSettings = {
|
||||||
|
method: 'PUT',
|
||||||
|
body: formData
|
||||||
|
};
|
||||||
|
|
||||||
|
//Send FETCH API request
|
||||||
|
fetch("http://localhost:8787/games/" + urlParams.get("id") + (!isEmpty(parameters) ? '?' + new URLSearchParams(parameters) : ''), fetchSettings)
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({status, json}) => {
|
||||||
|
if (status === 200) {
|
||||||
|
let message = "Game submission successful!"
|
||||||
|
document.getElementById('outputMessage').hidden = false;
|
||||||
|
document.getElementById('outputMessage').innerHTML = message;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
BIN
server/public/favicon-16x16.png
Normal file
After Width: | Height: | Size: 876 B |
BIN
server/public/favicon-32x32.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
server/public/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
server/public/fonts/IBMPlexMono-Regular.ttf
Normal file
BIN
server/public/fonts/IBMPlexSans-Regular.ttf
Normal file
BIN
server/public/fonts/Oswald-Regular.ttf
Normal file
BIN
server/public/fonts/VT323-Regular.ttf
Normal file
78
server/public/game.html
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Pressurized Gas -- Game Page</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="manifest" href="site.webmanifest">
|
||||||
|
<link rel="apple-touch-icon" href="icon.png">
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#488ea7">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="gameTitle"></div>
|
||||||
|
|
||||||
|
<div id="longDescription"></div>
|
||||||
|
|
||||||
|
<div id="coverArt"></div>
|
||||||
|
|
||||||
|
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
||||||
|
crossorigin="anonymous" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const isEmpty = (obj) => Object.keys(obj).length === 0;
|
||||||
|
const getParameters = {};
|
||||||
|
|
||||||
|
let gameID = new URL(document.location).searchParams.get("ID");
|
||||||
|
if (gameID == null) {
|
||||||
|
gameID = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Settings for FETCH API request
|
||||||
|
let fetchSettings = {
|
||||||
|
method: 'GET'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (gameID !== -1) {
|
||||||
|
fetch("http://localhost:8787/games/" + gameID, fetchSettings)
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({status, json}) => {
|
||||||
|
if (status === 200) {
|
||||||
|
document.title = "Pressurized Gas - " + json.data[0].title;
|
||||||
|
document.getElementById("gameTitle").innerHTML = json.data[0].title;
|
||||||
|
document.getElementById("longDescription").innerHTML = json.data[0].longDescription;
|
||||||
|
let coverImg = document.createElement('img');
|
||||||
|
coverImg.src = "http://localhost:8787/images/" + json.data[0].coverArt;
|
||||||
|
document.getElementById("coverArt").appendChild(coverImg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
document.title = "Pressurized Gas - ERROR"
|
||||||
|
document.getElementById("gameTitle").innerHTML = "Invalid game ID!"
|
||||||
|
document.getElementById("gameTitle").style.color = "#FF0000";
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
server/public/icon.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
server/public/icons/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
server/public/icons/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 170 KiB |
BIN
server/public/icons/tile-wide.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
server/public/icons/tile.png
Normal file
After Width: | Height: | Size: 174 KiB |
0
server/public/img/.gitignore
vendored
Normal file
277
server/public/index.html
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Kaj Forney -- GIMM 285 CRUD API Project</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="manifest" href="site.webmanifest">
|
||||||
|
<link rel="apple-touch-icon" href="icon.png">
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#488ea7">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="header" class="container">
|
||||||
|
<h1>View Game Data</h1>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="form">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Application ID</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="appID" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Title</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="title" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Developer</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="developer" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Publisher</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="publisher" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Release Date</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="releaseDate" type="date"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Supported OSes</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<span>Windows</span>
|
||||||
|
<input id="win" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span>MacOS</span>
|
||||||
|
<input id="mac" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span>Linux</span>
|
||||||
|
<input id="linux" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Limit Number of Results to:</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="limitNumber" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Order by:</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<select id="orderBy">
|
||||||
|
<option value="ASC">Ascending</option>
|
||||||
|
<option value="DESC">Descending</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col align-content-center">
|
||||||
|
<input id="submitButton" type="submit"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="outputTable" class="container overflow"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer id="footer">
|
||||||
|
<p>Page created by <a href="https://lunarpenguin.net/">Kaj Forney</a>, as work for class (GIMM 285).</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
||||||
|
crossorigin="anonymous" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const isEmpty = (obj) => Object.keys(obj).length === 0;
|
||||||
|
|
||||||
|
document.getElementById('submitButton').addEventListener('click', (event) => {
|
||||||
|
//const formData = new FormData();
|
||||||
|
const getParameters = {};
|
||||||
|
|
||||||
|
if (document.getElementById('appID').value.length !== 0) {
|
||||||
|
//formData.append('appID', document.getElementById('appID').value);
|
||||||
|
getParameters.appID = document.getElementById('appID').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('title').value.length !== 0) {
|
||||||
|
//formData.append('title', document.getElementById('title').value);
|
||||||
|
getParameters.title = document.getElementById('title').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('developer').value.length !== 0) {
|
||||||
|
//formData.append('developer', document.getElementById('developer').value);
|
||||||
|
getParameters.developer = document.getElementById('developer').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('publisher').value.length !== 0) {
|
||||||
|
//formData.append('publisher', document.getElementById('publisher').value);
|
||||||
|
getParameters.publisher = document.getElementById('publisher').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('releaseDate').value.length !== 0) {
|
||||||
|
//formData.append('releaseDate', document.getElementById('releaseDate').value);
|
||||||
|
getParameters.releaseDate = document.getElementById('releaseDate').value;
|
||||||
|
}
|
||||||
|
if (document.querySelector('#win:checked')) {
|
||||||
|
//formData.append('win', 1);
|
||||||
|
getParameters.win = 1;
|
||||||
|
}
|
||||||
|
if (document.querySelector('#mac:checked')) {
|
||||||
|
//formData.append('mac', 1);
|
||||||
|
getParameters.mac = 1;
|
||||||
|
}
|
||||||
|
if (document.querySelector('#linux:checked')) {
|
||||||
|
//formData.append('linux', 1);
|
||||||
|
getParameters.linux = 1;
|
||||||
|
}
|
||||||
|
if (document.getElementById('limitNumber').value.length !== 0) {
|
||||||
|
//formData.append('limitNumber', document.getElementById('limitNumber').value);
|
||||||
|
getParameters.limitNumber = document.getElementById('limitNumber').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('orderBy').value.length !== 0) {
|
||||||
|
//formData.append('orderBy', document.getElementById('orderBy').value);
|
||||||
|
getParameters.orderBy = document.getElementById('orderBy').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Settings for FETCH API request
|
||||||
|
let fetchSettings = {
|
||||||
|
method: 'GET'
|
||||||
|
};
|
||||||
|
|
||||||
|
//Send FETCH API request
|
||||||
|
fetch("http://localhost:8787/games" + (!isEmpty(getParameters) ? '?' + new URLSearchParams(getParameters) : ''), fetchSettings)
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({status, json}) => {
|
||||||
|
if (status === 200) {
|
||||||
|
let displayTable = '<table>' +
|
||||||
|
'<thead>' +
|
||||||
|
'<tr>' +
|
||||||
|
'<th>Edit Game</th>' +
|
||||||
|
'<th>Delete Game</th>' +
|
||||||
|
'<th>AppID</th>' +
|
||||||
|
'<th>Title</th>' +
|
||||||
|
'<th>Developer</th>' +
|
||||||
|
'<th>Publisher</th>' +
|
||||||
|
'<th>Release Date</th> ' +
|
||||||
|
'<th>Supported OSes</th>' +
|
||||||
|
'<th>Summary</th>' +
|
||||||
|
'<th>Cover Art</th>' +
|
||||||
|
'</tr>' +
|
||||||
|
'</thead>' +
|
||||||
|
'<tbody>';
|
||||||
|
|
||||||
|
function osSupport(win, mac, lnx) {
|
||||||
|
let osString = "";
|
||||||
|
if (win == 1) {
|
||||||
|
osString += "Windows, "
|
||||||
|
}
|
||||||
|
;
|
||||||
|
if (mac == 1) {
|
||||||
|
osString += "Mac, "
|
||||||
|
}
|
||||||
|
;
|
||||||
|
if (lnx == 1) {
|
||||||
|
osString += "Linux"
|
||||||
|
}
|
||||||
|
;
|
||||||
|
return osString;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof json.data !== 'undefined') {
|
||||||
|
for (row of json.data) {
|
||||||
|
displayTable += '<tr>' +
|
||||||
|
'<td> <a href="edit.html?id=' + row.appID.toString() + '">Edit</a></td>' +
|
||||||
|
'<td> <a href="delete.html?id=' + row.appID.toString() + '">Delete</a></td>' +
|
||||||
|
'<td>' + row.appID + '</td>' +
|
||||||
|
'<td>' + row.title + '</td>' +
|
||||||
|
'<td>' + row.developer + '</td>' +
|
||||||
|
'<td>' + row.publisher + '</td>' +
|
||||||
|
'<td>' + new Date(row.releaseDate).toDateString() + '</td>' +
|
||||||
|
'<td>' + osSupport(row.win.toString(), row.mac.toString(), row.linux.toString()) + '</td>' +
|
||||||
|
'<td>' + row.summary + '</td>' +
|
||||||
|
'<td> <img class="tableCoverArt" src="http://localhost:8787/images/' + row.coverArt + '"> </td>' +
|
||||||
|
'</tr>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayTable += '</tbody></table>';
|
||||||
|
document.getElementById('outputTable').innerHTML = displayTable;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
309
server/public/insert.html
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Kaj Forney -- GIMM 285 CRUD API Project</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="manifest" href="site.webmanifest">
|
||||||
|
<link rel="apple-touch-icon" href="icon.png">
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#488ea7">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="header" class="container">
|
||||||
|
<h1>Add New Game</h1>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card" id="successMessage"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card" id="errorMessage"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="form">
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Title</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="title" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>
|
||||||
|
Developer
|
||||||
|
<br/>
|
||||||
|
(<a href="insertDeveloper.html">Add New Developer</a>)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<select id="developer">
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>
|
||||||
|
Publisher
|
||||||
|
<br/>
|
||||||
|
(<a href="insertPublisher.html">Add New Publisher</a>)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<select id="publisher">
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Release Date</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="releaseDate" type="date"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Supported OSes</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<span>Windows</span>
|
||||||
|
<input id="win" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span>MacOS</span>
|
||||||
|
<input id="mac" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span>Linux</span>
|
||||||
|
<input id="linux" type="checkbox"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Cover Art</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="coverArt" type="file"
|
||||||
|
accept="image/jpeg, image/png"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Short Description</label>
|
||||||
|
<p>(maximum 300 characters)</p>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textarea id="shortDescription" rows="5" cols="40" maxlength="300"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Long Description</label>
|
||||||
|
<p>(supports <a href="https://www.markdownguide.org/">Markdown</a>) </p>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textarea id="longDescription" rows="15" cols="40"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col align-content-center">
|
||||||
|
<button id="submitButton" type="submit">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer id="footer">
|
||||||
|
<p>Page created by <a href="https://lunarpenguin.net/">Kaj Forney</a>, as work for class (GIMM 285).</p>
|
||||||
|
<p>All example data used is originally from <a href="https://store.steampowered.com/">Steam</a>.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
||||||
|
crossorigin="anonymous" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const isEmpty = (obj) => Object.keys(obj).length === 0;
|
||||||
|
|
||||||
|
document.getElementById("successMessage").hidden = true;
|
||||||
|
document.getElementById("errorMessage").hidden = true;
|
||||||
|
|
||||||
|
fetch("http://localhost:8787/developers", { method: 'GET' })
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({ status, json }) => {
|
||||||
|
if (200 === status) {
|
||||||
|
const developerSelect = document.getElementById('developer');
|
||||||
|
for (dev of json.data) {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.value = dev.id;
|
||||||
|
option.text = dev.name;
|
||||||
|
developerSelect.add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch("http://localhost:8787/publishers", { method: 'GET' })
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({ status, json }) => {
|
||||||
|
if (200 === status) {
|
||||||
|
const publisherSelect = document.getElementById('publisher');
|
||||||
|
for (publisher of json.data) {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.value = publisher.id;
|
||||||
|
option.text = publisher.name;
|
||||||
|
publisherSelect.add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('submitButton').addEventListener('click', (event) => {
|
||||||
|
//const formData = new FormData();
|
||||||
|
const parameters = {};
|
||||||
|
|
||||||
|
if (document.getElementById('title').value.length !== 0) {
|
||||||
|
//formData.append('title', document.getElementById('title').value);
|
||||||
|
parameters.title = document.getElementById('title').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('developer').value.length !== 0) {
|
||||||
|
//formData.append('developer', document.getElementById('developer').value);
|
||||||
|
parameters.developerID = document.getElementById('developer').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('publisher').value.length !== 0) {
|
||||||
|
//formData.append('publisher', document.getElementById('publisher').value);
|
||||||
|
parameters.publisherID = document.getElementById('publisher').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('releaseDate').value.length !== 0) {
|
||||||
|
//formData.append('releaseDate', document.getElementById('releaseDate').value);
|
||||||
|
parameters.releaseDate = document.getElementById('releaseDate').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById('win').checked) {
|
||||||
|
parameters.win = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parameters.win = 0;
|
||||||
|
}
|
||||||
|
if (document.getElementById('mac').checked) {
|
||||||
|
parameters.mac = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parameters.mac = 0;
|
||||||
|
}
|
||||||
|
if (document.getElementById('linux').checked) {
|
||||||
|
parameters.linux = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parameters.linux = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById('shortDescription').value.length !== 0) {
|
||||||
|
parameters.shortDescription = document.getElementById('shortDescription').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('longDescription').value.length !== 0) {
|
||||||
|
parameters.longDescription = document.getElementById('longDescription').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
const coverField = document.querySelector('input[type="file"]');
|
||||||
|
formData.append("coverArt", coverField.files[0]);
|
||||||
|
|
||||||
|
|
||||||
|
//Settings for FETCH API request
|
||||||
|
let fetchSettings = {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
};
|
||||||
|
|
||||||
|
//Send FETCH API request
|
||||||
|
fetch("http://localhost:8787/games" + (!isEmpty(parameters) ? '?' + new URLSearchParams(parameters) : ''), fetchSettings)
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({status, json}) => {
|
||||||
|
if (status === 200) {
|
||||||
|
let message = "Game submission successful!"
|
||||||
|
document.getElementById('successMessage').hidden = false;
|
||||||
|
document.getElementById('successMessage').innerHTML = message;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
148
server/public/insertDeveloper.html
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en-US">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Kaj Forney -- GIMM 285 CRUD API Project</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="manifest" href="site.webmanifest">
|
||||||
|
<link rel="apple-touch-icon" href="icon.png">
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#488ea7">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="header" class="container">
|
||||||
|
<h1>Add New Developer</h1>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="form">
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Name</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="name" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Description</label>
|
||||||
|
<p>(maximum 250 characters)</p>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textarea id="description" rows="5" cols="40" maxlength="250"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Homepage</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="homepage" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-2 align-content-center">
|
||||||
|
<button id="submitButton" type="submit">Submit</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 align-content-center">
|
||||||
|
<button id="backButton">Back</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-8"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card" id="outputMessage"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer id="footer">
|
||||||
|
<p>Page created by <a href="https://lunarpenguin.net/">Kaj Forney</a>, as work for class (GIMM 285).</p>
|
||||||
|
<p>All example data used is originally from <a href="https://store.steampowered.com/">Steam</a>.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
||||||
|
crossorigin="anonymous" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const isEmpty = (obj) => Object.keys(obj).length === 0;
|
||||||
|
|
||||||
|
document.getElementById("outputMessage").hidden = true;
|
||||||
|
|
||||||
|
document.getElementById('backButton').addEventListener('click', (event) => {
|
||||||
|
history.back();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('submitButton').addEventListener('click', (event) => {
|
||||||
|
//const formData = new FormData();
|
||||||
|
const parameters = {};
|
||||||
|
|
||||||
|
if (document.getElementById('name').value.length !== 0) {
|
||||||
|
parameters.name = document.getElementById('name').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('description').value.length !== 0) {
|
||||||
|
parameters.description = document.getElementById('description').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('homepage').value.length !== 0) {
|
||||||
|
parameters.homepage = document.getElementById('homepage').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Settings for FETCH API request
|
||||||
|
let fetchSettings = {
|
||||||
|
method: 'POST',
|
||||||
|
};
|
||||||
|
|
||||||
|
//Send FETCH API request
|
||||||
|
fetch("http://localhost:8787/developers" + (!isEmpty(parameters) ? '?' + new URLSearchParams(parameters) : ''), fetchSettings)
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({status, json}) => {
|
||||||
|
if (status === 200) {
|
||||||
|
let message = "Submission successful!"
|
||||||
|
document.getElementById('outputMessage').hidden = false;
|
||||||
|
document.getElementById('outputMessage').innerHTML = message;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
148
server/public/insertPublisher.html
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en-US">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Kaj Forney -- GIMM 285 CRUD API Project</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="manifest" href="site.webmanifest">
|
||||||
|
<link rel="apple-touch-icon" href="icon.png">
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#488ea7">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="header" class="container">
|
||||||
|
<h1>Add New Publisher</h1>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="form">
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Name</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="name" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Description</label>
|
||||||
|
<p>(maximum 250 characters)</p>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textarea id="description" rows="5" cols="40" maxlength="250"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label>Homepage</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input id="homepage" type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-2 align-content-center">
|
||||||
|
<button id="submitButton" type="submit">Submit</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 align-content-center">
|
||||||
|
<button id="backButton">Back</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-8"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col card" id="outputMessage"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer id="footer">
|
||||||
|
<p>Page created by <a href="https://lunarpenguin.net/">Kaj Forney</a>, as work for class (GIMM 285).</p>
|
||||||
|
<p>All example data used is originally from <a href="https://store.steampowered.com/">Steam</a>.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
||||||
|
crossorigin="anonymous" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const isEmpty = (obj) => Object.keys(obj).length === 0;
|
||||||
|
|
||||||
|
document.getElementById("outputMessage").hidden = true;
|
||||||
|
|
||||||
|
document.getElementById('backButton').addEventListener('click', (event) => {
|
||||||
|
history.back();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('submitButton').addEventListener('click', (event) => {
|
||||||
|
//const formData = new FormData();
|
||||||
|
const parameters = {};
|
||||||
|
|
||||||
|
if (document.getElementById('name').value.length !== 0) {
|
||||||
|
parameters.name = document.getElementById('name').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('description').value.length !== 0) {
|
||||||
|
parameters.description = document.getElementById('description').value;
|
||||||
|
}
|
||||||
|
if (document.getElementById('homepage').value.length !== 0) {
|
||||||
|
parameters.homepage = document.getElementById('homepage').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Settings for FETCH API request
|
||||||
|
let fetchSettings = {
|
||||||
|
method: 'POST',
|
||||||
|
};
|
||||||
|
|
||||||
|
//Send FETCH API request
|
||||||
|
fetch("http://localhost:8787/publishers" + (!isEmpty(parameters) ? '?' + new URLSearchParams(parameters) : ''), fetchSettings)
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve) => response.json()
|
||||||
|
.then((json) => resolve({
|
||||||
|
status: response.status,
|
||||||
|
json,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
})
|
||||||
|
.then(({status, json}) => {
|
||||||
|
if (status === 200) {
|
||||||
|
let message = "Submission successful!"
|
||||||
|
document.getElementById('outputMessage').hidden = false;
|
||||||
|
document.getElementById('outputMessage').innerHTML = message;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
0
server/public/js/main.js
Normal file
3
server/public/js/vendor/modernizr-3.11.2.min.js
vendored
Normal file
5
server/public/robots.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# www.robotstxt.org/
|
||||||
|
|
||||||
|
# Allow crawling of all content
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
1
server/public/site.webmanifest
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"name":"","short_name":"","icons":[{"src":"/icons/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/icons/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|