Copy to clipboard button flow, and return 404 page if url not found
This commit is contained in:
parent
9ed16ac6cd
commit
de85790ffa
9
api.py
9
api.py
@ -16,8 +16,13 @@ async def root():
|
|||||||
|
|
||||||
@app.get("/{url_id}", status_code=301, response_class=RedirectResponse)
|
@app.get("/{url_id}", status_code=301, response_class=RedirectResponse)
|
||||||
async def redirect_urls(url_id):
|
async def redirect_urls(url_id):
|
||||||
target_url = couch["urls"][url_id].get('full_url')
|
db = couch["urls"]
|
||||||
return RedirectResponse(target_url)
|
if url_id in db:
|
||||||
|
target_url = db[url_id].get('full_url')
|
||||||
|
return RedirectResponse(target_url)
|
||||||
|
else:
|
||||||
|
return RedirectResponse('static/404.html')
|
||||||
|
|
||||||
|
|
||||||
# TODO: Get JWT tokens working and use that to return only the user's urls
|
# TODO: Get JWT tokens working and use that to return only the user's urls
|
||||||
# TODO: Look into how FastAPI handles the Authentication header
|
# TODO: Look into how FastAPI handles the Authentication header
|
||||||
|
@ -32,6 +32,10 @@ GET :host/eecd98
|
|||||||
# Talk directly to CouchDB
|
# Talk directly to CouchDB
|
||||||
###
|
###
|
||||||
|
|
||||||
|
# Get value from key
|
||||||
|
GET http://admin:password@127.0.0.1:5984/_all_dbs
|
||||||
|
:headers
|
||||||
|
|
||||||
# Get value from key
|
# Get value from key
|
||||||
GET http://admin:password@127.0.0.1:5984/urls/_all_docs?include_docs=true
|
GET http://admin:password@127.0.0.1:5984/urls/_all_docs?include_docs=true
|
||||||
:headers
|
:headers
|
||||||
|
10
project.todo
10
project.todo
@ -2,10 +2,10 @@
|
|||||||
#+TODO: TODO INPROGRESS | DONE BACKLOG
|
#+TODO: TODO INPROGRESS | DONE BACKLOG
|
||||||
#+STARTUP: overview
|
#+STARTUP: overview
|
||||||
|
|
||||||
* TODO Move everything into an app directory
|
* DONE Add button to copy shortened URL to clipboard
|
||||||
* TODO Knock out source code TODOs
|
* DONE Add a 404 page in case the URL provided is invalid
|
||||||
* TODO Add button to copy shortened URL to clipboard
|
* TODO RTFM on how to create docker compose files
|
||||||
* TODO Add a 404 page in case the URL provided is invalid
|
* TODO Containerize couchdb
|
||||||
* TODO Get the container running with the Dockerfile
|
* TODO Get the container running with the Dockerfile
|
||||||
* TODO Point zipmy.link to joe-vps
|
* TODO Point zipmy.link to joe-vps
|
||||||
- [ ] Add DNS records
|
- [ ] Add DNS records
|
||||||
@ -14,8 +14,6 @@
|
|||||||
* TODO Create a README.org
|
* TODO Create a README.org
|
||||||
* TODO Add MIT license
|
* TODO Add MIT license
|
||||||
|
|
||||||
* BACKLOG Containerize couchdb
|
|
||||||
* BACKLOG RTFM on how to create docker compose files
|
|
||||||
* BACKLOG RTFM on how to create a container network
|
* BACKLOG RTFM on how to create a container network
|
||||||
* BACKLOG Gitea Actions
|
* BACKLOG Gitea Actions
|
||||||
* BACKLOG Unit tests
|
* BACKLOG Unit tests
|
||||||
|
15
static/404.html
Normal file
15
static/404.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Zip My Link</title>
|
||||||
|
<link rel="stylesheet" href="main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Zip My Link</h1>
|
||||||
|
<h1>404</h1>
|
||||||
|
<p>The shortened URL you provided was not found. Sorry about that!</p>
|
||||||
|
<a href="index.html">zipmy.link</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,20 +1,33 @@
|
|||||||
|
function copyUrlToClipboard() {
|
||||||
|
const urlInput = document.getElementById("url-input");
|
||||||
|
urlInput.select();
|
||||||
|
urlInput.setSelectionRange(0, 99999);
|
||||||
|
navigator.clipboard.writeText(urlInput.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetLinkGeneration() {
|
||||||
|
}
|
||||||
|
|
||||||
async function shortenUrl() {
|
async function shortenUrl() {
|
||||||
const url = document.getElementById("url-input").value;
|
const urlInput = document.getElementById("url-input");
|
||||||
const btn = document.getElementById("submit-btn").value;
|
const btn = document.getElementById("submit-btn");
|
||||||
// btn.enab
|
// btn.enab
|
||||||
const response = await fetch("/api/v1/urls", {
|
const response = await fetch("/api/v1/urls", {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ url: url, username: "anonymous" })
|
body: JSON.stringify({ url: urlInput.value, username: "anonymous" })
|
||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const resultElement = document.getElementById("result");
|
const resultElement = document.getElementById("result");
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
resultElement.textContent = `Shortened Url: ${data.shortenedUrl}`
|
resultElement.textContent = ''
|
||||||
resultElement.style.color = "black";
|
urlInput.value = data.shortenedUrl;
|
||||||
|
btn.innerText = "📋 Copy to Clipboard!";
|
||||||
|
btn.onclick = copyUrlToClipboard;
|
||||||
} else {
|
} else {
|
||||||
resultElement.textContent = `Error: ${data.detail}`
|
resultElement.textContent = `Error: ${data.detail}`
|
||||||
resultElement.style.color = "red";
|
resultElement.style.color = "red";
|
||||||
|
btn.value = "Shorten Url";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user