9e9124ecb0
Build and Deploy / build-and-deploy (push) Successful in 56s
Enables users to set a podcast contact email from the dashboard settings. This email is included in the RSS feed as itunes:owner/itunes:email, which podcast directories like Spotify and Apple Podcasts require for indexing and verification.
172 lines
7.6 KiB
HTML
172 lines
7.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Podstalk — Dashboard</title>
|
|
<link rel="stylesheet" href="https://unpkg.com/neobrutalismcss@latest" />
|
|
<link rel="stylesheet" href="/static/dashboard.css" />
|
|
</head>
|
|
<body>
|
|
<nav class="nb-navbar" role="navigation" aria-label="Main navigation">
|
|
<a href="/" class="nb-navbar-brand" aria-label="Go to homepage">{{.PodcastTitle}}</a>
|
|
<ul class="nb-navbar-nav" role="menubar">
|
|
<li class="nb-navbar-item" role="none">
|
|
<a href="/" class="nb-navbar-link active" role="menuitem" aria-current="page">Dashboard</a>
|
|
</li>
|
|
<li class="nb-navbar-item" role="none">
|
|
<a href="/signout" class="nb-navbar-link" role="menuitem">Sign Out</a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
<div class="container">
|
|
<div id="flash-error" class="flash flash-error hidden"></div>
|
|
<div id="flash-success" class="flash flash-success hidden"></div>
|
|
|
|
<div class="settings-section">
|
|
<h2>Podcast Settings</h2>
|
|
<form method="post" action="/settings" enctype="multipart/form-data">
|
|
<div class="settings-form">
|
|
<div class="form-group form-flex-1">
|
|
<label for="podcast_title">Podcast Title</label>
|
|
<input type="text" id="podcast_title" name="podcast_title" class="nb-input blue"
|
|
value="{{.PodcastTitle}}" />
|
|
</div>
|
|
<div class="form-group form-flex-slug">
|
|
<label for="podcast_slug">URL Slug</label>
|
|
<input type="text" id="podcast_slug" name="podcast_slug" class="nb-input blue"
|
|
value="{{.PodcastSlug}}" placeholder="my-podcast" />
|
|
</div>
|
|
<div class="form-group form-flex-1">
|
|
<label for="podcast_author">Author</label>
|
|
<input type="text" id="podcast_author" name="podcast_author" class="nb-input blue"
|
|
value="{{.PodcastAuthor}}" placeholder="Podcast Host" />
|
|
</div>
|
|
<div class="form-group form-flex-1">
|
|
<label for="podcast_email">Podcast Email</label>
|
|
<input type="email" id="podcast_email" name="podcast_email" class="nb-input blue"
|
|
value="{{.PodcastEmail}}" placeholder="podcast@example.com" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="podcast_image">Podcast Image</label>
|
|
<div class="file-upload">
|
|
<input type="file" id="podcast_image" name="podcast_image" accept="image/*" onchange="updateFileName(this)" />
|
|
<label for="podcast_image" class="nb-button blue file-label">Choose Image</label>
|
|
<span class="file-name" id="podcast_image_name"></span>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<button type="submit" class="nb-button green">Save</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
{{if .PodcastImageURL}}
|
|
<div class="podcast-img-preview">
|
|
<img src="{{.PodcastImageURL}}" alt="Podcast image" />
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="rss-row">
|
|
<span class="rss-label">RSS Feed</span>
|
|
<span id="rss-url-src" hidden>{{.RSSURL}}</span>
|
|
<button class="nb-button blue rss-url-btn" id="rss-url" onclick="copyRSS()"></button>
|
|
</div>
|
|
|
|
<script>
|
|
function updateFileName(input) {
|
|
const span = document.getElementById(input.id + '_name');
|
|
if (span && input.files.length > 0) {
|
|
span.textContent = input.files[0].name;
|
|
}
|
|
}
|
|
|
|
(function() {
|
|
const params = new URLSearchParams(window.location.search);
|
|
const err = params.get('error');
|
|
const ok = params.get('success');
|
|
if (err) {
|
|
const el = document.getElementById('flash-error');
|
|
el.textContent = err.replace(/\+/g, ' ').replace(/%20/g, ' ');
|
|
el.classList.remove('hidden');
|
|
}
|
|
if (ok) {
|
|
const el = document.getElementById('flash-success');
|
|
el.textContent = ok.replace(/\+/g, ' ').replace(/%20/g, ' ');
|
|
el.classList.remove('hidden');
|
|
}
|
|
if (err || ok) {
|
|
window.history.replaceState({}, '', window.location.pathname);
|
|
}
|
|
})();
|
|
|
|
const rssURL = document.getElementById('rss-url-src').textContent;
|
|
const rssBtn = document.getElementById('rss-url');
|
|
rssBtn.textContent = rssURL;
|
|
function copyRSS() {
|
|
navigator.clipboard.writeText(rssURL).then(() => {
|
|
const originalText = rssBtn.textContent;
|
|
rssBtn.textContent = 'Copied!';
|
|
rssBtn.disabled = true;
|
|
setTimeout(() => {
|
|
rssBtn.textContent = originalText;
|
|
rssBtn.disabled = false;
|
|
}, 1500);
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<h2>Episodes</h2>
|
|
|
|
<div class="new-ep-row">
|
|
<a href="/episodes/new" class="nb-button blue">+ New Episode</a>
|
|
<a href="/import" class="nb-button default">Import from RSS</a>
|
|
</div>
|
|
|
|
{{if .Episodes}}
|
|
<div class="nb-table-container">
|
|
<div class="nb-table-header">All Episodes ({{len .Episodes}})</div>
|
|
<table class="nb-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Title</th>
|
|
<th>Image</th>
|
|
<th>Published</th>
|
|
<th>Audio</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{range .Episodes}}
|
|
<tr>
|
|
<td>{{.Title}}</td>
|
|
<td>
|
|
{{if .ImageURL}}<img src="{{.ImageURL}}" class="ep-thumb" />{{else}}—{{end}}
|
|
</td>
|
|
<td>{{.PublishedAt}}</td>
|
|
<td>{{if .AudioPath}}✓{{else}}—{{end}}</td>
|
|
<td>
|
|
<div class="episode-actions">
|
|
<a href="/episodes/edit?id={{.ID}}" class="nb-button default">Edit</a>
|
|
<form method="post" action="/episodes/delete?id={{.ID}}" onsubmit="return confirm('Delete this episode?')">
|
|
<button type="submit" class="nb-button orange">Delete</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{{else}}
|
|
<div class="nb-card">
|
|
<div class="nb-card-content">
|
|
<h4 class="nb-card-title">No episodes yet</h4>
|
|
<p class="nb-card-text">Create your first episode to get started.</p>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</body>
|
|
</html>
|