Projet

Général

Profil

0001-cards-empty-digest-template-when-datasource-custom-v.patch

Lauréline Guérin, 22 octobre 2020 10:32

Télécharger (9,47 ko)

Voir les différences:

Subject: [PATCH] cards: empty digest template when datasource custom views
 (#46862)

 tests/test_cards_admin_pages.py | 60 +++++++++++++++++++++++++++++++++
 wcs/admin/forms.py              | 33 +++++++++++++++---
 wcs/backoffice/cards.py         | 25 ++------------
 wcs/carddef.py                  | 20 ++++++++++-
 4 files changed, 110 insertions(+), 28 deletions(-)
tests/test_cards_admin_pages.py
137 137
    resp = resp.form.submit('submit').follow()
138 138

  
139 139

  
140
def test_card_digest_template(pub, studio):
141
    create_superuser(pub)
142

  
143
    CardDef.wipe()
144
    carddef = CardDef()
145
    carddef.name = 'foo'
146
    carddef.fields = [
147
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
148
    ]
149
    carddef.digest_template = 'X{{ form_var_foo }}Y'
150
    carddef.store()
151
    carddef.data_class().wipe()
152
    carddata = carddef.data_class()()
153
    carddata.data = {'1': 'bar'}
154
    carddata.store()
155

  
156
    custom_view = pub.custom_view_class()
157
    custom_view.title = 'card view'
158
    custom_view.formdef = carddef
159
    custom_view.columns = {'list': [{'id': 'id'}]}
160
    custom_view.filters = {'filter-1': True, 'filter-1-value': 'FOO'}
161
    custom_view.visibility = 'datasource'
162
    custom_view.store()
163

  
164
    # carddef not used in formdef, it's ok to empty digest_template
165
    FormDef.wipe()
166

  
167
    app = login(get_app(pub))
168
    resp = app.get('/backoffice/cards/%s/options/templates' % carddef.id)
169
    resp.form['digest_template'] = ''
170
    resp = resp.form.submit().follow()
171
    carddef = CardDef.get(carddef.id)
172
    assert carddef.digest_template is None
173
    assert 'Existing cards will be updated in the background.' in resp.text
174

  
175
    carddef.digest_template = '{{ form_var_foo }}'
176
    carddef.store()
177

  
178
    # a formdef using the carddef as datasource
179
    FormDef.wipe()
180
    formdef = FormDef()
181
    formdef.name = 'test card def on data source'
182
    formdef.fields = [
183
        fields.ItemField(id='1', label='item', data_source={'type': 'carddef:foo'})
184
    ]
185
    formdef.store()
186

  
187
    # carddef used in formdef, can not empty digest_template
188
    resp = app.get('/backoffice/cards/%s/options/templates' % carddef.id)
189
    resp.form['digest_template'] = ''
190
    resp = resp.form.submit()
191
    assert 'Can not empty digest template: this card model is used as data source in some forms.' in resp.text
192
    carddef = CardDef.get(carddef.id)
193
    assert carddef.digest_template is not None
194

  
195
    # error: not stored, and no after jobs
196
    resp = app.get('/backoffice/cards/%s/' % carddef.id)
197
    assert 'Existing cards will be updated in the background.' not in resp.text
198

  
199

  
140 200
def test_card_custom_view_data_source(pub, studio):
141 201
    user = create_superuser(pub)
142 202
    Role.wipe()
wcs/admin/forms.py
40 40
from wcs.qommon.afterjobs import AfterJob
41 41

  
42 42
from wcs.formdef import FormDef, FormdefImportError, FormdefImportRecoverableError
43
from wcs.carddef import CardDef
43 44
from wcs.categories import Category
44 45
from wcs.roles import Role, logged_users_role, get_user_roles
45 46
from wcs.workflows import Workflow
......
279 280
                for formdata in self.formdef.data_class().select(order_by='id'):
280 281
                    formdata.store()
281 282
            job = get_response().add_after_job(N_('Updating digests'), update)
282
            get_session().message = ('info',
283
                    _('Existing forms will be updated in the background.'))
283
            if isinstance(self.formdef, CardDef):
284
                get_session().message = ('info',
285
                        _('Existing cards will be updated in the background.'))
286
            else:
287
                get_session().message = ('info',
288
                        _('Existing forms will be updated in the background.'))
284 289
        return result
285 290

  
286 291
    def handle(self, form, title):
......
302 307
            for attr in attrs:
303 308
                widget = form.get_widget(attr)
304 309
                if widget:
310
                    if hasattr(self, 'clean_%s' % attr):
311
                        has_error = getattr(self, 'clean_%s' % attr)(form)
312
                        if has_error:
313
                            continue
305 314
                    if attr == 'geoloc_label':
306 315
                        if widget.parse():
307 316
                            self.formdef.geolocations = {'base': widget.parse()}
......
312 321
                        if getattr(self.formdef, attr, None) != new_value:
313 322
                            self.changed = True
314 323
                            setattr(self.formdef, attr, new_value)
315
            self.formdef.store(comment=_('Changed "%s" parameters') % title)
316
            return redirect('..')
324
            if not form.has_errors():
325
                self.formdef.store(comment=_('Changed "%s" parameters') % title)
326
                return redirect('..')
317 327

  
318 328
        html_top('forms', title=self.formdef.name)
319 329
        r = TemplateIO(html=True)
......
321 331
        r += form.render()
322 332
        return r.getvalue()
323 333

  
334
    def clean_digest_template(self, form):
335
        if not isinstance(self.formdef, CardDef):
336
            return False
337

  
338
        widget = form.get_widget('digest_template')
339
        new_value = widget.parse()
340
        if new_value:
341
            return False
342

  
343
        if any(self.formdef.usage_in_formdefs()):
344
            widget.set_error(_('Can not empty digest template: this card model is used as data source in some forms.'))
345
            return True
346

  
347
        return False
348

  
324 349

  
325 350
class WorkflowRoleDirectory(Directory):
326 351
    def __init__(self, formdef):
wcs/backoffice/cards.py
27 27
from ..qommon.storage import NotEqual, Null
28 28

  
29 29
from wcs.carddef import CardDef
30
from wcs.formdef import get_formdefs_of_all_kinds
31 30
from wcs.roles import Role
32 31
from wcs.workflows import Workflow
33 32
from wcs.admin.forms import FormsDirectory, FormDefPage, FormDefUI, html_top
......
167 166
        r += self.get_preview()
168 167
        r += htmltext('</div>')
169 168

  
170
        formdefs = self.usage_in_formdefs()
169
        formdefs = list(self.formdef.usage_in_formdefs())
171 170
        if formdefs:
171
            formdefs.sort(key=lambda x: x.name.lower())
172 172
            r += htmltext('<div class="bo-block">')
173 173
            r += htmltext('<h3>%s</h3>') % _('Forms')
174 174
            r += htmltext('<p>%s ') % _('This card model is used as data source in the following forms:')
......
177 177
            r += htmltext('</div>')
178 178
        return r.getvalue()
179 179

  
180
    def usage_in_formdefs(self):
181
        def is_used_in_formdef(formdef):
182
            for field in formdef.fields or []:
183
                data_source = getattr(field, 'data_source', None)
184
                if not (data_source and data_source.get('type')):
185
                    continue
186
                data_source_id = 'carddef:%s' % self.formdef.url_name
187
                if data_source.get('type') == data_source_id:
188
                    return True
189
                if data_source.get('type').startswith('%s:' % data_source_id):
190
                    # custom view
191
                    return True
192
            return False
193

  
194
        formdefs = []
195
        for formdef in get_formdefs_of_all_kinds():
196
            if is_used_in_formdef(formdef):
197
                formdefs.append(formdef)
198
        formdefs.sort(key=lambda x: x.name.lower())
199
        return formdefs
200

  
201 180
    def duplicate(self):
202 181
        response = super(CardDefPage, self).duplicate()
203 182
        self.formdefui.formdef.disabled = False
wcs/carddef.py
22 22
from .qommon.storage import Contains, Equal, NotEqual, ILike
23 23

  
24 24
from wcs.carddata import CardData
25
from wcs.formdef import FormDef
25
from wcs.formdef import FormDef, get_formdefs_of_all_kinds
26 26

  
27 27
if not hasattr(types, 'ClassType'):
28 28
    types.ClassType = type
......
209 209
        if order_by is None:
210 210
            items.sort(key=lambda x: misc.simplify(x['text']))
211 211
        return items
212

  
213
    def usage_in_formdefs(self):
214
        def is_used_in_formdef(formdef):
215
            for field in formdef.fields or []:
216
                data_source = getattr(field, 'data_source', None)
217
                if not (data_source and data_source.get('type')):
218
                    continue
219
                data_source_id = 'carddef:%s' % self.url_name
220
                if data_source.get('type') == data_source_id:
221
                    return True
222
                if data_source.get('type').startswith('%s:' % data_source_id):
223
                    # custom view
224
                    return True
225
            return False
226

  
227
        for formdef in get_formdefs_of_all_kinds():
228
            if is_used_in_formdef(formdef):
229
                yield formdef
212
-