Commits

b7w committed 108cf4f Merge

Merge dev

  • Participants
  • Parent commits 4a915b8, e6df129
  • Branches default
  • Tags v1.0.9

Comments (0)

Files changed (16)

bviewer/archive/views.py

     if not holder:
         return message_view(request, message=NO_USER_DEFINED)
 
-    controller = GalleryController(holder, request.user, gid)
-    main = controller.get_object()
-    if not main:
+    controller = GalleryController(holder, request.user, uid=gid)
+    if not controller.exists():
         return message_view(request, message=NO_GALLERY_FOUND)
 
     if not controller.is_album():
     # links for redirect to download, and check status
     redirect = reverse('archive.download', kwargs=dict(gid=gid, uid=z.uid))
     link = reverse('archive.status', kwargs=dict(gid=gid, uid=z.uid))
+    main = controller.get_object()
 
     if z.status == 'DONE':
         return HttpResponseRedirect(redirect)
         raise Http404(NO_USER_DEFINED)
 
     controller = GalleryController(holder, request.user, gid)
-    main = controller.get_object()
-    if not main:
+    if not controller.exists():
         return HttpResponse(json.dumps(dict(error=NO_GALLERY_FOUND)))
 
     if not controller.is_album():
     if not holder:
         raise Http404(NO_USER_DEFINED)
 
-    controller = GalleryController(holder, request.user, gid)
-    main = controller.get_object()
-    if not main:
+    controller = GalleryController(holder, request.user, uid=gid)
+    if not controller.exists():
         raise Http404(NO_GALLERY_FOUND)
 
     if not controller.is_album():
     if z == 'NONE':
         raise Http404('No file found')
 
+    main = controller.get_object()
     logger.info(smart_text('download archive "%s"'), main.title)
     name = smart_text('{0} - {1}.zip').format(main.time.strftime('%Y-%m-%d'), main.title)
     return download_response(z.archive, name=name)

bviewer/core/controllers.py

 
 
 class BaseController(object):
-    def __init__(self, holder, user, uid):
+    def __init__(self, holder, user, uid=None, obj=None):
         """
         :type holder: bviewer.core.models.ProxyUser
         :type user: django.contrib.auth.models.User
         """
         self.holder = holder
         self.user = user
-        self.uid = uid
+        if uid:
+            self.uid = uid
+        else:
+            self.uid = obj.id
+        self.obj = obj
 
     def is_owner(self):
         """
         """
         return self.holder == self.user
 
+    def exists(self):
+        return bool(self.get_object())
+
+    @staticmethod
+    def from_obj(obj):
+        raise NotImplementedError()
+
     def get_object(self):
         raise NotImplementedError()
 
         if sorting == Gallery.DESK:
             return query_set.order_by('-time')
 
+    @staticmethod
+    def from_obj(obj):
+        """
+        :type obj: bviewer.core.models.Gallery
+        """
+        return GalleryController(obj.user, obj.user, obj=obj)
+
     @cache_method
     def get_object(self):
         """
 
         :rtype: bviewer.core.models.Gallery or None
         """
+        if self.obj:
+            return self.obj
         if self.is_owner():
             return Gallery.objects.safe_get(pk=self.uid, user_id=self.holder.id)
         return Gallery.objects.safe_get(Q(pk=self.uid), Q(user_id=self.holder.id), self.OPEN)
                 result.append(gallery)
         return result
 
+    def pre_cache(self):
+        ids = [self.get_object().id, ]
+        ids.extend(i.id for i in self.get_all_sub_galleries())
+        images = Image.objects.filter(gallery__in=ids)
+        sizes = [i for i in settings.VIEWER_IMAGE_SIZE.keys() if i != 'full']
+        for size in sizes:
+            for image in images:
+                storage = ImageStorage(self.holder)
+                self._pre_cache_image(storage, image, size)
+
+    def _pre_cache_image(self, storage, image, size):
+        options = ImageOptions.from_settings(size)
+        image_path = storage.get_path(image.path, options)
+        if image_path.exists and not image_path.cache_exists:
+            image_async = CacheImage(image_path)
+            as_job(image_async.process, waite=False)
+
     def is_archiving_allowed(self):
