Initial LinkLog implementation

This commit is contained in:
Olaf
2026-08-24 14:30:30 +02:00
commit 1c827956c4
50 changed files with 3436 additions and 0 deletions
+62
View File
@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>LinkLog Admin</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/static/style.css" />
</head>
<body>
<header class="site-header">
<div class="container">
<div class="header-row">
<div>
<h1>LinkLog Admin</h1>
<p>Manage users and plugin configuration</p>
</div>
<div class="header-actions">
<a id="admin-login-button" class="login-button" href="/login">Sign in</a>
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
</div>
</div>
</div>
</header>
<main class="container">
<p id="admin-auth-notice" class="auth-notice hidden"></p>
<div id="admin-controls" class="hidden">
<section class="link-item settings-panel">
<h2>Users</h2>
<form id="user-form">
<label>
Username
<input name="username" type="text" required />
</label>
<label>
Email
<input name="email" type="email" required />
</label>
<label>
Password
<input name="password" type="password" minlength="8" required />
</label>
<label class="checkbox-label">
<input name="is_admin" type="checkbox" />
Administrator
</label>
<button type="submit">Add user</button>
<p id="user-status" class="status" role="status"></p>
</form>
<div id="user-list" class="plugin-list" aria-live="polite">Loading users...</div>
</section>
<section class="link-item settings-panel">
<h2>Plugins</h2>
<div id="plugin-list" class="plugin-list" aria-live="polite">Loading plugins...</div>
</section>
</div>
</main>
<script src="/static/logout.js?v=2"></script>
<script src="/static/admin.js?v=2"></script>
</body>
</html>
+51
View File
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>LinkLog Feed</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/static/style.css" />
</head>
<body data-user-filter="{{ user_filter or '' }}">
<header class="site-header">
<div class="container">
<div class="header-row">
<div>
<h1>LinkLog</h1>
<p>Public link feed</p>
</div>
<a class="login-button" href="/login">Sign in</a>
</div>
</div>
</header>
<main class="container">
{% if profile %}
<section class="link-item profile-summary">
<div class="link-header">
<div class="avatar">{{ profile.username[:1].upper() }}</div>
<div class="user-name">{{ profile.username }}</div>
</div>
<p>{{ profile.bio or 'No profile information provided.' }}</p>
</section>
{% endif %}
<section class="toolbar">
<label>
Sort
<select id="sort-select">
<option value="newest">Newest first</option>
<option value="oldest">Oldest first</option>
</select>
</label>
<label>
User filter
<input id="user-filter" type="text" placeholder="alice" />
</label>
</section>
<section id="feed" class="feed" aria-live="polite"></section>
</main>
<script src="/static/feed.js"></script>
</body>
</html>
+34
View File
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Sign in - LinkLog</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/static/style.css" />
</head>
<body>
<header class="site-header">
<div class="container">
<h1>Sign in</h1>
<p>Access your LinkLog settings</p>
</div>
</header>
<main class="container">
<section class="link-item settings-panel">
<form id="login-form">
<label>
Username
<input id="username" name="username" type="text" autocomplete="username" required />
</label>
<label>
Password
<input id="password" name="password" type="password" autocomplete="current-password" required />
</label>
<button type="submit">Sign in</button>
<p id="login-status" class="status" role="status"></p>
</form>
</section>
</main>
<script src="/static/login.js"></script>
</body>
</html>
+71
View File
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>LinkLog Profile</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/static/style.css" />
</head>
<body>
<header class="site-header">
<div class="container">
<div class="header-row">
<h1>Profile</h1>
<div class="header-actions">
<a id="admin-link" class="login-button hidden" href="/admin">Admin</a>
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
</div>
</div>
</div>
</header>
<main class="container">
<p class="auth-notice">Sign in at <a href="/login">/login</a> to manage your settings.</p>
<section class="link-item settings-panel">
<h2>Profile Settings</h2>
<form id="profile-form">
<label>
Username
<output id="username" class="readonly-value">Loading...</output>
</label>
<label>
Email
<input id="email" name="email" type="email" required />
</label>
<label>
Bio
<textarea id="bio" name="bio" rows="4"></textarea>
</label>
<label>
Avatar URL
<input id="avatar-url" name="avatar_url" type="url" value="https://example.com/avatar.png" />
</label>
<button type="submit">Save profile</button>
<p id="profile-status" class="status" role="status"></p>
</form>
</section>
<section class="link-item settings-panel">
<h2>Mastodon</h2>
<form id="mastodon-form">
<label>
Instance
<input id="mastodon-instance" name="instance" type="text" value="mastodon.social" placeholder="mastodon.social" />
</label>
<label>
Access token
<input id="mastodon-access-token" name="access_token" type="password" autocomplete="off" />
</label>
<label>
Post prefix
<input id="mastodon-post-prefix" name="post_prefix" type="text" value="From my #LinkLog: &quot;" />
</label>
<button type="submit">Save Mastodon settings</button>
<p id="mastodon-status" class="status" role="status"></p>
</form>
</section>
</main>
<script src="/static/logout.js?v=2"></script>
<script src="/static/profile.js?v=2"></script>
</body>
</html>