chore(#8): Initial migration into the new frontend UI
This commit is contained in:
parent
35c8dfd21a
commit
c058835f73
5 changed files with 55 additions and 144 deletions
|
@ -6,6 +6,7 @@ Server:
|
|||
Web:
|
||||
host: 127.0.0.1
|
||||
port: 8000
|
||||
static_folder: frontend/build
|
||||
|
||||
Database:
|
||||
username: foo
|
||||
|
|
25
docs/conf.py
25
docs/conf.py
|
@ -6,29 +6,28 @@
|
|||
# -- Project information -----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
project = 'shortenit'
|
||||
copyright = '2024, Elia el Lazkani'
|
||||
author = 'Elia el Lazkani'
|
||||
release = '0.0.0'
|
||||
project = "shortenit"
|
||||
copyright = "2024, Elia el Lazkani"
|
||||
author = "Elia el Lazkani"
|
||||
release = "0.0.0"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx_autodoc_typehints',
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.coverage",
|
||||
"sphinx.ext.viewcode",
|
||||
"sphinx_autodoc_typehints",
|
||||
]
|
||||
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
exclude_patterns = []
|
||||
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
html_theme = 'alabaster'
|
||||
html_static_path = ['_static']
|
||||
html_theme = "alabaster"
|
||||
html_static_path = ["_static"]
|
||||
|
|
|
@ -32,14 +32,14 @@ export default function () {
|
|||
|
||||
// Send the POST request to the backend
|
||||
await axios
|
||||
.post("http://127.0.0.1:8000/shortenit", {
|
||||
.post("http://127.0.0.1:8000/api/v1/shorten", {
|
||||
url: url,
|
||||
timestamp: timestamp,
|
||||
})
|
||||
.then((response) => {
|
||||
if (response) {
|
||||
const code: string = response.data.url;
|
||||
const fullShortenedUrl: string = `http://127.0.0.1:8000/${code}`;
|
||||
const fullShortenedUrl: string = `http://127.0.0.1:8000/r/${code}`;
|
||||
setShortenedUrl(fullShortenedUrl);
|
||||
setShowInput(true);
|
||||
}
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="The personal URL Shortener">
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>ShortenIt</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.4/clipboard.min.js"></script>
|
||||
</head>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var href = window.location.href;
|
||||
|
||||
$(function() {
|
||||
$('#submitButton').click(function() {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/shortenit",
|
||||
data: JSON.stringify({'url' : $('#url-input').val(),
|
||||
'timestamp': Date.now()}),
|
||||
success: returnSuccess,
|
||||
error: returnFailure,
|
||||
dataType: 'json',
|
||||
contentType: "application/json",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function returnSuccess(data, textStatus, jqXHR) {
|
||||
var url = href.concat(data.url);
|
||||
console.log(href)
|
||||
if(data.url) {
|
||||
document.getElementById("url-result").value = url;
|
||||
} else {
|
||||
document.getElementById("url-result").value = "The URL was too short and somehow got lost on the way, please try generating a new one.";
|
||||
}
|
||||
}
|
||||
|
||||
function returnFailure(data, textStatus, jqXHR) {
|
||||
document.getElementById("url-result").value = "Please enter a valid URL!";
|
||||
}
|
||||
|
||||
window.onload=function() {
|
||||
console.log(ClipboardJS.isSupported())
|
||||
var clipboard = new ClipboardJS('.btn', {
|
||||
container: document.getElementById('copy-button')
|
||||
});
|
||||
|
||||
clipboard.on('success', function(e) {
|
||||
console.info('Action:', e.action);
|
||||
console.info('Text:', e.text);
|
||||
console.info('Trigger:', e.trigger);
|
||||
});
|
||||
|
||||
clipboard.on('error', function(e) {
|
||||
console.error('Action:', e.action);
|
||||
console.error('Trigger:', e.trigger);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- Page Content -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h1 class="mt-5">Shorten It!</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 form-group">
|
||||
<div class="form-row">
|
||||
<div class="col-9">
|
||||
<input type="text" class="form-control" name="url" id="url-input" placeholder="https://www.duckduckgo.com" />
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button id="submitButton" type="button" class="btn btn-outline-primary">Shorten URL</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <a href="#" id="url-result">Enter URL</a> -->
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 form-group">
|
||||
<div class="form-row">
|
||||
<div class="col-9">
|
||||
<input type="text" id="url-result" class="form-control" readonly>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div>
|
||||
<button class="btn btn-outline-primary" data-clipboard-target="#url-result" data-clipboard-action="copy">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap core JavaScript -->
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,10 +1,11 @@
|
|||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from flask_cors import CORS
|
||||
|
||||
import trafaret
|
||||
from flask import Flask, abort, redirect, render_template, request
|
||||
from flask import Flask, abort, redirect, request, send_from_directory
|
||||
from flask_cors import CORS
|
||||
|
||||
from .common import check_file
|
||||
|
||||
|
||||
class Web:
|
||||
|
@ -28,12 +29,21 @@ class Web:
|
|||
CORS(self.app)
|
||||
|
||||
def setup_routes(self):
|
||||
self.app.add_url_rule("/", "/", self.handler.index, methods=["GET"])
|
||||
self.app.add_url_rule(
|
||||
"/shortenit", "/shortenit", self.handler.shortenit, methods=["POST"]
|
||||
"/", "/", self.handler.index, methods=["GET"], defaults={"path": ""}
|
||||
)
|
||||
self.app.add_url_rule("/<path:path>", "/", self.handler.index, methods=["GET"])
|
||||
self.app.add_url_rule(
|
||||
"/static/css/<path:path>", "css", self.handler.css, methods=["GET"]
|
||||
)
|
||||
self.app.add_url_rule(
|
||||
"/<identifier>", "/identifier", self.handler.short_redirect, methods=["GET"]
|
||||
"/static/js/<path:path>", "js", self.handler.js, methods=["GET"]
|
||||
)
|
||||
self.app.add_url_rule(
|
||||
"/api/v1/shorten", "shorten", self.handler.shortenit, methods=["POST"]
|
||||
)
|
||||
self.app.add_url_rule(
|
||||
"/r/<identifier>", "redirect", self.handler.short_redirect, methods=["GET"]
|
||||
)
|
||||
|
||||
|
||||
|
@ -75,7 +85,29 @@ class SiteHandler:
|
|||
abort(404)
|
||||
return redirect(url)
|
||||
|
||||
def index(self):
|
||||
return render_template("index.html")
|
||||
def index(self, path):
|
||||
if path != "":
|
||||
return self._fetch_from_directory(path)
|
||||
else:
|
||||
return self._fetch_from_directory("index.html")
|
||||
|
||||
def css(self, path):
|
||||
path = "static/css/" + path
|
||||
return self._fetch_from_directory(path)
|
||||
|
||||
def js(self, path):
|
||||
path = "static/js/" + path
|
||||
return self._fetch_from_directory(path)
|
||||
|
||||
def _fetch_from_directory(self, path):
|
||||
try:
|
||||
project_root = Path(__file__).parent.parent
|
||||
static_folder = (
|
||||
f"{project_root}/" + self.configuration.get("Web")["static_folder"]
|
||||
)
|
||||
if check_file(static_folder + "/" + path):
|
||||
return send_from_directory(static_folder, path)
|
||||
else:
|
||||
abort(404)
|
||||
except:
|
||||
abort(500)
|
||||
|
|
Loading…
Reference in a new issue