-        obj = self.get_object()
-        return obj and obj.allow_archiving
+        return self.get_object().allow_archiving
+
+    def set_archiving(self, value):
+        self.get_object().allow_archiving = value
+        for gallery in self.get_all_sub_galleries():
+            gallery.allow_archiving = value
+            gallery.save()
 
     def is_album(self):
         """

bviewer/core/static/core/css/core.css

     }
 
     .container {
-        width: 90%;
+        width: 95%;
     }
 
     .preview {
 
 @media only screen and (max-width: 1050px) and (min-width: 651px) {
     /* Small desktop / ipad view: 3 tiles */
+    .container {
+        width: 95%;
+    }
+
+    .view-middle-hide {
+        display: none !important;
+    }
+
     .preview {
         width: 33.3%;
         padding-bottom: 33.3%;

bviewer/core/static/core/js/core.js

 
         function load() {
             var height = jQuery(window).scrollTop() + jQuery(window).height();
-            if (isMobile) height = height + jQuery(window).height() / 2
+            if (isMobile)
+                height = height + jQuery(window).height();
+            else
+                height = height + jQuery(window).height() / 2;
 
             jQuery('.gallery img[data-src]').each(function (i, img) {
                 var image = jQuery(img);

bviewer/core/templates/core/base.html

     <meta name="robots" content="NONE,NOARCHIVE"/>
     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
 
+    <meta name="apple-mobile-web-app-capable" content="yes">
+    <meta name="apple-mobile-web-app-status-bar-style" content="black">
+
     <link href="{% static 'core/css/core.css' %}" rel="stylesheet">
     <link href="{% static 'core/css/icons.css' %}" rel="stylesheet">
     {% block css %}
             <a class="view-full brand" href="{% url 'core.home' %}">Believe Viewer</a>
 
             <ul class="pull-left">
-                <li><a href="{% url 'core.home' %}">Home</a></li>
+                <li><a class="view-middle-hide" href="{% url 'core.home' %}">Home</a></li>
                 {% block navigation %}{% endblock %}
                 <li><a href="{% url 'core.about' %}">About</a></li>
             </ul>

bviewer/core/tests/test_controllers.py

 
         g121 = Gallery.objects.create(parent=g12, user=user, title='1.2.1')
 
-        controller = GalleryController(user, user, top_gallery.id)
+        controller = GalleryController(user, user, uid=top_gallery.id)
         galleries = controller.get_all_sub_galleries()
         self.assertEqual(len(galleries), 10)
 
-        controller = GalleryController(user, user, top_gallery.id)
+        controller = GalleryController(user, user, uid=top_gallery.id)
         galleries = controller.get_all_sub_galleries(parents=False)
         self.assertEqual(len(galleries), 6)
 
+    def test_gallery_controller_from_obj(self):
+        """
+        Tests GalleryController.from_obj
+        """
+        data = TestData()
+        data.load_users()
 
+        user = data.user_b7w
+        top_gallery = user.top_gallery
+
+        controller = GalleryController(user, user, uid=top_gallery.id)
+        self.assertEqual(controller.uid, top_gallery.id)
+        self.assertIsNone(controller.obj)
+        self.assertEqual(controller.get_object(), top_gallery)
+
+        controller = GalleryController(user, user, obj=top_gallery)
+        self.assertEqual(controller.uid, top_gallery.id)
+        self.assertEqual(controller.obj, top_gallery)
+        self.assertEqual(controller.get_object(), top_gallery)
+
+

bviewer/core/views.py

 # -*- coding: utf-8 -*-
 import logging
-
 from django.conf import settings
 from django.contrib.auth.views import login, logout
 from django.http import Http404
     if not holder:
         return message_view(request, message='No user defined')
 
-    controller = GalleryController(holder, request.user, holder.top_gallery_id)
-    main = controller.get_object()
-    if not main:
+    controller = GalleryController(holder, request.user, uid=holder.top_gallery_id)
+    if not controller.exists():
         return message_view(request, message='No main gallery')
 
     year_filter = get_year_parameter(request)
 
+    main = controller.get_object()
     galleries = controller.get_galleries(year=year_filter)
     years = controller.get_available_years()
 
     if not holder:
         return message_view(request, message='No user defined')
 
-    controller = GalleryController(holder, request.user, uid)
-    main = controller.get_object()
-    if not main:
+    controller = GalleryController(holder, request.user, uid=uid)
+    if not controller.exists():
         return message_view(request, message='No such gallery')
 
+    main = controller.get_object()
     galleries, images, videos, years = None, None, None, None
     year_filter = get_year_parameter(request)
     if controller.is_album():

bviewer/profile/admin.py

 from django.utils.encoding import smart_text
 
 from bviewer.core.admin import ProxyUserForm
+from bviewer.core.controllers import GalleryController
 from bviewer.core.files.storage import ImageStorage
 from bviewer.core.models import Gallery, Image, ProxyUser, Video
 from bviewer.profile.actions import bulk_time_update, update_time_from_exif
 
     search_fields = ('title', 'description',)
 
-    readonly_fields = ('images', 'thumbnails',)
+    readonly_fields = ('images', 'pre_cache', 'thumbnails',)
     fields = ('parent', 'title', 'visibility', 'gallery_sorting', 'allow_archiving',
-              'images', 'description', 'time', 'thumbnails', )
+              'images', 'pre_cache', 'description', 'time', 'thumbnails', )
 
     def images(self, obj):
         if Gallery.objects.safe_get(id=obj.id):
 
     images.allow_tags = True
 
+    def pre_cache(self, obj):
+        if Gallery.objects.safe_get(id=obj.id):
+            url = reverse('profile.gallery.pre-cache', kwargs=dict(uid=obj.id))
+            return smart_text('<b><a href="{url}">Run pre cache task</a></b>').format(url=url)
+        return smart_text('<b>Save gallery first</b>')
+
+    pre_cache.allow_tags = True
+
     def images_expected_path(self, gallery):
         """
         Get some gallery images
             obj.thumbnail_id = thumbnail_id
         else:
             obj.thumbnail = None
