Improve grid UI + disable actions for students.

pull/3064/head
Julio Montoya 6 years ago
parent 0a6a4f3194
commit a6975ceab1
  1. 20
      config/services.yaml
  2. 17
      main/exercise/exercise.class.php
  3. 7
      main/exercise/exercise.php
  4. 141
      src/ThemeBundle/Resources/views/Resource/grid.html.twig
  5. 161
      src/ThemeBundle/Resources/views/Resource/grid_theme.html.twig
  6. 135
      src/ThemeBundle/Resources/views/grid.html.twig

@ -122,7 +122,6 @@ services:
class: Chamilo\LtiBundle\Util\Utils
arguments: ['@chamilo.settings.manager']
apy_grid.factory:
class: APY\DataGridBundle\Grid\GridFactory
arguments: ['@service_container', '@apy_grid.registry']
@ -141,9 +140,22 @@ sonata_doctrine_orm_admin:
force: false # Audits are set in the admin.yml files with audit:true
# Grid default template
#apy_data_grid:
# theme: ChamiloThemeBundle::grid.html.twig
#
apy_data_grid:
theme: '@ChamiloTheme/Resource/grid_theme.html.twig'
limits: [20, 50, 100]
# persistence: false
# no_data_message: "No data"
# no_result_message: "No result"
# actions_columns_size: -1
# actions_columns_title: "Actions"
# actions_columns_separator: "<br />"
# pagerfanta:
# enable: false
# view_class: "Pagerfanta\View\DefaultView"
# options:
# prev_message: "«"
# next_message: "»"
# Course settings
chamilo_course:

