assets: display assets related to cell in popup (#40223)

This commit is contained in:
Lauréline Guérin 2020-03-10 16:39:04 +01:00
parent 624120dedf
commit 90f17f8595
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
9 changed files with 176 additions and 46 deletions

View File

@ -38,41 +38,7 @@
<div id="assets-browser"> <div id="assets-browser">
<div id="assets-listing"> <div id="assets-listing">
<table class="main"> {% include "combo/manager_assets_fragment.html" %}
<thead>
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "Size" %}</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for asset in object_list %}
<tr class="{{ asset.css_classes }}">
<td><a href="{{ asset.src }}">{{ asset.name }}</a></td>
<td>{% if asset.size %}{{ asset.size|filesizeformat }}{% else %}-{% endif %}</td>
<td class="image">{% if asset.is_image %}<img data-href="{{ asset.src }}" src="{{ asset.thumb }}"/>{% endif %}</td>
<td class="actions">
{% if asset.key %}{# theme asset #}
<a href="{% url 'combo-manager-slot-asset-upload' key=asset.key %}"
class="overwrite" rel="popup">{% trans 'Overwrite' %}</a>
{% if asset.asset %}
<a href="{% url 'combo-manager-slot-asset-delete' key=asset.key %}"
class="delete" rel="popup">{% trans 'Delete' %}</a>
{% endif %}
{% else %}
<a href="{% url 'combo-manager-asset-overwrite' %}?img={{asset.filepath|iriencode}}"
class="overwrite" rel="popup">{% trans 'Overwrite' %}</a>
<a href="{% url 'combo-manager-asset-delete' %}?img={{asset.filepath|iriencode}}"
class="delete" rel="popup">{% trans 'Delete' %}</a>
{% endif %}
</td>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
<div id="asset-preview"></div> <div id="asset-preview"></div>
</div> </div>

View File

@ -0,0 +1,35 @@
{% load i18n %}
<table class="main">
<thead>
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "Size" %}</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for asset in object_list %}
<tr class="{{ asset.css_classes }}">
<td><a href="{{ asset.src }}">{{ asset.name }}</a></td>
<td>{% if asset.size %}{{ asset.size|filesizeformat }}{% else %}-{% endif %}</td>
<td class="image">{% if asset.is_image %}<img data-href="{{ asset.src }}" src="{{ asset.thumb }}"/>{% endif %}</td>
<td class="actions">
{% if asset.key %}{# theme asset #}
<a href="{% url 'combo-manager-slot-asset-upload' key=asset.key %}{% if cell_reference %}?cell_reference={{ cell_reference }}{% endif %}"
class="overwrite" rel="popup">{% trans 'Overwrite' %}</a>
{% if asset.asset %}
<a href="{% url 'combo-manager-slot-asset-delete' key=asset.key %}{% if cell_reference %}?cell_reference={{ cell_reference }}{% endif %}"
class="delete" rel="popup">{% trans 'Delete' %}</a>
{% endif %}
{% else %}
<a href="{% url 'combo-manager-asset-overwrite' %}?img={{asset.filepath|iriencode}}"
class="overwrite" rel="popup">{% trans 'Overwrite' %}</a>
<a href="{% url 'combo-manager-asset-delete' %}?img={{asset.filepath|iriencode}}"
class="delete" rel="popup">{% trans 'Delete' %}</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,19 @@
{% extends "combo/manager_base.html" %}
{% load i18n %}
{% block appbar %}
<h2>{% trans 'Assets' %}</h2>
{% endblock %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'combo-manager-assets' %}">{% trans 'Assets' %}</a>
{% endblock %}
{% block content %}
<div id="assets-listing">
{% include "combo/manager_assets_fragment.html" %}
</div>
{% endblock %}

View File

@ -23,6 +23,7 @@ from . import api_views
assets_manager_urls = [ assets_manager_urls = [
url(r'^$', views.assets, name='combo-manager-assets'), url(r'^$', views.assets, name='combo-manager-assets'),
url(r'^slots/(?P<cell_reference>[\w_-]+)/$', views.slot_assets, name='combo-manager-slot-assets'),
url(r'^delete$', views.asset_delete, name='combo-manager-asset-delete'), url(r'^delete$', views.asset_delete, name='combo-manager-asset-delete'),
url(r'^overwrite/$', views.asset_overwrite, name='combo-manager-asset-overwrite'), url(r'^overwrite/$', views.asset_overwrite, name='combo-manager-asset-overwrite'),
url(r'^upload/$', views.asset_upload, name='combo-manager-asset-upload'), url(r'^upload/$', views.asset_upload, name='combo-manager-asset-upload'),
@ -37,6 +38,6 @@ urlpatterns = [
url(r'^manage/assets/', decorated_includes(manager_required, url(r'^manage/assets/', decorated_includes(manager_required,
include(assets_manager_urls))), include(assets_manager_urls))),
url('^api/assets/set/(?P<key>[\w_:-]+)/$', api_views.view_set, url(r'^api/assets/set/(?P<key>[\w_:-]+)/$', api_views.view_set,
name='api-assets-set'), name='api-assets-set'),
] ]

View File

@ -20,7 +20,7 @@ import os
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.core.exceptions import PermissionDenied from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.files.storage import default_storage from django.core.files.storage import default_storage
from django.core.urlresolvers import reverse, reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
@ -230,9 +230,41 @@ class AssetDelete(TemplateView):
Assets(request=self.request).get_anchored_url( Assets(request=self.request).get_anchored_url(
name=os.path.basename(img_orig))) name=os.path.basename(img_orig)))
asset_delete = AssetDelete.as_view() asset_delete = AssetDelete.as_view()
class SlotAssets(ListView):
template_name = 'combo/manager_slot_assets.html'
def get_assets(self, cell):
asset_slots = cell.get_asset_slots()
assets = dict([(x.key, x) for x in Asset.objects.filter(key__in=asset_slots.keys())])
for key, value in asset_slots.items():
yield SlotAsset(
key,
name=value.get('short_label'),
asset_type=value.get('asset-type', 'image'),
asset=assets.get(key))
def get_queryset(self):
cell_reference = self.kwargs['cell_reference']
try:
cell = CellBase.get_cell(cell_reference)
except ObjectDoesNotExist:
raise Http404()
return self.get_assets(cell)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['cell_reference'] = self.kwargs['cell_reference']
return context
slot_assets = SlotAssets.as_view()
class SlotAssetUpload(FormView): class SlotAssetUpload(FormView):
form_class = AssetUploadForm form_class = AssetUploadForm
template_name = 'combo/manager_asset_upload.html' template_name = 'combo/manager_asset_upload.html'
@ -248,8 +280,18 @@ class SlotAssetUpload(FormView):
return super(SlotAssetUpload, self).form_valid(form) return super(SlotAssetUpload, self).form_valid(form)
def get_success_url(self): def get_success_url(self):
if self.request.GET.get('cell_reference'):
cell_reference = self.request.GET['cell_reference']
try:
cell = CellBase.get_cell(cell_reference)
except ObjectDoesNotExist:
pass
else:
return reverse('combo-manager-page-view', kwargs={'pk': cell.page_id}) + '#cell-' + cell_reference
return Assets(request=self.request).get_anchored_url(key=self.kwargs['key']) return Assets(request=self.request).get_anchored_url(key=self.kwargs['key'])
slot_asset_upload = SlotAssetUpload.as_view() slot_asset_upload = SlotAssetUpload.as_view()
@ -258,8 +300,18 @@ class SlotAssetDelete(TemplateView):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
Asset.objects.filter(key=kwargs['key']).delete() Asset.objects.filter(key=kwargs['key']).delete()
if self.request.GET.get('cell_reference'):
cell_reference = self.request.GET['cell_reference']
try:
cell = CellBase.get_cell(cell_reference)
except ObjectDoesNotExist:
pass
else:
return redirect(
reverse('combo-manager-page-view', kwargs={'pk': cell.page_id}) + '#cell-' + cell_reference)
return redirect(Assets(request=self.request).get_anchored_url(key=kwargs['key'])) return redirect(Assets(request=self.request).get_anchored_url(key=kwargs['key']))
slot_asset_delete = SlotAssetDelete.as_view() slot_asset_delete = SlotAssetDelete.as_view()

