Add feed deletion and single video addition features
- Implemented DELETE /api/channels/<id> to remove channels and cleanup downloaded files - Added delete button to channels page with confirmation dialog - Added functionality to add single videos via URL - Updated navigation menu
This commit is contained in:
55
templates/add_video.html
Normal file
55
templates/add_video.html
Normal file
@@ -0,0 +1,55 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Add Video - YottoB{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="add-video-page">
|
||||
<div class="page-header">
|
||||
<h2>Add Individual Video</h2>
|
||||
<p>Add a specific YouTube video to your library</p>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<form method="POST" action="/add-video" class="channel-form">
|
||||
<div class="form-group">
|
||||
<label for="video_url">YouTube Video URL</label>
|
||||
<input
|
||||
type="url"
|
||||
id="video_url"
|
||||
name="video_url"
|
||||
placeholder="https://www.youtube.com/watch?v=VIDEO_ID"
|
||||
required
|
||||
class="form-input"
|
||||
>
|
||||
<small class="form-help">
|
||||
Enter the full YouTube video URL.
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">Add Video</button>
|
||||
<a href="/" class="btn btn-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="help-section">
|
||||
<h3>How to add a video</h3>
|
||||
<ol>
|
||||
<li>Go to the YouTube video you want to add</li>
|
||||
<li>Copy the URL from your browser's address bar</li>
|
||||
<li>Paste it into the form above</li>
|
||||
<li>Click "Add Video"</li>
|
||||
</ol>
|
||||
|
||||
<h4>Supported URL formats</h4>
|
||||
<ul>
|
||||
<li><code>https://www.youtube.com/watch?v=VIDEO_ID</code></li>
|
||||
<li><code>https://youtu.be/VIDEO_ID</code></li>
|
||||
</ul>
|
||||
|
||||
<h4>Note</h4>
|
||||
<p>YouTube Shorts are not supported and will be rejected.</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -16,6 +16,7 @@
|
||||
<li><a href="/channels" class="{% if request.path == '/channels' %}active{% endif %}">Channels</a></li>
|
||||
<li><a href="/downloads" class="{% if request.path == '/downloads' %}active{% endif %}">Downloads</a></li>
|
||||
<li><a href="/add-channel" class="{% if request.path == '/add-channel' %}active{% endif %}">Add Channel</a></li>
|
||||
<li><a href="/add-video" class="{% if request.path == '/add-video' %}active{% endif %}">Add Video</a></li>
|
||||
<li class="nav-user">
|
||||
<span>{{ current_user.username }}</span>
|
||||
<a href="{{ url_for('logout') }}">Logout</a>
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
<button class="btn btn-secondary" onclick="refreshChannel({{ channel.id }})">
|
||||
Refresh Videos
|
||||
</button>
|
||||
<button class="btn btn-danger" onclick="deleteChannel({{ channel.id }}, '{{ channel.title|replace("'", "\\'") }}')">
|
||||
Delete
|
||||
</button>
|
||||
<a href="/?channel={{ channel.id }}" class="btn btn-link">View Videos</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -71,5 +74,36 @@
|
||||
button.textContent = 'Refresh Videos';
|
||||
});
|
||||
}
|
||||
|
||||
function deleteChannel(channelId, channelTitle) {
|
||||
if (!confirm(`Are you sure you want to delete "${channelTitle}"?\n\nThis will permanently remove:\n- The channel subscription\n- All video history\n- ALL downloaded video files for this channel\n\nThis action cannot be undone.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = event.target;
|
||||
const originalText = button.textContent;
|
||||
button.disabled = true;
|
||||
button.textContent = 'Deleting...';
|
||||
|
||||
fetch(`/api/channels/${channelId}`, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
alert(data.message);
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Failed to delete: ' + data.message);
|
||||
button.disabled = false;
|
||||
button.textContent = originalText;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error: ' + error);
|
||||
button.disabled = false;
|
||||
button.textContent = originalText;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user