0001-manager-associate-a-page-to-a-card-model-68675.patch
combo/apps/wcs/utils.py | ||
---|---|---|
102 | 102 |
if not order: |
103 | 103 |
return matching_pages |
104 | 104 |
return Page.get_as_reordered_flat_hierarchy(matching_pages) |
105 | ||
106 | ||
107 |
def get_wcs_matching_card_model(sub_slug): |
|
108 |
card_models = get_wcs_options('/api/cards/@list') |
|
109 |
for carddef_reference, card_label in card_models: |
|
110 |
card_id = '%s_id' % carddef_reference.split(':')[1] |
|
111 |
if '<%s>' % card_id in sub_slug or sub_slug == card_id: |
|
112 |
return carddef_reference, card_label |
combo/data/models.py | ||
---|---|---|
64 | 64 |
from django.utils.translation import gettext_lazy as _ |
65 | 65 | |
66 | 66 |
from combo import utils |
67 |
from combo.apps.wcs.utils import get_wcs_matching_card_model, is_wcs_enabled |
|
67 | 68 |
from combo.utils import NothingInCacheException |
68 | 69 | |
69 | 70 |
from .fields import RichTextField, TemplatableURLField |
... | ... | |
273 | 274 |
return None |
274 | 275 |
return os.path.splitext(self.picture.name)[-1] |
275 | 276 | |
277 |
def get_sub_slug_details(self): |
|
278 |
if not self.sub_slug: |
|
279 |
return |
|
280 | ||
281 |
if not is_wcs_enabled(None): |
|
282 |
return self.sub_slug, None |
|
283 |
result = get_wcs_matching_card_model(self.sub_slug) |
|
284 |
if not result: |
|
285 |
return self.sub_slug, None |
|
286 |
return self.sub_slug.replace('-', '_'), result[1] |
|
287 | ||
276 | 288 |
def save(self, *args, **kwargs): |
277 | 289 |
if 'update_fields' in kwargs: |
278 | 290 |
return super().save(*args, **kwargs) |
combo/manager/forms.py | ||
---|---|---|
26 | 26 |
from django.utils.translation import gettext_lazy as _ |
27 | 27 | |
28 | 28 |
from combo import utils |
29 |
from combo.apps.wcs.utils import get_wcs_matching_card_model, get_wcs_options |
|
29 | 30 |
from combo.data.forms import get_page_choices |
30 | 31 |
from combo.data.models import Page, ParentContentCell, SiteSettings, compile_sub_slug |
31 | 32 | |
... | ... | |
151 | 152 |
model = Page |
152 | 153 |
fields = ('slug', 'sub_slug') |
153 | 154 | |
155 |
def __init__(self, *args, **kwargs): |
|
156 |
super().__init__(*args, **kwargs) |
|
157 | ||
158 |
if self.instance.sub_slug: |
|
159 |
result = get_wcs_matching_card_model(self.instance.sub_slug) |
|
160 |
if result: |
|
161 |
del self.fields['sub_slug'] |
|
162 | ||
154 | 163 |
def clean_slug(self): |
155 | 164 |
value = self.cleaned_data.get('slug') |
156 | 165 |
if self.instance.slug == value: |
... | ... | |
172 | 181 |
return value |
173 | 182 | |
174 | 183 | |
184 |
class PageEditLinkedCardForm(forms.ModelForm): |
|
185 |
carddef_reference = forms.ChoiceField( |
|
186 |
label=_('Linked card model'), |
|
187 |
required=False, |
|
188 |
) |
|
189 | ||
190 |
class Meta: |
|
191 |
model = Page |
|
192 |
fields = [] |
|
193 | ||
194 |
def __init__(self, *args, **kwargs): |
|
195 |
super().__init__(*args, **kwargs) |
|
196 | ||
197 |
card_models = get_wcs_options('/api/cards/@list') |
|
198 |
self.fields['carddef_reference'].choices = [('', '-----')] + card_models |
|
199 | ||
200 |
if self.instance.sub_slug: |
|
201 |
result = get_wcs_matching_card_model(self.instance.sub_slug) |
|
202 |
if result: |
|
203 |
self.initial['carddef_reference'] = result[0] |
|
204 | ||
205 |
def save(self, commit=True, *args, **kwargs): |
|
206 |
super().save(commit=False, *args, **kwargs) |
|
207 | ||
208 |
if self.cleaned_data.get('carddef_reference'): |
|
209 |
self.instance.sub_slug = '%s_id' % self.cleaned_data['carddef_reference'].split(':')[1] |
|
210 |
else: |
|
211 |
self.instance.sub_slug = '' |
|
212 | ||
213 |
if commit: |
|
214 |
self.instance.save() |
|
215 |
return self.instance |
|
216 | ||
217 | ||
175 | 218 |
class PageEditDescriptionForm(forms.ModelForm): |
176 | 219 |
class Meta: |
177 | 220 |
model = Page |
combo/manager/static/css/combo.manager.scss | ||
---|---|---|
481 | 481 |
opacity: 0.5; |
482 | 482 |
} |
483 | 483 | |
484 |
h2 span.extra-info { |
|
485 |
font-size: 60%; |
|
486 |
} |
|
487 | ||
484 | 488 |
img.page-picture { |
485 | 489 |
max-width: 100%; |
486 | 490 |
max-height: 250px; |
combo/manager/templates/combo/page_view.html | ||
---|---|---|
4 | 4 |
{% load thumbnail %} |
5 | 5 | |
6 | 6 |
{% block appbar %} |
7 |
<h2>{% trans 'Page' %} - {{ object.title }}</h2> |
|
7 |
{% with object.get_sub_slug_details as sub_slug_details %} |
|
8 |
<h2>{% trans 'Page' %} - {{ object.title }}{% if with_wcs and sub_slug_details.1 %} <span class="extra-info">({% blocktrans with card_model=sub_slug_details.1 %}page linked to card model "{{ card_model }}"{% endblocktrans %})</span>{% endif %}</h2> |
|
9 |
{% endwith %} |
|
8 | 10 |
<span class="actions"> |
9 | 11 |
<a class="extra-actions-menu-opener"></a> |
10 | 12 |
<a class="action-see-online" href="{{ object.get_online_url }}">{% trans 'See online' %}</a> |
... | ... | |
12 | 14 |
<li><a class="action-history" href="{% url 'combo-manager-page-history' pk=object.id %}">{% trans 'History' %}</a></li> |
13 | 15 |
<li><a {% if page_has_subpages %}rel="popup" data-autoclose-dialog="true" {% endif %}class="action-export" href="{% url 'combo-manager-page-export' pk=object.id %}">{% trans 'Export' %}</a></li> |
14 | 16 |
<li><a class="action-edit-page-variables" rel="popup" href="{% url 'combo-manager-page-edit-extra-variables' pk=object.id %}">{% trans "Edit extra page variables" %}</a></li> |
17 |
{% if with_wcs %} |
|
18 |
<li><a class="action-edit-page-linked-card" rel="popup" href="{% url 'combo-manager-page-edit-linked-card' pk=object.id %}">{% trans "Link a card model" %}</a></li> |
|
19 |
{% endif %} |
|
15 | 20 |
{% if perms.data.add_page %} |
16 | 21 |
<li><a class="action-add-child" rel="popup" href="{% url 'combo-manager-page-add-child' pk=object.id %}">{% trans 'Add a child page' %}</a></li> |
17 | 22 |
<li><a class="action-edit-roles" rel="popup" href="{% url 'combo-manager-page-edit-roles' pk=object.id %}">{% trans 'Manage edit roles' %}</a></li> |
... | ... | |
40 | 45 |
(<a rel="popup" href="{% url 'combo-manager-page-edit-title' pk=object.id %}">{% trans 'change' %}</a>) |
41 | 46 |
</p> |
42 | 47 | |
43 |
<p> |
|
44 |
<label>{% trans 'Slug:' %}</label> |
|
45 |
<tt>{{ object.slug }}{% if object.sub_slug %}/<span class="subslug">{{ object.sub_slug }}</span>{% endif %}</tt> |
|
46 |
(<a rel="popup" href="{% url 'combo-manager-page-edit-slug' pk=object.id %}">{% trans 'change' %}</a>) |
|
47 |
</p> |
|
48 |
{% with object.get_sub_slug_details as sub_slug_details %} |
|
49 |
<p> |
|
50 |
<label>{% trans 'Slug:' %}</label> |
|
51 |
<tt>{{ object.slug }}{% if sub_slug_details and not sub_slug_details.1 %}/<span class="subslug">{{ sub_slug_details.0 }}</span>{% endif %}</tt> |
|
52 |
(<a rel="popup" href="{% url 'combo-manager-page-edit-slug' pk=object.id %}">{% trans 'change' %}</a>) |
|
53 |
</p> |
|
54 |
{% endwith %} |
|
48 | 55 | |
49 | 56 |
<p> |
50 | 57 |
<label>{% trans 'Description:' %}</label> |
combo/manager/urls.py | ||
---|---|---|
52 | 52 |
name='combo-manager-page-edit-include-in-navigation', |
53 | 53 |
), |
54 | 54 |
re_path(r'^pages/(?P<pk>\d+)/slug$', views.page_edit_slug, name='combo-manager-page-edit-slug'), |
55 |
re_path( |
|
56 |
r'^pages/(?P<pk>\d+)/linked-card$', |
|
57 |
views.page_edit_linked_card, |
|
58 |
name='combo-manager-page-edit-linked-card', |
|
59 |
), |
|
55 | 60 |
re_path(r'^pages/(?P<pk>\d+)/title$', views.page_edit_title, name='combo-manager-page-edit-title'), |
56 | 61 |
re_path( |
57 | 62 |
r'^pages/(?P<pk>\d+)/description$', |
combo/manager/views.py | ||
---|---|---|
54 | 54 |
) |
55 | 55 | |
56 | 56 |
from combo import plugins |
57 |
from combo.apps.wcs.utils import is_wcs_enabled |
|
57 | 58 |
from combo.data.library import get_cell_class |
58 | 59 |
from combo.data.models import CellBase, LinkListCell, Page, PageSnapshot, ParentContentCell, SiteSettings |
59 | 60 |
from combo.data.utils import ( |
... | ... | |
75 | 76 |
PageEditDescriptionForm, |
76 | 77 |
PageEditExtraVariablesFormSet, |
77 | 78 |
PageEditIncludeInNavigationForm, |
79 |
PageEditLinkedCardForm, |
|
78 | 80 |
PageEditPictureForm, |
79 | 81 |
PageEditRedirectionForm, |
80 | 82 |
PageEditRolesForm, |
... | ... | |
335 | 337 |
page_edit_slug = PageEditSlugView.as_view() |
336 | 338 | |
337 | 339 | |
340 |
class PageEditLinkedCardView(PageEditView): |
|
341 |
form_class = PageEditLinkedCardForm |
|
342 |
comment = _('changed linked card') |
|
343 | ||
344 | ||
345 |
page_edit_linked_card = PageEditLinkedCardView.as_view() |
|
346 | ||
347 | ||
338 | 348 |
class PageEditDescriptionView(PageEditView): |
339 | 349 |
form_class = PageEditDescriptionForm |
340 | 350 |
comment = _('changed description') |
... | ... | |
441 | 451 |
context['cell_type_groups'] = list(cell_type_groups.items()) |
442 | 452 |
context['cell_type_groups'].sort(key=lambda x: x[0]) |
443 | 453 |
context['page_has_subpages'] = self.object.get_children().exists() |
454 |
context['with_wcs'] = is_wcs_enabled(None) |
|
444 | 455 | |
445 | 456 |
self.object.prefetched_cells = cells |
446 | 457 |
placeholders = [] |
tests/wcs/test_card.py | ||
---|---|---|
3154 | 3154 | |
3155 | 3155 | |
3156 | 3156 |
def test_page_snapshot_with_old_card_cells(): |
3157 |
""" |
|
3158 |
page_serialization = { |
|
3159 |
'cells': [{ |
|
3160 |
'model': 'data.parentcontentcell', |
|
3161 |
'fields': { |
|
3162 |
'slug': '', |
|
3163 |
'order': 0, |
|
3164 |
'groups': [], |
|
3165 |
'public': True, |
|
3166 |
'condition': None, |
|
3167 |
'placeholder': 'footer', |
|
3168 |
'template_name': None, |
|
3169 |
'extra_css_class': '', |
|
3170 |
'last_update_timestamp': '2022-08-08T13:55:29.599Z', |
|
3171 |
'restricted_to_unlogged': False, |
|
3172 |
'page': 14 |
|
3173 |
} |
|
3174 |
}, { |
|
3175 |
'model': 'wcs.wcscardinfoscell', |
|
3176 |
'fields': { |
|
3177 |
'slug': 'enfant', |
|
3178 |
'limit': None, |
|
3179 |
'order': 1, |
|
3180 |
'groups': [], |
|
3181 |
'public': True, |
|
3182 |
'card_ids': '', |
|
3183 |
'condition': '', |
|
3184 |
'title_type': 'auto', |
|
3185 |
'placeholder': 'content', |
|
3186 |
'custom_title': '', |
|
3187 |
'display_mode': 'card', |
|
3188 |
'without_user': False, |
|
3189 |
'custom_schema': {}, |
|
3190 |
'only_for_user': False, |
|
3191 |
'template_name': None, |
|
3192 |
'extra_css_class': '', |
|
3193 |
'carddef_reference': 'eservices:test-related-enfant', |
|
3194 |
'related_card_path': '', |
|
3195 |
'last_update_timestamp': '2022-08-11T13:57:43.362Z', |
|
3196 |
'restricted_to_unlogged': False, |
|
3197 |
'page': 14 |
|
3198 |
} |
|
3199 |
}, { |
|
3200 |
'model': 'wcs.wcscardinfoscell', |
|
3201 |
'fields': { |
|
3202 |
'slug': '', |
|
3203 |
'limit': None, |
|
3204 |
'order': 2, |
|
3205 |
'groups': [], |
|
3206 |
'public': True, |
|
3207 |
'card_ids': '', |
|
3208 |
'condition': '', |
|
3209 |
'title_type': 'auto', |
|
3210 |
'placeholder': 'content', |
|
3211 |
'custom_title': '', |
|
3212 |
'display_mode': 'card', |
|
3213 |
'without_user': False, |
|
3214 |
'custom_schema': {}, |
|
3215 |
'only_for_user': False, |
|
3216 |
'template_name': None, |
|
3217 |
'extra_css_class': '', |
|
3218 |
'carddef_reference': 'eservices:test-related-adulte:par-defaut', |
|
3219 |
'related_card_path': 'enfant/block_parents_parent', |
|
3220 |
'last_update_timestamp': '2022-08-08T19:53:02.097Z', |
|
3221 |
'restricted_to_unlogged': False, |
|
3222 |
'page': 14 |
|
3223 |
} |
|
3224 |
}, { |
|
3225 |
'model': 'wcs.wcscardinfoscell', |
|
3226 |
'fields': { |
|
3227 |
'slug': '', |
|
3228 |
'limit': None, |
|
3229 |
'order': 3, |
|
3230 |
'groups': [], |
|
3231 |
'public': True, |
|
3232 |
'card_ids': '', |
|
3233 |
'condition': '', |
|
3234 |
'title_type': 'empty', |
|
3235 |
'placeholder': 'content', |
|
3236 |
'custom_title': 'Les parents !', |
|
3237 |
'display_mode': 'table', |
|
3238 |
'without_user': False, |
|
3239 |
'custom_schema': {}, |
|
3240 |
'only_for_user': False, |
|
3241 |
'template_name': None, |
|
3242 |
'extra_css_class': '', |
|
3243 |
'carddef_reference': 'eservices:test-related-adulte:par-defaut', |
|
3244 |
'related_card_path': 'enfant/block_parents_parent', |
|
3245 |
'last_update_timestamp': '2022-08-11T13:07:35.757Z', |
|
3246 |
'restricted_to_unlogged': False, |
|
3247 |
'page': 14 |
|
3248 |
} |
|
3249 |
}], |
|
3250 |
'fields': { |
|
3251 |
'slug': 'related-enfant', |
|
3252 |
'order': 6, |
|
3253 |
'title': 'Related enfant', |
|
3254 |
'groups': [], |
|
3255 |
'parent': ['search-related'], |
|
3256 |
'public': True, |
|
3257 |
'picture': '', |
|
3258 |
'snapshot': None, |
|
3259 |
'sub_slug': 'test-related-enfant_id', |
|
3260 |
'edit_role': None, |
|
3261 |
'description': '', |
|
3262 |
'redirect_url': '', |
|
3263 |
'template_name': 'standard', |
|
3264 |
'extra_variables': {}, |
|
3265 |
'creation_timestamp': '2022-08-08T13:55:29.502Z', |
|
3266 |
'subpages_edit_role': None, |
|
3267 |
'placeholder_options': {}, |
|
3268 |
'last_update_timestamp': '2022-08-11T13:57:43.369Z', |
|
3269 |
'exclude_from_navigation': True |
|
3270 |
}, |
|
3271 |
'model': 'data.page', |
|
3272 |
'pk': 14 |
|
3273 |
} |
|
3274 |
""" |
|
3275 | 3157 |
page = Page.objects.create(title='xxx', slug='test_snapshots', template_name='standard') |
3276 | 3158 |
PageSnapshot.take(page) |
3277 | 3159 |
snapshot = page.pagesnapshot_set.first() |
... | ... | |
3415 | 3297 |
new_card_page = Page.objects.get(slug='card') |
3416 | 3298 |
new_cell = WcsCardCell.objects.get() |
3417 | 3299 |
assert new_cell.custom_schema['cells'][0]['page'] == '' |
3300 | ||
3301 | ||
3302 |
@mock.patch('requests.Session.send', side_effect=mocked_requests_send) |
|
3303 |
def test_page_edit_linked_card(mock_send, app, admin_user): |
|
3304 |
page = Page.objects.create(title='One', slug='one', template_name='two') |
|
3305 | ||
3306 |
app = login(app) |
|
3307 |
resp = app.get('/manage/pages/%s/' % page.pk) |
|
3308 | ||
3309 |
resp = resp.click(href='.*/linked-card') |
|
3310 |
assert [o[0] for o in resp.form['carddef_reference'].options] == [ |
|
3311 |
'', |
|
3312 |
'default:card_model_1', |
|
3313 |
'default:card_model_2', |
|
3314 |
'default:card_model_3', |
|
3315 |
'default:card_a', |
|
3316 |
'default:card_b', |
|
3317 |
'default:card_c', |
|
3318 |
'default:card_d', |
|
3319 |
'default:card_e', |
|
3320 |
'other:card_model_1', |
|
3321 |
'other:card_model_2', |
|
3322 |
'other:card_model_3', |
|
3323 |
'other:card_a', |
|
3324 |
'other:card_b', |
|
3325 |
'other:card_c', |
|
3326 |
'other:card_d', |
|
3327 |
'other:card_e', |
|
3328 |
] |
|
3329 |
resp.form['carddef_reference'] = 'default:card_model_3' |
|
3330 |
resp = resp.form.submit().follow() |
|
3331 |
page.refresh_from_db() |
|
3332 |
assert page.sub_slug == 'card_model_3_id' |
|
3333 |
resp = app.get('/manage/pages/%s/slug' % page.pk) |
|
3334 |
assert 'sub_slug' not in resp.context['form'].fields |
|
3335 | ||
3336 |
resp = app.get('/manage/pages/%s/linked-card' % page.pk) |
|
3337 |
assert resp.form['carddef_reference'].value == 'default:card_model_3' |
|
3338 |
resp.form['carddef_reference'] = '' |
|
3339 |
resp = resp.form.submit().follow() |
|
3340 |
page.refresh_from_db() |
|
3341 |
assert page.sub_slug == '' |
|
3342 | ||
3343 |
resp = app.get('/manage/pages/%s/slug' % page.pk) |
|
3344 |
assert 'sub_slug' in resp.context['form'].fields |
|
3345 |
resp.form['sub_slug'] = 'foobar' |
|
3346 |
resp = resp.form.submit().follow() |
|
3347 |
page.refresh_from_db() |
|
3348 |
assert page.sub_slug == 'foobar' |
|
3418 |
- |