add mini-live edit, for quick fixes
[chloro.git] / chloro / phyll / views.py
1 # chloro - personal space
2 # Copyright (C) 2019  Frederic Peters
3 #
4 # This program is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published
6 # by the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 import urllib.parse
18
19 from django.conf import settings
20 from django.contrib.syndication.views import Feed
21 from django.core.exceptions import PermissionDenied
22 from django.http import HttpResponse, Http404
23 from django.utils.feedgenerator import Atom1Feed
24 from django.views import View
25 from django.views.decorators.csrf import csrf_exempt
26 from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView, TemplateView
27
28 from .models import Note
29
30
31 class NoteView(DetailView):
32     model = Note
33
34     def get(self, request, *args, **kwargs):
35         note = self.get_object()
36         if kwargs.get('year'):
37             # check date does match
38             creation = self.get_object().creation_timestamp
39             if (creation.year, creation.month, creation.day) != (
40                 int(kwargs['year']),
41                 int(kwargs['month']),
42                 int(kwargs['day']),
43             ):
44                 raise Http404()
45         if not note.published and not request.user.is_staff:
46             raise PermissionDenied()
47         return super(NoteView, self).get(request, *args, **kwargs)
48
49
50 class NoteEditView(UpdateView):
51     model = Note
52     fields = ['title', 'slug', 'text', 'tags', 'published']
53
54
55 class NoteApiSaveView(View):
56     http_method_names = ['post']
57
58     @csrf_exempt
59     def dispatch(self, *args, **kwargs):
60         return super().dispatch(*args, **kwargs)
61
62     def post(self, request, *args, **kwargs):
63         note = Note.objects.get(slug=kwargs['slug'])
64         note.text = request.POST['text']
65         note.save()
66         return HttpResponse('ok')
67
68
69 class NoteAddView(CreateView):
70     model = Note
71     fields = ['title', 'slug', 'text', 'tags', 'published']
72
73
74 class NoteDeleteView(DeleteView):
75     model = Note
76
77     def get_success_url(self):
78         return '/'
79
80
81 class HomeView(TemplateView):
82     template_name = 'phyll/home.html'
83
84     def get_context_data(self, **kwargs):
85         context = super(HomeView, self).get_context_data(**kwargs)
86         context['posts'] = Note.objects.filter(published=True).order_by('-creation_timestamp')[:5]
87         return context
88
89
90 class ArchivesView(ListView):
91     model = Note
92
93     def get_queryset(self):
94         qs = super(ArchivesView, self).get_queryset()
95         if not self.request.user.is_staff:
96             qs = qs.filter(published=True)
97         return qs
98
99
100 class ListOnTagView(ListView):
101     model = Note
102
103     def get_queryset(self):
104         qs = Note.objects.filter(tags__name__in=[self.kwargs['tag']])
105         if not self.request.user.is_staff:
106             qs = qs.filter(published=True)
107         return qs
108
109
110 class Atom1FeedWithBaseXml(Atom1Feed):
111     def root_attributes(self):
112         root_attributes = super(Atom1FeedWithBaseXml, self).root_attributes()
113         scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(self.feed['feed_url'])
114         root_attributes['xml:base'] = urllib.parse.urlunparse((scheme, netloc, '/', params, query, fragment))
115         return root_attributes
116
117
118 class AtomFeed(Feed):
119     title = settings.SITE_TITLE
120     link = '/'
121     feed_type = Atom1FeedWithBaseXml
122     author_name = settings.SITE_AUTHOR
123
124     def get_object(self, request, *args, **kwargs):
125         self.sub = kwargs.get('sub', 'default')
126         return super(AtomFeed, self).get_object(request, *args, **kwargs)
127
128     def items(self):
129         qs = Note.objects.filter(published=True)
130         if self.sub == 'default':
131             pass
132         elif self.sub == 'gnome-en':
133             qs = qs.filter(tags__name__in=['gnome']).filter(tags__name__in=['lang-en'])
134         else:
135             qs = qs.filter(tags__name__in=[self.sub])
136         return qs.select_related()[:20]
137
138     def item_description(self, item):
139         return item.text
140
141     def item_guid(self, item):
142         for tag in item.tags.all():
143             if tag.name.startswith('old-post-id-'):
144                 return 'http://www.0d.be/posts/%s' % tag.name.split('-')[-1]
145         return 'https://www.0d.be' + item.get_absolute_url()
146
147     def item_title(self, item):
148         return item.title
149
150     def item_pubdate(self, item):
151         return item.creation_timestamp