Work on big refactor

This commit is contained in:
2018-10-13 23:01:45 +03:00
parent ae77251883
commit 1d5c7ea24b
447 changed files with 67198 additions and 1226 deletions

View File

View File

@ -0,0 +1,82 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from django import forms
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth.models import User
from django.contrib.auth.views import LoginView
from django.urls import reverse_lazy
from django.views.generic import FormView, TemplateView
class ExtendedAuthenticationForm(AuthenticationForm):
remember_me = forms.BooleanField(label='Remember me', required=False, initial=False)
def clean(self):
remember_me = self.cleaned_data.get('remember_me')
if remember_me:
expiry = 3600 * 24 * 30
else:
expiry = 0
self.request.session.set_expiry(expiry)
return super().clean()
class ExtendedLoginView(LoginView):
form_class = ExtendedAuthenticationForm
class ExtendedUserCreationForm(UserCreationForm):
email = forms.EmailField(required=False,
label='E-mail address',
help_text='The e-mail address is optional, but it is the only way to recover a lost '
'password.')
first_name = forms.CharField(max_length=30, required=False,
label='First name')
last_name = forms.CharField(max_length=150, required=False,
label='Last name')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.label_class = 'col-3'
self.helper.field_class = 'col-9'
self.helper.form_class = 'form-horizontal'
self.helper.form_method = 'post'
self.helper.form_action = reverse_lazy('register')
self.helper.add_input(Submit('submit', 'register'))
class Meta(UserCreationForm.Meta):
fields = ['username', 'email', 'first_name', 'last_name']
class RegisterView(FormView):
template_name = 'registration/register.html'
form_class = ExtendedUserCreationForm
success_url = reverse_lazy('register_done')
def form_valid(self, form):
is_first_user = (User.objects.count() == 0)
user = form.save()
if is_first_user:
user.is_staff = True
user.is_superuser = True
user.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=password)
login(self.request, user)
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['is_first_user'] = (User.objects.count() == 0)
return context
class RegisterDoneView(TemplateView):
template_name = 'registration/register_done.html'

View File

View File

@ -0,0 +1,34 @@
from django.views.generic import TemplateView
class ModalView(TemplateView):
template_name = 'YtManagerApp/controls/modal.html'
def __init__(self, modal_id='dialog', title='', fade=True, centered=True, small=False, large=False, *args, **kwargs):
super().__init__(*args, **kwargs)
self.id = modal_id
self.title = title
self.fade = fade
self.centered = centered
self.small = small
self.large = large
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
data['modal_id'] = self.id
data['modal_classes'] = ''
if self.fade:
data['modal_classes'] += 'fade '
data['modal_dialog_classes'] = ''
if self.centered:
data['modal_dialog_classes'] += 'modal-dialog-centered '
if self.small:
data['modal_dialog_classes'] += 'modal-sm '
elif self.large:
data['modal_dialog_classes'] += 'modal-lg '
data['modal_title'] = self.title
return data

169
YtManagerApp/views/index.py Normal file
View File

