# Path: privagal/core/mixins.py
# class AuthTokenPageMixin(object):
# 
#     def serve_password_required_response(self, request, form, action_url):
#         if not request.user.is_staff and settings.PRIVAGAL_AUTH_TOKEN_REQUIRED:
#             return TemplateResponse(request, 'token_required.html')
# 
#         return super(AuthTokenPageMixin, self).serve_password_required_response(
#             request, form, action_url)
# 
# Path: privagal/gallery/models.py
# class Gallery(AuthTokenPageMixin, Page):
#     date = models.DateField("Post date", default=timezone.now)
#     body = RichTextField(blank=True)
# 
#     content_panels = Page.content_panels + [
#         FieldPanel('date'),
#         FieldPanel('body', classname="full"),
#         InlinePanel('images', label=_('Images')),
#     ]
# 
#     parent_page_types = ['timeline.Timeline']
#     subpage_types = []
# 
#     class Meta:
#         db_table = 'privagal_gallery'
#         verbose_name = _("Gallery")
# 
#     def delete(self, *args, **kwargs):
#         with transaction.atomic():
#             # We need to call model instance method BEFORE deleting the
#             # instance itself to delete image in cascade. This is worst for
#             # performance than using QuerySet manager but it keep it stupid.
#             for image in self.images.all():
#                 image.delete()
#             super(Gallery, self).delete(*args, **kwargs)
# 
#     @property
#     def image_teaser(self):
#         return self.images.first()
# 
#     @property
#     def teaser(self):
#         return loader.render_to_string(
#             'gallery/gallery_teaser.html',
#             {
#                 PAGE_TEMPLATE_VAR: self,
#             },
#         )
# 
#     def serve_download(self, request):
#         file = self._get_archive()
#         return sendfile(request, file.filename, attachment=True)
# 
#     def _get_archive(self):
#         directory = os.path.join(settings.MEDIA_ROOT, 'archives')
#         if not os.path.exists(directory):
#             os.makedirs(directory)
# 
#         filepath = os.path.join(
#             directory, '{gallery.date}-{gallery.pk}.zip'.format(gallery=self))
#         # Force the moment, don't use cache but recreate it each time. Anyway,
#         # store it in global private directory to be served by sendfile.
#         return self._generate_zipfile(filepath)
# 
#     def _generate_zipfile(self, filepath):
#         zf = zipfile.ZipFile(filepath, mode='w')
#         for image in self.images.all().prefetch_related('image'):
#             zf.write(
#                 image.image.file.path, os.path.basename(image.image.file.name))
#         zf.close()
#         return zf
# 
# class ImageGallery(Orderable):
#     page = ParentalKey(
#         Gallery,
#         related_name='images',
#         on_delete=models.CASCADE,
#     )
#     image = models.ForeignKey(
#         settings.WAGTAILIMAGES_IMAGE_MODEL,
#         related_name='images_gallery',
#         on_delete=models.CASCADE,
#     )
#     description = models.TextField(default='', blank=True)
# 
#     panels = [
#         ImageChooserPanel('image'),
#         FieldPanel('description'),
#     ]
# 
#     class Meta:
#         db_table = 'privagal_gallery_image'
#         verbose_name = _("Gallery")
# 
#     def delete(self, *args, **kwargs):
#         with transaction.atomic():
#             self.image.delete()
#             super(ImageGallery, self).delete(*args, **kwargs)


