first commit
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}Account administration | Eternity Project{% endblock %}
|
||||
{% block content %}
|
||||
<section class="editor-wrap">
|
||||
<div class="section-head"><span>ACCOUNT QUEUE</span><span>{{ users|length }} REGISTERED</span></div>
|
||||
<div class="account-table" role="table">
|
||||
<div class="account-row account-head" role="row"><span>HANDLE</span><span>REGISTERED</span><span>MFA</span><span>STATUS</span></div>
|
||||
{% for user in users %}
|
||||
<div class="account-row" role="row">
|
||||
<strong>{{ user.username }}{% if user.role == 'admin' %} <small>ADMIN</small>{% endif %}</strong>
|
||||
<span>{{ user.created_at[:10] }}</span>
|
||||
<span>{{ 'ENABLED' if user.mfa_enabled else 'PENDING' }}</span>
|
||||
<span>{% if user.is_approved %}APPROVED{% elif user.role == 'member' %}<form method="post" action="{{ url_for('approve_user', user_id=user.id) }}"><button class="button compact" type="submit">Approve</button></form>{% else %}ADMIN{% endif %}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,13 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}{{ 'Create account' if mode == 'register' else 'Sign in' }} | Eternity Project{% endblock %}
|
||||
{% block content %}
|
||||
<section class="auth-layout">
|
||||
<div class="auth-copy"><span class="signal-label">MEMBER ACCESS</span><h1>{{ 'Join the circuit.' if mode == 'register' else 'Resume the signal.' }}</h1><p>Accounts let you publish and maintain your own engineering notes.</p></div>
|
||||
<form class="auth-form" method="post">
|
||||
<label>Handle<input name="username" autocomplete="username" required pattern="[a-z0-9_-]{3,32}" placeholder="your-handle"></label>
|
||||
<label>Password<input name="password" type="password" autocomplete="{{ 'new-password' if mode == 'register' else 'current-password' }}" required minlength="10" placeholder="10+ characters"></label>
|
||||
<button class="button" type="submit">{{ 'Create account' if mode == 'register' else 'Sign in' }} <span aria-hidden="true">→</span></button>
|
||||
<p class="form-switch">{% if mode == 'register' %}Already publishing? <a href="{{ url_for('login') }}">Sign in</a>{% else %}New to the project? <a href="{{ url_for('register') }}">Create an account</a>{% endif %}</p>
|
||||
</form>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,48 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Eternity Project: field notes on code, circuits, and systems.">
|
||||
<title>{% block title %}Eternity Project{% endblock %}</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/site.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<a class="brand" href="{{ url_for('index') }}" aria-label="Eternity Project home">
|
||||
<span class="brand-mark" aria-hidden="true"><i></i><i></i><i></i></span>
|
||||
<span><strong>ETERNITY</strong><small>PROJECT / FI</small></span>
|
||||
</a>
|
||||
<nav aria-label="Main navigation">
|
||||
<a href="{{ url_for('index') }}#journal">Journal</a>
|
||||
{% if current_user %}
|
||||
<a href="{{ url_for('write') }}">Write</a>
|
||||
{% if current_user.role == 'admin' %}<a href="{{ url_for('admin_users') }}">Accounts</a>{% endif %}
|
||||
<span class="user-chip">{{ current_user.username }}</span>
|
||||
<form action="{{ url_for('logout') }}" method="post"><button class="text-button" type="submit">Log out</button></form>
|
||||
{% else %}
|
||||
<a href="{{ url_for('login') }}">Sign in</a>
|
||||
<a class="button compact" href="{{ url_for('register') }}">Create account</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% for category, message in messages %}
|
||||
<div class="flash {{ category }}">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<span>ETERNITY PROJECT</span>
|
||||
<span>CODE / CIRCUITS / CONTINUITY</span>
|
||||
<span>HELSINKI, FI</span>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}{{ 'Edit' if post else 'Write' }} | Eternity Project{% endblock %}
|
||||
{% block content %}
|
||||
<section class="editor-wrap"><div class="section-head"><span>{{ 'EDIT TRANSMISSION' if post else 'NEW TRANSMISSION' }}</span><span>AUTHOR / {{ current_user.username }}</span></div>
|
||||
<form class="editor-form" method="post">
|
||||
<label>Title<input name="title" required value="{{ post.title if post else '' }}" placeholder="A clear, useful heading"></label>
|
||||
<div class="two-col"><label>Category<input name="category" value="{{ post.category if post else 'Engineering' }}" placeholder="Engineering"></label><label>Summary<input name="excerpt" required value="{{ post.excerpt if post else '' }}" placeholder="The one-paragraph signal"></label></div>
|
||||
<label>Article<textarea name="body" required rows="16" placeholder="Write in plain text. Paragraph breaks are preserved.">{{ post.body if post else '' }}</textarea></label>
|
||||
<button class="button" type="submit">Publish transmission <span aria-hidden="true">→</span></button>
|
||||
</form>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,27 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<section class="hero">
|
||||
<div class="signal-label">ELECTRONIC FIELD NOTES / 001</div>
|
||||
<h1>Build for the<br><em>long current.</em></h1>
|
||||
<p>Notes from Eternity Project on embedded systems, durable software, and the strange pleasure of making electrons do useful work.</p>
|
||||
<a class="button" href="#journal">Read the journal <span aria-hidden="true">↓</span></a>
|
||||
<div class="scope" aria-hidden="true"><span></span><span></span><span></span><b>∞</b></div>
|
||||
</section>
|
||||
<section class="journal" id="journal">
|
||||
<div class="section-head"><span>THE JOURNAL</span><span>{{ posts|length }} TRANSMISSIONS</span></div>
|
||||
{% if posts %}
|
||||
<div class="post-grid">
|
||||
{% for post in posts %}
|
||||
<article class="post-card">
|
||||
<div class="post-meta"><span>{{ post.category }}</span><time datetime="{{ post.created_at }}">{{ post.created_at[:10] }}</time></div>
|
||||
<h2><a href="{{ url_for('post', slug=post.slug) }}">{{ post.title }}</a></h2>
|
||||
<p>{{ post.excerpt }}</p>
|
||||
<div class="post-foot"><span>BY {{ post.username }}</span><a href="{{ url_for('post', slug=post.slug) }}" aria-label="Read {{ post.title }}">→</a></div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state"><span class="empty-icon">//</span><h2>The signal is quiet.</h2><p>Be the first account to publish a field note.</p>{% if current_user %}<a class="button" href="{{ url_for('write') }}">Write a post</a>{% endif %}</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,21 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}Multi-factor verification | Eternity Project{% endblock %}
|
||||
{% block content %}
|
||||
<section class="auth-layout">
|
||||
<div class="auth-copy">
|
||||
<span class="signal-label">ACCOUNT SECURITY</span>
|
||||
{% if mode == 'setup' %}
|
||||
<h1>Bind your<br>authenticator.</h1>
|
||||
<p>Add this secret to an authenticator app as a time-based one-time password account, then enter its current six-digit code.</p>
|
||||
<code class="mfa-secret">{{ secret }}</code>
|
||||
{% else %}
|
||||
<h1>Confirm the<br>signal.</h1>
|
||||
<p>Open your authenticator application and enter the current code for {{ username }}.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<form class="auth-form" method="post">
|
||||
<label>Authenticator code<input name="code" inputmode="numeric" autocomplete="one-time-code" required pattern="[0-9]{6}" maxlength="6" placeholder="000000"></label>
|
||||
<button class="button" type="submit">Verify account <span aria-hidden="true">→</span></button>
|
||||
</form>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,5 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}{{ post.title }} | Eternity Project{% endblock %}
|
||||
{% block content %}
|
||||
<article class="article"><div class="post-meta"><span>{{ post.category }}</span><time datetime="{{ post.created_at }}">{{ post.created_at[:10] }}</time></div><h1>{{ post.title }}</h1><p class="article-lead">{{ post.excerpt }}</p><div class="byline">WRITTEN BY {{ post.username }}{% if post.updated_at != post.created_at %} / UPDATED {{ post.updated_at[:10] }}{% endif %}</div><div class="article-body">{{ post.body }}</div>{% if current_user and current_user.id == post.author_id %}<a class="button compact" href="{{ url_for('edit_post', slug=post.slug) }}">Edit post</a>{% endif %}</article>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user