@ -0,0 +1,169 @@
from django.http import HttpRequest, HttpResponseBadRequest, JsonResponse
from django.shortcuts import render
from django import forms
from django.views.generic import CreateView
from YtManagerApp.management.folders import traverse_tree
from YtManagerApp.management.videos import get_videos
from YtManagerApp.models import Subscription, SubscriptionFolder
from YtManagerApp.views.controls.modal import ModalView
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Field
class VideoFilterForm(forms.Form):
CHOICES_SORT = (
('newest', 'Newest'),
('oldest', 'Oldest'),
('playlist', 'Playlist order'),
('playlist_reverse', 'Reverse playlist order'),
('popularity', 'Popularity'),
('rating', 'Top rated'),
)
# Map select values to actual column names
MAPPING_SORT = {
'newest': '-publish_date',
'oldest': 'publish_date',
'playlist': 'playlist_index',
'playlist_reverse': '-playlist_index',
'popularity': '-views',
'rating': '-rating'
}
CHOICES_SHOW_WATCHED = (
('y', 'Watched'),
('n', 'Not watched'),
('all', '(All)')
)
CHOICES_SHOW_DOWNLOADED = (
('y', 'Downloaded'),
('n', 'Not downloaded'),
('all', '(All)')
)
MAPPING_SHOW = {
'y': True,
'n': False,
'all': None
}
query = forms.CharField(label='', required=False)
sort = forms.ChoiceField(label='Sort:', choices=CHOICES_SORT, initial='newest')
show_watched = forms.ChoiceField(label='Show only: ', choices=CHOICES_SHOW_WATCHED, initial='all')
show_downloaded = forms.ChoiceField(label='', choices=CHOICES_SHOW_DOWNLOADED, initial='all')
subscription_id = forms.IntegerField(
required=False,
widget=forms.HiddenInput()
)
folder_id = forms.IntegerField(
required=False,
widget=forms.HiddenInput()
)
def __init__(self, data=None):
super().__init__(data, auto_id='form_video_filter_%s')
self.helper = FormHelper()
self.helper.form_id = 'form_video_filter'
self.helper.form_class = 'form-inline'
self.helper.form_method = 'POST'
self.helper.form_action = 'ajax_index_get_videos'
self.helper.field_class = 'mr-1'
self.helper.label_class = 'ml-2 mr-1 no-asterisk'
self.helper.layout = Layout(
Field('query', placeholder='Search'),
'sort',
'show_watched',
'show_downloaded',
'subscription_id',
'folder_id'
)
def clean_sort(self):
data = self.cleaned_data['sort']
return VideoFilterForm.MAPPING_SORT[data]
def clean_show_downloaded(self):
data = self.cleaned_data['show_downloaded']
return VideoFilterForm.MAPPING_SHOW[data]
def clean_show_watched(self):
data = self.cleaned_data['show_watched']
return VideoFilterForm.MAPPING_SHOW[data]
def __tree_folder_id(fd_id):
if fd_id is None:
return '#'
return 'folder' + str(fd_id)
def __tree_sub_id(sub_id):
if sub_id is None:
return '#'
return 'folder' + str(sub_id)
def index(request: HttpRequest):
if request.user.is_authenticated:
context = {
'filter_form': VideoFilterForm()
}
return render(request, 'YtManagerApp/index.html', context)
else:
return render(request, 'YtManagerApp/index_unauthenticated.html')
def ajax_get_tree(request: HttpRequest):
def visit(node):
if isinstance(node, SubscriptionFolder):
return {
"id": __tree_folder_id(node.id),
"text": node.name,
"type": "folder",
"state": {"opened": True},
"parent": __tree_folder_id(node.parent_id)
}
elif isinstance(node, Subscription):
return {
"id": __tree_sub_id(node.id),
"type": "sub",
"text": node.name,
"icon": node.icon_default,
"parent": __tree_folder_id(node.parent_folder_id)
}
result = traverse_tree(None, request.user, visit)
return JsonResponse(result, safe=False)
def ajax_get_videos(request: HttpRequest):
if request.method == 'POST':
form = VideoFilterForm(request.POST)
if form.is_valid():
videos = get_videos(
user=request.user,
sort_order=form.cleaned_data['sort'],
query=form.cleaned_data['query'],
subscription_id=form.cleaned_data['subscription_id'],
folder_id=form.cleaned_data['folder_id'],
only_watched=form.cleaned_data['show_watched'],
only_downloaded=form.cleaned_data['show_downloaded']
)
context = {
'videos': videos
}
return render(request, 'YtManagerApp/index_videos.html', context)
return HttpResponseBadRequest()
class CreateFolderForm(CreateView, ModalView):
model = SubscriptionFolder
template_name = 'YtManagerApp/controls/folder_create_dialog.html'
fields = ['name', 'parent']

View File

@ -0,0 +1,103 @@
from django.shortcuts import render
from django.http import HttpResponse, HttpRequest, JsonResponse
from YtManagerApp.models import SubscriptionFolder, Subscription
from YtManagerApp.management.management import FolderManager, SubscriptionManager
def get_children_recurse(parent_id):
children = []
for folder in SubscriptionFolder.objects.filter(parent_id=parent_id).order_by('name'):
children.append({
"id": "folder" + str(folder.id),
"text": folder.name,
"type": "folder",
"state": {"opened": True},
"children": get_children_recurse(folder.id)
})
for sub in Subscription.objects.filter(parent_folder_id=parent_id).order_by('name'):
children.append({
"id": "sub" + str(sub.id),
"type": "sub",
"text": sub.name,
"icon": sub.icon_default
})
return children
def get_folders(parent_id, path=""):
folders = []
prefix = path + "/"
if len(path) == 0:
prefix = ""
for folder in SubscriptionFolder.objects.filter(parent_id=parent_id).order_by('name'):
folder_path = prefix + folder.name
folders.append({
"id": folder.id,
"text": folder_path
})
folders.extend(get_folders(folder.id, folder_path))
return folders
def ajax_get_children(request: HttpRequest):
return JsonResponse(get_children_recurse(None), safe=False)
def ajax_get_folders(request: HttpRequest):
return JsonResponse(get_folders(None), safe=False)
def ajax_edit_folder(request: HttpRequest):
if request.method == 'POST':
fid = request.POST['id']
name = request.POST['name']
parent_id = request.POST['parent']
FolderManager.create_or_edit(fid, name, parent_id)
return HttpResponse()
def ajax_delete_folder(request: HttpRequest, fid):
FolderManager.delete(fid)
return HttpResponse()
def ajax_edit_subscription(request: HttpRequest):
if request.method == 'POST':
sid = request.POST['id']
name = request.POST['name']
url = request.POST['url']
parent_id = request.POST['parent']
SubscriptionManager.create_or_edit(sid, url, name, parent_id)
return HttpResponse()
def ajax_delete_subscription(request: HttpRequest, sid):
SubscriptionManager.delete(sid)
return HttpResponse()
def ajax_list_videos(request: HttpRequest):
if request.method == 'POST':
type = request.POST['type']
id = request.POST['id']
context = {}
if type == 'sub':
context['videos'] = SubscriptionManager.list_videos(int(id))
else:
context['videos'] = FolderManager.list_videos(int(id))
return render(request, 'YtManagerApp/index_videos.html', context)
def index(request: HttpRequest):
context = {}
return render(request, 'YtManagerApp/index.html', context)