@ -8363,7 +8363,7 @@ class Exercise
}
}
public static function exerciseGridResource($categoryId, $keyboard)
public static function exerciseGridResource($categoryId, $keyword)
{
$courseId = api_get_course_int_id();
$sessionId = api_get_session_id();
@ -8382,7 +8382,6 @@ class Exercise
//$category = $repo->find($categoryId);
$qb->andWhere($qb->expr()->eq('resource.exerciseCategory', $categoryId));
} else {
$qb->andWhere($qb->expr()->isNull('resource.exerciseCategory'));
}
@ -8392,6 +8391,8 @@ class Exercise
// 4. Get the grid builder.
$builder = Container::$container->get('apy_grid.factory');
$editAccess = Container::getAuthorizationChecker()->isGranted(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER);
// 5. Set parameters and properties.
$grid = $builder->createBuilder(
'grid',
@ -8399,8 +8400,8 @@ class Exercise
[
'persistence' => false,
'route' => 'home',
'filterable' => true,
'sortable' => true,
'filterable' => $editAccess,
'sortable' => $editAccess,
'max_per_page' => 10,
]
)->add(
@ -8416,6 +8417,7 @@ class Exercise
'text',
[
'title' => get_lang('Name'),
'safe' => false // does not escape html
]
);
@ -8423,13 +8425,13 @@ class Exercise
// Url link.
$grid->getColumn('title')->manipulateRenderCell(
function ($value, $row, $router) use ($course) {
//?cidReq=TEST123&id_session=0&gidReq=0&gradebook=0&origin=&exerciseId=1
function ($value, $row, $router) use ($course, $sessionId) {
$url = $router->generate(
'legacy_main',
[
'name' => 'exercise/overview.php',
'cidReq' => $course->getCode(),
'id_session' => $sessionId,
'exerciseId' => $row->getField('id'),
]
);
@ -8438,7 +8440,7 @@ class Exercise
);
// 7. Add actions
if (Container::getAuthorizationChecker()->isGranted(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)) {
if ($editAccess) {
// Add row actions
$myRowAction = new RowAction(
get_lang('Edit'),
@ -8453,7 +8455,6 @@ class Exercise
'name' => 'exercise/admin.php',
'cidReq' => $course->getCode(),
'id_session' => $sessionId,
//'choice' => 'edit',
]
);

@ -4,8 +4,6 @@
/**
* Exercise list: This script shows the list of exercises for administrators and students.
*
* @package chamilo.exercise
*
* @author Olivier Brouckaert, original author
* @author Wolfgang Schneider, code/html cleanup
* @author Julio Montoya <gugli100@gmail.com>, lots of cleanup + several improvements
@ -460,7 +458,7 @@ if ($is_allowedToEdit && $origin !== 'learnpath') {
}
// Create a search-box
$form = new FormValidator('search_simple', 'get', $currentUrl, null, null, FormValidator::LAYOUT_INLINE);
/*$form = new FormValidator('search_simple', 'get', $currentUrl, null, null, FormValidator::LAYOUT_INLINE);
$form->addCourseHiddenParams();
if (api_get_configuration_value('allow_exercise_categories')) {
@ -485,7 +483,8 @@ if ($is_allowedToEdit && $origin !== 'learnpath') {
]
);
$form->addButtonSearch(get_lang('Search'));
$actionsRight = $form->returnForm();
$actionsRight = $form->returnForm();*/
$actionsRight = '';
}
if ($is_allowedToEdit) {

@ -1,142 +1,5 @@
<style>
.grid table
{
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
border-collapse: collapse;
color: #555555;
font-size: 1em;
width: 100%;
}
{# Official grid style #}
.grid td, .grid th
{
border: 1px solid #D4E0EE;
padding: 3px 7px 2px 7px;
}
.grid th
{
background-color: #E6EDF5;
vertical-align: top;
}
.grid th a {
color: #4F76A3;
text-decoration: none;
}
.grid th a.grid-reset {
margin-left: 5px;
font-weight: normal;
}
.grid tr.even
{
background-color: #FCFDFE;
}
.grid tr.odd {
background-color: #F7F9FC;
}
.grid_header, .grid_footer {
margin: 5px 0;
}
/* Icons for order */
/* You can find this icons in the images directory of the docuementation */
th div {
height: 10px;
width: 20px;
float: right;
padding-top: 4px;
}
.grid th div.sort_up {
background: transparent url("data:image/gif;base64,R0lGODlhFwAKAIABAJCQkO/v7yH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEKAAEALAAAAAAXAAoAAAIajI+py+0GwGsxTmVDvlqe/YCQ52wmyaXqUQAAOw==") no-repeat bottom left;
}
.grid th div.sort_down {
background: transparent url("data:image/gif;base64,R0lGODlhFwAKAHAAACH5BAEAAAIALAAAAAAXAAoAgQAAAJCQkAAAAAAAAAIalI+py60RDpTRiZmwvdXozXkdKH6keKZqUwAAOw==") no-repeat bottom left;
}
/* Boolean column */
.grid .grid_boolean_true {
background: transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACl0lEQVR42q2T60uTYRiH/Tv2bnttAwlkRCGChFD7FCQSm2ZDMQ/L0nRnj7TNGDbTooychzFSSssstdqc8zB1anNrSpm47FVCzH3pQLVhdLBfzztoJlifvOEHz4fnuu7nGBe311XgOyLMnTmsz/akMBljB8OSEVFY4kpkJM5Efbp9v/C/cJ43VSrzJId0HhluBy3oW+mKpnOpGSWuExD30iFxDy3dFSZdpZkTSZHr80Y41/phe3UDpvnKaNixY60PjbNVOGTjRZJtvJ2SHE+KINOdtMHC7MSaQBkq/CXQzJ6DjqScpNp3HvY3D3B5ugIiC3dDdJMriAlk7iSDajwr2pmFWVDlPQPFTCEU0wVQTxfCvT4Ig1cJB5Hk9hxDwjWuISbIGBExncFmWINNqPAVQ/lUTsB8KKdIPPmYeOsCW6HIOtpeNMI234j4ei4TExy3J2w+Wr2L2oAGWm8RWckAlj4uQDVZiPH1oSj8c+sH2p5fgWGyGH3BTvCN1GZMIH5Ib/avdMPoV6HWr8Xnb5+i0Iev72KwZa4ealc29O6z6A92gF/zt6CHZm4tNKF98Sp0U3KYfdWIfP8Shbd+bcHy7BLKnFnQEEFLoA7tXjPoKmp7C6l3+Ab5QBrsq/dRPSmH2n0adTPlWH6/iLa5BpQOnoTCcQo6Zw7sr7uRbj0KupLaPsRkK09wgFyN2aPBY+YeKkfzoB3OgWpIBqWDDQtn48lyF4xDxeCrORu0mhLseAuJTVxpfAMVMbnL4CCS1oAZ+tEiXBiWo5VswU5gvbMIvFJOhMC7v8Z9DVwpbaJCkg4x2v1m9L60onfBCovXhLSWVPAVnBCt+gf8p+iLXCFtoPR0DcXwtZwwX8UJk44MiZ4upYR7/nt/A+w9sdKFchsrAAAAAElFTkSuQmCC") no-repeat bottom left;
display: inline-block;
text-indent: 16px;
width: 16px;
overflow: hidden;
}
.grid .grid_boolean_false {
background: transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACSElEQVR42q2Ty0vUURTHv/5SJ1SmUaGckUYdG5FyVdAicGMkFAXBtEl8gJseIP0FEVEtbNNiFm0iMMUgGKhVIUj0oqKFQ40N2TwwdewxOik6zcy953tbmD/HxFV9d/dwz+f7PXAO8I8q+bugb1xspjFdhuwlWUcSJL+SvEfhaPXgcHxbQOH6hYChCa6WlLvLm/eh1OkEAKjlJWSjUVjZpXlSBvbcehDaAshfOx8w5FB+t7eyosUPSU2DqWkAgOX2wvI0YPljFLmpD6sU6fPefhSyAbmr53wkXxTqvJ7KlhYUXo0BACou3wEArFzpB2hQ3t6JpcgkVqITKSHb/XefJCwAENHdWcux0WwMDI09GjUh2iA7/hjO1v0wVbUerVQ3AFgAoLXucfj9kNkkDA0oBkZzE4BKIAUin4hjV2sblFI9xYD6MpcLeiYJo2k7rksKhKi1ei4WR5mrBlrp+g2A0jBi7MZ1RzUV2RhB/YEIASG0VihKoOby6UVY7gY7qiji18txrDy8b7tTEaV7G5FNp6GVnitOMPwz8h47PI32Z1GEs/8Sqk6fBRUhmhAhHI0+fA+/g9Z62AYopUYKC6lUZjKCio7jNmQxeBMLwUGIrL1dJ07iRySMzMznlNZ6ZNMiTXZ3BCgy5DpwuLK6tQ25ZAK5WBzGGDiafHA0+ZCOhPHl9dgqyb6jTz+FtqzyxJkjASGDO2s87tq2g3C4qmEMkMss4tvEW2RmY/MkB449mwpte0xvTh1qJtlFYS8pm4+JHO18Hovjf+o3Xg+XX4ZLBPIAAAAASUVORK5CYII=") no-repeat bottom left;
display: inline-block;
text-indent: 16px;
width: 16px;
overflow: hidden;
}
/* Alignement */
.grid .align-left {
text-align: left;
}
.grid .align-center {
text-align: center;
}
.grid .align-right {
text-align: right;
}
/* Column filter */
.grid .grid-filter-operator select{
width: 70px;
}
.grid .grid-filter-input-query input, .grid .grid-filter-select-query select{
width: 50px;
}
.grid .grid-filter-input-query-to, .grid .grid-filter-select-query-to{
margin-left: 77px;
display: block;
}
/* Grid Search */
.grid-search {
border: 1px solid #D4E0EE;
padding: 10px;
}
.grid-search label{
width: 80px;
display: inline-block;
text-align: right;
}
.grid-search select, .grid-search .grid-filter-input-query input {
width: 150px;
}
</style>
{% if is_granted('ROLE_CURRENT_COURSE_TEACHER') %}
{# <div class="actions">#}
{# <a class="btn btn-secondary"#}
{# href="{{ url('app_document_create', { 'course': course.code, 'parent': parent_id}) }}">#}
{# {{ 'Add' | trans }}#}
{# </a>#}
{# <a class="btn btn-secondary"#}
{# href="{{ url('app_document_create_document', { 'course': course.code, 'parent': parent_id }) }}">#}
{# {{ 'AddDocument' | trans }}#}
{# </a>#}
{# </div>#}
{% endif %}
{{ grid_search(grid) }}
{#{{ grid_search(grid) }}#}
{{ grid(grid) }}

@ -0,0 +1,161 @@
{% extends 'APYDataGridBundle::blocks.html.twig' %}
{# See block documentation here: #}
{# https://github.com/APY/APYDataGridBundle/blob/master/Resources/doc/template/overriding_internal_blocks.md #}
{% block grid_actions %}
<div class="mass-actions">
<div class="btn-group" role="group">
<a class="btn btn-secondary" href="#" onclick="return {{ grid.hash }}_markVisible(true);">
{{ 'Select visible'|trans }}
</a>
<a class="btn btn-secondary" href="#" onclick="return {{ grid.hash }}_markVisible(false);">
{{ 'Deselect visible'|trans }}
</a>
<a class="btn btn-secondary" href="#" onclick="return {{ grid.hash }}_markAll(true);">
{{ 'Select all'|trans }}
</a>
<a class="btn btn-secondary" href="#" onclick="return {{ grid.hash }}_markAll(false);">
{{ 'Deselect all'|trans }}
</a>
<span class="mass-actions-selected" id="{{ grid.hash }}_mass_action_selected"></span>
</div>
{% apply spaceless %}
<div style="float:right;" class="grid_massactions">
{{ 'Action'|trans }}
<input type="hidden" id="{{ grid.hash }}_mass_action_all"
name="{{ grid.hash }}[{{ constant('APY\\DataGridBundle\\Grid\\Grid::REQUEST_QUERY_MASS_ACTION_ALL_KEYS_SELECTED') }}]"
value="0"/>
<select name="{{ grid.hash }}[{{ constant('APY\\DataGridBundle\\Grid\\Grid::REQUEST_QUERY_MASS_ACTION') }}]"
class="show-tick">
<option value="-1"></option>
{% for key, massAction in grid.massActions %}
<option value="{{ key }}">{{ massAction.title|trans }}</option>
{% endfor %}
</select>
<input class="btn btn-secondary" type="submit" value="{{ 'Submit'|trans }}"/>
</div>
{% endapply %}
</div>
{% endblock grid_actions %}
{# Bootstrap changes #}
{% block grid_column_actions_cell %}
{% set actions = column.getActionsToRender(row) %}
<div class="btn-group">
{% for action in actions %}
{% if action.attributes.form_delete is defined and action.attributes.form_delete %}
<div class="btn-group">
<form method="post" action="{{ url(action.route, column.routeParameters(row, action), false) }}">
<input type="hidden" name="_method" value="DELETE" />
<button type="submit" class="btn btn-danger">
{{ action.title|trans }}
</button>
</form>
</div>
{% else %}
<a class="btn btn-secondary"
href="{{ url(action.route, column.routeParameters(row, action), false) }}"
target="{{ action.target }}"{% if action.confirm %} onclick="return confirm('{{ action.confirmMessage }}')"{% endif %}{% for name, value in action.attributes %} {{ name }}="{{ value }}" {% endfor %}>
{{ action.title|trans }}
</a>
{% endif %}
{% endfor %}
</div>
{% endblock grid_column_actions_cell %}
{% block grid %}
<div class="col-md-12">
<div class="box box-primary">
<div class="box-body table-responsive no-padding">
{% if grid.totalCount > 0 or grid.isFiltered or grid.noDataMessage is same as(false) %}
<form id="{{ grid.hash }}" action="{{ grid.routeUrl }}"
method="post">
<div class="grid_header">
{% if grid.massActions|length > 0 %}
{{ grid_actions(grid) }}
{% endif %}
</div>
<div class="grid_body">
<table class="table table-bordered table-striped">
{% if grid.isTitleSectionVisible %}
{{ grid_titles(grid) }}
{% endif %}
{% if grid.isFilterSectionVisible %}
{{ grid_filters(grid) }}
{% endif %}
{{ grid_rows(grid) }}
</table>
</div>
<div class="grid_footer">
{% if grid.isPagerSectionVisible %}
{{ grid_pager(grid) }}
{% endif %}
{% if grid.exports|length > 0 %}
{{ grid_exports(grid) }}
{% endif %}
{% if grid.tweaks|length > 0 %}
{{ grid_tweaks(grid) }}
{% endif %}
</div>
{% if withjs %}
{{ grid_scripts(grid) }}
{% endif %}
</form>
{% else %}
{{ grid_no_data(grid) }}
{% endif %}
</div>
</div>
</div>
{% endblock grid %}
{% block grid_search %}
{% if grid.isFilterSectionVisible %}
<div class="col-md-12">
{% set searchContent %}
<form id="{{ grid.hash }}_search" action="{{ grid.routeUrl }}" method="post">
{% for column in grid.columns %}
{% if column.isFilterable and column.type not in ['actions', 'massaction'] %}
{% set columnTitle = grid.prefixTitle ~ column.title %}
<div class="{{ cycle(['odd', 'even'], loop.index) }}">
<label>{{ columnTitle|trans }}</label>
{{ grid_filter(column, grid, false)|raw }}
</div>
{% endif %}
{% endfor %}
<div class="grid-search-action">
<input type="submit" class="btn btn-secondary grid-search-submit" value="{{ 'Search'|trans }}"/>
<input type="button" class="btn btn-secondary grid-search-reset" value="{{ 'Reset'|trans }}"
onclick="return {{ grid.hash }}_reset();"/>
</div>
</form>
{% endset %}
<div class="card">
<div class="card-header"> {{ 'Filters' | trans }} </div>
<div class="card-body">
{{ searchContent }}
</div>
</div>
</div>
{% endif %}
{% endblock grid_search %}
{% block grid_column_filter_type_input %}
{% set btwOperator = constant('APY\\DataGridBundle\\Grid\\Column\\Column::OPERATOR_BTW') %}
{% set btweOperator = constant('APY\\DataGridBundle\\Grid\\Column\\Column::OPERATOR_BTWE') %}
{% set isNullOperator = constant('APY\\DataGridBundle\\Grid\\Column\\Column::OPERATOR_ISNULL') %}
{% set isNotNullOperator = constant('APY\\DataGridBundle\\Grid\\Column\\Column::OPERATOR_ISNOTNULL') %}
{% set op = column.data.operator is defined ? column.data.operator : column.defaultOperator %}
{% set from = column.data.from is defined ? column.data.from : null %}
{% set to = column.data.to is defined ? column.data.to : null %}
<div class="form-group row">
<label for="staticEmail" class="col-sm-2 col-form-label">
{{ grid_column_operator(column, grid, op, submitOnChange) }}
<input type="{{ column.inputType }}" value="{{ to }}" class="grid-filter-input-query-to" name="{{ grid.hash }}[{{ column.id }}][to]" id="{{ grid.hash }}__{{ column.id }}__query__to" {% if submitOnChange is same as (true) %}onkeypress="return {{ grid.hash }}_submitForm(event, this.form);"{% endif%} {{ ( op == btwOperator or op == btweOperator ) ? '': 'style="display: none;" disabled="disabled"' }} />
</label>
<div class="col-sm-10">
<input type="{{ column.inputType }}" value="{{ from }}" class="form-control grid-filter-input-query-from" name="{{ grid.hash }}[{{ column.id }}][from]" id="{{ grid.hash }}__{{ column.id }}__query__from" {% if submitOnChange is same as (true) %}onkeypress="return {{ grid.hash }}_submitForm(event, this.form);"{% endif%} {{ ( op == isNullOperator or op == isNotNullOperator ) ? 'style="display: none;" disabled="disabled"' : '' }} />
</div>
</div>
{% endblock grid_column_filter_type_input %}

@ -1,135 +0,0 @@
{% import "@ChamiloTheme/Macros/box.html.twig" as macro %}
{% extends 'APYDataGridBundle::blocks.html.twig' %}
{% block grid_actions %}
<div class="mass-actions">
<div class="btn-group" role="group">
{#<a class="btn btn-secondary" href="#" onclick="return {{ grid.hash }}_markVisible(true);">#}
{#{{ 'Select visible'|trans }}#}
{#</a>#}
{#<a class="btn btn-secondary" href="#" onclick="return {{ grid.hash }}_markVisible(false);">#}
{#{{ 'Deselect visible'|trans }}#}
{#</a>#}
<a class="btn btn-secondary" href="#" onclick="return {{ grid.hash }}_markAll(true);">
{{ 'Select all'|trans }}
</a>
<a class="btn btn-secondary" href="#" onclick="return {{ grid.hash }}_markAll(false);">
{{ 'Deselect all'|trans }}
</a>
<span class="mass-actions-selected" id="{{ grid.hash }}_mass_action_selected"></span>
</div>
{% apply spaceless %}
<div style="float:right;" class="grid_massactions">
{{ 'Action'|trans }}
<input type="hidden" id="{{ grid.hash }}_mass_action_all"
name="{{ grid.hash }}[{{ constant('APY\\DataGridBundle\\Grid\\Grid::REQUEST_QUERY_MASS_ACTION_ALL_KEYS_SELECTED') }}]"
value="0"/>
<select name="{{ grid.hash }}[{{ constant('APY\\DataGridBundle\\Grid\\Grid::REQUEST_QUERY_MASS_ACTION') }}]">
<option value="-1"></option>
{% for key, massAction in grid.massActions %}
<option value="{{ key }}">{{ massAction.title|trans }}</option>
{% endfor %}
</select>
<input class="btn btn-secondary" type="submit" value="{{ 'Submit Action'|trans }}"/>
</div>
{% endapply %}
</div>
{% endblock grid_actions %}
{# Bootstrap changes #}
{% block grid_column_actions_cell %}
{% set actions = column.getActionsToRender(row) %}
<div class="btn-group">
{% for action in actions %}
{% if action.attributes.form_delete is defined and action.attributes.form_delete %}
<div class="btn-group">
<form method="post" action="{{ url(action.route, column.routeParameters(row, action), false) }}">
<input type="hidden" name="_method" value="DELETE" />
<button type="submit" class="btn btn-danger">
{{ action.title|trans }}
</button>
</form>
</div>
{% else %}
<a class="btn btn-secondary"
href="{{ url(action.route, column.routeParameters(row, action), false) }}"
target="{{ action.target }}"{% if action.confirm %} onclick="return confirm('{{ action.confirmMessage }}')"{% endif %}{% for name, value in action.attributes %} {{ name }}="{{ value }}" {% endfor %}>
{{ action.title|trans }}
</a>
{% endif %}
{% endfor %}
</div>
{% endblock grid_column_actions_cell %}
{% block grid %}
<div class="col-md-10">
<div class="box box-primary">
<div class="box-body table-responsive no-padding">
{% if grid.totalCount > 0 or grid.isFiltered or grid.noDataMessage is same as(false) %}
<form id="{{ grid.hash }}" action="{{ grid.routeUrl }}"
method="post">
<div class="grid_header">
{% if grid.massActions|length > 0 %}
{{ grid_actions(grid) }}
{% endif %}
</div>
<div class="grid_body">
<table class="table table-bordered table-striped">
{% if grid.isTitleSectionVisible %}
{{ grid_titles(grid) }}
{% endif %}
{% if grid.isFilterSectionVisible %}
{{ grid_filters(grid) }}
{% endif %}
{{ grid_rows(grid) }}
</table>
</div>
<div class="grid_footer">
{% if grid.isPagerSectionVisible %}
{{ grid_pager(grid) }}
{% endif %}
{% if grid.exports|length > 0 %}
{{ grid_exports(grid) }}
{% endif %}
{% if grid.tweaks|length > 0 %}
{{ grid_tweaks(grid) }}
{% endif %}
</div>
{% if withjs %}
{{ grid_scripts(grid) }}
{% endif %}
</form>
{% else %}
{{ grid_no_data(grid) }}
{% endif %}
</div>
</div>
</div>
{% endblock grid %}
{% block grid_search %}
{% if grid.isFilterSectionVisible %}
<div class="col-md-2">
{% set searchContent %}
<form id="{{ grid.hash }}_search" action="{{ grid.routeUrl }}" method="post">
{% for column in grid.columns %}
{% if column.isFilterable and column.type not in ['actions', 'massaction'] %}
{% set columnTitle = grid.prefixTitle ~ column.title %}
<div class="{{ cycle(['odd', 'even'], loop.index) }}">
<label>{{ columnTitle|trans }}</label>
{{ grid_filter(column, grid, false)|raw }}
</div>
{% endif %}
{% endfor %}
<div class="grid-search-action">
<input type="submit" class="grid-search-submit" value="{{ 'Search'|trans }}"/>
<input type="button" class="grid-search-reset" value="{{ 'Reset'|trans }}" onclick="return {{ grid.hash }}_reset();"/>
</div>
</form>
{% endset %}
{{ macro.panel('Filters' | trans, searchContent) }}
</div>
{% endif %}
{% endblock grid_search %}
Loading…
Cancel
Save