Generalize the Javascript menu rendering into an API for templates that only refresh the menu when there are changes. Closes GitLab issue #511. Thanks to Daniel Carrico @daniel1113 for the report.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2018-09-16 21:48:37 -04:00
parent 654f2a1ad2
commit fafdb538b3
10 changed files with 98 additions and 29 deletions

View File

@@ -147,6 +147,10 @@
- Improve the speed of the document indexing.
- Move the matchHeight call from lazy loading to image loading.
Reduces the chance of wrongly sized cards.
- Generalize the Javascript menu rendering into an API for
templates that only refresh the menu when there are changes.
Closes GitLab issue #511. Thanks to Daniel Carrico
@daniel1113 for the report.
3.0.3 (2018-08-17)
==================

View File

@@ -363,6 +363,10 @@ classes beyond the provide line chart.
- Improve the speed of the document indexing.
- Move the matchHeight call from lazy loading to image loading.
Reduces the chance of wrongly sized cards.
- Generalize the Javascript menu rendering into an API for
templates that only refresh the menu when there are changes.
Closes GitLab issue #511. Thanks to Daniel Carrico
@daniel1113 for the report.
Removals
--------
@@ -446,5 +450,6 @@ Bugs fixed or issues closed
* `GitLab issue #7 <https://gitlab.com/mayan-edms/mayan-edms/issues/7>`_ Feature: other compressors than zip for compressed documents
* `GitLab issue #259 <https://gitlab.com/mayan-edms/mayan-edms/issues/259>`_ Thumbnails: why are they created on the fly (therefore: not cached)
* `GitLab issue #360 <https://gitlab.com/mayan-edms/mayan-edms/issues/360>`_ Should quick rename (optionally) retain original file type extension?
* `GitLab issue #511 <https://gitlab.com/mayan-edms/mayan-edms/issues/511>`_ Menu bar flickering in 3.1b1
.. _PyPI: https://pypi.python.org/pypi/mayan-edms/

View File

