diff --git a/comic/migrations/0013_comicstatus_finished.py b/comic/migrations/0013_comicstatus_finished.py new file mode 100644 index 0000000..06c4cd5 --- /dev/null +++ b/comic/migrations/0013_comicstatus_finished.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-04-04 11:28 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('comic', '0012_auto_20160401_0949'), + ] + + operations = [ + migrations.AddField( + model_name='comicstatus', + name='finished', + field=models.BooleanField(default=False), + ), + ] diff --git a/comic/migrations/0014_auto_20160404_1402.py b/comic/migrations/0014_auto_20160404_1402.py new file mode 100644 index 0000000..b458aa2 --- /dev/null +++ b/comic/migrations/0014_auto_20160404_1402.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-04-04 13:02 +from __future__ import unicode_literals + +from django.db import migrations +from django.db.models import Max + +def set_finished(apps, schema_editor): + comicstatus = apps.get_model('comic', 'comicstatus') + comicpage = apps.get_model('comic', 'ComicPage') + for row in comicstatus.objects.all(): + last_page = comicpage.objects.filter(Comic=row.comic).aggregate(Max('index')) + if row.last_read_page == last_page['index__max']: + row.finished = True + row.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('comic', '0013_comicstatus_finished'), + ] + + operations = [ + migrations.RunPython(set_finished, reverse_code=migrations.RunPython.noop), + ] diff --git a/comic/models.py b/comic/models.py index d16ec99..d1fd7cf 100644 --- a/comic/models.py +++ b/comic/models.py @@ -353,5 +353,12 @@ class ComicStatus(models.Model): comic = models.ForeignKey(ComicBook, unique=False, null=False) last_read_page = models.IntegerField(default=0) unread = models.BooleanField(default=True) + finished = models.BooleanField(default=False) + @property + def read(self): + return self.last_read_page + + def __str__(self): + return 'C:{0} P:{1}'.format(self.comic.file_name, self.last_read_page) # TODO: add support to reference items last being read diff --git a/comic/static/css/base.css b/comic/static/css/base.css index 3200523..19fa66d 100644 --- a/comic/static/css/base.css +++ b/comic/static/css/base.css @@ -31,4 +31,12 @@ body { max-height: 300px; overflow: auto; box-shadow: none; + } + + td a { + display:block; + width:100%; + } + tr.clickable-row { + cursor: pointer; } \ No newline at end of file diff --git a/comic/templates/base.html b/comic/templates/base.html index 8293d1d..cacdff5 100644 --- a/comic/templates/base.html +++ b/comic/templates/base.html @@ -73,6 +73,7 @@ + {% block script %} {% endblock %} diff --git a/comic/templates/comic/comic_list.html b/comic/templates/comic/comic_list.html index ec7fe8a..dd367fc 100644 --- a/comic/templates/comic/comic_list.html +++ b/comic/templates/comic/comic_list.html @@ -3,6 +3,24 @@ {% block content %}
+ + + + + + + + + + + + + + + + +

Comics

