more polish, add picocss, add more js and web features
This commit is contained in:
parent
a5b6232c77
commit
ce47b12e09
25 changed files with 593 additions and 1862 deletions
9
examples/docker-compose.yml
Normal file
9
examples/docker-compose.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
services:
|
||||
|
||||
db:
|
||||
image: postgres
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_PASSWORD: example
|
||||
POSTGRES_USER: go-urlsh
|
||||
POSTGRES_DB: go-urlsh
|
|
@ -58,6 +58,7 @@ func SetupFiber() error {
|
|||
|
||||
fiberapp.Get("/admin/", web.HandleAdminLinkIndexGet)
|
||||
fiberapp.Get("/admin/links/new", web.HandleAdminLinkNewGet)
|
||||
fiberapp.Get("/admin/links/edit/:id", web.HandleAdminLinkEditGet)
|
||||
|
||||
fiberapp.Static("/admin/", "./web")
|
||||
|
||||
|
|
|
@ -1,22 +1,62 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"codeberg.org/lauralani/go-urlsh/internal/db"
|
||||
"codeberg.org/lauralani/go-urlsh/internal/misc"
|
||||
"codeberg.org/lauralani/go-urlsh/models"
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"log"
|
||||
)
|
||||
|
||||
func HandleAdminLinkNewGet(c *fiber.Ctx) error {
|
||||
return c.Render("add_link", nil)
|
||||
}
|
||||
|
||||
func HandleAdminLinkIndexGet(c *fiber.Ctx) error {
|
||||
var links []models.Link
|
||||
|
||||
err := models.DB.NewSelect().Model(&links).Scan(context.Background())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error querying links: %v", err.Error())
|
||||
func HandleAdminLinkEditGet(c *fiber.Ctx) error {
|
||||
if !db.IsCookieValid(c.Cookies(misc.CookieName, "")) {
|
||||
c.Location("/admin/")
|
||||
c.Status(fiber.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
|
||||
var link = new(models.Link)
|
||||
var id = c.Params("id", "")
|
||||
|
||||
if id == "" {
|
||||
log.Println("[HandleAdminLinkEditGet] no id param given")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "400 Bad Request")
|
||||
}
|
||||
|
||||
err := models.DB.NewSelect().Model(link).Where("id = ?", id).Scan(context.Background())
|
||||
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
log.Printf("[HandleAdminLinkEditGet] Shortlink %v not found\n", id)
|
||||
return fiber.NewError(fiber.StatusNotFound, "404 Not Found")
|
||||
} else {
|
||||
log.Printf("[HandleAdminLinkEditGet] Error querying Shortlink %v from database: %v\n", id, err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error")
|
||||
}
|
||||
}
|
||||
|
||||
return c.Render("edit_link", link)
|
||||
}
|
||||
|
||||
func HandleAdminLinkIndexGet(c *fiber.Ctx) error {
|
||||
if !db.IsCookieValid(c.Cookies(misc.CookieName, "")) {
|
||||
c.Location("/admin/login")
|
||||
c.Status(fiber.StatusSeeOther)
|
||||
return nil
|
||||
} else {
|
||||
var links []models.Link
|
||||
|
||||
err := models.DB.NewSelect().Model(&links).Scan(context.Background())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error querying links: %v", err.Error())
|
||||
}
|
||||
return c.Render("links", links)
|
||||
}
|
||||
return c.Render("links", links)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"codeberg.org/lauralani/go-urlsh/internal/db"
|
||||
"codeberg.org/lauralani/go-urlsh/internal/misc"
|
||||
"codeberg.org/lauralani/go-urlsh/models"
|
||||
"context"
|
||||
|
@ -31,8 +32,14 @@ func HandleAdminLoginPost(c *fiber.Ctx) error {
|
|||
|
||||
if passwordsum == user.PasswordHash {
|
||||
// Passwords match
|
||||
var expires time.Time
|
||||
|
||||
if login.Remember == "on" {
|
||||
expires = time.Now().Add(30 * 24 * time.Hour)
|
||||
} else {
|
||||
expires = time.Now().Add(24 * time.Hour)
|
||||
}
|
||||
|
||||
expires := time.Now().Add(30 * 24 * time.Hour)
|
||||
key := uuid.New().String()
|
||||
dblogin := new(models.Login)
|
||||
|
||||
|
@ -68,5 +75,11 @@ func HandleAdminLoginPost(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
func HandleAdminLoginGet(c *fiber.Ctx) error {
|
||||
return c.Render("login", nil)
|
||||
if db.IsCookieValid(c.Cookies(misc.CookieName, "")) {
|
||||
c.Location("/admin/")
|
||||
c.Status(fiber.StatusSeeOther)
|
||||
return nil
|
||||
} else {
|
||||
return c.Render("login", nil)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,5 @@ type Login struct {
|
|||
type LoginRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Remember string `json:"remember"`
|
||||
}
|
||||
|
|
|
@ -1,53 +1,74 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<title>Add new Shortlink - go-urlsh</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel="stylesheet" href="/admin/style.css">
|
||||
<link rel="stylesheet" href="/admin/pico.min.css">
|
||||
<link rel="stylesheet" href="/admin/custom.css">
|
||||
<script src="/admin/link_add.js" defer></script>
|
||||
<script src="/admin/misc.js" defer></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form action="javascript:void(0);" style="margin-top: 2em">
|
||||
<fieldset id="form_fields">
|
||||
<legend>Add a new Shortlink</legend>
|
||||
<p>* shows a required field</p>
|
||||
<label for="linkname">Shortlink Name (leave empty for random)</label>
|
||||
<input type="text" name="linkname" id="linkname" placeholder="shortlink">
|
||||
<nav class="container-fluid">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/" class="contrast"><strong>go-urlsh</strong></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/">Links</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/apikeys/">API Keys</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: void(0)" >Users (coming soon)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: Logout()" style="color: red;">Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main class="container" style="padding: 0">
|
||||
<form action="javascript:HandleSubmit();" style="margin: 0">
|
||||
<fieldset id="form_fields">
|
||||
<hgroup>
|
||||
<h1>Add new shortlink</h1>
|
||||
<h2><i style="color: red;">*</i> marks required fields</h2>
|
||||
</hgroup>
|
||||
<label for="linkname">Shortlink Name (leave empty for random)</label>
|
||||
<input type="text" name="linkname" id="linkname" placeholder="shortlink">
|
||||
|
||||
<label for="link">Link *</label>
|
||||
<input type="text" name="link" id="link" placeholder="https://" style="width: 97%" onchange="HandleChange()">
|
||||
<label for="link">Link <i style="color: red;">*</i></label>
|
||||
<input type="text" name="link" id="link" placeholder="https://" onchange="HandleChange()">
|
||||
|
||||
<label for="description">Description</label>
|
||||
<input type="text" name="description" id="description" placeholder="" style="width: 97%">
|
||||
<label for="description">Description</label>
|
||||
<input type="text" name="description" id="description" placeholder="">
|
||||
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<input type="submit" id="submit" value="Add" onclick="HandleSubmit()" style="margin-top: 1em;">
|
||||
<input type="submit" id="submit" value="Add" style="margin-top: 1em;">
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<dialog id="dialog-info">
|
||||
<h2 id="dialog-heading"></h2>
|
||||
<p id="dialog-text"></p>
|
||||
<form method="dialog">
|
||||
<button>Close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<dialog id="dialog-info">
|
||||
<h2 id="dialog-heading"></h2>
|
||||
<p id="dialog-text"></p>
|
||||
<form method="dialog">
|
||||
<button>Close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
<footer>
|
||||
<p>go-urlsh - <a href="/">Home</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh" target="_blank">Source Code</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh/src/branch/main/LICENSE" target="_blank">License</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<script src="/admin/link_add.js"></script>
|
||||
|
||||
</main>
|
||||
{{template "partials/footer" .}}
|
||||
</body>
|
||||
|
||||
</html>
|
74
views/edit_link.tmpl
Normal file
74
views/edit_link.tmpl
Normal file
|
@ -0,0 +1,74 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<title>Edit Shortlink - go-urlsh</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel="stylesheet" href="/admin/pico.min.css">
|
||||
<link rel="stylesheet" href="/admin/custom.css">
|
||||
<script src="/admin/link_add.js" defer></script>
|
||||
<script src="/admin/misc.js" defer></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="container-fluid">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/" class="contrast"><strong>go-urlsh</strong></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/">Links</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/apikeys/">API Keys</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: void(0)" >Users (coming soon)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: Logout()" style="color: red;">Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main class="container" style="padding: 0">
|
||||
<form action="javascript:HandleSubmit();" style="margin: 0">
|
||||
<fieldset id="form_fields">
|
||||
<hgroup>
|
||||
<h1>Edit shortlink</h1>
|
||||
<h2><i style="color: red;">*</i> marks required fields</h2>
|
||||
</hgroup>
|
||||
<label for="linkname">Shortlink Name (to change this, delete the shortlink and add it again)</label>
|
||||
<input type="text" name="linkname" id="linkname" value="{{.ID}}" data-tooltip="" readonly>
|
||||
|
||||
<label for="link">Link <i style="color: red;">*</i></label>
|
||||
<input type="text" name="link" id="link" value="{{.URL}}">
|
||||
|
||||
<label for="description">Description</label>
|
||||
<input type="text" name="description" id="description" value="{{.Description}}">
|
||||
|
||||
<div>
|
||||
|
||||
<input type="submit" id="submit" value="Save" style="margin-top: 1em;">
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<dialog id="dialog-info">
|
||||
<h2 id="dialog-heading"></h2>
|
||||
<p id="dialog-text"></p>
|
||||
<form method="dialog">
|
||||
<button>Close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
</form>
|
||||
</main>
|
||||
{{template "partials/footer" .}}
|
||||
</body>
|
||||
|
||||
</html>
|
108
views/links.tmpl
108
views/links.tmpl
|
@ -1,57 +1,77 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<title>Shortlinks - go-urlsh</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel="stylesheet" href="/admin/style.css">
|
||||
<link rel="stylesheet" href="/admin/pico.min.css">
|
||||
<link rel="stylesheet" href="/admin/custom.css">
|
||||
<script src="/admin/links.js" defer></script>
|
||||
<script src="/admin/misc.js" defer></script>
|
||||
|
||||
<style>
|
||||
td { vertical-align: middle; }
|
||||
td {
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a href="/admin/links/new"><button type="button" id="add-new-button">Add new Shortlink</button></a>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Shortlink</th>
|
||||
<th>URL</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .}}
|
||||
<tr>
|
||||
<td><a href="#" onclick="HandleCopy('{{.ID}}')">{{.ID}}</a></td>
|
||||
<td><a href="{{.URL}}" target="_blank">{{.URL}}</a></td>
|
||||
<td style="text-align: right;">
|
||||
<button type="button" id="edit-button" onclick="HandleEdit('{{.ID}}')">
|
||||
Edit
|
||||
</button>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<button type="button" id="delete-button" onclick="HandleDelete('{{.ID}}')">
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<footer>
|
||||
<p>go-urlsh - <a href="/admin/">Home</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh" target="_blank">Source Code</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh/src/branch/main/LICENSE" target="_blank">License</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<script src="/admin/links.js"></script>
|
||||
|
||||
<nav class="container-fluid">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/" class="contrast"><strong>go-urlsh</strong></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/links/new" style="color: greenyellow;">Add new Shortlink</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/apikeys/">API Keys</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: void(0)" >Users (coming soon)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: Logout()" style="color: red;">Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main class="container">
|
||||
<table class="n-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Shortlink</th>
|
||||
<th>URL</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .}}
|
||||
<tr>
|
||||
<td><a href="javascript: HandleCopy('{{.ID}}');" data-tooltip="click to copy">{{.ID}}</a></td>
|
||||
<td><a href="{{.URL}}" target="_blank" {{if .Description}}data-tooltip="{{.Description}}"{{end}}>{{.URL}}</a></td>
|
||||
<td style="text-align: right;">
|
||||
<a href="/admin/links/edit/{{.ID}}">
|
||||
Edit
|
||||
</a>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<a href="javascript: HandleDelete('{{.ID}}');">
|
||||
Delete
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
{{template "partials/footer" .}}
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,22 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<title>Page Title</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel="stylesheet" href="/admin/style.css">
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<title>Login - go-urlsh</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel="stylesheet" href="/admin/pico.min.css">
|
||||
<style>
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h3 id="form-elements">Form elements</h3>
|
||||
<form method="post" action="/admin/login">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" name="username" id="username" placeholder="username">
|
||||
<main class="container">
|
||||
<article class="grid">
|
||||
<div>
|
||||
<hgroup>
|
||||
<h1 style='--color: var(--h1-color); font-weight: var(--font-weight); font-size: var(--font-size); font-family: var(--font-family);'>Sign in</h1>
|
||||
</hgroup>
|
||||
<form method="post" action="/admin/login" style="margin-bottom: 0;" autocomplete="off">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" name="username" id="username" placeholder="Username">
|
||||
|
||||
<label for="password">Password</label>
|
||||
<input type="hidden" name="password" id="password" placeholder="password">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" name="password" id="password" placeholder="*******">
|
||||
|
||||
<input type="submit" value="Login">
|
||||
</form>
|
||||
<fieldset>
|
||||
<label for="remember">
|
||||
<input type="checkbox" role="switch" id="remember" name="remember" />
|
||||
Stay logged in
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<input type="submit" value="Login" class="contrast">
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
8
views/partials/footer.tmpl
Normal file
8
views/partials/footer.tmpl
Normal file
|
@ -0,0 +1,8 @@
|
|||
<footer class="container-fluid">
|
||||
<small>
|
||||
© 2023 Laura Kalb -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh" target="_blank" class="secondary">Source Code</a> -
|
||||
<a href="https://picocss.com" target="_blank" class="secondary">Theme: PicoCSS</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh/src/branch/main/LICENSE" target="_blank" class="secondary">License</a>
|
||||
</small>
|
||||
</footer>
|
|
@ -1,49 +1,74 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<title>Add new Shortlink - go-urlsh</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel="stylesheet" href="/admin/simple.min.css">
|
||||
<link rel="stylesheet" href="/admin/pico.min.css">
|
||||
<link rel="stylesheet" href="/admin/custom.css">
|
||||
<script src="/admin/link_add.js" defer></script>
|
||||
<script src="/admin/misc.js" defer></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form action="javascript:void(0);" style="margin-top: 2em">
|
||||
<fieldset id="form_fields">
|
||||
<legend>Add a new Shortlink</legend>
|
||||
<p>* shows a required field</p>
|
||||
<label for="linkname">Shortlink Name (leave empty for random)</label>
|
||||
<input type="text" name="linkname" id="linkname" placeholder="shortlink">
|
||||
<nav class="container-fluid">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/" class="contrast"><strong>go-urlsh</strong></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/">Links</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/apikeys/">API Keys</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: void(0)" >Users (coming soon)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: Logout()" style="color: red;">Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main class="container" style="padding: 0">
|
||||
<form action="javascript:HandleSubmit();" style="margin: 0">
|
||||
<fieldset id="form_fields">
|
||||
<hgroup>
|
||||
<h1>Add new shortlink</h1>
|
||||
<h2><i style="color: red;">*</i> marks required fields</h2>
|
||||
</hgroup>
|
||||
<label for="linkname">Shortlink Name (leave empty for random)</label>
|
||||
<input type="text" name="linkname" id="linkname" placeholder="shortlink">
|
||||
|
||||
<label for="link">Link *</label>
|
||||
<input type="text" name="link" id="link" placeholder="https://" style="width: 100%" onchange="HandleChange()">
|
||||
<label for="link">Link <i style="color: red;">*</i></label>
|
||||
<input type="text" name="link" id="link" placeholder="https://" onchange="HandleChange()">
|
||||
|
||||
<label for="description">Description</label>
|
||||
<input type="text" name="description" id="description" placeholder="" style="width: 100%">
|
||||
<label for="description">Description</label>
|
||||
<input type="text" name="description" id="description" placeholder="">
|
||||
|
||||
<input type="submit" id="submit" value="Login" onclick="HandleSubmit()" disabled>
|
||||
</fieldset>
|
||||
<div>
|
||||
|
||||
<input type="submit" id="submit" value="Add" style="margin-top: 1em;">
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<dialog id="dialog-info">
|
||||
<h2 id="dialog-heading"></h2>
|
||||
<p id="dialog-text"></p>
|
||||
<form method="dialog">
|
||||
<button>Close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<dialog id="dialog-info">
|
||||
<h2 id="dialog-heading"></h2>
|
||||
<p id="dialog-text"></p>
|
||||
<form method="dialog">
|
||||
<button>Close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
<footer>
|
||||
<p>go-urlsh - <a href="/">Home</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh" target="_blank">Source Code</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh/src/branch/main/LICENSE" target="_blank">License</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<script src="/admin/links.js"></script>
|
||||
|
||||
</main>
|
||||
{{template "partials/footer" .}}
|
||||
</body>
|
||||
|
||||
</html>
|
74
web/custom.css
Normal file
74
web/custom.css
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* Grid */
|
||||
body>main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-height: calc(100vh - 7rem);
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
article {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
article div {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
body>main {
|
||||
padding: 1.25rem 0;
|
||||
}
|
||||
|
||||
article div {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
body>main {
|
||||
padding: 1.5rem 0;
|
||||
}
|
||||
|
||||
article div {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
body>main {
|
||||
padding: 1.75rem 0;
|
||||
}
|
||||
|
||||
article div {
|
||||
padding: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
body>main {
|
||||
padding: 2rem 0;
|
||||
}
|
||||
|
||||
article div {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nav */
|
||||
summary[role="link"].secondary:is([aria-current], :hover, :active, :focus) {
|
||||
background-color: transparent;
|
||||
color: var(--secondary-hover);
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.grid>div:nth-of-type(2) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
body>footer {
|
||||
padding: 1rem 0;
|
||||
}
|
74
web/link_edit.html
Normal file
74
web/link_edit.html
Normal file
|
@ -0,0 +1,74 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<title>Edit Shortlink - go-urlsh</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel="stylesheet" href="/admin/pico.min.css">
|
||||
<link rel="stylesheet" href="/admin/custom.css">
|
||||
<script src="/admin/link_add.js" defer></script>
|
||||
<script src="/admin/misc.js" defer></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="container-fluid">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/" class="contrast"><strong>go-urlsh</strong></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/">Links</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/apikeys/">API Keys</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: void(0)" >Users (coming soon)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: Logout()" style="color: red;">Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main class="container" style="padding: 0">
|
||||
<form action="javascript:HandleSubmit();" style="margin: 0">
|
||||
<fieldset id="form_fields">
|
||||
<hgroup>
|
||||
<h1>Edit shortlink</h1>
|
||||
<h2><i style="color: red;">*</i> marks required fields</h2>
|
||||
</hgroup>
|
||||
<label for="linkname">Shortlink Name (to change this, delete the shortlink and add it again)</label>
|
||||
<input type="text" name="linkname" id="linkname" value="{{.ID}}" data-tooltip="" readonly>
|
||||
|
||||
<label for="link">Link <i style="color: red;">*</i></label>
|
||||
<input type="text" name="link" id="link" value="{{.URL}}">
|
||||
|
||||
<label for="description">Description</label>
|
||||
<input type="text" name="description" id="description" value="{{.Description}}">
|
||||
|
||||
<div>
|
||||
|
||||
<input type="submit" id="submit" value="Save" style="margin-top: 1em;">
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<dialog id="dialog-info">
|
||||
<h2 id="dialog-heading"></h2>
|
||||
<p id="dialog-text"></p>
|
||||
<form method="dialog">
|
||||
<button>Close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
</form>
|
||||
</main>
|
||||
{{template "partials/footer" .}}
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,54 +1,77 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<title>Shortlinks - go-urlsh</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel="stylesheet" href="/admin/style.css">
|
||||
<link rel="stylesheet" href="/admin/pico.min.css">
|
||||
<link rel="stylesheet" href="/admin/custom.css">
|
||||
<script src="/admin/links.js" defer></script>
|
||||
<script src="/admin/misc.js" defer></script>
|
||||
|
||||
<style>
|
||||
td {
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Shortlink</th>
|
||||
<th>URL</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<body>
|
||||
<nav class="container-fluid">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/" class="contrast"><strong>go-urlsh</strong></a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/admin/links/new" style="color: greenyellow;">Add new Shortlink</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/apikeys/">API Keys</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: void(0)" >Users (coming soon)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript: Logout()" style="color: red;">Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main class="container">
|
||||
<table class="n-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Shortlink</th>
|
||||
<th>URL</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .}}
|
||||
<tr>
|
||||
<td><a onclick="HandleCopy('{{.id}}')">{{.ID}}</a></td>
|
||||
<td><a href="{{.URL}}" target="_blank">{{.URL}}</a></td>
|
||||
|
||||
<td>
|
||||
<button type="button" id="edit-button" onclick="HandleEdit('{{.ID}}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" /></svg>
|
||||
</button>
|
||||
<td><a href="javascript: HandleCopy('{{.ID}}');" data-tooltip="click to copy">{{.ID}}</a></td>
|
||||
<td><a href="{{.URL}}" target="_blank" {{if .Description}}data-tooltip="{{.Description}}"{{end}}>{{.URL}}</a></td>
|
||||
<td style="text-align: right;">
|
||||
<a href="/admin/links/edit/{{.ID}}">
|
||||
Edit
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" id="delete-button" onclick="HandleDelete('{{.ID}}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" /></svg>
|
||||
</button>
|
||||
<td style="text-align: right;">
|
||||
<a href="javascript: HandleDelete('{{.ID}}');">
|
||||
Delete
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<footer>
|
||||
<p>go-urlsh - <a href="/">Home</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh" target="_blank">Source Code</a> -
|
||||
<a href="https://codeberg.org/lauralani/go-urlsh/src/branch/main/LICENSE" target="_blank">License</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<script src="/admin/links.js"></script>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
{{template "partials/footer" .}}
|
||||
</body>
|
||||
|
||||
</html>
|
4
web/misc.js
Normal file
4
web/misc.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
function Logout() {
|
||||
document.cookie = 'gourlsh_auth=; Max-Age=-1; path=/; domain=' + location.hostname;
|
||||
document.location = "/admin/login"
|
||||
}
|
5
web/pico.classless.min.css
vendored
Normal file
5
web/pico.classless.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
web/pico.classless.min.css.gz
Normal file
BIN
web/pico.classless.min.css.gz
Normal file
Binary file not shown.
1
web/pico.classless.min.css.map
Normal file
1
web/pico.classless.min.css.map
Normal file
File diff suppressed because one or more lines are too long
BIN
web/pico.classless.min.css.map.gz
Normal file
BIN
web/pico.classless.min.css.map.gz
Normal file
Binary file not shown.
5
web/pico.min.css
vendored
Normal file
5
web/pico.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
web/pico.min.css.gz
Normal file
BIN
web/pico.min.css.gz
Normal file
Binary file not shown.
1
web/pico.min.css.map
Normal file
1
web/pico.min.css.map
Normal file
File diff suppressed because one or more lines are too long
BIN
web/pico.min.css.map.gz
Normal file
BIN
web/pico.min.css.map.gz
Normal file
Binary file not shown.
1689
web/style.css
1689
web/style.css
File diff suppressed because it is too large
Load diff
BIN
web/style.css.gz
BIN
web/style.css.gz
Binary file not shown.
Loading…
Reference in a new issue