Remove unused templates for newsletter creation, settings, and submissions; update unsubscribe confirmation link; add tests for email templates API.
All checks were successful
CI / test (3.11) (pull_request) Successful in 1m59s
CI / build-image (pull_request) Successful in 2m43s

This commit is contained in:
2025-11-06 11:10:10 +01:00
parent 3a11b00fd5
commit c1e3ce185f
26 changed files with 1921 additions and 1732 deletions

View File

@@ -0,0 +1,68 @@
{% extends "_base.html" %} {% block title %}Admin Dashboard{% endblock %} {%
block heading %}Admin Dashboard{% endblock %} {% block extra_styles %}
<link rel="stylesheet" href="/static/css/admin.css" /> {% endblock %} {% block
content %}
<div id="message"></div>
<div class="stats">
<div class="stat-card">
<h3 id="contact-count">--</h3>
<p>Contact Submissions</p>
</div>
<div class="stat-card">
<h3 id="newsletter-count">--</h3>
<p>Newsletter Subscribers</p>
</div>
<div class="stat-card">
<h3 id="settings-count">--</h3>
<p>App Settings</p>
</div>
</div>
<div class="dashboard-grid">
<div class="dashboard-card">
<h2>Contact Form Submissions</h2>
<p>View and manage contact form submissions from your website visitors.</p>
<a href="/admin/submissions">Manage Submissions</a>
</div>
<div class="dashboard-card">
<h2>Newsletter Subscribers</h2>
<p>
Manage newsletter subscriptions and send newsletters to your subscribers.
</p>
<a href="/admin/newsletter">Manage Subscribers</a>
</div>
<div class="dashboard-card">
<h2>Application Settings</h2>
<p>Configure application settings and environment variables.</p>
<a href="/admin/settings">Manage Settings</a>
</div>
<div class="dashboard-card">
<h2>Create Newsletter</h2>
<p>Create and send newsletters to your subscribers.</p>
<a href="/admin/newsletter/create">Create Newsletter</a>
</div>
<div class="dashboard-card">
<h2>Embeddable Forms</h2>
<p>
Instructions for embedding contact and newsletter forms on other websites.
</p>
<a href="/admin/embeds">View Embed Codes</a>
</div>
</div>
<div class="logout">
<a href="/auth/logout">Logout</a>
</div>
{% endblock %}{% block extra_scripts %}
<script src="/static/js/admin.js"></script>
<script>
// Load stats when page loads
if (typeof window.admin.loadDashboardStats === "function") {
window.admin.loadDashboardStats();
}
</script>
{% endblock %}

View File

@@ -0,0 +1,21 @@
{% extends "_base.html" %} {% block title %}Email Templates{% endblock %} {%
block heading %}Email Templates{% endblock %} {% block extra_styles %}
<link rel="stylesheet" href="/static/css/admin.css" /> {% endblock %} {% block
content %}
<div class="settings-management">
<h2>Newsletter Confirmation Template</h2>
<p>Edit the HTML template used for the newsletter confirmation email.</p>
<div id="message"></div>
<form id="templateForm">
<div class="form-group">
<label for="newsletterTemplate">Template HTML</label>
<textarea id="newsletterTemplate" rows="15" cols="80"></textarea>
</div>
<div class="form-group">
<button class="btn btn-primary" type="submit">Save Template</button>
</div>
</form>
</div>
{% endblock %} {% block extra_scripts %}
<script src="/static/js/admin.js"></script>
{% endblock %}

View File