View File

@ -658,8 +658,13 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)):
'label': self.get_label_for_asset(), 'label': self.get_label_for_asset(),
'suffix': suffix 'suffix': suffix
} }
short_label = u'%(prefix)s%(suffix)s' % {
'prefix': slot_template_data['prefix'],
'suffix': suffix
}
slots[slot_key] = { slots[slot_key] = {
'label': label 'label': label,
'short_label': short_label,
} }
slots[slot_key].update(slot_template_data) slots[slot_key].update(slot_template_data)
return slots return slots

View File

@ -258,23 +258,23 @@ div.navigation li.nav-up::before {
width: 80%; width: 80%;
} }
#assets-browser #assets-listing table th, #assets-listing table th,
#assets-browser #assets-listing table td { #assets-listing table td {
text-align: left; text-align: left;
padding-left: 1ex; padding-left: 1ex;
} }
#assets-browser #assets-listing table td.image { #assets-listing table td.image {
padding: 0; padding: 0;
text-align: center; text-align: center;
} }
#assets-browser #assets-listing table td.actions { #assets-listing table td.actions {
width: 80px; width: 80px;
} }
#assets-browser #assets-listing table td.actions a.overwrite, #assets-listing table td.actions a.overwrite,
#assets-browser #assets-listing table td.actions a.delete { #assets-listing table td.actions a.delete {
display: inline-block; display: inline-block;
border: none; border: none;
overflow: hidden; overflow: hidden;
@ -283,7 +283,7 @@ div.navigation li.nav-up::before {
line-height: 30px; line-height: 30px;
} }
#assets-browser #assets-listing table td.actions a.delete::before { #assets-listing table td.actions a.delete::before {
text-align: center; text-align: center;
font-family: FontAwesome; font-family: FontAwesome;
content: "\f057"; /* remove-sign */ content: "\f057"; /* remove-sign */
@ -291,7 +291,7 @@ div.navigation li.nav-up::before {
width: 30px; width: 30px;
} }
#assets-browser #assets-listing table td.actions a.overwrite::before { #assets-listing table td.actions a.overwrite::before {
text-align: center; text-align: center;
font-family: FontAwesome; font-family: FontAwesome;
content: "\f093"; /* upload */ content: "\f093"; /* upload */