@@ -8,6 +8,15 @@ class MayanApp {
this.ajaxSpinnerSeletor = '#ajax-spinner';
this.ajaxExecuting = false;
this.ajaxMenusOptions = [
{
app: this,
interval: 5000,
menuSelector: '#main-menu',
url: apiTemplateMainMenuURL,
}
];
this.ajaxMenuHashes = {};
this.window = $(window);
}
@@ -113,25 +122,22 @@ class MayanApp {
}
}
doRefreshMainMenu (options) {
var self = this;
var $mainMenu = $('#main-menu');
var $mainMenuBuffer = $('#main-menu-buffer');
doRefreshAJAXMenu (options) {
$.ajax({
complete: function() {
setTimeout(app.doRefreshMainMenu, options.interval, options);
setTimeout(app.doRefreshAJAXMenu, options.interval, options);
},
success: function(data) {
var $elements = $('.dropdown.open');
if ($elements.length === 0) {
// Don't refresh the HTML if there are open dropdowns
$mainMenuBuffer.html(data);
$mainMenuBuffer.show();
$mainMenu.hide();
$mainMenu.html($mainMenuBuffer.html());
$mainMenu.show();
$mainMenuBuffer.hide();
console.log(data);
var menuHash = options.app.ajaxMenuHashes[data.name];
console.log('menuHash' + menuHash);
if ((menuHash === undefined) || (menuHash !== data.hex_hash)) {
$(options.menuSelector).html(data.html);
if (options.callback !== undefined) {
options.callback();
}
options.app.ajaxMenuHashes[data.name] = data.hex_hash;
}
},
url: options.url,
@@ -217,9 +223,8 @@ class MayanApp {
this.setupItemsSelector();
this.setupNavbarCollapse();
this.setupNewWindowAnchor();
this.doRefreshMainMenu({
interval: 5000,
url: '/main_menu'
$.each(this.ajaxMenusOptions, function(index, value) {
app.doRefreshAJAXMenu(value);
});
partialNavigation.initialize();
}

View File

@@ -36,7 +36,6 @@
<div id="main-menu">
{% include 'appearance/main_menu.html' %}
</div>
<div id="main-menu-buffer" style="display: none;"></div>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
@@ -114,6 +113,7 @@
{# Transfer variable from Django to javascript #}
var initialURL = '{% url home_view %}';
var djangoDEBUG = {% if debug %}true{% else %}false{% endif %};
var apiTemplateMainMenuURL = '{% url "rest_api:template-detail" "main_menu" %}';
</script>
<script src="{% static 'appearance/js/base.js' %}" type="text/javascript"></script>
<script>

View File

@@ -4,7 +4,8 @@ from django.contrib.contenttypes.models import ContentType
from rest_framework import generics
from .serializers import ContentTypeSerializer
from .classes import Template
from .serializers import ContentTypeSerializer, TemplateSerializer
class APIContentTypeList(generics.ListAPIView):
@@ -13,3 +14,14 @@ class APIContentTypeList(generics.ListAPIView):
"""
serializer_class = ContentTypeSerializer
queryset = ContentType.objects.order_by('app_label', 'model')
class APITemplateView(generics.RetrieveAPIView):
"""
Returns the selected partial template details.
get: Retrieve the details of the partial template.
"""
serializer_class = TemplateSerializer
def get_object(self):
return Template.get(self.kwargs['name']).render(request=self.request)

View File

@@ -17,6 +17,7 @@ from django.utils.translation import ugettext_lazy as _
from mayan.celery import app
from .classes import Template
from .handlers import (
handler_pre_initial_setup, handler_pre_upgrade,
user_locale_profile_session_config, user_locale_profile_create
@@ -89,6 +90,10 @@ class CommonApp(MayanAppConfig):
if check_for_sqlite():
warnings.warn(force_text(MESSAGE_SQLITE_WARNING))
Template(
name='main_menu', template_name='appearance/main_menu.html'
)
app.conf.CELERYBEAT_SCHEDULE.update(
{
'task_delete_stale_uploads': {

View File

@@ -1,8 +1,12 @@
from __future__ import unicode_literals
import hashlib
from django.apps import apps
from django.conf import settings
from django.db import models
from django.template import loader
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.translation import ugettext
@@ -287,3 +291,33 @@ class PropertyHelper(object):
by each subclass.
"""
raise NotImplementedError
class Template(object):
_registry = {}
@classmethod
def get(cls, name):
return cls._registry[name]
def __init__(self, name, template_name):
self.name = name
self.template_name = template_name
self.__class__._registry[name] = self
def get_absolute_url(self):
return reverse('rest_api:template-detail', args=(self.name,))
def render(self, request):
context = {
'home_view': settings.HOME_VIEW,
}
result = TemplateResponse(
request=request,
template=self.template_name,
context=context,
).render()
self.html = result.content
self.hex_hash = hashlib.sha256(result.content).hexdigest()
return self

View File

@@ -9,3 +9,9 @@ class ContentTypeSerializer(serializers.ModelSerializer):
class Meta:
fields = ('app_label', 'id', 'model')
model = ContentType
class TemplateSerializer(serializers.Serializer):
hex_hash = serializers.CharField(read_only=True)
name = serializers.CharField(read_only=True)
html = serializers.CharField(read_only=True)

View File

@@ -3,11 +3,11 @@ from __future__ import unicode_literals
from django.conf.urls import url
from django.views.i18n import javascript_catalog, set_language
from .api_views import APIContentTypeList
from .api_views import APIContentTypeList, APITemplateView
from .views import (
AboutView, CheckVersionView, CurrentUserDetailsView, CurrentUserEditView,
CurrentUserLocaleProfileDetailsView, CurrentUserLocaleProfileEditView,
FaviconRedirectView, HomeView, LicenseView, MainMenuView,
FaviconRedirectView, HomeView, LicenseView,
ObjectErrorLogEntryListClearView, ObjectErrorLogEntryListView,
PackagesLicensesView, RootView, SetupListView, ToolsListView,
multi_object_action_view
@@ -22,7 +22,6 @@ urlpatterns = [
name='check_version_view'
),
url(r'^license/$', LicenseView.as_view(), name='license_view'),
url(r'^main_menu/$', MainMenuView.as_view(), name='main_menu_view'),
url(
r'^packages/licenses/$', PackagesLicensesView.as_view(),
name='packages_licenses_view'
@@ -78,4 +77,8 @@ api_urls = [
r'^content_types/$', APIContentTypeList.as_view(),
name='content-type-list'
),
url(
r'^templates/(?P<name>[-\w]+)/$', APITemplateView.as_view(),
name='template-detail'
),
]

View File

@@ -168,11 +168,6 @@ class LicenseView(SimpleView):
template_name = 'appearance/generic_form.html'
class MainMenuView(SimpleView):
extra_context = {'home_view': settings.HOME_VIEW}
template_name = 'appearance/main_menu.html'
class ObjectErrorLogEntryListClearView(ConfirmView):
def get_extra_context(self):
return {