add hidden documents, fix untagged

This commit is contained in:
Tomáš Mládek 2020-03-20 15:35:34 +01:00
parent 954cdd8d97
commit 9f61506839
6 changed files with 106 additions and 17 deletions

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.4 on 2020-03-19 19:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pile', '0003_auto_20200318_2201'),
]
operations = [
migrations.AddField(
model_name='document',
name='hidden',
field=models.BooleanField(default=False),
),
]

View file

@ -0,0 +1,17 @@
# Generated by Django 3.0.4 on 2020-03-20 12:29
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pile', '0004_document_hidden'),
]
operations = [
migrations.AlterModelOptions(
name='document',
options={'ordering': ['-id'], 'permissions': [('see_hidden', 'Can see hidden documents')]},
),
]

View file

@ -1,6 +1,7 @@
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.files.storage import FileSystemStorage from django.core.files.storage import FileSystemStorage
from django.db import models from django.db import models
from django.db.models import Count
from model_utils.models import SoftDeletableModel from model_utils.models import SoftDeletableModel
@ -8,10 +9,29 @@ class Tag(SoftDeletableModel):
name = models.CharField(max_length=128, null=False, blank=False) name = models.CharField(max_length=128, null=False, blank=False)
description = models.TextField(null=False, blank=True) description = models.TextField(null=False, blank=True)
@property
def documents_exclude_hidden(self):
return Document.exclude_hidden.filter(tags__in=[self])
def __str__(self): def __str__(self):
return self.name return self.name
class DocumentManager(models.Manager):
def __init__(self, include_hidden=True):
super(DocumentManager, self).__init__()
self._include_hidden = include_hidden
def get_queryset(self):
if self._include_hidden:
return super().get_queryset()
else:
return super().get_queryset().filter(hidden=False)
def untagged(self):
return self.get_queryset().annotate(tag_count=Count('tags')).filter(tag_count=0)
class Document(SoftDeletableModel): class Document(SoftDeletableModel):
title = models.CharField(max_length=512, null=False, blank=False) title = models.CharField(max_length=512, null=False, blank=False)
description = models.TextField(null=False, blank=True) description = models.TextField(null=False, blank=True)
@ -19,9 +39,13 @@ class Document(SoftDeletableModel):
published = models.CharField(max_length=128, null=False, blank=True) published = models.CharField(max_length=128, null=False, blank=True)
external_url = models.URLField(null=True, blank=True) external_url = models.URLField(null=True, blank=True)
file = models.FileField(null=True, blank=True, storage=FileSystemStorage(location='docs')) file = models.FileField(null=True, blank=True, storage=FileSystemStorage(location='docs'))
tags = models.ManyToManyField(Tag, related_name="documents") hidden = models.BooleanField(default=False, null=False, blank=False)
tags = models.ManyToManyField(Tag, related_name="documents", blank=True)
uploaded = models.DateTimeField(auto_now_add=True, null=True) uploaded = models.DateTimeField(auto_now_add=True, null=True)
objects = DocumentManager()
exclude_hidden = DocumentManager(include_hidden=False)
@property @property
def url(self): def url(self):
if self.file: if self.file:
@ -30,6 +54,9 @@ class Document(SoftDeletableModel):
class Meta: class Meta:
ordering = ['-id'] ordering = ['-id']
permissions = [
("see_hidden", "Can see hidden documents")
]
def get_absolute_url(self): def get_absolute_url(self):
from django.urls import reverse from django.urls import reverse

View file

@ -28,12 +28,12 @@
<div id="sidebar-taglist"> <div id="sidebar-taglist">
<ul> <ul>
<li id="sidebar-taglist-top"><a href="{% url "pile:tag" "*" %}">ALL ({{ document_count }})</a></li> <li id="sidebar-taglist-top"><a href="{% url "pile:tag" "*" %}">ALL ({{ document_count }})</a></li>
{% if untagged.count %} {% if untagged_count %}
<li id="sidebar-taglist-top"><a href="?tag=_">UNTAGGED ({{ untagged_count }})</a></li> <li id="sidebar-taglist-top"><a href="/tag/_">UNTAGGED ({{ untagged_count }})</a></li>
{% endif %} {% endif %}
{% for tag in tags %} {% for tag, tag_count in tags %}
{% if tag.documents.count > 0 %} {% if tag_count > 0 %}
<li><a href="{% url 'pile:tag' tag.id %}">{{ tag.name }} ({{ tag.documents.count }})</a></li> <li><a href="{% url 'pile:tag' tag.id %}">{{ tag.name }} ({{ tag_count }})</a></li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</ul> </ul>