@@ -0,0 +1,93 @@
{% extends "_base.html" %} {% block title %}Embeddable Forms{% endblock %} {%
block heading %}Embeddable Forms{% endblock %} {% block extra_styles %}
<link rel="stylesheet" href="/static/css/admin.css" /> {% endblock %} {% block
content %}
<div class="settings-management">
<div id="contactForm" style="display: flex; justify-content: space-between">
<div id="contactFormSettings" style="min-height: 300px">
<h2>Contact Form</h2>
<p>
Use the following HTML code to embed the contact form on other websites:
</p>
<div class="embed-config">
<label
>Width: <input id="contactWidth" type="text" value="400"
/></label>
<label
>Height: <input id="contactHeight" type="text" value="600"
/></label>
<button
class="btn btn-primary"
onclick="saveEmbedSetting('embed_contact_width','contactWidth')"
>
Save
</button>
<button
class="btn btn-primary"
onclick="saveEmbedSetting('embed_contact_height','contactHeight')"
>
Save
</button>
</div>
<textarea id="iframeCode" class="iframe-code" readonly></textarea>
<button class="btn btn-secondary" onclick="copyIframeCode()">
Copy Contact Iframe
</button>
</div>
<div id="contactFormPreview"></div>
</div>
</div>
<div class="settings-management">
<div
id="newsletterForm"
style="display: flex; justify-content: space-between"
>
<div id="newsletterFormSettings" style="min-height: 400px">
<h2>Newsletter Subscription Form</h2>
<p>
Use the following HTML code to embed the newsletter subscription form on
other websites:
</p>
<div class="embed-config">
<label
>Width: <input id="newsletterWidth" type="text" value="600"
/></label>
<label
>Height: <input id="newsletterHeight" type="text" value="300"
/></label>
<button
class="btn btn-primary"
onclick="saveEmbedSetting('embed_newsletter_width','newsletterWidth')"
>
Save
</button>
<button
class="btn btn-primary"
onclick="saveEmbedSetting('embed_newsletter_height','newsletterHeight')"
>
Save
</button>
</div>
<textarea
id="iframeNewsletterCode"
class="iframe-code"
readonly
></textarea>
<button class="btn btn-secondary" onclick="copyNewsletterIframeCode()">
Copy Newsletter Iframe
</button>
</div>
<div id="newsletterFormPreview"></div>
</div>
</div>
<div class="settings-management">
<p>
Replace <code>http://your-server-domain</code> with your actual server
domain and port (e.g., https://yourdomain.com).
</p>
</div>
{% endblock %} {% block extra_scripts %}
<script src="/static/js/admin.js"></script>
{% endblock %}
</div>

View File

@@ -0,0 +1,42 @@
{% extends "_base.html" %} {% block title %}Newsletter Subscribers{% endblock %}
{% block heading %}Newsletter Subscribers{% endblock %} {% block extra_styles %}
<link rel="stylesheet" href="/static/css/admin.css" /> {% endblock %} {% block
content %}
<div id="message"></div>
<div class="filters">
<input type="text" id="emailFilter" placeholder="Filter by email..." />
<select id="sortBy">
<option value="subscribed_at">Sort by Date</option>
<option value="email">Sort by Email</option>
</select>
<select id="sortOrder">
<option value="desc">Newest First</option>
<option value="asc">Oldest First</option>
</select>
<button onclick="applyFilters()">Apply Filters</button>
<button onclick="clearFilters()">Clear</button>
</div>
<div id="loading" class="loading">Loading subscribers...</div>
<table id="subscribersTable" class="subscribers-table" style="display: none">
<thead>
<tr>
<th>Email</th>
<th>Subscribed Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="subscribersBody"></tbody>
</table>
<div id="pagination" class="pagination" style="display: none">
<button id="prevBtn" onclick="changePage(currentPage - 1)">Previous</button>
<span id="pageInfo"></span>
<button id="nextBtn" onclick="changePage(currentPage + 1)">Next</button>
</div>
{% endblock %} {% block extra_scripts %}
<script src="/static/js/admin.js"></script>
{% endblock %}

View File

@@ -0,0 +1,98 @@
{% extends "_base.html" %} {% block title %}Create Newsletter{% endblock %} {%
block heading %}Create Newsletter{% endblock %} {% block extra_styles %}
<link rel="stylesheet" href="/static/css/admin.css" /> {% endblock %} {% block
content %}
<div id="message"></div>
<div class="newsletter-stats">
<div class="stat-card">
<h4>Total Subscribers</h4>
<div class="number" id="totalSubscribers">--</div>
</div>
<div class="stat-card">
<h4>Active Subscribers</h4>
<div class="number" id="activeSubscribers">--</div>
</div>
<div class="stat-card">
<h4>Last Sent</h4>
<div class="number" id="lastSent">--</div>
</div>
</div>
<form id="newsletterForm">
<div class="form-section">
<h2>Newsletter Details</h2>
<div class="form-row">
<div class="form-group">
<label for="subject">Subject Line *</label>
<input
type="text"
id="subject"
name="subject"
required
placeholder="Enter newsletter subject"
/>
</div>
<div class="form-group">
<label for="senderName">Sender Name</label>
<input
type="text"
id="senderName"
name="sender_name"
placeholder="Your Name"
/>
</div>
</div>
<div class="form-group">
<label for="content">Content *</label>
<textarea
id="content"
name="content"
required
placeholder="Write your newsletter content here..."
></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="sendDate">Send Date (optional)</label>
<input type="datetime-local" id="sendDate" name="send_date" />
</div>
<div class="form-group">
<label for="status">Status</label>
<select id="status" name="status">
<option value="draft">Draft</option>
<option value="scheduled">Scheduled</option>
<option value="sent">Sent</option>
</select>
</div>
</div>
</div>
<div class="form-section">
<h2>Actions</h2>
<button
type="button"
class="btn btn-secondary"
onclick="previewNewsletter()"
>
Preview
</button>
<button type="button" class="btn btn-primary" onclick="saveDraft()">
Save Draft
</button>
<button type="button" class="btn btn-success" onclick="sendNewsletter()">
Send Newsletter
</button>
<button type="button" class="btn btn-danger" onclick="clearForm()">
Clear
</button>
</div>
</form>
<div id="previewSection" class="newsletter-preview hidden">
<h3>Newsletter Preview</h3>
<div id="previewContent"></div>
</div>
{% endblock %}{% block extra_scripts %}
<script src="/static/js/admin.js"></script>
{% endblock %}

View File

@@ -0,0 +1,59 @@
{% extends "_base.html" %} {% block title %}Settings{% endblock %} {% block
heading %}Application Settings{% endblock %} {% block extra_styles %}
<link rel="stylesheet" href="/static/css/admin.css" />
{% endblock %} {% block content %}
<div class="settings-cards">
{% for category, category_settings in settings.items() %}
<div class="settings-card">
<h2 class="card-title">{{ category }}</h2>
<div class="card-body">
{% for key, value in category_settings.items() %}
<div class="setting"><strong>{{ key }}:</strong> {{ value }}</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="settings-management">
<h2>Dynamic Settings Management</h2>
<div id="message"></div>
<div class="settings-list" id="settingsList">
<p>Loading settings...</p>
</div>
<h3>Add New Setting</h3>
<form id="addSettingForm">
<div class="form-row">
<div class="form-group">
<label for="newKey">Setting Key:</label>
<input
type="text"
id="newKey"
name="key"
required
placeholder="e.g., maintenance_mode"
/>
</div>
<div class="form-group">
<label for="newValue">Setting Value:</label>
<input
type="text"
id="newValue"
name="value"
required
placeholder="e.g., false"
/>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Add Setting</button>
</div>
</div>
</form>
</div>
{% endblock %} {% block extra_scripts %}
<script src="/static/js/admin.js"></script>
{% endblock %}

View File

@@ -0,0 +1,80 @@
{% extends "_base.html" %} {% block title %}Contact Submissions{% endblock %} {%
block heading %}Contact Form Submissions{% endblock %} {% block extra_styles %}
<link rel="stylesheet" href="/static/css/admin.css" />
<style>
.filters {
background: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
}
.filters form {
display: flex;
gap: 10px;
flex-wrap: wrap;
align-items: end;
}
</style>
{% endblock %} {% block content %}
<div id="message"></div>
<div class="filters">
<form id="filterForm">
<div>
<label for="email">Email Filter:</label>
<input
type="text"
id="email"
name="email"
placeholder="Filter by email"
/>
</div>
<div>
<label for="date_from">Date From:</label>
<input type="date" id="date_from" name="date_from" />
</div>
<div>
<label for="date_to">Date To:</label>
<input type="date" id="date_to" name="date_to" />
</div>
<div>
<label for="per_page">Items per page:</label>
<select id="per_page" name="per_page">
<option value="25">25</option>
<option value="50" selected>50</option>
<option value="100">100</option>
</select>
</div>
<button type="submit">Apply Filters</button>
<button type="button" class="clear-btn" onclick="clearFilters()">
Clear
</button>
</form>
</div>
<div id="loading" class="loading" style="display: none">Loading...</div>
<table id="submissionsTable">
<thead>
<tr>
<th data-sort="id">ID</th>
<th data-sort="name">Name</th>
<th data-sort="email">Email</th>
<th data-sort="company">Company</th>
<th>Message</th>
<th data-sort="created_at">Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="submissionsBody">
<tr>
<td colspan="7" class="no-data">Loading submissions...</td>
</tr>
</tbody>
</table>
<div class="pagination" id="pagination"></div>
{% endblock %} {% block extra_scripts %}
<script src="/static/js/admin.js"></script>
{% endblock %}