from django.db.models import Prefetch
from wagtail.utils.pagination import paginate
from wagtail.wagtailcore.models import Page
from privagal.core.mixins import AuthTokenPageMixin
from privagal.gallery.models import Gallery, ImageGallery
class Timeline(AuthTokenPageMixin, Page):

    parent_page_types = []
    subpage_types = ['gallery.Gallery']

    paginate_by = 20

    class Meta:
        db_table = 'privagal_timeline'

    def get_context(self, request, *args, **kwargs):
        context = super(Timeline, self).get_context(request, *args, **kwargs)

        search_query = request.GET.get('query', None)
        context['search_query'] = search_query

        paginator, page = self.get_galleries(request, search_query)
        context['page_obj'] = page
        context['object_list'] = page.object_list
        context['is_paginated'] = page.has_other_pages()

        return context

    def get_galleries(self, request, search_query):
        qs = (
            Gallery.objects
            .live()
            .prefetch_related(
                Prefetch(
                    'images',

# Path: privagal/core/mixins.py
# class AuthTokenPageMixin(object):
# 
#     def serve_password_required_response(self, request, form, action_url):
#         if not request.user.is_staff and settings.PRIVAGAL_AUTH_TOKEN_REQUIRED:
#             return TemplateResponse(request, 'token_required.html')
# 
#         return super(AuthTokenPageMixin, self).serve_password_required_response(
#             request, form, action_url)
# 
# Path: privagal/gallery/models.py
# class Gallery(AuthTokenPageMixin, Page):
#     date = models.DateField("Post date", default=timezone.now)
#     body = RichTextField(blank=True)
# 
#     content_panels = Page.content_panels + [
#         FieldPanel('date'),
#         FieldPanel('body', classname="full"),
#         InlinePanel('images', label=_('Images')),
#     ]
# 
#     parent_page_types = ['timeline.Timeline']
#     subpage_types = []
# 
#     class Meta:
#         db_table = 'privagal_gallery'
#         verbose_name = _("Gallery")
# 
#     def delete(self, *args, **kwargs):
#         with transaction.atomic():
#             # We need to call model instance method BEFORE deleting the
#             # instance itself to delete image in cascade. This is worst for
#             # performance than using QuerySet manager but it keep it stupid.
#             for image in self.images.all():
#                 image.delete()
#             super(Gallery, self).delete(*args, **kwargs)
# 
#     @property
#     def image_teaser(self):
#         return self.images.first()
# 
#     @property
#     def teaser(self):
#         return loader.render_to_string(
#             'gallery/gallery_teaser.html',
#             {
#                 PAGE_TEMPLATE_VAR: self,
#             },
#         )
# 
#     def serve_download(self, request):
#         file = self._get_archive()
#         return sendfile(request, file.filename, attachment=True)
# 
#     def _get_archive(self):
#         directory = os.path.join(settings.MEDIA_ROOT, 'archives')
#         if not os.path.exists(directory):
#             os.makedirs(directory)
# 
#         filepath = os.path.join(
#             directory, '{gallery.date}-{gallery.pk}.zip'.format(gallery=self))
#         # Force the moment, don't use cache but recreate it each time. Anyway,
#         # store it in global private directory to be served by sendfile.
#         return self._generate_zipfile(filepath)
# 
#     def _generate_zipfile(self, filepath):
#         zf = zipfile.ZipFile(filepath, mode='w')
#         for image in self.images.all().prefetch_related('image'):
#             zf.write(
#                 image.image.file.path, os.path.basename(image.image.file.name))
#         zf.close()
#         return zf
# 
# class ImageGallery(Orderable):
#     page = ParentalKey(
#         Gallery,
#         related_name='images',
#         on_delete=models.CASCADE,
#     )
#     image = models.ForeignKey(
#         settings.WAGTAILIMAGES_IMAGE_MODEL,
#         related_name='images_gallery',
#         on_delete=models.CASCADE,
#     )
#     description = models.TextField(default='', blank=True)
# 
#     panels = [
#         ImageChooserPanel('image'),
#         FieldPanel('description'),
#     ]
# 
#     class Meta:
#         db_table = 'privagal_gallery_image'
#         verbose_name = _("Gallery")
# 
#     def delete(self, *args, **kwargs):
#         with transaction.atomic():
#             self.image.delete()
#             super(ImageGallery, self).delete(*args, **kwargs)


# Path: privagal/timeline/models.py
from django.db.models import Prefetch
from wagtail.utils.pagination import paginate
from wagtail.wagtailcore.models import Page
from privagal.core.mixins import AuthTokenPageMixin
from privagal.gallery.models import Gallery, ImageGallery

class Timeline(AuthTokenPageMixin, Page):

    parent_page_types = []
    subpage_types = ['gallery.Gallery']

    paginate_by = 20

    class Meta:
        db_table = 'privagal_timeline'

    def get_context(self, request, *args, **kwargs):
        context = super(Timeline, self).get_context(request, *args, **kwargs)

        search_query = request.GET.get('query', None)
        context['search_query'] = search_query

        paginator, page = self.get_galleries(request, search_query)
        context['page_obj'] = page
        context['object_list'] = page.object_list
        context['is_paginated'] = page.has_other_pages()

        return context

    def get_galleries(self, request, search_query):
        qs = (
            Gallery.objects
            .live()
            .prefetch_related(
                Prefetch(
                    'images',

                    queryset=ImageGallery.objects.select_related('image'),