admin: option to move fields when a page is moved (#49585)

This commit is contained in:
Lauréline Guérin 2021-01-07 14:42:01 +01:00
parent e833ab2ba0
commit 67abf4f379
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
3 changed files with 171 additions and 10 deletions

View File

@ -2049,16 +2049,84 @@ def test_form_fields_reorder(pub):
formdef.store()
app = login(get_app(pub))
app.get('/backoffice/forms/%s/fields/update_order?order=0;3;1;2;' % formdef.id)
# missing element in params: do nothing
resp = app.get('/backoffice/forms/%s/fields/update_order?order=0;3;1;2;' % formdef.id)
assert resp.json == {'success': 'ko'}
# missing order in params: do nothing
resp = app.get('/backoffice/forms/%s/fields/update_order?element=0' % formdef.id)
assert resp.json == {'success': 'ko'}
resp = app.get('/backoffice/forms/%s/fields/update_order?order=0;3;1;2;&element=3' % formdef.id)
assert resp.json == {'success': 'ok'}
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['0', '3', '1', '2']
# unknown id: ignored
app.get('/backoffice/forms/%s/fields/update_order?order=0;1;2;3;4;' % formdef.id)
resp = app.get('/backoffice/forms/%s/fields/update_order?order=0;1;2;3;4;&element=3' % formdef.id)
assert resp.json == {'success': 'ok'}
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['0', '1', '2', '3']
# missing id: do nothing
app.get('/backoffice/forms/%s/fields/update_order?order=0;3;1;' % formdef.id)
resp = app.get('/backoffice/forms/%s/fields/update_order?order=0;3;1;&element=3' % formdef.id)
assert resp.json == {'success': 'ko'}
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['0', '1', '2', '3']
# move a page
resp = app.get('/backoffice/forms/%s/fields/update_order?order=2;0;1;3;&element=2' % formdef.id)
assert resp.json == {'success': 'ok', 'additional-action': {
'message': 'Also move the fields of the page', 'url': 'move_page_fields?fields=3&page=2'}}
# reset
resp = app.get('/backoffice/forms/%s/fields/update_order?order=0;1;2;3;&element=2' % formdef.id)
assert resp.json == {'success': 'ok'}
# move the first page
resp = app.get('/backoffice/forms/%s/fields/update_order?order=1;2;3;0;&element=0' % formdef.id)
assert resp.json == {'success': 'ok', 'additional-action': {
'message': 'Also move the fields of the page', 'url': 'move_page_fields?fields=1&page=0'}}
def test_form_move_page_fields(pub):
create_superuser(pub)
create_role()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='2', label='2nd page', type='page'),
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='string', type='string'),
fields.StringField(id='3', label='string 2', type='string')
]
formdef.store()
app = login(get_app(pub))
# missing element in params: do nothing
app.get('/backoffice/forms/%s/fields/move_page_fields?fields=3' % formdef.id)
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['2', '0', '1', '3']
# missing order in params: do nothing
app.get('/backoffice/forms/%s/fields/move_page_fields?page=2' % formdef.id)
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['2', '0', '1', '3']
# unknown id: do nothing
app.get('/backoffice/forms/%s/fields/move_page_fields?fields=4&page=2' % formdef.id)
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['2', '0', '1', '3']
# move the fields of the page
app.get('/backoffice/forms/%s/fields/move_page_fields?fields=3&page=2' % formdef.id)
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['2', '3', '0', '1']
# move the new first page
app.get('/backoffice/forms/%s/fields/update_order?order=3;0;1;2&element=2' % formdef.id)
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['3', '0', '1', '2']
# and the fields
app.get('/backoffice/forms/%s/fields/move_page_fields?fields=3&page=2' % formdef.id)
formdef = FormDef.get(formdef.id)
assert [x.id for x in formdef.fields] == ['0', '1', '2', '3']

View File

