mirror of
https://github.com/chibicitiberiu/ytsm.git
synced 2024-02-24 05:43:31 +00:00
Added docker support
This commit is contained in:
@ -0,0 +1,21 @@
|
||||
{% extends 'YtManagerApp/controls/modal.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block modal_title %}
|
||||
New folder
|
||||
{% endblock modal_title %}
|
||||
|
||||
{% block modal_content %}
|
||||
<form action="{% url 'modal_create_folder' %}" method="post">
|
||||
{{ block.super }}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal_body %}
|
||||
{% crispy form %}
|
||||
{% endblock modal_body %}
|
||||
|
||||
{% block modal_footer %}
|
||||
<input class="btn btn-primary" type="submit" value="Create">
|
||||
<input class="btn btn-secondary" type="button" value="Cancel" data-dismiss="modal" aria-label="Cancel">
|
||||
{% endblock modal_footer %}
|
@ -0,0 +1,23 @@
|
||||
{% extends 'YtManagerApp/controls/modal.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block modal_title %}
|
||||
Delete folder
|
||||
{% endblock modal_title %}
|
||||
|
||||
{% block modal_content %}
|
||||
<form action="{% url 'modal_delete_folder' object.id %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ block.super }}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal_body %}
|
||||
<p>Are you sure you want to delete folder "{{ object }}" and all its subfolders?</p>
|
||||
{{ form | crispy }}
|
||||
{% endblock modal_body %}
|
||||
|
||||
{% block modal_footer %}
|
||||
<input class="btn btn-danger" type="submit" value="Delete" aria-label="Delete">
|
||||
<input class="btn btn-secondary" type="button" value="Cancel" data-dismiss="modal" aria-label="Cancel">
|
||||
{% endblock modal_footer %}
|
@ -0,0 +1,21 @@
|
||||
{% extends 'YtManagerApp/controls/modal.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block modal_title %}
|
||||
Edit folder
|
||||
{% endblock modal_title %}
|
||||
|
||||
{% block modal_content %}
|
||||
<form action="{% url 'modal_update_folder' form.instance.pk %}" method="post">
|
||||
{{ block.super }}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal_body %}
|
||||
{% crispy form %}
|
||||
{% endblock modal_body %}
|
||||
|
||||
{% block modal_footer %}
|
||||
<input class="btn btn-primary" type="submit" value="Save" aria-label="Save">
|
||||
<input class="btn btn-secondary" type="button" value="Cancel" data-dismiss="modal" aria-label="Cancel">
|
||||
{% endblock modal_footer %}
|
43
app/YtManagerApp/templates/YtManagerApp/controls/modal.html
Normal file
43
app/YtManagerApp/templates/YtManagerApp/controls/modal.html
Normal file
@ -0,0 +1,43 @@
|
||||
{% block modal_stylesheets %}
|
||||
{% endblock %}
|
||||
|
||||
<div id="{{ modal_id }}" class="modal {{ modal_classes }}" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog {{ modal_dialog_classes }}" role="document">
|
||||
<div class="modal-content">
|
||||
{% block modal_content %}
|
||||
|
||||
{% block modal_header_wrapper %}
|
||||
<div class="modal-header">
|
||||
{% block modal_header %}
|
||||
<h5 id="{{ modal_id }}_Title" class="modal-title">
|
||||
{% block modal_title %}{{ modal_title }}{% endblock modal_title %}
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
{% endblock modal_header %}
|
||||
</div>
|
||||
{% endblock modal_header_wrapper %}
|
||||
|
||||
{% block modal_body_wrapper %}
|
||||
<div class="modal-body">
|
||||
{% block modal_body %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock modal_body_wrapper %}
|
||||
|
||||
{% block modal_footer_wrapper %}
|
||||
<div class="modal-footer">
|
||||
<div id="modal-loading-ring" class="loading-dual-ring-small mr-auto" style="display: none;"></div>
|
||||
{% block modal_footer %}
|
||||
{% endblock modal_footer %}
|
||||
</div>
|
||||
{% endblock modal_footer_wrapper %}
|
||||
|
||||
{% endblock modal_content %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block modal_scripts %}
|
||||
{% endblock %}
|
@ -0,0 +1,21 @@
|
||||
{% extends 'YtManagerApp/controls/modal.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block modal_title %}
|
||||
New subscription
|
||||
{% endblock modal_title %}
|
||||
|
||||
{% block modal_content %}
|
||||
<form action="{% url 'modal_create_subscription' %}" method="post">
|
||||
{{ block.super }}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal_body %}
|
||||
{% crispy form %}
|
||||
{% endblock modal_body %}
|
||||
|
||||
{% block modal_footer %}
|
||||
<input class="btn btn-primary" type="submit" value="Create">
|
||||
<input class="btn btn-secondary" type="button" value="Cancel" data-dismiss="modal" aria-label="Cancel">
|
||||
{% endblock modal_footer %}
|
@ -0,0 +1,23 @@
|
||||
{% extends 'YtManagerApp/controls/modal.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block modal_title %}
|
||||
Delete subscription
|
||||
{% endblock modal_title %}
|
||||
|
||||
{% block modal_content %}
|
||||
<form action="{% url 'modal_delete_subscription' object.id %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ block.super }}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal_body %}
|
||||
<p>Are you sure you want to delete subscription "{{ object }}"?</p>
|
||||
{{ form | crispy }}
|
||||
{% endblock modal_body %}
|
||||
|
||||
{% block modal_footer %}
|
||||
<input class="btn btn-danger" type="submit" value="Delete" aria-label="Delete">
|
||||
<input class="btn btn-secondary" type="button" value="Cancel" data-dismiss="modal" aria-label="Cancel">
|
||||
{% endblock modal_footer %}
|
@ -0,0 +1,21 @@
|
||||
{% extends 'YtManagerApp/controls/modal.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block modal_title %}
|
||||
Edit subscription
|
||||
{% endblock modal_title %}
|
||||
|
||||
{% block modal_content %}
|
||||
<form action="{% url 'modal_update_subscription' form.instance.pk %}" method="post">
|
||||
{{ block.super }}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal_body %}
|
||||
{% crispy form %}
|
||||
{% endblock modal_body %}
|
||||
|
||||
{% block modal_footer %}
|
||||
<input class="btn btn-primary" type="submit" value="Save" aria-label="Save">
|
||||
<input class="btn btn-secondary" type="button" value="Cancel" data-dismiss="modal" aria-label="Cancel">
|
||||
{% endblock modal_footer %}
|
74
app/YtManagerApp/templates/YtManagerApp/index.html
Normal file
74
app/YtManagerApp/templates/YtManagerApp/index.html
Normal file
@ -0,0 +1,74 @@
|
||||
{% extends "YtManagerApp/master_default.html" %}
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
|
||||
<script>
|
||||
{% include 'YtManagerApp/js/index.js' %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div id="modal-wrapper">
|
||||
<div id="modal-loading" class="black-overlay">
|
||||
<div class="loading-dual-ring loading-dual-ring-center-screen"></div>
|
||||
</div>
|
||||
|
||||
<div id="modal-wrapper">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-3">
|
||||
{# Tree toolbar #}
|
||||
<div class="btn-toolbar" role="toolbar" aria-label="Subscriptions toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button id="btn_create_sub" type="button" class="btn btn-secondary" >
|
||||
<span class="typcn typcn-plus" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button id="btn_create_folder" type="button" class="btn btn-secondary">
|
||||
<span class="typcn typcn-folder-add" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button id="btn_edit_node" type="button" class="btn btn-secondary" >
|
||||
<span class="typcn typcn-edit" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button id="btn_delete_node" type="button" class="btn btn-secondary" >
|
||||
<span class="typcn typcn-trash" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tree-wrapper">
|
||||
<div class="d-flex">
|
||||
<div class="loading-dual-ring mx-auto my-5"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-9">
|
||||
{# Video toolbar #}
|
||||
<div class="btn-toolbar" role="toolbar" aria-label="Subscriptions toolbar">
|
||||
{% crispy filter_form %}
|
||||
</div>
|
||||
|
||||
<div id="videos-wrapper">
|
||||
</div>
|
||||
|
||||
<div id="videos-loading" style="display: none">
|
||||
<div class="d-flex">
|
||||
<div class="loading-dual-ring mx-auto my-5"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,9 @@
|
||||
{% extends "YtManagerApp/master_default.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<h1>Hello</h1>
|
||||
<h2>Please log in to continue</h2>
|
||||
|
||||
{% endblock %}
|
61
app/YtManagerApp/templates/YtManagerApp/index_videos.html
Normal file
61
app/YtManagerApp/templates/YtManagerApp/index_videos.html
Normal file
@ -0,0 +1,61 @@
|
||||
{% load humanize %}
|
||||
{% load ratings %}
|
||||
|
||||
<div class="video-gallery container-fluid">
|
||||
<div class="row">
|
||||
{% for video in videos %}
|
||||
<div class="card-wrapper col-12 col-sm-6 col-lg-4 col-xl-3 d-flex align-items-stretch">
|
||||
<div class="card mx-auto">
|
||||
<img class="card-img-top" src="{{ video.icon_best }}" alt="Thumbnail">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
{% if not video.watched %}
|
||||
<sup class="badge badge-primary">New</sup>
|
||||
{% endif %}
|
||||
{{ video.name }}
|
||||
</h5>
|
||||
<p class="card-text small text-muted">
|
||||
<span>{{ video.views | intcomma }} views</span>
|
||||
<span>•</span>
|
||||
<span>{{ video.publish_date | naturaltime }}</span>
|
||||
</p>
|
||||
<p class="card-text">{{ video.description | truncatechars:120 }}</p>
|
||||
</div>
|
||||
<div class="card-footer dropdown show">
|
||||
<span class="typcn typcn-eye {{ video.watched | yesno:"video-icon-yes,video-icon-no" }}"
|
||||
title="{{ video.watched | yesno:"Watched,Not watched" }}"></span>
|
||||
<span class="typcn typcn-download {{ video.downloaded_path | yesno:"video-icon-yes,,video-icon-no" }}"
|
||||
title="{{ video.downloaded_path | yesno:"Downloaded,,Not downloaded" }}"></span>
|
||||
<small class="text-muted">{{ video.publish_date }}</small>
|
||||
<a class="card-more float-right text-muted"
|
||||
href="#" role="button" id="dropdownMenuLink"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="typcn typcn-cog"></span>
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
|
||||
{% if video.watched %}
|
||||
<a class="dropdown-item ajax-link" href="#" data-post-url="{% url 'ajax_action_mark_video_unwatched' video.id %}">
|
||||
Mark not watched
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="dropdown-item ajax-link" href="#" data-post-url="{% url 'ajax_action_mark_video_watched' video.id %}">
|
||||
Mark watched
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if video.downloaded_path %}
|
||||
<a class="dropdown-item ajax-link" href="#" data-post-url="{% url 'ajax_action_delete_video_files' video.id %}">
|
||||
Delete downloaded
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="dropdown-item ajax-link" href="#" data-post-url="{% url 'ajax_action_download_video_files' video.id %}" >
|
||||
Download
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
185
app/YtManagerApp/templates/YtManagerApp/js/common.js
Normal file
185
app/YtManagerApp/templates/YtManagerApp/js/common.js
Normal file
@ -0,0 +1,185 @@
|
||||
class AjaxModal
|
||||
{
|
||||
constructor(url)
|
||||
{
|
||||
this.wrapper = $("#modal-wrapper");
|
||||
this.loading = $("#modal-loading");
|
||||
this.url = url;
|
||||
this.modal = null;
|
||||
this.form = null;
|
||||
this.submitCallback = null;
|
||||
this.modalLoadingRing = null;
|
||||
}
|
||||
|
||||
setSubmitCallback(callback) {
|
||||
this.submitCallback = callback;
|
||||
}
|
||||
|
||||
_showLoading() {
|
||||
this.loading.fadeIn(500);
|
||||
}
|
||||
|
||||
_hideLoading() {
|
||||
this.loading.fadeOut(100);
|
||||
}
|
||||
|
||||
_showModal() {
|
||||
if (this.modal != null)
|
||||
this.modal.modal();
|
||||
}
|
||||
|
||||
_hideModal() {
|
||||
if (this.modal != null)
|
||||
this.modal.modal('hide');
|
||||
}
|
||||
|
||||
_load(result) {
|
||||
this.wrapper.html(result);
|
||||
|
||||
this.modal = this.wrapper.find('.modal');
|
||||
this.form = this.wrapper.find('form');
|
||||
this.modalLoadingRing = this.wrapper.find('#modal-loading-ring');
|
||||
|
||||
let pThis = this;
|
||||
this.form.submit(function(e) {
|
||||
pThis._submit(e);
|
||||
})
|
||||
}
|
||||
|
||||
_loadFailed() {
|
||||
this.wrapper.html('<div class="alert alert-danger">An error occurred while displaying the dialog!</div>');
|
||||
}
|
||||
|
||||
_submit(e) {
|
||||
let pThis = this;
|
||||
let url = this.form.attr('action');
|
||||
$.post(url, this.form.serialize())
|
||||
.done(function(result) {
|
||||
pThis._submitDone(result);
|
||||
})
|
||||
.fail(function() {
|
||||
pThis._submitFailed();
|
||||
})
|
||||
.always(function() {
|
||||
pThis.modalLoadingRing.fadeOut(100);
|
||||
pThis.wrapper.find(":input").prop("disabled", false);
|
||||
});
|
||||
|
||||
this.modalLoadingRing.fadeIn(200);
|
||||
this.wrapper.find(":input").prop("disabled", true);
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
_submitDone(result) {
|
||||
// Clear old errors first
|
||||
this.form.find('.modal-field-error').remove();
|
||||
|
||||
if (!result.hasOwnProperty('success')) {
|
||||
this._submitInvalidResponse();
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.success) {
|
||||
this._hideModal();
|
||||
if (this.submitCallback != null)
|
||||
this.submitCallback();
|
||||
}
|
||||
else {
|
||||
if (!result.hasOwnProperty('errors')) {
|
||||
this._submitInvalidResponse();
|
||||
return;
|
||||
}
|
||||
|
||||
for (let field in result.errors)
|
||||
if (result.errors.hasOwnProperty(field))
|
||||
{
|
||||
let errorsArray = result.errors[field];
|
||||
let errorsConcat = "<div class=\"alert alert-danger modal-field-error\"><ul>";
|
||||
|
||||
for(let error of errorsArray) {
|
||||
errorsConcat += `<li>${error.message}</li>`;
|
||||
}
|
||||
errorsConcat += '</ul></div>';
|
||||
|
||||
if (field === '__all__')
|
||||
this.form.find('.modal-body').append(errorsConcat);
|
||||
else
|
||||
this.form.find(`[name='${field}']`).after(errorsConcat);
|
||||
}
|
||||
|
||||
let errorsHtml = '';
|
||||
|
||||
let err = this.modal.find('#__modal_error');
|
||||
if (err.length) {
|
||||
err.html('An error occurred');
|
||||
}
|
||||
else {
|
||||
this.modal.find('.modal-body').append(errorsHtml)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_submitFailed() {
|
||||
// Clear old errors first
|
||||
this.form.find('.modal-field-error').remove();
|
||||
this.form.find('.modal-body')
|
||||
.append(`<div class="alert alert-danger modal-field-error">An error occurred while processing request!</div>`);
|
||||
}
|
||||
|
||||
_submitInvalidResponse() {
|
||||
// Clear old errors first
|
||||
this.form.find('.modal-field-error').remove();
|
||||
this.form.find('.modal-body')
|
||||
.append(`<div class="alert alert-danger modal-field-error">Invalid server response!</div>`);
|
||||
}
|
||||
|
||||
loadAndShow()
|
||||
{
|
||||
let pThis = this;
|
||||
this._showLoading();
|
||||
|
||||
$.get(this.url)
|
||||
.done(function (result) {
|
||||
pThis._load(result);
|
||||
pThis._showModal();
|
||||
})
|
||||
.fail(function () {
|
||||
pThis._loadFailed();
|
||||
})
|
||||
.always(function() {
|
||||
pThis._hideLoading();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function syncNow() {
|
||||
$.post("{% url 'ajax_action_sync_now' %}", {
|
||||
csrfmiddlewaretoken: '{{ csrf_token }}'
|
||||
});
|
||||
}
|
||||
|
||||
function ajaxLink_Clicked() {
|
||||
let url_post = $(this).data('post-url');
|
||||
let url_get = $(this).data('get-url');
|
||||
|
||||
if (url_post != null) {
|
||||
$.post(url_post, {
|
||||
csrfmiddlewaretoken: '{{ csrf_token }}'
|
||||
});
|
||||
}
|
||||
else if (url_get != null) {
|
||||
$.get(url_get, {
|
||||
csrfmiddlewaretoken: '{{ csrf_token }}'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Initialization
|
||||
///
|
||||
$(document).ready(function ()
|
||||
{
|
||||
$(".ajax-link").on("click", ajaxLink_Clicked);
|
||||
$("#btn_sync_now").on("click", syncNow);
|
||||
});
|
189
app/YtManagerApp/templates/YtManagerApp/js/index.js
Normal file
189
app/YtManagerApp/templates/YtManagerApp/js/index.js
Normal file
@ -0,0 +1,189 @@
|
||||
function treeNode_Edit()
|
||||
{
|
||||
let selectedNodes = $("#tree-wrapper").jstree('get_selected', true);
|
||||
if (selectedNodes.length === 1)
|
||||
{
|
||||
let node = selectedNodes[0];
|
||||
|
||||
if (node.type === 'folder') {
|
||||
let id = node.id.replace('folder', '');
|
||||
let modal = new AjaxModal("{% url 'modal_update_folder' 98765 %}".replace('98765', id));
|
||||
modal.setSubmitCallback(tree_Refresh);
|
||||
modal.loadAndShow();
|
||||
}
|
||||
else {
|
||||
let id = node.id.replace('sub', '');
|
||||
let modal = new AjaxModal("{% url 'modal_update_subscription' 98765 %}".replace('98765', id));
|
||||
modal.setSubmitCallback(tree_Refresh);
|
||||
modal.loadAndShow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function treeNode_Delete()
|
||||
{
|
||||
let selectedNodes = $("#tree-wrapper").jstree('get_selected', true);
|
||||
if (selectedNodes.length === 1)
|
||||
{
|
||||
let node = selectedNodes[0];
|
||||
|
||||
if (node.type === 'folder') {
|
||||
let id = node.id.replace('folder', '');
|
||||
let modal = new AjaxModal("{% url 'modal_delete_folder' 98765 %}".replace('98765', id));
|
||||
modal.setSubmitCallback(tree_Refresh);
|
||||
modal.loadAndShow();
|
||||
}
|
||||
else {
|
||||
let id = node.id.replace('sub', '');
|
||||
let modal = new AjaxModal("{% url 'modal_delete_subscription' 98765 %}".replace('98765', id));
|
||||
modal.setSubmitCallback(tree_Refresh);
|
||||
modal.loadAndShow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function tree_Initialize()
|
||||
{
|
||||
let treeWrapper = $("#tree-wrapper");
|
||||
treeWrapper.jstree({
|
||||
core : {
|
||||
data : {
|
||||
url : "{% url 'ajax_get_tree' %}"
|
||||
},
|
||||
check_callback : tree_ValidateChange,
|
||||
themes : {
|
||||
dots : false
|
||||
},
|
||||
},
|
||||
types : {
|
||||
folder : {
|
||||
icon : "typcn typcn-folder"
|
||||
},
|
||||
sub : {
|
||||
icon : "typcn typcn-user",
|
||||
max_depth : 0
|
||||
}
|
||||
},
|
||||
plugins : [ "types", "wholerow", "dnd" ]
|
||||
});
|
||||
treeWrapper.on("changed.jstree", tree_OnSelectionChanged);
|
||||
}
|
||||
|
||||
function tree_Refresh()
|
||||
{
|
||||
$("#tree-wrapper").jstree("refresh");
|
||||
}
|
||||
|
||||
function tree_ValidateChange(operation, node, parent, position, more)
|
||||
{
|
||||
if (more.dnd)
|
||||
{
|
||||
// create_node, rename_node, delete_node, move_node and copy_node
|
||||
if (operation === "copy_node" || operation === "move_node")
|
||||
{
|
||||
if (more.ref.type === "sub")
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function tree_OnSelectionChanged(e, data)
|
||||
{
|
||||
let filterForm = $('#form_video_filter');
|
||||
let filterForm_folderId = filterForm.find('#form_video_filter_folder_id');
|
||||
let filterForm_subId = filterForm.find('#form_video_filter_subscription_id');
|
||||
|
||||
let node = data.instance.get_selected(true)[0];
|
||||
|
||||
// Fill folder/sub fields
|
||||
if (node == null) {
|
||||
filterForm_folderId.val('');
|
||||
filterForm_subId.val('');
|
||||
}
|
||||
else if (node.type === 'folder') {
|
||||
let id = node.id.replace('folder', '');
|
||||
filterForm_folderId.val(id);
|
||||
filterForm_subId.val('');
|
||||
}
|
||||
else {
|
||||
let id = node.id.replace('sub', '');
|
||||
filterForm_folderId.val('');
|
||||
filterForm_subId.val(id);
|
||||
}
|
||||
|
||||
videos_Reload();
|
||||
}
|
||||
|
||||
function videos_Reload()
|
||||
{
|
||||
videos_Submit.call($('#form_video_filter'));
|
||||
}
|
||||
|
||||
let videos_timeout = null;
|
||||
|
||||
function videos_ReloadWithTimer()
|
||||
{
|
||||
clearTimeout(videos_timeout);
|
||||
videos_timeout = setTimeout(function()
|
||||
{
|
||||
videos_Submit.call($('#form_video_filter'));
|
||||
videos_timeout = null;
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function videos_Submit(e)
|
||||
{
|
||||
let loadingDiv = $('#videos-loading');
|
||||
loadingDiv.fadeIn(300);
|
||||
|
||||
let form = $(this);
|
||||
let url = form.attr('action');
|
||||
|
||||
$.post(url, form.serialize())
|
||||
.done(function(result) {
|
||||
$("#videos-wrapper").html(result);
|
||||
$(".ajax-link").on("click", ajaxLink_Clicked);
|
||||
})
|
||||
.fail(function() {
|
||||
$("#videos-wrapper").html('<div class="alert alert-danger">An error occurred while retrieving the video list!</div>');
|
||||
})
|
||||
.always(function() {
|
||||
loadingDiv.fadeOut(100);
|
||||
});
|
||||
|
||||
if (e != null)
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
///
|
||||
/// Initialization
|
||||
///
|
||||
$(document).ready(function ()
|
||||
{
|
||||
tree_Initialize();
|
||||
|
||||
// Subscription toolbar
|
||||
$("#btn_create_sub").on("click", function () {
|
||||
let modal = new AjaxModal("{% url 'modal_create_subscription' %}");
|
||||
modal.setSubmitCallback(tree_Refresh);
|
||||
modal.loadAndShow();
|
||||
});
|
||||
$("#btn_create_folder").on("click", function () {
|
||||
let modal = new AjaxModal("{% url 'modal_create_folder' %}");
|
||||
modal.setSubmitCallback(tree_Refresh);
|
||||
modal.loadAndShow();
|
||||
});
|
||||
$("#btn_edit_node").on("click", treeNode_Edit);
|
||||
$("#btn_delete_node").on("click", treeNode_Delete);
|
||||
|
||||
// Videos filters
|
||||
let filters_form = $("#form_video_filter");
|
||||
filters_form.submit(videos_Submit);
|
||||
filters_form.find('input[name=query]').on('change', videos_ReloadWithTimer);
|
||||
filters_form.find('select[name=sort]').on('change', videos_ReloadWithTimer);
|
||||
filters_form.find('select[name=show_watched]').on('change', videos_ReloadWithTimer);
|
||||
filters_form.find('select[name=show_downloaded]').on('change', videos_ReloadWithTimer);
|
||||
videos_Reload();
|
||||
});
|
76
app/YtManagerApp/templates/YtManagerApp/master_default.html
Normal file
76
app/YtManagerApp/templates/YtManagerApp/master_default.html
Normal file
@ -0,0 +1,76 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>{% block title %}YouTube Subscription Manager{% endblock %}</title>
|
||||
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'YtManagerApp/import/typicons/typicons.min.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'YtManagerApp/css/style.css' %}">
|
||||
{% block stylesheets %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
{% include 'YtManagerApp/js/common.js' %}
|
||||
</script>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="{% url 'home' %}">YouTube Manager</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
{% if request.user.is_authenticated %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Welcome,
|
||||
{% if request.user.first_name %}
|
||||
{{ request.user.first_name }}
|
||||
{% else %}
|
||||
{{ request.user.username }}
|
||||
{% endif %}
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="userDropdown">
|
||||
<a class="dropdown-item" href="{% url 'settings' %}">Settings</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="{% url 'logout' %}">Log out</a>
|
||||
</div>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'login' %}">Login</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'register' %}">Register</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
<div id="main_body" class="container-fluid">
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<footer id="main_footer" class="footer bg-light">
|
||||
<span class="ml-auto text-muted">Last synchronized: just now</span>
|
||||
<button id="btn_sync_now" class="btn btn-sm btn-light" title="Synchronize now!">
|
||||
<span class="typcn typcn-arrow-sync" aria-hidden="true"></span>
|
||||
</button>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
12
app/YtManagerApp/templates/YtManagerApp/settings.html
Normal file
12
app/YtManagerApp/templates/YtManagerApp/settings.html
Normal file
@ -0,0 +1,12 @@
|
||||
{% extends "YtManagerApp/master_default.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="container">
|
||||
<h1>Settings</h1>
|
||||
<p>If no value is set, the server's defaults will be used.</p>
|
||||
{% crispy form %}
|
||||
</div>
|
||||
|
||||
{% endblock body %}
|
27
app/YtManagerApp/templates/registration/logged_out.html
Normal file
27
app/YtManagerApp/templates/registration/logged_out.html
Normal file
@ -0,0 +1,27 @@
|
||||
{% extends 'YtManagerApp/master_default.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
|
||||
window.setTimeout(function(){
|
||||
window.location.href = "/";
|
||||
}, 3000);
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="alert-card mx-auto">
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
You have been logged out!
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
44
app/YtManagerApp/templates/registration/login.html
Normal file
44
app/YtManagerApp/templates/registration/login.html
Normal file
@ -0,0 +1,44 @@
|
||||
{% extends 'YtManagerApp/master_default.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{% static 'YtManagerApp/css/login.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="login-card mx-auto">
|
||||
|
||||
{% if next %}
|
||||
{% if user.is_authenticated %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
Your account doesn't have access to this page. To proceed,
|
||||
please login with an account that has access.
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
Please login or register to see this page.
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<h5>Login</h5>
|
||||
|
||||
<form method="post" action="{% url 'login' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="next" value="{{ next }}"/>
|
||||
|
||||
{{ form | crispy }}
|
||||
|
||||
<div class="form-group">
|
||||
<input class="btn btn-primary" type="submit" value="login"/>
|
||||
|
||||
<a class="ml-2" href="{% url 'password_reset' %}">Recover password</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,26 @@
|
||||
{% extends 'YtManagerApp/master_default.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
|
||||
window.setTimeout(function(){
|
||||
window.location.href = "/";
|
||||
}, 5000);
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="alert-card mx-auto">
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
The password has been changed!
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,33 @@
|
||||
{% extends 'YtManagerApp/master_default.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{% static 'YtManagerApp/css/login.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
{% if validlink %}
|
||||
<div class="login-card mx-auto">
|
||||
<h5>Confirm password reset</h5>
|
||||
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{{ form | crispy }}
|
||||
<div class="form-group">
|
||||
<input class="btn btn-primary" type="submit" value="change password"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert-card mx-auto">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
The password reset link was invalid, possibly because it has already been used. Please request a new password reset.
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,28 @@
|
||||
{% extends 'YtManagerApp/master_default.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
|
||||
window.setTimeout(function(){
|
||||
window.location.href = "/";
|
||||
}, 10000);
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="alert-card mx-auto">
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
<p>We've emailed you instructions for resetting your password.</p>
|
||||
<p>If they haven't arrived in a few minutes, check your spam folder.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,2 @@
|
||||
Someone asked for password reset for email {{ email }}. Follow the link below:
|
||||
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
|
@ -0,0 +1,45 @@
|
||||
{% extends 'YtManagerApp/master_default.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{% static 'YtManagerApp/css/login.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="login-card mx-auto">
|
||||
|
||||
{% if next %}
|
||||
{% if user.is_authenticated %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
Your account doesn't have access to this page. To proceed,
|
||||
please login with an account that has access.
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
Please login or register to see this page.
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<h5>Password reset</h5>
|
||||
|
||||
<form method="post" action="{% url 'password_reset' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="next" value="{{ next }}"/>
|
||||
|
||||
{{ form | crispy }}
|
||||
|
||||
<p>If there is any account associated with the given e-mail address,
|
||||
an e-mail will be sent containing the password reset link.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<input class="btn btn-primary" type="submit" value="reset"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
38
app/YtManagerApp/templates/registration/register.html
Normal file
38
app/YtManagerApp/templates/registration/register.html
Normal file
@ -0,0 +1,38 @@
|
||||
{% extends 'YtManagerApp/master_default.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{% static 'YtManagerApp/css/login.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="register-card mx-auto">
|
||||
|
||||
{% if next %}
|
||||
{% if user.is_authenticated %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
Your account doesn't have access to this page. To proceed,
|
||||
please login with an account that has access.
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
Please login or register to see this page.
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if is_first_user %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
Since this is the first user to register, it will be the system administrator.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5>Register</h5>
|
||||
|
||||
{% crispy form %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
27
app/YtManagerApp/templates/registration/register_done.html
Normal file
27
app/YtManagerApp/templates/registration/register_done.html
Normal file
@ -0,0 +1,27 @@
|
||||
{% extends 'YtManagerApp/master_default.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
|
||||
window.setTimeout(function(){
|
||||
window.location.href = "/";
|
||||
}, 3000);
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="alert-card mx-auto">
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
You have registered successfully!
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
Reference in New Issue
Block a user