summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2023-10-19 03:17:21 -0400
committerCarson Fleming <cflems@cflems.net>2023-10-19 03:17:21 -0400
commitc6d0cd3fca3cc9cacdb4c5a88797d00ae5560841 (patch)
tree061a3a5bbaeb5d99086ddd3a93ba20e6a2667126
parent85f217f63e248ae0df44368a6a0d03620955f170 (diff)
downloadfle.ms-c6d0cd3fca3cc9cacdb4c5a88797d00ae5560841.tar.gz
Dream up a style for the frontend
-rw-r--r--api-routes.js2
-rw-r--r--index.js3
-rw-r--r--routes.js8
-rw-r--r--static/css/mobile.css3
-rw-r--r--static/css/standard.css148
-rw-r--r--static/img/chaos.jpgbin0 -> 665897 bytes
-rw-r--r--static/img/earth.jpgbin0 -> 1612951 bytes
-rw-r--r--static/img/lake.jpgbin0 -> 2353970 bytes
-rw-r--r--static/img/logo.pngbin0 -> 55444 bytes
-rw-r--r--static/index.html34
-rw-r--r--utils.js22
11 files changed, 207 insertions, 13 deletions
diff --git a/api-routes.js b/api-routes.js
index 9f02edb..5c0ed7c 100644
--- a/api-routes.js
+++ b/api-routes.js
@@ -10,7 +10,7 @@ router.all('/', async (req, res) => {
router.put('/:slug', async (req, res) => {
try {
const {url} = req.body;
- const slug = req.params.slug;
+ const slug = req.params.slug.toLowerCase();
if (!utils.isUrlFormatted(url))
return utils.sendBadRequestError(res, 'URL "'+url+'" is malformatted. Must be a valid URL.');
if (!utils.isAlphaNumeric(slug))
diff --git a/index.js b/index.js
index fa848a3..db64231 100644
--- a/index.js
+++ b/index.js
@@ -21,6 +21,9 @@ async function serve() {
app.use(express.urlencoded({extended: true}));
app.use(express.json());
+ app.use('/css', express.static(__dirname+'/static/css'));
+ app.use('/js', express.static(__dirname+'/static/js'));
+ app.use('/img', express.static(__dirname+'/static/img'));
app.use('/api', apiRoutes);
app.use('/', routes);
diff --git a/routes.js b/routes.js
index d07e791..012befe 100644
--- a/routes.js
+++ b/routes.js
@@ -5,14 +5,12 @@ const utils = require('./utils.js');
const router = express.Router();
router.get('/', async (req, res) => {
- res.sendFile('static/index.html', {
- root: path.join(__dirname)
- }, () => utils.sendNotFoundError(res));
+ utils.sendFile(res, 'static/index.html');
});
router.get('/:slug', async (req, res) => {
try {
- const url = await Url.findOne({slug: req.params.slug});
+ const url = await Url.findOne({slug: req.params.slug.toLowerCase()});
if (url)
res.redirect(301, url.url);
else
@@ -24,6 +22,6 @@ router.get('/:slug', async (req, res) => {
router.all('/*', async (req, res) => {
utils.sendNotFoundError(res);
-})
+});
module.exports = router;
diff --git a/static/css/mobile.css b/static/css/mobile.css
new file mode 100644
index 0000000..364d400
--- /dev/null
+++ b/static/css/mobile.css
@@ -0,0 +1,3 @@
+@media screen and (max-width: 700px) {
+
+}
diff --git a/static/css/standard.css b/static/css/standard.css
new file mode 100644
index 0000000..26af287
--- /dev/null
+++ b/static/css/standard.css
@@ -0,0 +1,148 @@
+body,h1,h2,h3,h4,h5,h6,p {
+ margin: 0;
+}
+body {
+ margin: 0rem 8rem;
+ min-height: 100vh;
+ width: calc(100vw - 16rem);
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-attachment: fixed;
+ font-family: var(--cflems-ff-text-primary);
+}
+body.dark {
+ color: #ffffff;
+ background-image:
+ linear-gradient(to top, #000000f0 20%, #00000090 50%, #00000050),
+ url('../img/earth.jpg');
+}
+body.light {
+ color: #000000;
+ background-image:
+ linear-gradient(to bottom, #fffffff0 10%, #ffffff90 50%, #ffffff50),
+ url('../img/lake.jpg');
+}
+#header {
+ padding: 2rem 0;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+ cursor: default;
+ user-select: none;
+}
+#header #logo {
+ padding: 0.25em 0em 0em 1.75em;
+ background-image: url('../img/logo.png');
+ background-repeat: no-repeat;
+ background-size: contain;
+ background-position: left center;
+ flex-grow: 1;
+ font-family: var(--cflems-ff-text-primary);
+ font-size: 3rem;
+}
+#content {
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ height: 100%;
+}
+#content #lhs {
+ padding: 0rem 1rem;
+ flex-grow: 2;
+ background-color: #fcfcfc;
+ margin-right: 2rem;
+ color: #000000;
+ box-shadow: 0px 0px 0.5rem #000000b0;
+ border-radius: 0.25rem;
+ font-size: 16pt;
+ font-family: var(--cflems-ff-text-secondary);
+ font-weight: 400;
+ line-height: 1.5;
+}
+body.light #content #lhs {
+ background-color: #fdfbf9;
+ color: #28282b;
+ box-shadow: 0px 0px 0.5rem #d4d4d7b0;
+}
+body.dark #content #lhs {
+ background-color: #28282b;
+ color: #fdfbf9;
+ box-shadow: #000000b0;
+}
+#content #rhs {
+ flex-grow: 3;
+ font-family: var(--cflems-ff-text-primary);
+ font-size: 14pt;
+}
+.form-element {
+ margin: 1rem 0;
+}
+.form-element p {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: left;
+ margin: 0.25rem 0;
+}
+#base-url {
+ font-family: var(--cflems-ff-text-mono);
+ font-weight: 200;
+ font-size: 14pt;
+ margin: 0 0.25rem 0 0;
+}
+#slug {
+ width: 4.5rem;
+}
+body.dark #shortenButton {
+ background-color: #7550a6;
+ color: #fdfbf9;
+ border: none;
+ box-shadow: none;
+}
+body.dark #shortenButton:hover {
+ background-color: #6f4c9d;
+}
+body.dark #shortenButton:active {
+ background-color: #68369b;
+}
+body.light #shortenButton {
+ background-color: #6a8fd4;
+ color: #fdfbf9;
+ border: none;
+ box-shadow: none;
+}
+body.light #shortenButton:hover {
+ background-color: #6487c9;
+}
+body.light #shortenButton:active {
+ background-color: #5f80be;
+}
+.form-element p .fullsize {
+ flex-grow: 1;
+}
+.form-element input, .form-element button {
+ font-size: 14pt;
+ border-radius: 0.5rem;
+ border-style: solid;
+ border-width: 1px;
+}
+.form-element input[type=text] {
+ font-family: var(--cflems-ff-text-mono);
+ font-weight: 200;
+ padding: 0.33rem;
+}
+body.light .form-element input[type=text], body.light .form-element button {
+ border-color: #28282b;
+}
+body.dark .form-element input[type=text], body.dark .form-element button {
+ border-color: none;
+ /*box-shadow: 0rem 0rem 0.5rem #fdfbf9b0;*/
+}
+.form-element button {
+ font-family: var(--cflems-ff-text-primary);
+ font-weight: 400;
+ padding: 0.75rem;
+ cursor: pointer;
+ user-select: none;
+}
diff --git a/static/img/chaos.jpg b/static/img/chaos.jpg
new file mode 100644
index 0000000..ad8c7f4
--- /dev/null
+++ b/static/img/chaos.jpg
Binary files differ
diff --git a/static/img/earth.jpg b/static/img/earth.jpg
new file mode 100644
index 0000000..e1a8200
--- /dev/null
+++ b/static/img/earth.jpg
Binary files differ
diff --git a/static/img/lake.jpg b/static/img/lake.jpg
new file mode 100644
index 0000000..1539756
--- /dev/null
+++ b/static/img/lake.jpg
Binary files differ
diff --git a/static/img/logo.png b/static/img/logo.png
new file mode 100644
index 0000000..b71c949
--- /dev/null
+++ b/static/img/logo.png
Binary files differ
diff --git a/static/index.html b/static/index.html
index b59e0ef..4deeefb 100644
--- a/static/index.html
+++ b/static/index.html
@@ -2,10 +2,38 @@
<html>
<head>
<meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="canonical" href="https://fle.ms/" />
+ <link rel="icon" type="image/png" href="img/logo.png" />
+ <link rel="stylesheet" type="text/css" href="https://cflems.net/css/fonts.css" />
+ <link rel="stylesheet" type="text/css" href="css/standard.css" />
+ <link rel="stylesheet" type="text/css" href="css/mobile.css" />
<title>fle.ms</title>
</head>
- <body>
- <h1>fle.ms</h1>
- <p>URL Shortener</p>
+ <body class="dark">
+ <div id="header">
+ <h1 id="logo">fle.ms</h1>
+ </div>
+ <div id="content">
+ <div id="lhs">
+ <div class="form-element">
+ <p><label for="url">Paste a Long URL</label></p>
+ <p><input id="url" type="text" placeholder="https://docs.google.com/spreadsheets/d/1SIXl0TxDgaTU49ZOph5s8HA5ZqtEakBCdQkqHzzfhf8/edit" class="fullsize" /></p>
+ </div>
+ <div class="form-element">
+ <p><label for="slug">Customize Short URL</label></p>
+ <p>
+ <label id="base-url" for="slug">fle.ms/</label>
+ <input id="slug" type="text" />
+ </p>
+ </div>
+ <div class="form-element">
+ <p><button id="shortenButton" class="fullsize">Shorten URL</button></p>
+ </div>
+ </div>
+ <div id="rhs">
+ <p>A URL shortener is a thing that does blah blah blah.</p>
+ </div>
+ </div>
</body>
</html>
diff --git a/utils.js b/utils.js
index 7ea6b42..bd03888 100644
--- a/utils.js
+++ b/utils.js
@@ -2,11 +2,25 @@ const path = require('path');
const config = require('./config.js');
const helperFunctions = {
+ sendFile : function (res, fileName) {
+ res.sendFile(fileName, {
+ root: path.join(__dirname)
+ }, err => {
+ if (!err) return;
+ utils.sendNotFoundError(res)
+ });
+ },
sendNotFoundError : function (res) {
- res.status(404).sendFile('static/notfound.html', {root: path.join(__dirname)},
- err => res.json(
- {status: "ERROR", statusCode: 404, errorType: "NOT FOUND", errorMessage: "Not Found"}
- ));
+ if (!res.headersSent) res.status(404);
+ const statusJson = {status: "ERROR", statusCode: 404, errorType: "NOT FOUND", errorMessage: "Not Found"};
+ res.sendFile('static/notfound.html', {root: path.join(__dirname)},
+ err => {
+ if (!err) return;
+
+ console.error('[express] Encountered an error:', err);
+ if (!res.headersSent) res.json(statusJson);
+ else res.send(JSON.stringify(statusJson));
+ });
},
sendBadRequestError : function (res, errorMessage) {
res.status(400).json({status: "ERROR", statusCode: 400, errorType: "BAD REQUEST", errorMessage});