+        # allow archiving
+        if change and 'allow_archiving' in form.changed_data:
+            controller = GalleryController.from_obj(obj)
+            controller.set_archiving(obj.allow_archiving)
         super(ProfileGalleryAdmin, self).save_model(request, obj, form, change)
 
     def get_form(self, request, obj=None, **kwargs):
     list_select_related = True
     actions = [bulk_time_update, update_time_from_exif, ]
 
-    list_display = ('path', 'file_name', 'gallery_title', 'time', )
+    list_display = ('path', 'file_name', 'gallery_title', 'image_thumbnail_popup', 'time', )
     list_filter = ('gallery__title', 'time',)
     ordering = ('-time', 'gallery', )
 
 
     image_thumbnail.allow_tags = True
 
+    def image_thumbnail_popup(self, obj):
+        url = reverse('core.download', kwargs=dict(size='tiny', uid=obj.id))
+        return smart_text('<img class="preview" src="{0}">').format(url)
+
+    image_thumbnail_popup.allow_tags = True
+
     def queryset(self, request):
         return super(ProfileImageAdmin, self).queryset(request).filter(gallery__user=request.user)
 
             kwargs['queryset'] = Gallery.objects.filter(user=request.user)
         return super(ProfileImageAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
 
+    class Media:
+        css = {
+            'all': ('profile/css/profile.css',)
+        }
+        js = ('my_code.js',)
+
 
 profile.register(Image, ProfileImageAdmin)
 

bviewer/profile/static/profile/css/profile.css

 
 .thumbnails li:hover .caption {
     opacity: 1;
-}
+}
+
+.preview {
+    width: 32px;
+    height: 32px;
+}
+
+.preview:hover {
+    width: auto;
+    height: auto;
+}

bviewer/profile/urls.py

 from bviewer.profile.admin import profile
 
 
