0001-placeholder-optional-placeholders-display-and-editio.patch
combo/data/models.py | ||
---|---|---|
84 | 84 | |
85 | 85 | |
86 | 86 |
class Placeholder(object): |
87 |
def __init__(self, key, name=None, acquired=False, render=True, cell=None,
|
|
88 |
force_synchronous=False): |
|
87 |
def __init__(self, key, name=None, acquired=False, optional=False,
|
|
88 |
render=True, cell=None, force_synchronous=False):
|
|
89 | 89 |
self.key = key |
90 | 90 |
self.name = name |
91 | 91 |
self.acquired = acquired |
92 |
self.optional = optional |
|
92 | 93 |
self.render = render |
93 | 94 |
self.cell = cell |
94 | 95 |
self.force_synchronous = force_synchronous |
combo/manager/templates/combo/page_view.html | ||
---|---|---|
106 | 106 |
</div> |
107 | 107 |
{% endif %} |
108 | 108 | |
109 |
{% if optional_placeholders %} |
|
110 |
<div class="page-options"> |
|
111 |
<h3>{% trans 'Optional sections' %}</h3> |
|
112 |
<ul> |
|
113 |
{% for placeholder in optional_placeholders %} |
|
114 |
<li> |
|
115 |
{{ placeholder.name }} ({% if placeholder.is_empty %}{% trans "empty" %}{% else %}{% trans "like parent" %}{% endif %}) |
|
116 |
<a href="{% url 'combo-manager-page-view' pk=object.id %}?include-section={{ placeholder.key }}">{% trans 'edit' %}</a> |
|
117 |
</li> |
|
118 |
{% endfor %} |
|
119 |
</ul> |
|
120 |
</div> |
|
121 |
{% endif %} |
|
122 | ||
109 | 123 |
</aside> |
110 | 124 |
{% endblock %} {# sidebar #} |
111 | 125 |
combo/manager/views.py | ||
---|---|---|
124 | 124 |
return super(CreateView, self).get_initial() |
125 | 125 | |
126 | 126 |
def dispatch(self, request, *args, **kwargs): |
127 |
print(request.POST) |
|
128 | 127 |
self.parent = get_object_or_404(Page, pk=kwargs['pk']) |
129 | 128 |
return super(PageAddChildView, self).dispatch(request, *args, **kwargs) |
130 | 129 | |
... | ... | |
265 | 264 |
cells = CellBase.get_cells(page_id=self.object.id) |
266 | 265 |
template = self.object.template_name |
267 | 266 |
placeholders = [] |
267 |
optional_placeholders = [] |
|
268 | 268 |
combo_template = settings.COMBO_PUBLIC_TEMPLATES.get(template) |
269 | 269 | |
270 | 270 |
for placeholder in self.object.get_placeholders(request=self.request, traverse_cells=True): |
... | ... | |
273 | 273 |
'name': placeholder.get_name(), |
274 | 274 |
} |
275 | 275 |
placeholder_dict['cells'] = [x for x in cells if x.placeholder == placeholder.key] |
276 | ||
277 |
# not optional placeholder |
|
278 |
if not placeholder.optional: |
|
279 |
placeholders.append(placeholder_dict) |
|
280 |
continue |
|
281 | ||
282 |
# optional placeholder, but requested for edition |
|
283 |
if self.request.GET.get('include-section') == placeholder.key: |
|
284 |
placeholders.append(placeholder_dict) |
|
285 |
continue |
|
286 | ||
287 |
# empty optional placeholder: in optional sections |
|
288 |
if not placeholder_dict['cells']: |
|
289 |
placeholder_dict['is_empty'] = True |
|
290 |
optional_placeholders.append(placeholder_dict) |
|
291 |
continue |
|
292 | ||
293 |
# optional placeholder with at least 2 cells: in page edition |
|
294 |
if len(placeholder_dict['cells']) > 1: |
|
295 |
placeholders.append(placeholder_dict) |
|
296 |
continue |
|
297 | ||
298 |
# optional placeholder with only one ParentContentCell: in optional sections |
|
299 |
if isinstance(placeholder_dict['cells'][0], ParentContentCell): |
|
300 |
placeholder_dict['is_empty'] = False |
|
301 |
optional_placeholders.append(placeholder_dict) |
|
302 |
continue |
|
303 | ||
304 |
# other cases: in page edition |
|
276 | 305 |
placeholders.append(placeholder_dict) |
277 | 306 | |
278 | 307 |
context['placeholders'] = placeholders |
308 |
context['optional_placeholders'] = optional_placeholders |
|
279 | 309 | |
280 | 310 |
context.update({ |
281 | 311 |
'previous_page': self.object.get_previous_page(check_visibility=False), |
combo/public/templates/combo/page_template.html | ||
---|---|---|
38 | 38 |
<div id="footer"> |
39 | 39 |
{% block footer %} |
40 | 40 |
{% trans "Footer" as name %} |
41 |
{% placeholder "footer" name=name acquired=True %} |
|
41 |
{% placeholder "footer" name=name acquired=True optional=True %}
|
|
42 | 42 |
{% skeleton_extra_placeholder footer %} |
43 | 43 |
<span style="display: none">{% now "Y-m-d H:i:s" %}</span> {# generation time #} |
44 | 44 |
{% end_skeleton_extra_placeholder %} |
tests/test_manager.py | ||
---|---|---|
21 | 21 |
from webtest import Upload |
22 | 22 | |
23 | 23 |
from combo.wsgi import application |
24 |
from combo.data.models import Page, CellBase, TextCell, LinkCell, ConfigJsonCell, JsonCell, PageSnapshot |
|
24 |
from combo.data.models import Page, CellBase, TextCell, LinkCell, ConfigJsonCell, JsonCell, PageSnapshot, ParentContentCell
|
|
25 | 25 |
from combo.apps.assets.models import Asset |
26 | 26 |
from combo.apps.family.models import FamilyInfosCell |
27 | 27 |
from combo.apps.search.models import SearchCell |
... | ... | |
139 | 139 |
resp = resp.follow() |
140 | 140 |
assert Page.objects.all()[0].exclude_from_navigation is True |
141 | 141 | |
142 | ||
143 |
def test_edit_page_optional_placeholder(app, admin_user): |
|
144 |
Page.objects.all().delete() |
|
145 |
page = Page.objects.create(title='One', slug='one', template_name='standard') |
|
146 |
app = login(app) |
|
147 | ||
148 |
# empty placeholder footer |
|
149 |
resp = app.get('/manage/pages/%s/' % page.pk) |
|
150 |
assert len(resp.context['optional_placeholders']) == 1 |
|
151 |
assert resp.context['optional_placeholders'][0]['key'] == 'footer' |
|
152 |
assert resp.context['optional_placeholders'][0]['name'] == 'Footer' |
|
153 |
assert resp.context['optional_placeholders'][0]['is_empty'] is True |
|
154 |
assert '/manage/pages/%s/?include-section=footer' % page.pk in resp.text |
|
155 |
assert 'Footer (empty)' in resp.text |
|
156 |
assert '<div class="placeholder" data-placeholder-key="footer">' not in resp.text |
|
157 | ||
158 |
# add a ParentContentCell |
|
159 |
like_parent_cell = ParentContentCell.objects.create(page=page, placeholder='footer', order=0) |
|
160 |
resp = app.get('/manage/pages/%s/' % page.pk) |
|
161 |
assert len(resp.context['optional_placeholders']) == 1 |
|
162 |
assert resp.context['optional_placeholders'][0]['key'] == 'footer' |
|
163 |
assert resp.context['optional_placeholders'][0]['name'] == 'Footer' |
|
164 |
assert resp.context['optional_placeholders'][0]['is_empty'] is False |
|
165 |
assert '/manage/pages/%s/?include-section=footer' % page.pk in resp.text |
|
166 |
assert 'Footer (like parent)' in resp.text |
|
167 |
assert '<div class="placeholder" data-placeholder-key="footer">' not in resp.text |
|
168 | ||
169 |
# click on the edit link |
|
170 |
resp = resp.click(href='.*?include-section=footer') |
|
171 |
assert len(resp.context['optional_placeholders']) == 0 |
|
172 |
assert '<div class="placeholder" data-placeholder-key="footer">' in resp.text |
|
173 |
assert '<option data-add-url="/manage/pages/%s/add-cell-to-footer/data_textcell/default/"' % page.pk in resp.text |
|
174 | ||
175 |
# add a cell (so there is 2 cells) |
|
176 |
resp = app.get('/manage/pages/%s/add-cell-to-footer/data_textcell/default/' % page.pk) |
|
177 |
resp = app.get('/manage/pages/%s/' % page.pk) |
|
178 |
assert len(resp.context['optional_placeholders']) == 0 |
|
179 |
assert '<div class="placeholder" data-placeholder-key="footer">' in resp.text |
|
180 | ||
181 |
# remove parent content cell |
|
182 |
like_parent_cell.delete() |
|
183 |
resp = app.get('/manage/pages/%s/' % page.pk) |
|
184 |
assert len(resp.context['optional_placeholders']) == 0 |
|
185 |
assert '<div class="placeholder" data-placeholder-key="footer">' in resp.text |
|
186 | ||
187 | ||
142 | 188 |
def test_edit_page_unknown_template(app, admin_user): |
143 | 189 |
Page.objects.all().delete() |
144 | 190 |
page = Page(title='One', slug='one', template_name='broken') |
145 |
- |