inspecteur: faire apparaître les custom views dans l'inspect formdef et carddef et enregistrer un snapshot du formdef/carddef à la modif d'une custom view (#80235) #579
|
@ -4,6 +4,7 @@
|
|||
.coverage
|
||||
/wcs/qommon/static/css/dc2/admin.css
|
||||
/wcs/qommon/static/css/qommon.css
|
||||
/wcs/qommon/static/css/item-with-image.css
|
||||
MANIFEST
|
||||
build/
|
||||
coverage.xml
|
||||
|
|
|
@ -3962,6 +3962,36 @@ def test_admin_form_inspect(pub):
|
|||
)
|
||||
assert resp.pyquery('[data-field-id="14"] .parameter-data_source a').attr['href'] == '#invalid-xxx'
|
||||
|
||||
assert '>Custom views</button>' not in resp
|
||||
|
||||
custom_view_owner = pub.custom_view_class()
|
||||
custom_view_owner.title = 'card view owner'
|
||||
custom_view_owner.formdef = formdef
|
||||
custom_view_owner.visibility = 'owner'
|
||||
custom_view_owner.store()
|
||||
custom_view_role = pub.custom_view_class()
|
||||
custom_view_role.title = 'card view role'
|
||||
custom_view_role.formdef = formdef
|
||||
custom_view_role.visibility = 'role'
|
||||
custom_view_role.store()
|
||||
custom_view_any = pub.custom_view_class()
|
||||
custom_view_any.title = 'card view any'
|
||||
custom_view_any.formdef = formdef
|
||||
custom_view_any.visibility = 'any'
|
||||
custom_view_any.store()
|
||||
custom_view_datasource = pub.custom_view_class()
|
||||
custom_view_datasource.title = 'card view datasource'
|
||||
custom_view_datasource.formdef = formdef
|
||||
custom_view_datasource.visibility = 'datasource'
|
||||
custom_view_datasource.store()
|
||||
|
||||
resp = app.get('/backoffice/forms/%s/inspect' % formdef.id)
|
||||
assert '>Custom views</button>' in resp
|
||||
assert '<h4>card view owner</h4>' not in resp
|
||||
assert '<h4>card view role</h4>' in resp
|
||||
assert '<h4>card view any</h4>' in resp
|
||||
assert '<h4>card view datasource</h4>' in resp
|
||||
|
||||
|
||||
def test_admin_form_inspect_validation(pub):
|
||||
create_superuser(pub)
|
||||
|
|
|
@ -1743,3 +1743,96 @@ def test_backoffice_folded_data_sources(pub):
|
|||
resp = resp.click('datasource view')
|
||||
assert resp.pyquery('.sidebar-custom-views').length == 2
|
||||
assert resp.pyquery('fieldset.foldable:not(.folded) .sidebar-custom-views').length == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize('formdef_class', [FormDef, CardDef])
|
||||
def test_backoffice_custom_view_and_snapshots(pub, formdef_class):
|
||||
user = create_superuser(pub)
|
||||
pub.custom_view_class.wipe()
|
||||
pub.snapshot_class.wipe()
|
||||
formdef_class.wipe()
|
||||
formdef = formdef_class()
|
||||
formdef.name = 'foo'
|
||||
formdef.fields = [
|
||||
fields.StringField(id='1', label='Test', varname='foo'),
|
||||
]
|
||||
formdef.backoffice_submission_roles = user.roles
|
||||
formdef.workflow_roles = {'_editor': user.roles[0], '_receiver': 1}
|
||||
formdef.digest_templates = {
|
||||
'default': 'plop',
|
||||
}
|
||||
formdef.store()
|
||||
|
||||
assert pub.snapshot_class.count() == 1
|
||||
app = login(get_app(pub))
|
||||
resp = app.get(formdef.get_backoffice_url())
|
||||
|
||||
resp.forms['listing-settings']['filter-1'].checked = True
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
resp.forms['save-custom-view']['title'] = 'custom test view - owner'
|
||||
resp.forms['save-custom-view']['visibility'] = 'owner'
|
||||
resp = resp.forms['save-custom-view'].submit()
|
||||
assert resp.location.endswith('/user-custom-test-view-owner/')
|
||||
resp = resp.follow()
|
||||
custom_view = pub.custom_view_class.select()[-1]
|
||||
assert custom_view.visibility == 'owner'
|
||||
assert pub.custom_view_class.count() == 1
|
||||
assert pub.snapshot_class.count() == 1 # owner custom view, no store on formdef
|
||||
|
||||
resp = resp.click('Delete')
|
||||
resp = resp.form.submit().follow()
|
||||
assert pub.custom_view_class.count() == 0
|
||||
assert pub.snapshot_class.count() == 1 # owner custom view, no store on formdef
|
||||
|
||||
resp.forms['listing-settings']['filter-1'].checked = True
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
resp.forms['save-custom-view']['title'] = 'custom test view - role'
|
||||
resp.forms['save-custom-view']['role'] = user.roles[0]
|
||||
resp.forms['save-custom-view']['visibility'] = 'role'
|
||||
resp = resp.forms['save-custom-view'].submit()
|
||||
assert resp.location.endswith('/custom-test-view-role/')
|
||||
resp = resp.follow()
|
||||
custom_view = pub.custom_view_class.select()[-1]
|
||||
assert custom_view.visibility == 'role'
|
||||
assert pub.custom_view_class.count() == 1
|
||||
assert pub.snapshot_class.count() == 2 # role custom view, store formdef
|
||||
|
||||
resp = resp.click('Delete')
|
||||
resp = resp.form.submit().follow()
|
||||
assert pub.custom_view_class.count() == 0
|
||||
assert pub.snapshot_class.count() == 3 # role custom view, store formdef
|
||||
|
||||
resp.forms['listing-settings']['filter-1'].checked = True
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
resp.forms['save-custom-view']['title'] = 'custom test view - any'
|
||||
resp.forms['save-custom-view']['visibility'] = 'any'
|
||||
resp = resp.forms['save-custom-view'].submit()
|
||||
assert resp.location.endswith('/custom-test-view-any/')
|
||||
resp = resp.follow()
|
||||
custom_view = pub.custom_view_class.select()[-1]
|
||||
assert custom_view.visibility == 'any'
|
||||
assert pub.custom_view_class.count() == 1
|
||||
assert pub.snapshot_class.count() == 4 # any custom view, store formdef
|
||||
|
||||
resp = resp.click('Delete')
|
||||
resp = resp.form.submit().follow()
|
||||
assert pub.custom_view_class.count() == 0
|
||||
assert pub.snapshot_class.count() == 5 # any custom view, store formdef
|
||||
|
||||
if formdef_class == CardDef:
|
||||
resp.forms['listing-settings']['filter-1'].checked = True
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
resp.forms['save-custom-view']['title'] = 'custom test view - datasource'
|
||||
resp.forms['save-custom-view']['visibility'] = 'datasource'
|
||||
resp = resp.forms['save-custom-view'].submit()
|
||||
assert resp.location.endswith('/custom-test-view-datasource/')
|
||||
resp = resp.follow()
|
||||
custom_view = pub.custom_view_class.select()[-1]
|
||||
assert custom_view.visibility == 'datasource'
|
||||
assert pub.custom_view_class.count() == 1
|
||||
assert pub.snapshot_class.count() == 6 # datasource custom view, store formdef
|
||||
|
||||
resp = resp.click('Delete')
|
||||
resp = resp.form.submit().follow()
|
||||
assert pub.custom_view_class.count() == 0
|
||||
assert pub.snapshot_class.count() == 7 # datasource custom view, store formdef
|
||||
|
|
|
@ -1683,6 +1683,31 @@ class FormDefPage(Directory):
|
|||
if str(x.id) in self.formdef.tracking_code_verify_fields
|
||||
]
|
||||
)
|
||||
if hasattr(self.formdef, '_custom_views'):
|
||||
# loaded from snapshot
|
||||
custom_views = self.formdef._custom_views
|
||||
else:
|
||||
custom_views = []
|
||||
for view in get_publisher().custom_view_class.select():
|
||||
if view.match(user=None, formdef=self.formdef, for_export=True):
|
||||
custom_views.append(view)
|
||||
for view in custom_views:
|
||||
view.digest_template = (self.formdef.digest_templates or {}).get(
|
||||
'custom-view:%s' % view.get_url_slug()
|
||||
)
|
||||
if view.visibility == 'role':
|
||||
role_id = view.role_id
|
||||
if role_id:
|
||||
try:
|
||||
role = get_publisher().role_class.get(role_id)
|
||||
role_label = role.name
|
||||
except KeyError:
|
||||
# removed role ?
|
||||
role_label = _('Unknown role (%s)') % role_id
|
||||
else:
|
||||
role_label = '-'
|
||||
view.role = role_label
|
||||
context['custom_views'] = sorted(custom_views, key=lambda x: getattr(x, 'title'))
|
||||
return template.QommonTemplateResponse(templates=[self.inspect_template_name], context=context)
|
||||
|
||||
|
||||
|
|
|
@ -1691,6 +1691,20 @@ class FormPage(FormdefDirectoryBase):
|
|||
custom_view.group_by = form.get_widget('group_by').parse()
|
||||
custom_view.store()
|
||||
|
||||
if custom_view.is_default and custom_view.visibility != 'datasource':
|
||||
# need to clean other views to have only one default per owner/any visibility
|
||||
for view in self.get_custom_views():
|
||||
if view.id == custom_view.id:
|
||||
continue
|
||||
if (
|
||||
custom_view.visibility == view.visibility
|
||||
and view.is_default
|
||||
and view.role_id == custom_view.role_id
|
||||
):
|
||||
view.is_default = False
|
||||
view.store()
|
||||
|
||||
formdef_stored = False
|
||||
if form.get_widget('digest_template') and custom_view.visibility != 'owner':
|
||||
if not self.formdef.digest_templates:
|
||||
self.formdef.digest_templates = {}
|
||||
|
@ -1701,6 +1715,7 @@ class FormPage(FormdefDirectoryBase):
|
|||
'custom-view:%s' % custom_view.get_url_slug()
|
||||
] = form.get_widget('digest_template').parse()
|
||||
self.formdef.store()
|
||||
formdef_stored = True
|
||||
if self.formdef.data_class().count():
|
||||
get_response().add_after_job(UpdateDigestAfterJob(formdefs=[self.formdef]))
|
||||
elif (
|
||||
|
@ -1715,19 +1730,12 @@ class FormPage(FormdefDirectoryBase):
|
|||
if old_view_digest_key in (self.formdef.digest_templates or {}):
|
||||
del self.formdef.digest_templates[old_view_digest_key]
|
||||
self.formdef.store()
|
||||
|
||||
if custom_view.is_default and custom_view.visibility != 'datasource':
|
||||
# need to clean other views to have only one default per owner/any visibility
|
||||
for view in self.get_custom_views():
|
||||
if view.id == custom_view.id:
|
||||
continue
|
||||
if (
|
||||
custom_view.visibility == view.visibility
|
||||
and view.is_default
|
||||
and view.role_id == custom_view.role_id
|
||||
):
|
||||
view.is_default = False
|
||||
view.store()
|
||||
formdef_stored = True
|
||||
if custom_view.visibility != 'owner':
|
||||
# store to always have a snapshot, except if owner view
|
||||
if not formdef_stored:
|
||||
# a snapshot will be stored only if there is changes
|
||||
self.formdef.store()
|
||||
|
||||
if self.view:
|
||||
return redirect('../' + custom_view.get_url_slug() + '/')
|
||||
|
|
|
@ -69,6 +69,7 @@ class CustomView(StorableObject):
|
|||
self.formdef_type = value.xml_root_node
|
||||
|
||||
def remove_self(self):
|
||||
super().remove_self()
|
||||
try:
|
||||
formdef = self.formdef
|
||||
except KeyError:
|
||||
|
@ -78,7 +79,9 @@ class CustomView(StorableObject):
|
|||
if view_digest_key in (formdef.digest_templates or {}):
|
||||
del formdef.digest_templates[view_digest_key]
|
||||
formdef.store()
|
||||
super().remove_self()
|
||||
elif self.visibility != 'owner':
|
||||
# a snapshot will be stored only if there is changes
|
||||
formdef.store()
|
||||
|
||||
def match(self, user, formdef, for_export=False):
|
||||
if self.formdef_type != formdef.xml_root_node:
|
||||
|
|
|
@ -2196,18 +2196,6 @@ div.mail-body {
|
|||
}
|
||||
}
|
||||
|
||||
.snapshots-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.snapshots-list .collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
p.snapshots-navigation {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sidebar-custom-views {
|
||||
.active {
|
||||
font-weight: bold;
|
||||
|
@ -2467,9 +2455,16 @@ div.timetable-widget {
|
|||
}
|
||||
}
|
||||
|
||||
.snapshots-list .counter {
|
||||
display: inline-block;
|
||||
min-width: 4em;
|
||||
.snapshots-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.snapshots-list .collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
p.snapshots-navigation {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.diff {
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
<button role="tab" aria-selected="false" aria-controls="inspect-workflow" id="tab-workflow" tabindex="-1">{% trans "Workflow" %}</button>
|
||||
<button role="tab" aria-selected="false" aria-controls="inspect-options" id="tab-options" tabindex="-1">{% trans "Options" %}</button>
|
||||
<button role="tab" aria-selected="false" aria-controls="inspect-fields" id="tab-fields" tabindex="-1">{% trans "Fields" %}</button>
|
||||
{% if custom_views %}
|
||||
<button role="tab" aria-selected="false" aria-controls="inspect-customviews" id="tab-customviews" tabindex="-1">{% trans "Custom views" %}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="pk-tabs--container">
|
||||
|
||||
|
@ -81,6 +84,33 @@
|
|||
{% include "wcs/backoffice/includes/inspect-field.html" with path=formdef.get_admin_url|add:"fields/" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div id="inspect-customviews" role="tabpanel" tabindex="0" aria-labelledby="tab-customviews" hidden>
|
||||
<div>
|
||||
{% for custom_view in custom_views %}
|
||||
<h4>{{ custom_view.title }}</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<span class='parameter'>{% trans "Visibility" %}{% trans ":" %}</span>
|
||||
{% if custom_view.visibility == 'any' %}
|
||||
{% trans "to any users" %}
|
||||
{% elif custom_view.visibility == 'datasource' %}
|
||||
{% trans "as data source" %}
|
||||
{% elif custom_view.visibility == 'role' %}
|
||||
{% trans "to role" %} ({{ custom_view.role|default:'-' }})
|
||||
{% endif %}</li>
|
||||
<li><span class='parameter'>{% trans "Default view" %}{% trans ":" %}</span> {{ custom_view.is_default|yesno }}</li>
|
||||
|
||||
<li><span class='parameter'>{% trans "Digest" %}{% trans ":" %}</span> {{ custom_view.digest_template|default:'-' }}</li>
|
||||
<li><span class='parameter'>{% trans "Columns" %}{% trans ":" %}</span> {{ custom_view.columns|default:'-' }}</li>
|
||||
<li><span class='parameter'>{% trans "Filters" %}{% trans ":" %}</span> {{ custom_view.filters|default:'-' }}</li>
|
||||
<li><span class='parameter'>{% trans "Order by" %}{% trans ":" %}</span> {{ custom_view.order_by|default:'-' }}</li>
|
||||
fpeters
commented
Comme j'ai ajouté le regroupement, il pourrait être repris ici :
Comme j'ai ajouté le regroupement, il pourrait être repris ici :
```
{% if custom_view.visibility == 'datasource' %}
<li><span class='parameter'>{% trans "Group by" %}{% trans ":" %}</span> {{ custom_view.group_by|default:'-' }}</li>
{% endif %}
```
lguerin
commented
ajouté ajouté
|
||||
{% if custom_view.visibility == 'datasource' %}
|
||||
<li><span class='parameter'>{% trans "Group by" %}{% trans ":" %}</span> {{ custom_view.group_by|default:'-' }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -68,8 +68,6 @@
|
|||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<ul class="objects-list snapshots-list">
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
|
@ -85,10 +83,6 @@
|
|||
$('.snapshots-list tr[data-day="' + day + '"]:not(.new-day)').toggleClass('collapsed');
|
||||
return false;
|
||||
});
|
||||
$('input[name="version1"]').on('click', function() {
|
||||
var next = $(this).parent('tr').next();
|
||||
$('input[name="version2"]', next).prop('checked', true);
|
||||
});
|
||||
fpeters
commented
Cette partie pourrait plutôt être corrigée,
Cette partie pourrait plutôt être corrigée,
```
- var next = $(this).parent('tr').next();
+ var next = $(this).parents('tr').next()
```
lguerin
commented
Je ne sais pas: ça n'a pas l'air d'avoir manqué, et le système de comparaison de version fait de toute façon l'inversion si version1 > version2 (ou le contraire, je ne sais plus). Et je n'ai pas repris ce JS dans combo :) Je ne sais pas: ça n'a pas l'air d'avoir manqué, et le système de comparaison de version fait de toute façon l'inversion si version1 > version2 (ou le contraire, je ne sais plus).
Autant laisser l'utilisateur cliquer là où il veut sans que ça change sa sélection ?
Et je n'ai pas repris ce JS dans combo :)
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Default view.
corrigé