manager: list pages outside applications (#85927)
gitea/combo/pipeline/head This commit looks good
Details
gitea/combo/pipeline/head This commit looks good
Details
This commit is contained in:
parent
dd877aad7c
commit
97d0fd650e
|
@ -71,34 +71,23 @@ class Application(models.Model):
|
|||
@classmethod
|
||||
def populate_objects(cls, object_class, objects):
|
||||
content_type = ContentType.objects.get_for_model(object_class)
|
||||
elements = ApplicationElement.objects.filter(content_type=content_type)
|
||||
elements = ApplicationElement.objects.filter(
|
||||
content_type=content_type, application__visible=True
|
||||
).prefetch_related('application')
|
||||
elements_by_objects = collections.defaultdict(list)
|
||||
for element in elements:
|
||||
elements_by_objects[element.content_object].append(element)
|
||||
applications_by_ids = {
|
||||
a.pk: a for a in cls.objects.filter(pk__in=elements.values('application'), visible=True)
|
||||
}
|
||||
elements_by_objects[element.object_id].append(element)
|
||||
for obj in objects:
|
||||
applications = []
|
||||
elements = elements_by_objects.get(obj) or []
|
||||
for element in elements:
|
||||
application = applications_by_ids.get(element.application_id)
|
||||
if application:
|
||||
applications.append(application)
|
||||
applications = [element.application for element in elements_by_objects.get(obj.pk) or []]
|
||||
obj._applications = sorted(applications, key=lambda a: a.name)
|
||||
|
||||
@classmethod
|
||||
def load_for_object(cls, obj):
|
||||
content_type = ContentType.objects.get_for_model(obj.__class__)
|
||||
elements = ApplicationElement.objects.filter(content_type=content_type, object_id=obj.pk)
|
||||
applications_by_ids = {
|
||||
a.pk: a for a in cls.objects.filter(pk__in=elements.values('application'), visible=True)
|
||||
}
|
||||
applications = []
|
||||
for element in elements:
|
||||
application = applications_by_ids.get(element.application_id)
|
||||
if application:
|
||||
applications.append(application)
|
||||
elements = ApplicationElement.objects.filter(
|
||||
content_type=content_type, object_id=obj.pk, application__visible=True
|
||||
).prefetch_related('application')
|
||||
applications = [element.application for element in elements]
|
||||
obj._applications = sorted(applications, key=lambda a: a.name)
|
||||
|
||||
def get_objects_for_object_class(self, object_class):
|
||||
|
@ -106,6 +95,12 @@ class Application(models.Model):
|
|||
elements = ApplicationElement.objects.filter(content_type=content_type, application=self)
|
||||
return object_class.objects.filter(pk__in=elements.values('object_id'))
|
||||
|
||||
@classmethod
|
||||
def get_orphan_objects_for_object_class(cls, object_class):
|
||||
content_type = ContentType.objects.get_for_model(object_class)
|
||||
elements = ApplicationElement.objects.filter(content_type=content_type, application__visible=True)
|
||||
return object_class.objects.exclude(pk__in=elements.values('object_id'))
|
||||
|
||||
|
||||
class ApplicationElement(models.Model):
|
||||
application = models.ForeignKey(Application, on_delete=models.CASCADE)
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
{% endif %}
|
||||
{{ application }}
|
||||
</h2>
|
||||
{% elif no_application %}
|
||||
<h2>{% trans 'Pages outside applications' %}</h2>
|
||||
{% else %}
|
||||
<h2>{% trans 'Pages' %}</h2>
|
||||
{% endif %}
|
||||
|
@ -20,6 +22,8 @@
|
|||
{{ block.super }}
|
||||
{% if application %}
|
||||
<a href="{% url 'combo-manager-homepage' %}?application={{ application.slug }}">{{ application }}</a>
|
||||
{% elif no_application %}
|
||||
<a href="{% url 'combo-manager-homepage' %}?no-application">{% trans "Pages outside applications" %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -27,7 +31,7 @@
|
|||
|
||||
{% if object_list %}
|
||||
|
||||
{% if not application %}
|
||||
{% if not application and not no_application %}
|
||||
<p class="hint">
|
||||
{% blocktrans %}
|
||||
Use drag and drop with the ⣿ handles to reorder and change hierarchy of pages.
|
||||
|
@ -38,10 +42,10 @@
|
|||
<div class="objects-list" id="pages-list" data-page-order-url="{% url 'combo-manager-page-order' %}">
|
||||
{% for page in object_list %}
|
||||
<div class="page level-{{page.level}}{% if collapse_pages %} untoggled{% endif %}" data-page-id="{{page.id}}" data-level="{{page.level}}">
|
||||
{% if user.is_superuser and not application %}<span class="handle">⣿</span>{% endif %}
|
||||
{% if user.is_superuser and not application and not no_application %}<span class="handle">⣿</span>{% endif %}
|
||||
<span class="group1">
|
||||
<a href="{% url 'combo-manager-page-view' pk=page.id %}">
|
||||
{% if not application %}
|
||||
{% if not application and not no_application %}
|
||||
{% for application in page.applications %}
|
||||
{% if application.icon %}
|
||||
{% thumbnail application.icon '16x16' format='PNG' as im %}
|
||||
|
@ -80,7 +84,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% if not application %}
|
||||
{% if not application and not no_application %}
|
||||
<aside id="sidebar">
|
||||
{% if can_add_page or user.is_superuser %}
|
||||
<h3>{% trans "Actions" %}</h3>
|
||||
|
@ -112,6 +116,9 @@
|
|||
{{ application.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
<a class="button button-paragraph" href="?no-application">
|
||||
{% trans "Pages outside applications" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</aside>
|
||||
{% endif %}
|
||||
|
|
|
@ -115,15 +115,20 @@ class HomepageView(ListView):
|
|||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.application = None
|
||||
self.no_application = False
|
||||
if 'application' in self.request.GET:
|
||||
self.application = get_object_or_404(
|
||||
Application, slug=self.request.GET['application'], visible=True
|
||||
)
|
||||
elif 'no-application' in self.request.GET:
|
||||
self.no_application = True
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
if self.application:
|
||||
return self.application.get_objects_for_object_class(Page)
|
||||
if self.no_application:
|
||||
return Application.get_orphan_objects_for_object_class(Page)
|
||||
return super().get_queryset()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
@ -136,9 +141,10 @@ class HomepageView(ListView):
|
|||
context['can_add_page'] = can_add_page(self.request.user)
|
||||
if self.application:
|
||||
context['application'] = self.application
|
||||
else:
|
||||
elif not self.no_application:
|
||||
Application.populate_objects(Page, self.object_list)
|
||||
context['applications'] = Application.select_for_object_class(Page)
|
||||
context['no_application'] = self.no_application
|
||||
return context
|
||||
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ def test_pages(app, admin_user, application_with_icon, application_without_icon,
|
|||
assert len(resp.pyquery('h3:contains("Applications") + .button-paragraph img.application-icon')) == 1
|
||||
else:
|
||||
assert len(resp.pyquery('h3:contains("Applications") + .button-paragraph img')) == 0
|
||||
assert 'Pages outside applications' in resp
|
||||
|
||||
# check application view
|
||||
resp = resp.click(application.name)
|
||||
|
@ -93,6 +94,14 @@ def test_pages(app, admin_user, application_with_icon, application_without_icon,
|
|||
assert resp.pyquery('#pages-list div.page:nth-child(2)').text() == 'Page 3'
|
||||
assert len(resp.pyquery('#pages-list div.page img')) == 0
|
||||
|
||||
# check pages outside applications
|
||||
resp = app.get('/manage/')
|
||||
resp = resp.click('Pages outside applications')
|
||||
assert resp.pyquery('h2').text() == 'Pages outside applications'
|
||||
assert len(resp.pyquery('#pages-list div.page')) == 1
|
||||
assert resp.pyquery('#pages-list div.page:nth-child(1)').attr['data-level'] == '0'
|
||||
assert resp.pyquery('#pages-list div.page:nth-child(1)').text() == 'Page 1'
|
||||
|
||||
# check detail page
|
||||
resp = app.get('/manage/pages/%s/' % page1.pk)
|
||||
assert len(resp.pyquery('h3:contains("Applications")')) == 0
|
||||
|
|
|
@ -703,7 +703,7 @@ def test_edit_page_num_queries(settings, app, admin_user):
|
|||
app.get('/manage/pages/%s/' % page.pk) # load once to populate caches
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
app.get('/manage/pages/%s/' % page.pk)
|
||||
assert len(ctx.captured_queries) == 43
|
||||
assert len(ctx.captured_queries) == 42
|
||||
|
||||
|
||||
def test_delete_page(app, admin_user):
|
||||
|
@ -2668,7 +2668,7 @@ def test_page_versionning(app, admin_user):
|
|||
resp = resp.click('restore', index=6)
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
resp = resp.form.submit().follow()
|
||||
assert len(ctx.captured_queries) == 150
|
||||
assert len(ctx.captured_queries) == 149
|
||||
|
||||
resp2 = resp.click('See online')
|
||||
assert resp2.text.index('Foobar1') < resp2.text.index('Foobar2') < resp2.text.index('Foobar3')
|
||||
|
|
Loading…
Reference in New Issue