-urlpatterns = patterns('',
-    url(r'^gallery/(?P<uid>\w+)/$', 'bviewer.profile.views.images_view', name='profile.gallery'),
-    url(r'^download/$', 'bviewer.profile.views.download_image', name='profile.download'),
+urlpatterns = patterns('bviewer.profile.views',
+    url(r'^gallery/(?P<uid>\w+)/$', 'images_view', name='profile.gallery'),
+    url(r'^gallery/(?P<uid>\w+)/pre-cache/$', 'gallery_pre_cache', name='profile.gallery.pre-cache'),
+    url(r'^download/$', 'download_image', name='profile.download'),
     url(r'^', include(profile.urls)),
 )

bviewer/profile/views.py

 # -*- coding: utf-8 -*-
 import logging
-
 from django.contrib.auth.decorators import login_required, permission_required
-from django.http import Http404
+from django.http import Http404, HttpResponseRedirect
 from django.shortcuts import render
 from django.utils.encoding import smart_text
 
     if not holder:
         raise Http404()
 
-    controller = GalleryController(holder, request.user, uid)
-    main = controller.get_object()
-    if not main:
+    controller = GalleryController(holder, request.user, uid=uid)
+    if not controller.exists():
         return message_view(request, message='No such gallery')
 
     images = controller.get_images()
         logger.exception(e)
         return message_view(request, message=smart_text(e))
     return render(request, 'profile/images.html', {
-        'gallery': main,
+        'gallery': controller.get_object(),
         'folder': folder,
         'title': 'Select images',
     })
 
 @login_required
 @permission_required('core.user_holder')
+def gallery_pre_cache(request, uid):
+    holder = get_gallery_user(request)
+    if not holder:
+        raise Http404()
+
+    controller = GalleryController(holder, request.user, uid=uid)
+    if not controller.exists():
+        return message_view(request, message='No such gallery')
+
+    try:
+        controller.pre_cache()
+    except FileError as e:
+        logger.exception(e)
+        return message_view(request, message=smart_text(e))
+    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
+
+
+@login_required
+@permission_required('core.user_holder')
 def download_image(request):
     if request.GET.get('p', None):
         path = request.GET['p']

bviewer/settings/debug.py

 #
 # Debug toolbar configs
 #
-
 DEBUG_TOOLBAR_PANELS = (
     'debug_toolbar.panels.versions.VersionsPanel',
     'debug_toolbar.panels.timer.TimerPanel',
     'debug_toolbar.panels.headers.HeadersPanel',
     'debug_toolbar.panels.request.RequestPanel',
     'debug_toolbar.panels.sql.SQLPanel',
+    'debug_toolbar.panels.staticfiles.StaticFilesPanel',
     'debug_toolbar.panels.templates.TemplatesPanel',
     'debug_toolbar.panels.cache.CachePanel',
     'debug_toolbar.panels.signals.SignalsPanel',

bviewer/slideshow/controllers.py

 # -*- coding: utf-8 -*-
 import logging
 import random
-
 from django.db.models import Q
 
 from bviewer.core.controllers import GalleryController
         self.redis = redis
         self.holder = slideshow.gallery.user
         self.user = slideshow.user
-        self.gallery_ctrl = GalleryController(self.holder, self.user, slideshow.gallery_id)
+        self.gallery_ctrl = GalleryController(self.holder, self.user, uid=slideshow.gallery_id)
 
     def get_key(self):
         return 'slideshow-id:' + self.slideshow.id

bviewer/slideshow/views.py

 # -*- coding: utf-8 -*-
 import logging
-
 from django.core.urlresolvers import reverse
 from django.shortcuts import render
 
     if not holder:
         return message_view(request, message='No user defined')
 
-    controller = GalleryController(holder, request.user, holder.top_gallery_id)
-    main = controller.get_object()
-    if not main:
+    controller = GalleryController(holder, request.user, uid=holder.top_gallery_id)
+    if not controller.exists():
         return message_view(request, message='No such gallery')
 
+    main = controller.get_object()
     link = reverse('actions-slideshow-get-or-create') + '?gallery={0}'.format(holder.top_gallery_id)
     return render(request, 'slideshow/index.html', {
         'holder': holder,
     if not holder:
         return message_view(request, message='No user defined')
 
-    controller = GalleryController(holder, request.user, gallery_id)
-    main = controller.get_object()
-    if not main:
+    controller = GalleryController(holder, request.user, uid=gallery_id)
+    if not controller.exists():
         return message_view(request, message='No such gallery')
 
+    main = controller.get_object()
     link = reverse('actions-slideshow-get-or-create') + '?gallery={0}'.format(gallery_id)
     return render(request, 'slideshow/index.html', {
         'holder': holder,
 # The short X.Y version.
 version = '1.0'
 # The full version, including alpha/beta/rc tags.
-release = '1.0.8'
+release = '1.0.9'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.

docs/releases/notes.rst

 
 .. index:: Release notes
 
+| **v1.0.9** - 4.06.2014
+| Add some features to profile and improve mobile styles.
+
+* Fix menu links on ipad
+* Pre cache function
+* On setting gallery allow archive set child too
+* Image popup in profile list images
+* Make body on ipad more wide
+
+
 | **v1.0.8** - *20.05.1014*
 | Add some small features to profile. Need database scheme update.