View File

@ -17,6 +17,7 @@
<a rel="popup" href="{% url 'combo-manager-page-delete-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Delete' %}</a> | <a rel="popup" href="{% url 'combo-manager-page-delete-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Delete' %}</a> |
<a rel="popup" href="{% url 'combo-manager-page-visibility-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Visibility' %}</a> | <a rel="popup" href="{% url 'combo-manager-page-visibility-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Visibility' %}</a> |
<a rel="popup" href="{% url 'combo-manager-page-options-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Options' %}</a> | <a rel="popup" href="{% url 'combo-manager-page-options-cell' page_pk=page.id cell_reference=cell.get_reference %}">{% trans 'Options' %}</a> |
{% if cell.can_have_assets %}<a rel="popup" data-selector="div#assets-listing" href="{% url 'combo-manager-slot-assets' cell_reference=cell.get_reference %}">{% trans 'Assets' %}</a> |{% endif %}
<a class="close-button" href="#">{% trans 'Close' %}</a> <a class="close-button" href="#">{% trans 'Close' %}</a>
{% if form %} {% if form %}
<button class="save submit-button">{% trans 'Save' %}</button> <button class="save submit-button">{% trans 'Save' %}</button>

View File

@ -1136,6 +1136,7 @@ def test_asset_management_search(app, admin_user):
resp = resp.form.submit() resp = resp.form.submit()
assert resp.text.count('<tr class="asset') == 2 assert resp.text.count('<tr class="asset') == 2
def test_asset_slots_management(app, admin_user): def test_asset_slots_management(app, admin_user):
app = login(app) app = login(app)
assert Asset.objects.count() == 0 assert Asset.objects.count() == 0
@ -1198,6 +1199,56 @@ def test_asset_slots_management(app, admin_user):
assert '>CGU<' in resp.text assert '>CGU<' in resp.text
def test_asset_slots_for_cells_management(settings, app, admin_user):
app = login(app)
assert Asset.objects.count() == 0
settings.COMBO_CELL_ASSET_SLOTS = {'data_textcell': {'picture': {'prefix': 'Picture'}}}
page = Page.objects.create(title='xxx', slug='test_cell_assets', template_name='standard')
cell = TextCell.objects.create(page=page, order=0, slug='foo')
resp = app.get('/manage/assets/slots/%s/' % cell.get_reference())
assert '>Overwrite<' in resp.text
assert '>Delete<' not in resp.text
resp = resp.click('Overwrite')
resp.form['upload'] = Upload(
'test.png',
base64.decodebytes(b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAgAABAADRWoApgAA\nAABJRU5ErkJggg=='),
'image/png')
resp = resp.form.submit()
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
assert Asset.objects.filter(key=cell.get_asset_slot_key('picture')).count() == 1
assert app.get('/assets/%s' % cell.get_asset_slot_key('picture'), status=302)['location'].endswith('test.png')
# upload a new version of image
resp = app.get('/manage/assets/slots/%s/' % cell.get_reference())
resp = resp.click('Overwrite')
resp.form['upload'] = Upload(
'test2.png',
base64.decodebytes(b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAgAABAADRWoApgAA\nAABJRU5ErkJggg=='),
'image/png')
resp = resp.form.submit()
resp = app.get('/manage/assets/slots/%s/' % cell.get_reference())
assert 'test2.png' in resp.text
assert '<img data-href' in resp.text # thumbnail
assert '>Delete<' in resp.text
assert Asset.objects.filter(key=cell.get_asset_slot_key('picture')).count() == 1
# delete the image
resp = app.get('/manage/assets/slots/%s/' % cell.get_reference())
resp = resp.click('Delete')
resp = resp.form.submit()
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
resp = app.get('/manage/assets/slots/%s/' % cell.get_reference())
assert '>Overwrite<' in resp.text
assert '>Delete<' not in resp.text
assert Asset.objects.filter(key=cell.get_asset_slot_key('picture')).count() == 0
assert app.get('/assets/%s' % cell.get_asset_slot_key('picture'), status=404)
def test_asset_slots_export(app, admin_user): def test_asset_slots_export(app, admin_user):
app = login(app) app = login(app)