wcs: card cell & link entry with file field (#71984) #8

Merged
lguerin merged 1 commits from wip/71984-wcs-card-cell-link-target-field into main 2022-12-13 08:35:34 +01:00
6 changed files with 183 additions and 43 deletions

View File

@ -33,14 +33,27 @@
</div> </div>
{% endif %} {% endif %}
{% elif item.varname == "@link@" %} {% elif item.varname == "@link@" %}
{% if item.template and item.page|default:item.url_template %} {% firstof item.link_field item.page item.url_template as link %}
{% if item.template and link %}
<div class="{{ item.cell_size|default:"" }}"> <div class="{{ item.cell_size|default:"" }}">
{% with item.page|default:item.url_template as url_key %} {% with card.custom_fields|get:item.template|force_escape as link_label %}
{% with card.custom_fields|get:item.template|force_escape as link_label and card.urls|get:url_key|force_escape as link_url %} {% if link_label %}
{% if link_label and link_url %} {% if item.link_field %}
<div class="value"><a href="{{ link_url }}"{% if item.display_mode == 'button' %} class="pk-button"{% endif %}>{{ link_label }}</a></div> {% with fields_by_varnames|get:item.link_field as field and card.fields|get:item.link_field as value %}
{% if field and value and field.type == 'file' %}
<div class="value"><a href="{% make_public_url url=value.url %}"{% if item.display_mode == 'button' %} class="pk-button"{% endif %} download="{{ value.filename }}">{{ link_label }}</a></div>
{% endif %}
{% endwith %}
{% else %}
{% with item.page|default:item.url_template as url_key %}
{% with card.urls|get:url_key|force_escape as link_url %}
{% if link_url %}
<div class="value"><a href="{{ link_url }}"{% if item.display_mode == 'button' %} class="pk-button"{% endif %}>{{ link_label }}</a></div>
{% endif %}
{% endwith %}
{% endwith %}
{% endif %} {% endif %}
{% endwith %} {% endif %}
{% endwith %} {% endwith %}
</div> </div>
{% endif %} {% endif %}

View File

@ -6,28 +6,37 @@
{% endwith %} {% endwith %}
{% endif %} {% endif %}
{% elif item.varname == "@link@" %} {% elif item.varname == "@link@" %}
{% if item.template and item.page|default:item.url_template %} {% firstof item.link_field item.page item.url_template as link %}
{% with item.page|default:item.url_template as url_key %} {% if item.template and link %}
{% with card.custom_fields|get:item.template|force_escape as link_label and card.urls|get:url_key|force_escape as link_url %} {% if not ul_display %}<td>{% endif %}
{% if not ul_display %}<td>{% endif %} {% with card.custom_fields|get:item.template|force_escape as link_label %}
{% if link_label and link_url %} {% if link_label %}
<a href="{{ link_url }}"{% if item.display_mode == 'button' %} class="pk-button"{% endif %}>{{ link_label }}</a> {% if item.link_field %}
{% with fields_by_varnames|get:item.link_field as field and card.fields|get:item.link_field as value %}
{% if field and value and field.type == 'file' %}
<a href="{% make_public_url url=value.url %}"{% if item.display_mode == 'button' %} class="pk-button"{% endif %} download="{{ value.filename }}">{{ link_label }}</a>
{% endif %}
{% endwith %}
{% else %}
{% with item.page|default:item.url_template as url_key %}
{% with card.urls|get:url_key|force_escape as link_url %}
{% if link_url %}
<a href="{{ link_url }}"{% if item.display_mode == 'button' %} class="pk-button"{% endif %}>{{ link_label }}</a>
{% endif %}
{% endwith %}
{% endwith %}
{% endif %} {% endif %}
{% if not ul_display %}</td>{% endif %} {% endif %}
{% endwith %}
{% endwith %} {% endwith %}
{% if not ul_display %}</td>{% endif %}
{% endif %} {% endif %}
{% else %} {% else %}
{% if item.varname %} {% if item.varname %}
{% with fields_by_varnames|get:item.varname as field %} {% with fields_by_varnames|get:item.varname as field and card.fields|get:item.varname as value %}
{% if field %} {% if field and value %}
{% with card.fields|get:item.varname as value %} {% if not ul_display %}<td>{% endif %}{% include "combo/wcs/card-field-value.html" with mode='inline' %}{% if not ul_display %}</td>{% endif %}
{% if value %} {% elif field %}
{% if not ul_display %}<td>{% endif %}{% include "combo/wcs/card-field-value.html" with mode='inline' %}{% if not ul_display %}</td>{% endif %} {% if not ul_display %}<td>{% endif %}{% include "combo/wcs/card-field-value.html" with mode='inline' value=item.empty_value %}{% if not ul_display %}</td>{% endif %}
{% else %}
{% if not ul_display %}<td>{% endif %}{% include "combo/wcs/card-field-value.html" with mode='inline' value=item.empty_value %}{% if not ul_display %}</td>{% endif %}
{% endif %}
{% endwith %}
{% endif %} {% endif %}
{% endwith %} {% endwith %}
{% endif %} {% endif %}

View File

@ -20,7 +20,8 @@
<th>{{ item.header|default:"" }}</th> <th>{{ item.header|default:"" }}</th>
{% endif %} {% endif %}
{% elif item.varname == "@link@" %} {% elif item.varname == "@link@" %}
{% if item.template and item.page|default:item.url_template %} {% firstof item.link_field item.page item.url_template as link %}
{% if item.template and link %}
<th>{{ item.header|default:"" }}</th> <th>{{ item.header|default:"" }}</th>
{% endif %} {% endif %}
{% else %} {% else %}

View File

@ -127,12 +127,12 @@
</p> </p>
<p> <p>
<label> <label>
{% trans "URL" %} {% trans "Link destination" %}
<select name="link_page" data-dynamic-display-parent="true"> <select name="link_page" data-dynamic-display-parent="true">
{% for page in cell.get_matching_pages %} {% for page in cell.get_matching_pages %}
<option value="{{ page.pk }}">{{ page.get_full_path_titles }}</option> <option value="{{ page.pk }}">{{ page.get_full_path_titles }}</option>
{% endfor %} {% endfor %}
<option value="">{% trans "URL template" %}</option> <option value="">{% trans "URL (Template)" %}</option>
</select> </select>
</label> </label>
</p> </p>
@ -166,7 +166,7 @@
</p> </p>
</form> </form>
</script> </script>
<script type="text/template" class="as-card wcs-cards-cell--grid-cell-tpl"> <script type="text/template" class="as-card wcs-cards-cell--grid-cell-tpl">
<div class="as-card wcs-cards-cell--grid-cell"> <div class="as-card wcs-cards-cell--grid-cell">
<div class="as-card wcs-cards-cell--grid-cell-content"></div> <div class="as-card wcs-cards-cell--grid-cell-content"></div>
<div class="as-card wcs-cards-cell--grid-cell-buttons"> <div class="as-card wcs-cards-cell--grid-cell-buttons">
@ -264,12 +264,12 @@
</p> </p>
<p> <p>
<label> <label>
{% trans "URL" %} {% trans "Link destination" %}
<select name="link_page" data-dynamic-display-parent="true"> <select name="link_page" data-dynamic-display-parent="true">
{% for page in cell.get_matching_pages %} {% for page in cell.get_matching_pages %}
<option value="{{ page.pk }}">{{ page.get_full_path_titles }}</option> <option value="{{ page.pk }}">{{ page.get_full_path_titles }}</option>
{% endfor %} {% endfor %}
<option value="">{% trans "URL template" %}</option> <option value="">{% trans "URL (Template)" %}</option>
</select> </select>
</label> </label>
</p> </p>
@ -290,7 +290,7 @@
</div> </div>
</form> </form>
</script> </script>
<script type="text/template" class="as-table wcs-cards-cell--grid-cell-tpl"> <script type="text/template" class="as-table wcs-cards-cell--grid-cell-tpl">
<div class="as-table wcs-cards-cell--grid-cell"> <div class="as-table wcs-cards-cell--grid-cell">
<div class="as-table wcs-cards-cell--grid-cell-content"></div> <div class="as-table wcs-cards-cell--grid-cell-content"></div>
<div class="as-table wcs-cards-cell--grid-cell-buttons"> <div class="as-table wcs-cards-cell--grid-cell-buttons">

View File

@ -602,12 +602,19 @@ Card_cell_custom.prototype = {
const _self = this; const _self = this;
this.grid_cell__init_form_fields(); this.grid_cell__init_form_fields();
const varname_select = this.grid_cell_form.field_varname; const varname_select = this.grid_cell_form.field_varname;
const link_select = this.grid_cell_form.link_page;
this.cardSchema.fields.forEach(function(el, id) { this.cardSchema.fields.forEach(function(el, id) {
if (el.varname) { if (el.varname) {
$('<option />') $('<option />')
.attr('value', el.varname) .attr('value', el.varname)
.text(el.label) .text(el.label)
.appendTo(varname_select); .appendTo(varname_select);
if (el.type == 'file') {
$('<option />')
.attr('value', 'field:' + el.varname)
.text(el.label + ' (' + gettext('File') + ')')
.appendTo(link_select);
}
} }
}); });
this.cardSchema.user.fields.forEach(function(el, id) { this.cardSchema.user.fields.forEach(function(el, id) {
@ -681,6 +688,11 @@ Card_cell_custom.prototype = {
cell_content = (schema_cell.template || '') + ': '; cell_content = (schema_cell.template || '') + ': ';
if (schema_cell.page) { if (schema_cell.page) {
cell_content += $(this.grid_cell_form).find('select[name="link_page"] option[value="' + schema_cell.page + '"]').text(); cell_content += $(this.grid_cell_form).find('select[name="link_page"] option[value="' + schema_cell.page + '"]').text();
} else if (schema_cell.link_field) {
let link_field = _self.field_with_varname(schema_cell.link_field)
if (link_field) {
cell_content += link_field.label + ' ( ' + gettext('File') + ')';
}
} else { } else {
cell_content += (schema_cell.url_template || ''); cell_content += (schema_cell.url_template || '');
} }
@ -762,8 +774,13 @@ Card_cell_custom.prototype = {
this.grid_cell_form.custom_template.value = ''; this.grid_cell_form.custom_template.value = '';
this.grid_cell_form.custom_display_mode.value = ''; this.grid_cell_form.custom_display_mode.value = '';
this.grid_cell_form.link_label_template.value = grid_cell.dataset.template || ''; this.grid_cell_form.link_label_template.value = grid_cell.dataset.template || '';
this.grid_cell_form.link_page.value = grid_cell.dataset.page || ''; if (grid_cell.dataset.link_field) {
this.grid_cell_form.link_url_template.value = grid_cell.dataset.url_template || ''; this.grid_cell_form.link_page.value = 'field:' + grid_cell.dataset.link_field;
this.grid_cell_form.link_url_template.value = '';
} else {
this.grid_cell_form.link_page.value = grid_cell.dataset.page || '';
this.grid_cell_form.link_url_template.value = grid_cell.dataset.url_template || '';
}
this.grid_cell_form.link_display_mode.value = grid_cell.dataset.display_mode; this.grid_cell_form.link_display_mode.value = grid_cell.dataset.display_mode;
} else { } else {
this.grid_cell_form.entry_type.value = '@field@'; this.grid_cell_form.entry_type.value = '@field@';
@ -808,8 +825,13 @@ Card_cell_custom.prototype = {
this.grid_cell_form.custom_template.value = ''; this.grid_cell_form.custom_template.value = '';
this.grid_cell_form.link_header.value = grid_cell.dataset.header || ''; this.grid_cell_form.link_header.value = grid_cell.dataset.header || '';
this.grid_cell_form.link_label_template.value = grid_cell.dataset.template || ''; this.grid_cell_form.link_label_template.value = grid_cell.dataset.template || '';
this.grid_cell_form.link_page.value = grid_cell.dataset.page || ''; if (grid_cell.dataset.link_field) {
this.grid_cell_form.link_url_template.value = grid_cell.dataset.url_template || ''; this.grid_cell_form.link_page.value = 'field:' + grid_cell.dataset.link_field;
this.grid_cell_form.link_url_template.value = '';
} else {
this.grid_cell_form.link_page.value = grid_cell.dataset.page || '';
this.grid_cell_form.link_url_template.value = grid_cell.dataset.url_template || '';
}
this.grid_cell_form.link_display_mode.value = grid_cell.dataset.display_mode; this.grid_cell_form.link_display_mode.value = grid_cell.dataset.display_mode;
} else { } else {
this.grid_cell_form.entry_type.value = '@field@'; this.grid_cell_form.entry_type.value = '@field@';
@ -861,16 +883,24 @@ Card_cell_custom.prototype = {
schema_cell.template = form_datas.custom_template; schema_cell.template = form_datas.custom_template;
delete schema_cell.page; delete schema_cell.page;
delete schema_cell.url_template; delete schema_cell.url_template;
delete schema_cell.link_field;
} else if (form_datas.entry_type == '@link@') { } else if (form_datas.entry_type == '@link@') {
schema_cell.varname = '@link@'; schema_cell.varname = '@link@';
delete schema_cell.field_content; delete schema_cell.field_content;
schema_cell.display_mode = form_datas.link_display_mode; schema_cell.display_mode = form_datas.link_display_mode;
schema_cell.template = form_datas.link_label_template; schema_cell.template = form_datas.link_label_template;
schema_cell.page = form_datas.link_page; if (form_datas.link_page.startsWith('field:')) {
if (form_datas.link_page) { schema_cell.page = '';
schema_cell.url_template = ''; schema_cell.url_template = '';
schema_cell.link_field = form_datas.link_page.substring(6);
} else { } else {
schema_cell.url_template = form_datas.link_url_template; schema_cell.page = form_datas.link_page;
if (form_datas.link_page) {
schema_cell.url_template = '';
} else {
schema_cell.url_template = form_datas.link_url_template;
}
schema_cell.link_field = '';
} }
} else { } else {
schema_cell.varname = form_datas.field_varname; schema_cell.varname = form_datas.field_varname;
@ -887,6 +917,7 @@ Card_cell_custom.prototype = {
delete schema_cell.template; delete schema_cell.template;
delete schema_cell.page; delete schema_cell.page;
delete schema_cell.url_template; delete schema_cell.url_template;
delete schema_cell.link_field;
} }
schema_cell.cell_size = form_datas.cell_size; schema_cell.cell_size = form_datas.cell_size;
} else { } else {
@ -902,11 +933,18 @@ Card_cell_custom.prototype = {
schema_cell.header = form_datas.link_header; schema_cell.header = form_datas.link_header;
schema_cell.display_mode = form_datas.link_display_mode; schema_cell.display_mode = form_datas.link_display_mode;
schema_cell.template = form_datas.link_label_template; schema_cell.template = form_datas.link_label_template;
schema_cell.page = form_datas.link_page; if (form_datas.link_page.startsWith('field:')) {
if (form_datas.link_page) { schema_cell.page = '';
schema_cell.url_template = ''; schema_cell.url_template = '';
schema_cell.link_field = form_datas.link_page.substring(6);
} else { } else {
schema_cell.url_template = form_datas.link_url_template; schema_cell.page = form_datas.link_page;
if (form_datas.link_page) {
schema_cell.url_template = '';
} else {
schema_cell.url_template = form_datas.link_url_template;
}
schema_cell.link_field = '';
} }
} else { } else {
schema_cell.varname = form_datas.field_varname; schema_cell.varname = form_datas.field_varname;

View File

@ -1056,17 +1056,28 @@ def test_card_cell_table_mode_render_custom_schema_link_entry(mock_send, context
cell.modify_global_context(context, request) cell.modify_global_context(context, request)
context['synchronous'] = True # to get fresh content context['synchronous'] = True # to get fresh content
def test(value, href, class_name): def test(value, href, class_name, is_file=False):
result = cell.render(context) result = cell.render(context)
if nb_cells > 1: if nb_cells > 1:
assert PyQuery(result).find('ul li') == [] assert PyQuery(result).find('ul li') == []
assert PyQuery(result).find('table tr:first-child td:first-child a').text() == value assert PyQuery(result).find('table tr:first-child td:first-child a').text() == value
assert PyQuery(result).find('table tr:first-child td:first-child a').attr['href'] == href if not is_file:
assert PyQuery(result).find('table tr:first-child td:first-child a').attr['href'] == href
else:
assert (
PyQuery(result)
.find('table tr:first-child td:first-child a')
.attr['href']
.startswith(href)
)
assert PyQuery(result).find('table tr:first-child td:first-child a').attr['class'] == class_name assert PyQuery(result).find('table tr:first-child td:first-child a').attr['class'] == class_name
else: else:
assert PyQuery(result).find('table tr td') == [] assert PyQuery(result).find('table tr td') == []
assert PyQuery(result).find('ul li:first-child a').text() == value assert PyQuery(result).find('ul li:first-child a').text() == value
assert PyQuery(result).find('ul li:first-child a').attr['href'] == href if not is_file:
assert PyQuery(result).find('ul li:first-child a').attr['href'] == href
else:
assert PyQuery(result).find('ul li:first-child a').attr['href'].startswith(href)
assert PyQuery(result).find('ul li:first-child a').attr['class'] == class_name assert PyQuery(result).find('ul li:first-child a').attr['class'] == class_name
test('<i>a</i> - Foo Bar', '/foo/bar/42/', None) test('<i>a</i> - Foo Bar', '/foo/bar/42/', None)
@ -1129,6 +1140,38 @@ def test_card_cell_table_mode_render_custom_schema_link_entry(mock_send, context
assert PyQuery(result).find('ul li a') == [] assert PyQuery(result).find('ul li a') == []
assert PyQuery(result).find('table tr td a') == [] assert PyQuery(result).find('table tr td a') == []
# check with field
cell.custom_schema['cells'][0]['page'] = ''
cell.custom_schema['cells'][0]['link_field'] = 'fieldd'
cell.custom_schema['cells'][0]['template'] = '{{ card.fields.fielda }} - {{ card.fields.related }}'
cell.save()
test('<i>a</i> - Foo Bar', '/api/wcs/file/', 'pk-button', is_file=True)
cell.custom_schema['cells'][0]['display_mode'] = 'link'
cell.save()
test('<i>a</i> - Foo Bar', '/api/wcs/file/', None, is_file=True)
# empty label or no value/no file field/unknown field: no link in output
result = cell.render(context)
assert PyQuery(result).find('ul li:last-child a') == []
assert PyQuery(result).find('table tr:last-child td a') == []
cell.custom_schema['cells'][0]['link_field'] = 'fielda'
cell.save()
result = cell.render(context)
assert PyQuery(result).find('ul li a') == []
assert PyQuery(result).find('table tr td a') == []
cell.custom_schema['cells'][0]['link_field'] = 'unknown'
cell.save()
result = cell.render(context)
assert PyQuery(result).find('ul li a') == []
assert PyQuery(result).find('table tr td a') == []
cell.custom_schema['cells'][0]['link_field'] = 'fieldd'
cell.custom_schema['cells'][0]['template'] = '{{ None|default:"" }}'
cell.save()
result = cell.render(context)
assert PyQuery(result).find('ul li a') == []
assert PyQuery(result).find('table tr td a') == []
@mock.patch('requests.Session.send', side_effect=mocked_requests_send) @mock.patch('requests.Session.send', side_effect=mocked_requests_send)
@pytest.mark.parametrize('with_headers', [True, False]) @pytest.mark.parametrize('with_headers', [True, False])
@ -2184,6 +2227,42 @@ def test_card_cell_card_mode_render_custom_schema_link_entry(mock_send, context,
result = cell.render(context) result = cell.render(context)
assert PyQuery(result).find('.value a') == [] assert PyQuery(result).find('.value a') == []
# check with field
cell.custom_schema['cells'][0]['page'] = ''
cell.custom_schema['cells'][0]['link_field'] = 'fieldd'
cell.custom_schema['cells'][0]['template'] = '{{ card.fields.fielda }} - {{ card.fields.related }}'
cell.save()
result = cell.render(context)
assert PyQuery(result).find('.value a').attr['href'].startswith('/api/wcs/file/')
assert PyQuery(result).find('.value a').attr['class'] == 'pk-button'
cell.custom_schema['cells'][0]['display_mode'] = 'link'
cell.save()
result = cell.render(context)
assert PyQuery(result).find('.value a').attr['href'].startswith('/api/wcs/file/')
assert PyQuery(result).find('.value a').attr['class'] is None
# empty label or no value/no file field/unknown field: no link in output
context[cell.global_context_key] = [12]
result = cell.render(context)
assert PyQuery(result).find('.value a') == []
context[cell.global_context_key] = [11]
cell.modify_global_context(context, request)
cell.repeat_index = 0
cell.custom_schema['cells'][0]['link_field'] = 'fielda'
cell.save()
result = cell.render(context)
assert PyQuery(result).find('.value a') == []
cell.custom_schema['cells'][0]['link_field'] = 'unknown'
cell.save()
result = cell.render(context)
assert PyQuery(result).find('.value a') == []
cell.custom_schema['cells'][0]['link_field'] = 'fieldd'
cell.custom_schema['cells'][0]['template'] = '{{ None|default:"" }}'
cell.save()
result = cell.render(context)
assert PyQuery(result).find('.value a') == []
@mock.patch('requests.Session.send', side_effect=mocked_requests_send) @mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_card_cell_card_mode_render_all_cards(mock_send, nocache, app): def test_card_cell_card_mode_render_all_cards(mock_send, nocache, app):