View file

@ -1,6 +1,15 @@
{% extends "front_base.html" %} {% extends "front_base.html" %}
{% block title %}{% if tag %}: Filed under "{{ tag.name }}"{% else %}: All documents{% endif %}{% endblock %} {% block title %}{% spaceless %}
{% if tag %}
: Filed under "{{ tag.name }}"
{% elif untagged %}
: Untagged
{% else %}
: All documents
{% endif %}
{% endspaceless %}{% endblock %}
{% block content %} {% block content %}
{% if tag %} {% if tag %}

View file

@ -1,7 +1,8 @@
# Create your views here. # Create your views here.
from operator import itemgetter
from django.contrib.syndication.views import Feed from django.contrib.syndication.views import Feed
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Count
from django.http import Http404 from django.http import Http404
from django.views.generic import TemplateView from django.views.generic import TemplateView
@ -9,12 +10,25 @@ from sdbs_pile.pile.models import Tag, Document
class BasePileView(TemplateView): class BasePileView(TemplateView):
@property
def include_hidden(self):
return self.request.user.has_perm('document.see_hidden')
@property
def documents(self):
return Document.objects if self.include_hidden else Document.exclude_hidden
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
tags = list(Tag.objects.all())
tags.sort(key=lambda tag: tag.name)
tags = [(tag, (tag.documents if self.include_hidden else tag.documents_exclude_hidden).count()) for tag in tags]
tags.sort(key=itemgetter(1), reverse=True)
return { return {
'tags': sorted(sorted(Tag.objects.all(), key=lambda tag: tag.name), 'tags': tags,
key=lambda tag: tag.documents.count(), reverse=True), 'document_count': self.documents.count(),
'document_count': Document.objects.count(), 'untagged_count': self.documents.untagged().count()
'untagged_count': Document.objects.annotate(tag_count=Count('tags')).filter(tag_count__gt=0).count()
} }
@ -25,7 +39,7 @@ class IndexView(BasePileView):
base_context_data = super(IndexView, self).get_context_data(**kwargs) base_context_data = super(IndexView, self).get_context_data(**kwargs)
return { return {
'recent_documents': Document.objects.order_by('-uploaded')[:5], 'recent_documents': self.documents.order_by('-uploaded')[:5],
**base_context_data **base_context_data
} }
@ -38,19 +52,23 @@ class TagView(BasePileView):
if name_or_id == "*": if name_or_id == "*":
tag = None tag = None
documents = Document.objects.all() documents = self.documents.all()
elif name_or_id == "_":
tag = "UNTAGGED"
documents = self.documents.untagged()
else: else:
try: try:
try: try:
tag = Tag.objects.get(id=int(name_or_id)) tag = Tag.objects.get(id=int(name_or_id))
except ValueError: except ValueError:
tag = Tag.objects.get(name=name_or_id) tag = Tag.objects.get(name=name_or_id)
documents = tag.documents.all() documents = tag.documents.all() if self.include_hidden else tag.documents_exclude_hidden
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404 raise Http404
return { return {
'tag': tag, 'tag': tag if tag != "UNTAGGED" else None,
'untagged': tag == "UNTAGGED",
'documents': documents, 'documents': documents,
**base_context_data **base_context_data
} }
@ -63,7 +81,7 @@ class DocumentView(BasePileView):
base_context_data = super(DocumentView, self).get_context_data() base_context_data = super(DocumentView, self).get_context_data()
try: try:
document = Document.objects.get(pk=document_id) document = self.documents.get(pk=document_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404 raise Http404