File/FolderStatus
loading data1/23
+
{% endblock %} {% block script %} {% endblock %} \ No newline at end of file diff --git a/comic/urls.py b/comic/urls.py index e4c4ef9..ad519f3 100644 --- a/comic/urls.py +++ b/comic/urls.py @@ -11,5 +11,7 @@ urlpatterns = [ url(r'^account/$', views.account_page, name='account'), url(r'^read/(?P[\w-]+)/(?P[0-9]+)/$', views.read_comic, name='read_comic'), url(r'^read/(?P[\w-]+)/(?P[0-9]+)/img$', views.get_image, name='get_image'), + url(r'^list_json/$', views.comic_list_json, name='comic_list_json1'), + url(r'^list_json/(?P[\w-]+)/$', views.comic_list_json, name='comic_list_json2'), url(r'^(?P[\w-]+)/$', views.comic_list, name='comic_list'), ] diff --git a/comic/util.py b/comic/util.py index f8f623e..fbc5951 100644 --- a/comic/util.py +++ b/comic/util.py @@ -75,6 +75,20 @@ def generate_breadcrumbs_from_menu(paths): return output +class DirFile: + def __init__(self): + self.name = '' + self.isdir = False + self.icon = '' + self.iscb = False + self.location = '' + self.label = '' + self.cur_page = 0 + + def __str__(self): + return self.name + + def generate_directory(user, directory=False): """ @@ -90,7 +104,7 @@ def generate_directory(user, directory=False): dir_path = '' ordered_dir_list = get_ordered_dir_list(base_dir) for file_name in ordered_dir_list: - df = ComicBook.DirFile() + df = DirFile() df.name = file_name if path.isdir(path.join(base_dir, dir_path, file_name)): if directory: @@ -101,7 +115,8 @@ def generate_directory(user, directory=False): parent__isnull=True) df.isdir = True df.icon = 'glyphicon-folder-open' - df.location = urlsafe_base64_encode(d.selector.bytes) + df.location = '/comic/{0}/'.format(urlsafe_base64_encode(d.selector.bytes).decode()) + df.label = generate_dir_status(user, d) elif file_name.lower()[-4:] in ['.rar', '.zip', '.cbr', '.cbz']: df.iscb = True df.icon = 'glyphicon-book' @@ -114,16 +129,18 @@ def generate_directory(user, directory=False): directory__isnull=True) except ComicBook.DoesNotExist: book = ComicBook.process_comic_book(file_name, directory) - df.location = urlsafe_base64_encode(book.selector.bytes) + status, _ = ComicStatus.objects.get_or_create(comic=book, user=user) last_page = status.last_read_page + df.location = '/comic/read/{0}/{1}/'.format(urlsafe_base64_encode(book.selector.bytes).decode(), + last_page) if status.unread: - df.label = 'Unread' + df.label = '
Unread
' elif (last_page + 1) == book.page_count: - df.label = 'Read' + df.label = '
Read
' df.cur_page = last_page else: - label_text = '%s/%s' % \ + label_text = '
%s/%s
' % \ (last_page + 1, book.page_count) df.label = label_text df.cur_page = last_page @@ -133,6 +150,21 @@ def generate_directory(user, directory=False): return files +def generate_dir_status(user, directory): + cb_list = ComicBook.objects.filter(directory=directory) + total = cb_list.count() + total_read = ComicStatus.objects.filter(user=user, + comic__in=cb_list, + finished=True).count() + if total == 0: + return '
Empty
' + elif total == total_read: + return '
All Read
' + elif total_read == 0: + return '
Unread
' + return '
{0}/{1}
'.format(total_read, total) + + def get_ordered_dir_list(folder): directories = [] files = [] diff --git a/comic/views.py b/comic/views.py index ec67a05..dcfb258 100644 --- a/comic/views.py +++ b/comic/views.py @@ -1,5 +1,6 @@ import uuid from os import path +import json from django.contrib.auth import login, authenticate from django.contrib.auth.decorators import login_required, user_passes_test @@ -7,13 +8,16 @@ from django.contrib.auth.models import User from django.http import HttpResponse from django.shortcuts import render, redirect, get_object_or_404 from django.utils.http import urlsafe_base64_decode +from django.views.decorators.csrf import ensure_csrf_cookie +from django.db.models import Max from .forms import SettingsForm, AccountForm, EditUserForm, AddUserForm, InitialSetupForm -from .models import Setting, ComicBook, ComicStatus, Directory +from .models import Setting, ComicBook, ComicStatus, Directory, ComicPage from .util import generate_breadcrumbs_from_path, generate_breadcrumbs_from_menu, \ generate_title_from_path, Menu, generate_directory, scan_directory +@ensure_csrf_cookie @login_required def comic_list(request, directory_selector=False): try: @@ -24,8 +28,8 @@ def comic_list(request, directory_selector=False): return redirect('/comic/settings/') if directory_selector: - directory_selector = uuid.UUID(bytes=urlsafe_base64_decode(directory_selector)) - directory = Directory.objects.get(selector=directory_selector) + selector = uuid.UUID(bytes=urlsafe_base64_decode(directory_selector)) + directory = Directory.objects.get(selector=selector) else: directory = False @@ -34,19 +38,46 @@ def comic_list(request, directory_selector=False): if directory: title = generate_title_from_path(directory.path) breadcrumbs = generate_breadcrumbs_from_path(directory) + json_url = '/comic/list_json/{0}/'.format(directory_selector) else: title = generate_title_from_path('Home') breadcrumbs = generate_breadcrumbs_from_path() - files = generate_directory(request.user, directory) + json_url = '/comic/list_json/' + files = generate_directory(request.user) return render(request, 'comic/comic_list.html', { 'file_list': files, 'breadcrumbs': breadcrumbs, 'menu': Menu(request.user, 'Browse'), 'title': title, + 'json_url': json_url }) +@login_required +def comic_list_json(request, directory_selector=False): + icon_str = '' + if directory_selector: + directory_selector = uuid.UUID(bytes=urlsafe_base64_decode(directory_selector)) + directory = Directory.objects.get(selector=directory_selector) + else: + directory = False + files = generate_directory(request.user, directory) + response_data = dict() + response_data['data'] = [] + for file in files: + response_data['data'].append({ + 'icon': icon_str.format(file.icon), + 'name': file.name, + 'label': file.label, + 'url': file.location, + }) + return HttpResponse( + json.dumps(response_data), + content_type="application/json" + ) + + @login_required def account_page(request): success_message = [] @@ -208,6 +239,10 @@ def read_comic(request, comic_selector, page): status, _ = ComicStatus.objects.get_or_create(comic=book, user=request.user) status.unread = False status.last_read_page = page + if ComicPage.objects.filter(Comic=book).aggregate(Max('index'))['index__max'] == status.last_read_page: + status.finished = True + else: + status.finished = False status.save() title = 'CBWebReader - ' + book.file_name + ' - Page: ' + str(page) context = {