@ -17,6 +17,7 @@
# along with this program; if not, see <http://www.gnu.org/licenses/>.
import copy
import json
from quixote import redirect
from quixote.directory import Directory
@ -213,7 +214,7 @@ class FieldsPagesDirectory(Directory):
class FieldsDirectory(Directory):
_q_exports = ['', 'update_order', 'new', 'pages']
_q_exports = ['', 'update_order', 'move_page_fields', 'new', 'pages']
field_def_page_class = FieldDefPage
blacklisted_types = []
page_id = None
@ -395,19 +396,87 @@ class FieldsDirectory(Directory):
pass
def update_order(self):
get_response().set_content_type('application/json')
request = get_request()
if 'element' not in request.form:
return json.dumps({'success': 'ko'})
if 'order' not in request.form:
return json.dumps({'success': 'ko'})
dropped_element = request.form['element']
dropped_page_index = None
new_order = request.form['order'].strip(';').split(';')
new_fields = []
# build new ordered field list
for y in new_order:
for x in self.objectdef.fields:
if x.id == y:
new_fields.append(x)
for i, x in enumerate(self.objectdef.fields):
if x.id != y:
continue
new_fields.append(x)
# if dropped field is a page, keep it's old index
if x.id == dropped_element and x.type == 'page':
dropped_page_index = i
break
# get the list of dropped page fields from old field list
page_field_ids = []
if dropped_page_index is not None:
for field in self.objectdef.fields[dropped_page_index + 1:]:
if field.type == 'page':
# next page found; break
break
page_field_ids.append(field.id)
# check new field list composition
if set(self.objectdef.fields) != set(new_fields):
return 'ko'
return json.dumps({'success': 'ko'})
self.objectdef.fields = new_fields
self.objectdef.store(comment=_('Change in order of fields'))
return 'ok'
if not page_field_ids:
return json.dumps({'success': 'ok'})
# propose to move also page fields
return json.dumps({
'success': 'ok',
'additional-action': {
'message': _('Also move the fields of the page'),
'url': 'move_page_fields?fields=%s&page=%s' % (';'.join(page_field_ids), dropped_element)
}
})
def move_page_fields(self):
request = get_request()
if 'fields' not in request.form:
return redirect('.')
if 'page' not in request.form:
return redirect('.')
field_ids = request.form['fields'].strip(';').split(';')
# keep all fields except page fields
new_fields = [f for f in self.objectdef.fields if f.id not in field_ids]
# find page fields
page_fields = [f for f in self.objectdef.fields if f.id in field_ids]
# find page in new fields, and insert page_fields
for i, field in enumerate(new_fields):
if field.id != request.form['page']:
continue
new_fields = new_fields[:i+1] + page_fields + new_fields[i+1:]
break
# check new field list composition
if set(self.objectdef.fields) != set(new_fields):
return redirect('.')
self.objectdef.fields = new_fields
self.objectdef.store(comment=_('Change in order of fields'))
return redirect('.')
def new(self):
form = Form(enctype='multipart/form-data', action = 'new')

View File

@ -8,6 +8,22 @@ $(document).ready(
$('ul.biglist.sortable li').each(function(i, elem) {
$('<span class="handle">⣿</span>').prependTo(elem);
});
const $move_page_field = $('<div class="move-page-field-content"></div>');
const $move_page_field_link = $('<a class="move-page-field-link"></a>').appendTo($move_page_field);
$move_page_field.dialog({
autoOpen: false,
minHeight: 0,
dialogClass: "move-page-field oneline-dialog feedback-on-open",
draggable: false,
open: function() {
$move_page_field.dialog('widget').removeClass('feedback-on-open');
},
close: function() {
$move_page_field.dialog('widget').addClass('feedback-on-open');
}
});
$('ul.biglist.sortable').sortable(
{
handle: '.handle',
@ -35,8 +51,16 @@ $(document).ready(
page_index += 1;
}
}
$move_page_field.dialog('close');
var order_function = $(this).data('order-function') || 'update_order';
$.post(order_function, {'order': result});
$.post(order_function, {'order': result, 'element': $(ui.item)[0].id.substr(7, 50)})
.done(function(data) {
if (data['success'] != "ok") return;
if (!data['additional-action']) return;
$move_page_field_link.attr('href', data['additional-action']['url']).html(data['additional-action']['message']);
$move_page_field.dialog('option', 'position', { my: 'left top', at: 'left bottom', of: $(ui.item) });
$move_page_field.dialog('open');
});
},
}
);