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:
@@ -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)
|
||||
==================
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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': {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'
|
||||
),
|
||||
]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user