Skip to content

Commit

Permalink
feat(admin/datatable): checkable option and actions with events (#1000)
Browse files Browse the repository at this point in the history
  • Loading branch information
Davidmattei authored Sep 12, 2024
1 parent cce9f0e commit 567caa6
Show file tree
Hide file tree
Showing 5 changed files with 429 additions and 180 deletions.
39 changes: 31 additions & 8 deletions configs/admin/content-type/media_file.json
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,30 @@
"autoPublish": false,
"environment": "default",
"templates": [],
"views": [],
"views": [
{
"class": "EMS\\CoreBundle\\Entity\\View",
"arguments": [],
"properties": {
"name": "overview",
"type": "ems.view.report",
"label": "Overview",
"icon": "fa fa-list",
"options": {
"body": "{}",
"size": 0,
"template": "{{ block(\"template\", \"@EMSCH/template_ems/view/overview_media_library.twig\") }}",
"header": "{{ block(\"css\", \"@EMSCH/template_ems/view/overview_media_library.twig\") }}",
"javascript": "{{ block(\"javascript\", \"@EMSCH/template_ems/view/overview_media_library.twig\") }}"
},
"orderKey": 1,
"public": false,
"role": "ROLE_AUTHOR",
"definition": "default_overview"
},
"replaced": []
}
],
"defaultValue": null,
"versionTags": [],
"versionOptions": {
Expand All @@ -532,15 +555,15 @@
"version_tag": null
},
"roles": {
"view": "ROLE_SUPER_ADMIN",
"view": "ROLE_PUBLISHER",
"create": "ROLE_SUPER_ADMIN",
"edit": "ROLE_SUPER_ADMIN",
"publish": "ROLE_SUPER_ADMIN",
"delete": "ROLE_SUPER_ADMIN",
"trash": "not-defined",
"edit": "ROLE_PUBLISHER",
"publish": "not-defined",
"delete": "ROLE_PUBLISHER",
"trash": "ROLE_PUBLISHER",
"archive": "not-defined",
"show_link_create": "ROLE_SUPER_ADMIN",
"show_link_search": "ROLE_SUPER_ADMIN"
"show_link_create": "ROLE_PUBLISHER",
"show_link_search": "not-defined"
},
"fields": {
"display": null,
Expand Down
6 changes: 3 additions & 3 deletions configs/admin/content-type/route.json
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,9 @@
"options": {
"body": "{}",
"size": 0,
"template": "{% set columns = [] %}\r\n{% set columns = columns|merge([\r\n {\r\n \"label\": \"#\",\r\n \"template\": \"{{ data.source.order|default(999) }}\",\r\n \"orderField\": \"order\"\r\n },{\r\n \"label\": \"Name\",\r\n \"template\": '<a href=\"' ~ \"{{path('data.revisions', {ouuid: data.id, type: data.contentType} ) }}\"~'\">' ~\"{{ data.source.name }}</a>\",\r\n \"orderField\": \"name\"\r\n },{\r\n \"label\": \"Path\",\r\n \"template\": \"\r\n {% set path = attribute(data.source.config|default({})|ems_json_decode, 'path')|default('N/A') %}\r\n {% if path is iterable %}\r\n <ul>\r\n {% for l, item in path %}\r\n <li>{{ l }} : {{ item }}</li>\r\n {% endfor %}\r\n </ul>\r\n {% else %}\r\n <span class=\"~'\"'~\"{% if attribute(data.source.config|default({})|ems_json_decode, 'path') is not defined %}text-gray{% endif %}\"~'\"'~\">{{ path }}</span>\r\n {% endif %}\r\n \"\r\n },{\r\n \"label\": \"Template\",\r\n \"template\": \"<span class=\"~'\"'~\"{% if data.source.template_static is not defined %}text-gray{% endif %}\"~'\"'~\">{{ data.source.template_static|default('N/A')|data_link }}</span>\"\r\n },{\r\n \"label\": \"Query\",\r\n \"template\": \"{{ data.source.query is defined ? 'Yes' : 'No' }}\"\r\n }\r\n]) %}\r\n\r\n{% set columnLive %}{% verbatim %}\r\n <i style=\"color: {{ docInfo.published('live') and docInfo.aligned('live') ? 'green' : 'red' }}\" \r\n class=\"{{ docInfo.published('live') and docInfo.aligned('live') ? 'fa fa-check' : 'fa fa-eye-slash' }}\"></i>\r\n{% endverbatim %}{% endset %}\r\n\r\n{% set columns = columns|merge([\r\n {\r\n \"label\": \"Last Update\", \r\n \"template\": '\r\n <div style=\"width: 130px;\" data-toggle=\"tooltip\" data-placement=\"top\" aria-hidden=\"true\" title=\"By {{ data.source._finalized_by }}\" >\r\n {{ data.source._finalization_datetime|default ? data.source._finalization_datetime|date(\"d/m/Y (H:i)\") : \"N.A.\" }}\r\n </div>\r\n ', \r\n \"orderField\": \"_finalization_datetime\"\r\n },\r\n { \"label\": \"Live\", \"template\": columnLive|format },\r\n {\r\n \"label\": \"Action\",\r\n \"template\": '\r\n <div class=\"btn-group btn-group-sm\" style=\"width: 130px;\">\r\n <a href=\"{{ docInfo.draft ? path(\"ems_revision_edit\", {revisionId: revisionId}) : docInfo.aligned(\"live\") ? path(\"revision.new-draft\", {type: data.contentType, ouuid: data.id }) : path(\"revision.publish_to\", {revisionId: revisionId, envId: liveId, redirectToUrl: path(\"data.customindexview\", {viewId: '~view.id~'})}) }}\" class=\"btn btn-default\" style=\"width: 100px;\">\r\n {{ docInfo.draft ? \"Edit draft\" : docInfo.aligned(\"live\") ? \"Edit\" : \"Publish in live\" }}\r\n </a>\r\n <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"false\">\r\n <span class=\"caret\">\r\n </span>\r\n <span class=\"sr-only\">Toggle Dropdown\r\n </span>\r\n </button>\r\n <ul class=\"dropdown-menu\" role=\"menu\">\r\n <li>\r\n <a href=\"{{ path(\"data.revisions\", {ouuid: data.id, type: data.contentType} ) }}\">Revision</a>\r\n </li>\r\n {% if docInfo.draft %}\r\n <li><a href=\"{{ path(\"revision.publish_to\", {revisionId: revisionId, envId: previewId}) }}\">Publish in preview</a></li>\r\n {% elseif not docInfo.aligned(\\'live\\') %}\r\n <li><a href=\"{{ path(\"revision.new-draft\", {type: data.contentType, ouuid: data.id }) }}\">Edit</a></li>\r\n {% endif %}\r\n </ul>\r\n </div>\r\n ',\r\n \"orderField\": \"_finalization_datetime\" \r\n }\r\n]) %}\r\n\r\n{% set must = {} %}\r\n{% set filterQuery = [ {\r\n \"multi_match\": {\r\n \"fields\": [\r\n \"live_search\",\r\n \"live_search._2gram\",\r\n \"live_search._3gram\"\r\n ],\r\n \"query\": \"%query%\",\r\n \"operator\": \"and\", \r\n \"type\": \"bool_prefix\"\r\n \r\n } } ] %}\r\n\r\n{{ emsco_datatable(['preview'],[contentType.name], {\r\n \"frontendOptions\": { \"pageLength\": 100, \"order\": [[(columns|length - 3), 'desc']] },\r\n \"default_sort\": { \"_finalization_datetime\": \"desc\", \"_score\": \"asc\" },\r\n \"empty_query\": must,\r\n \"query\": { \"bool\": { \"must\": must|merge(filterQuery) } },\r\n \"row_context\": \"{% set docInfo = [line.data.contentType, line.data.id]|join(':')|emsco_document_info %}{% set revisionId = line.data.id|get_revision_id(line.data.contentType) %}{% set liveId = 3 %}{% set previewId = 2 %}\",\r\n \"columns\": columns\r\n}) }}",
"header": null,
"javascript": "<script>\r\n $('#DataTables_Table_0').on( 'draw.dt', function () {\r\n $('[data-toggle=\"tooltip\"]').tooltip();\r\n });\r\n</script>"
"template": "{{ block(\"template\", \"@EMSCH/template_ems/view/overview.twig\") }}",
"header": "{{ block(\"css\", \"@EMSCH/template_ems/view/overview.twig\") }}",
"javascript": "{{ block(\"javascript\", \"@EMSCH/template_ems/view/overview.twig\") }}"
},
"orderKey": 3,
"public": false,
Expand Down
138 changes: 138 additions & 0 deletions skeleton/template_ems/view/base_overview.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
{%- block renderDatatable -%}
{% set requestQuery = app.request.query %}
{% set filterTerms = [] %}

{% for filterName, f in filters|default([]) %}
{% set field = f.field|default(filterName) %}
{% set fieldValue = requestQuery.get(filterName, f.defaultValue|default([])) %}

{% set current = attribute(filterTerms, field)|default([]) %}
{% if fieldValue|length > 0 %}
{% set filterTerms = filterTerms|merge({ (field) : (current|merge(fieldValue)) }) %}
{% endif %}
{% endfor %}

{% set emptyMust = [] %}
{% for field, terms in filterTerms|default([]) %}
{% set emptyMust = emptyMust|merge([{ 'terms': { (field) : (terms) } }]) %}
{% endfor %}

{% set queryMust = emptyMust|merge([ {
'multi_match': {
'fields': ['live_search', 'live_search._2gram', 'live_search._3gram'],
'query': '%query%',
'operator': 'and',
'type': 'bool_prefix'
}
}]) %}

{% if filters is defined %}
{% with { 'filters' : filters, 'filterTerms': filterTerms } %}
{{ block('filters') }}
{% endwith %}
{% endif %}

{{ emsco_datatable([env.name],[contentType.name], {
'frontendOptions': { 'pageLength': 100, 'order': [] },
'query': { 'bool': { 'must': queryMust } },
'empty_query': {'bool': { 'must': emptyMust } },
'row_context': rowContext,
'columns': columns
}|merge(dataTableOptions|default({}))) }}
{%- endblock -%}

{% block css %}{% endblock %}

{% block javascript %}
<script type="text/javascript">
window.addEventListener('emsReady', function () {
let filterForm = document.getElementById('form-filters');
if (document.body.contains(filterForm)) {
filterForm.addEventListener('change', function () { filterForm.submit(); });
}
$('#DataTables_Table_0').on( 'draw.dt', function () {
$('[data-toggle="tooltip"]').tooltip();
});
});
</script>
{% endblock %}

{% block filters %}
{# handle search filters #}
{% for filterName, f in filters|filter(v => v.type|default(false) == 'search') %}
{% set query = {
'index': env.alias,
'size': 500,
'_source': [f.search_field],
'body': { 'query': { 'term': { '_contenttype': { 'value': (f.search_contentType) } } } } ,
} %}
{% if f.search_sort is defined %}{% set query = query|merge({ 'sort': [ { (f.search_sort) :{'order':'asc'} } ] }) %}{% endif %}

{% set search = query|search.hits.hits %}
{% set options = {} %}
{% for h in search %}
{% set options = options|merge({ (attribute(h._source, f.search_field)): ("#{h._source._contenttype}:#{h._id}") }) %}
{% endfor %}

{% set filters = filters|merge({ (filterName) : (f|merge({'options': options })) }) %}
{% endfor %}

{# handle aggs filters #}
{% for filterName, f in filters|filter(v => v.agg is defined) %}
{% set field = f.field|default(filterName) %}
{% set aggsMust = [{ 'term': { '_contenttype': { 'value': (contentType.name) } } }] %}

{% for field, terms in filterTerms|filter((v,k) => k != field) %}
{% set aggsMust = aggsMust|merge([{ 'terms': { (field) : (terms) } }]) %}
{% endfor %}

{% set aggOrder = f.agg_sort is defined ? { '_term': (f.agg_sort|default('asc')) } : { '_count': 'desc' } %}

{% set aggSearch = {
'index': env.alias,
'size': 0,
'body': {
'query': { 'bool': { 'must' : (aggsMust) } },
'aggs': { 'count': { 'terms': { 'field': (f.agg), 'size': 500, 'order': (aggOrder) } } }
}
}|search.aggregations.count.buckets|default([]) %}

{% set aggOptions = {} %}

{% if f.search_sort is defined %}
{% for optionLabel, optionValue in f.options %}
{% set b = aggSearch|filter(v => v.key == optionValue)|first %}
{% if b %}
{% set aggOptions = aggOptions|merge({ ("#{optionLabel} (#{b.doc_count})"): (b.key) }) %}
{% endif %}
{% endfor %}
{% else %}
{% for b in aggSearch %}
{% set bucketKey = b.key_as_string|default(b.key) %}
{% set optionLabel = f.options|default([])|filter(v => v == bucketKey)|keys|first|default(bucketKey) %}
{% set aggOptions = aggOptions|merge({ ("#{optionLabel} (#{b.doc_count})"): (b.key_as_string|default(bucketKey)) }) %}
{% endfor %}
{% endif %}

{% set filters = filters|merge({ (filterName) : (f|merge({'options': aggOptions })) }) %}
{% endfor %}
<div class="row">
<div class="col-sm-12 pb-5">
<form method="GET" id="form-filters">
{% for filterName, f in filters %}
{% set field = f.field|default(filterName) %}
{% set filterSelection = attribute(filterTerms, field)|default([]) %}
<div class="form-group col-md-2">
<select name="{{ filterName }}[]" title="{{ f.label|default(filterName|capitalize) }}" id="filter-{{ filterName }}" class="selectpicker form-control input-sm" {{ f.multiple|default(true) ? 'multiple' }}>
{% for optionsLabel,optionValue in f.options|default([]) %}
<option value="{{ optionValue }}" {{ optionValue in filterSelection ? 'selected' }}>{{ optionsLabel }}</option>
{% endfor %}
</select>
</div>
{% endfor %}
</form>
</div>
</div>
{% endblock %}
Loading

0 comments on commit 567caa6

Please sign in to comment.