Projekt

Obecné

Profil

« Předchozí | Další » 

Revize dd522430

Přidáno uživatelem Filip Jani před téměř 6 roky(ů)

Re #7217 přidání datagridů

Zobrazit rozdíly:

app/bootstrap.php
17 17
$configurator->addConfig(__DIR__ . '/config/config.neon');
18 18
$configurator->addConfig(__DIR__ . '/config/config.local.neon');
19 19
$configurator->addConfig(__DIR__ . '/config/model.neon');
20
$configurator->addConfig(__DIR__ . '/config/components.neon');
20 21

  
21 22
$container = $configurator->createContainer();
22 23

  
app/component/ExampleGrid.php
1
<?php
2

  
3

  
4
namespace App\Components;
5

  
6

  
7
use App\Utils\DataGrid\DataGrid;
8
use Model\Repository\LineRepository;
9
use Ublaboo\DataGrid\Exception\DataGridException;
10

  
11
/**
12
 * Ukázkový datagrid, bude smazán při předání
13
 *  - všechny možnosti použití gridu lze vidět na
14
 *  https://gitlab.com/Fifal/dvm/blob/21afc037e3604093197e140defc05925df0b8c28/web-project/app/components/variant/VariantGrid.php
15
 *
16
 * @package App\Components
17
 */
18
class ExampleGrid extends DataGrid
19
{
20
    /** @var LineRepository */
21
    private $lineRepository;
22

  
23
    public function __construct(LineRepository $lineRepository)
24
    {
25
        $this->lineRepository = $lineRepository;
26

  
27
        parent::__construct();
28
    }
29

  
30
    /**
31
     * Abstraktní metoda, slouží k nastavení primárního klíče a nastavení datasource
32
     *  1. $this->setPrimaryKey();
33
     *  2. $this->setDataSource();
34
     *
35
     * @throws DataGridException
36
     */
37
    public function init()
38
    {
39
        $this->setPrimaryKey(LineRepository::COLUMN_ID);
40
        $this->setDataSource($this->lineRepository->findAll());
41
    }
42

  
43
    /**
44
     * Definice sloupečků, akcí, vyhledávácích filtrů gridu
45
     *
46
     * @throws DataGridException
47
     */
48
    public function define()
49
    {
50
        $this->addColumnNumber(LineRepository::COLUMN_ID, "ID");
51
        $this->addColumnText(LineRepository::COLUMN_TRANSLITERATION, "Transliterace");
52
        $this->addFilterText(LineRepository::COLUMN_TRANSLITERATION, "Transliterace");
53

  
54
        $this->addAction(LineRepository::COLUMN_TRANSLITERATION, "Smazat");
55
    }
56
}
57

  
58
interface IExampleGirdFactory
59
{
60
    /**
61
     * Funkce create je implementována již v předkovi
62
     *
63
     * @return ExampleGrid
64
     */
65
    public function create();
66
}
app/config/components.neon
1
services:
2
    # Gridy
3
    - App\Components\IExampleGirdFactory
4

  
5
    # Formuláře
app/presenters/HomepagePresenter.php
2 2

  
3 3
namespace App\Presenters;
4 4

  
5
use App\Components\IExampleGirdFactory;
5 6
use Nette;
6 7

  
7 8

  
8 9
final class HomepagePresenter extends Nette\Application\UI\Presenter
9 10
{
11
    /** @var IExampleGirdFactory  */
12
    private $exampleGridFactory;
13

  
14
    public function __construct(IExampleGirdFactory $exampleGridFactory)
15
    {
16
        parent::__construct();
17

  
18
        $this->exampleGridFactory = $exampleGridFactory;
19
    }
20

  
21
    public function actionDefault(){
22

  
23
    }
24

  
25
    public function createComponentDataGrid(){
26
        return $this->exampleGridFactory->create();
27
    }
10 28
}
app/presenters/templates/@layout.latte
1 1
<!DOCTYPE html>
2 2
<html>
3 3
<head>
4
	<meta charset="utf-8">
5
	<meta name="viewport" content="width=device-width">
4
    <meta charset="utf-8">
5
    <meta name="viewport" content="width=device-width">
6 6

  
7
	<title>{ifset title}{include title|stripHtml} | {/ifset}Nette Web</title>
7
    <title>{ifset title}{include title|stripHtml} | {/ifset}Nette Web</title>
8

  
9
    <!-- jQuery -->
10
    <script
11
            src="https://code.jquery.com/jquery-3.3.1.min.js"
12
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
13
            crossorigin="anonymous"></script>
14

  
15
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.js"
16
            integrity="sha256-wqAoCRn9//AnHSl4qbXVhqdvmgFQqN5Elqp4Eb2wOXA=" crossorigin="anonymous"></script>
17

  
18
    <!-- Bootstrap CDN -->
19
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"
20
          integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
21
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"
22
            integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T"
23
            crossorigin="anonymous"></script>
24

  
25
    <!-- Bootstrap Select -->
26
    <link rel="stylesheet"
27
          href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.4/css/bootstrap-select.min.css">
28
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.4/js/bootstrap-select.min.js"></script>
29

  
30
    <!-- Bootstrap Datepicker -->
31
    <link rel="stylesheet"
32
          href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker3.min.css"
33
          integrity="sha256-mlKJFBS1jbZwwDrZD1ApO7YFS6MA1XDN37jZ9GDFC64=" crossorigin="anonymous"/>
34
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js"
35
            integrity="sha256-tW5LzEC7QjhG0CiAvxlseMTs2qJS7u3DRPauDjFJ3zo=" crossorigin="anonymous"></script>
36
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/locales/bootstrap-datepicker.cs.min.js"
37
            integrity="sha256-pbW7ult8QcDlimj+JQplrsCieqCvQ/8VGr7ZdTuev8c=" crossorigin="anonymous"></script>
38

  
39
    <!-- Font awesome -->
40
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css"
41
          integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
42

  
43

  
44
    <script src="https://nette.github.io/resources/js/netteForms.min.js"></script>
45
    <script src="{$basePath}/js/nette.ajax.js"></script>
8 46
</head>
9 47

  
10 48
<body>
11
	<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">{$flash->message}</div>
49
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">{$flash->message}</div>
12 50

  
13
	{include content}
51
{include content}
14 52

  
15
	{block scripts}
16
	<script src="https://nette.github.io/resources/js/netteForms.min.js"></script>
17
	{/block}
53
{block scripts}
54
    <script>
55
        $(function () {
56
            $.nette.init();
57
        });
58
    </script>
59
{/block}
18 60
</body>
19 61
</html>
app/presenters/templates/Homepage/default.latte
1 1
{* This is the welcome page, you can delete it *}
2 2

  
3 3
{block content}
4
<div id="banner">
5
	<h1 n:block=title>Congratulations!</h1>
6
</div>
7 4

  
8
<div id="content">
9
	<h2>You have successfully created your <a href="https://nette.org">Nette</a> Web project.</h2>
10

  
11
	<p><img src="data:image/png;base64,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" alt="">
12
	If you are exploring Nette for the first time, you should read the
13
	<a href="https://doc.nette.org/quickstart">Quick Start</a>, <a href="https://doc.nette.org">documentation</a>,
14
	<a href="https://pla.nette.org">tutorials</a> and <a href="https://forum.nette.org">forum</a>.</p>
15

  
16
	<h2>We hope you enjoy Nette!</h2>
17
</div>
18

  
19
<style>
20
	html { font: normal 18px/1.3 Georgia, "New York CE", utopia, serif; color: #666; -webkit-text-stroke: 1px rgba(0,0,0,0); overflow-y: scroll; }
21
	body { background: #3484d2; color: #333; margin: 2em auto; padding: 0 .5em; max-width: 600px; min-width: 320px; }
22

  
23
	a { color: #006aeb; padding: 3px 1px; }
24
	a:hover, a:active, a:focus { background-color: #006aeb; text-decoration: none; color: white; }
25

  
26
	#banner { border-radius: 12px 12px 0 0; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAB5CAMAAADPursXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGBQTFRFD1CRDkqFDTlmDkF1D06NDT1tDTNZDk2KEFWaDTZgDkiCDTtpDT5wDkZ/DTBVEFacEFOWD1KUDTRcDTFWDkV9DkR7DkN4DkByDTVeDC9TDThjDTxrDkeADkuIDTRbDC9SbsUaggAAAEdJREFUeNqkwYURgAAQA7DH3d3335LSKyxAYpf9vWCpnYbf01qcOdFVXc14w4BznNTjkQfsscAdU3b4wIh9fDVYc4zV8xZgAAYaCMI6vPgLAAAAAElFTkSuQmCC); }
27

  
28
	h1 { font: inherit; color: white; font-size: 50px; line-height: 121px; margin: 0; padding-left: 4%; background: url(https://files.nette.org/images/logo-nette@2.png) no-repeat 95%; background-size: 130px auto; text-shadow: 1px 1px 0 rgba(0, 0, 0, .9); }
29
	@media (max-width: 600px) {
30
		h1 { background: none; font-size: 40px; }
31
	}
32

  
33
	#content { background: white; border: 1px solid #eff4f7; border-radius: 0 0 12px 12px; padding: 10px 4%; overflow: hidden; }
34

  
35
	h2 { font: inherit; padding: 1.2em 0; margin: 0; }
36

  
37
	img { border: none; float: right; margin: 0 0 1em 3em; }
38
</style>
5
<div class="container">
6
    <div class="row">
7
        <div class="col-md-12">
8
            {control dataGrid}
9
        </div>
10
    </div>
11
</div>
app/utils/datagrid/DataGrid.php
1
<?php
2

  
3
namespace App\Utils\DataGrid;
4

  
5
use Nette\ComponentModel\IContainer;
6
use Nette\Database\Table\Selection;
7
use Ublaboo\DataGrid\Column\ColumnDateTime;
8
use Ublaboo\DataGrid\Column\ColumnNumber;
9
use Ublaboo\DataGrid\Column\ColumnText;
10
use Ublaboo\DataGrid\DataGrid as BaseDataGrid;
11
use Ublaboo\DataGrid\Exception\DataGridException;
12
use Ublaboo\DataGrid\Filter\FilterText;
13
use Ublaboo\DataGrid\Localization\SimpleTranslator;
14

  
15
/**
16
 * Třída DataGrid poskytuje DataGrid s českou lokalizací, šablonou pro Bootstrap 4 a vyhledáváním s použitím LIKE
17
 * @package App\Utils\DataGrid
18
 */
19
abstract class DataGrid extends BaseDataGrid
20
{
21
    /**
22
     * DataGrid konstruktor.
23
     * @param IContainer|null $parent
24
     * @param null $name
25
     */
26
    public function __construct(IContainer $parent = null, $name = null)
27
    {
28
        parent::__construct($parent, $name);
29

  
30
        $translator = new SimpleTranslator([
31
            'ublaboo_datagrid.no_item_found_reset' => 'Žádné položky nenalezeny. Filtr můžete vynulovat',
32
            'ublaboo_datagrid.no_item_found' => 'Žádné položky nenalezeny.',
33
            'ublaboo_datagrid.here' => 'zde',
34
            'ublaboo_datagrid.items' => 'Položky',
35
            'ublaboo_datagrid.all' => 'všechny',
36
            'ublaboo_datagrid.from' => 'z',
37
            'ublaboo_datagrid.reset_filter' => 'Resetovat filtr',
38
            'ublaboo_datagrid.group_actions' => 'Hromadné akce',
39
            'ublaboo_datagrid.show_all_columns' => 'Zobrazit všechny sloupce',
40
            'ublaboo_datagrid.hide_column' => 'Skrýt sloupec',
41
            'ublaboo_datagrid.action' => 'Akce',
42
            'ublaboo_datagrid.previous' => 'Předchozí',
43
            'ublaboo_datagrid.next' => 'Další',
44
            'ublaboo_datagrid.choose' => 'Vyberte',
45
            'ublaboo_datagrid.execute' => 'Provést',
46
            'ublaboo_datagrid.show_default_columns' => 'Zobrazit výchozí sloupce',
47
            'ublaboo_datagrid.filter_submit_button' => 'Filtrovat',
48

  
49
            'Name' => 'Jméno',
50
            'Inserted' => 'Vloženo'
51
        ]);
52

  
53
        $this->setTranslator($translator);
54

  
55
        $this->setTemplateFile(__DIR__ . '/templates/datagrid.latte');
56

  
57
        $this->setColumnsHideable();
58

  
59
        $this->setAutoSubmit(false);
60

  
61
        $this->setStrictSessionFilterValues(false);
62

  
63
        $this->init();
64

  
65
        $this->define();
66
    }
67

  
68
    /**
69
     * Abstraktní metoda, slouží k nastavení primárního klíče a nastavení datasource
70
     *  1. $this->setPrimaryKey();
71
     *  2. $this->setDataSource();
72
     *
73
     * @throws DataGridException
74
     */
75
    public abstract function init();
76

  
77
    /**
78
     * Definice sloupečků, akcí, vyhledávácích filtrů gridu
79
     *
80
     * @throws DataGridException
81
     */
82
    public abstract function define();
83

  
84
    /**
85
     * Vrací vytvořený datagrid - používáno v továrničkách
86
     *
87
     * @return $this
88
     */
89
    public function create()
90
    {
91
        return $this;
92
    }
93

  
94
    /**
95
     * Nastavuje každý sloupeček řaditelný jako výchozí nastavení
96
     *
97
     * @param string $key : column name
98
     * @param string $name : filter label
99
     * @param null $column
100
     * @return null|ColumnText
101
     */
102
    public function addColumnText($key, $name, $column = null): ColumnText
103
    {
104
        $column = parent::addColumnText($key, $name, $column);
105
        $column->setSortable();
106

  
107
        return $column;
108
    }
109

  
110
    /**
111
     * Nastavuje každý sloupeček řaditelný jako výchozí nastavení
112
     *
113
     * @param string $key : column name
114
     * @param string $name : filter label
115
     * @param null $column
116
     * @return ColumnNumber
117
     */
118
    public function addColumnNumber($key, $name, $column = null): ColumnNumber
119
    {
120
        $column = parent::addColumnNumber($key, $name, $column);
121
        $column->setSortable();
122

  
123
        return $column;
124
    }
125

  
126
    /**
127
     * Nastavuje každý sloupeček řaditelný jako výchozí nastavení
128
     *
129
     * @param string $key : column name
130
     * @param string $name : filter label
131
     * @param null $column
132
     * @return ColumnDateTime
133
     */
134
    public function addColumnDateTime($key, $name, $column = null): ColumnDateTime
135
    {
136
        $column = parent::addColumnDateTime($key, $name, $column);
137
        $column->setSortable();
138

  
139
        return $column;
140
    }
141

  
142
    /**
143
     * Umožňění filtrování sloupečků s textem podle jeho jednotlivých částí pomocí LIKE SQL commandu
144
     *
145
     * @param string $key : column name
146
     * @param string $name : filter label
147
     * @param null $columns
148
     * @return FilterText
149
     * @throws DataGridException
150
     */
151
    public function addFilterText($key, $name, $columns = null): FilterText
152
    {
153
        $filterText = parent::addFilterText($key, $name, $columns);
154

  
155
        $filter = parent::getFilter($key);
156

  
157
        $filter->setCondition(function ($selection, $value) use ($key)
158
        {
159
            /** @var Selection $selection */
160
            $selection->where($key . ' LIKE', '%' . $value . '%');
161
        });
162

  
163
        return $filterText;
164
    }
165
}
app/utils/datagrid/templates/column_multi_action.latte
1
{**
2
 * @param $multi_action Ublaboo\DataGrid\Column\MultiAction
3
 *}
4

  
5
<div class="dropdown">
6
	{$multi_action->renderButton()|noescape}
7
	<ul class="dropdown-menu">
8
		<li n:foreach="$multi_action->getActions() as $actionKey => $action">
9
			{continueIf !$multi_action->testRowCondition($actionKey, $row)}
10

  
11
			{if $action->hasTemplate()}
12
				{include $action->getTemplate(), item => $row->getItem(), (expand) $action->getTemplateVariables(), row => $row}
13
			{else}
14
				{$action->render($row)|noescape}
15
			{/if}
16
		</li>
17
	</ul>
18
</div>
app/utils/datagrid/templates/column_status.latte
1
{**
2
 * @param $row    Ublaboo\DataGrid\Row
3
 * @param $status Ublaboo\DataGrid\Column\ColumnStatus
4
 *}
5

  
6
{var $active_option = $status->getCurrentOption($row)}
7

  
8
<div class="dropdown">
9
	{if $active_option}
10
		<button class="dropdown-toggle {$active_option->getClass()} {$active_option->getClassSecondary()}" type="button" data-toggle="dropdown">
11
			{if $active_option->getIcon()}<i class="{$icon_prefix}{$active_option->getIcon()}"></i> {/if}
12
			{$active_option->getText()|translate} <i n:if="$status->hasCaret()" class="caret"></i>
13
		</button>
14
	{else}
15
		{$row->getValue($status->getColumn())}
16
	{/if}
17
	<ul class="dropdown-menu">
18
		<li n:foreach="$status->getOptions() as $option">
19
			<a class="{$option->getClassInDropdown()}" n:href="changeStatus!, id => $row->getId(), key => $status->getKey(), value => $option->getValue()">
20
				{if $option->getIconSecondary()}<i class="datagrid-column-status-option-icon {$icon_prefix}{$option->getIconSecondary()}"></i> {/if}
21
				{$option->getText()|translate}
22
			</a>
23
		</li>
24
	</ul>
25
</div>
app/utils/datagrid/templates/datagrid.latte
1
{**
2
 * @param Column[]        $columns            Available columns
3
 * @param Action[]        $actions            Available actions
4
 * @param Export[]        $exports            Available exports
5
 * @param Filter[]        $filters            Available filters
6
 * @param ToolBarButton[] $toolbar_buttons    Available toolbar_buttons
7
 * @param Form            $filter             Workaround for latte snippets
8
 * @param Row[]           $rows               List of rows (each contain a item from data source)
9
 * @param DataGrid        $control            Parent (DataGrid)
10
 * @param string          $original_template  Original template file path
11
 * @param string          $icon_prefix        Icon prefix (fa fa-)
12
 * @param array           $columns_visibility What columns are visible
13
 * @param InlineEdit|null $inlineEdit  Inline editing data
14
 * @param InlineEdit|null $inlineAdd   Inline add data
15
 *}
16

  
17
<div class="datagrid datagrid-{$control->getName()}" data-refresh-state="{link refreshState!}">
18
	{**
19
	 * Own data
20
	 *}
21
	<div n:snippet="grid">
22
	{snippetArea gridSnippets}
23
		{form filter, class => 'ajax'}
24
			{**
25
			 * Filter form
26
			 *}
27
			{if $control->hasOuterFilterRendering()}
28
				{block outer-filters}
29
					<div class="row text-right datagrid-collapse-filters-button-row" n:if="$control->hasCollapsibleOuterFilters()">
30
						<div class="col-sm-12">
31
							<button class="btn btn-xs btn-primary active" type="button" data-toggle="collapse" data-target="#datagrid-{$control->getName()}-row-filters">
32
								<i n:block = "icon-filter" class="{$icon_prefix}filter"></i> {='ublaboo_datagrid.show_filter'|translate}
33
							</button>
34
						</div>
35
					</div>
36

  
37
					{if $control->hasCollapsibleOuterFilters() && !$filter_active}
38
						{var $filter_row_class = 'row-filters collapse'}
39
					{elseif $filter_active}
40
						{var $filter_row_class = 'row-filters collapse in'}
41
					{else}
42
						{var $filter_row_class = 'row-filters'}
43
					{/if}
44
					<div class="{$filter_row_class}" id="datagrid-{$control->getName()}-row-filters">
45
						<div class="row">
46
							{var $i = 0}
47
							{var $filter_columns_class = 'col-sm-' . (12 / $control->getOuterFilterColumnsCount())}
48
							<div class="datagrid-row-outer-filters-group {$filter_columns_class}" n:foreach="$filters as $f">
49
								{**
50
								 * Each fitler is rendered separately in its own template
51
								 *}
52
								{var $filter_block = 'filter-' . $f->getKey()}
53
								{var $filter_type_block = 'filtertype-' . $f->getType()}
54

  
55
								{ifset #$filter_block}
56
									{include #$filter_block, filter => $f, input => $form['filter'][$f->getKey()], outer => TRUE}
57
								{else}
58
									{ifset #$filter_type_block}
59
										{include #$filter_type_block, filter => $f, input => $form['filter'][$f->getKey()], outer => TRUE}
60
										{else}
61
											{include $f->getTemplate(), filter => $f, input => $form['filter'][$f->getKey()], outer => TRUE}
62
									{/ifset}
63
								{/ifset}
64
								{var $i = $i+1}
65
							</div>
66
							<div class="col-sm-12" n:if="!$control->hasAutoSubmit()">
67
								<div class="text-right datagrid-manual-submit">
68
									{input $filter['filter']['submit']}
69
								</div>
70
							</div>
71
						</div>
72
					</div>
73
				{/block}
74
			{/if}
75
			<table class="{block table-class}table table-hover table-striped table-bordered table-sm{/block}" n:snippet="table" n:block="data">
76
				<thead n:block="header">
77
					<tr class="row-group-actions" n:if="$hasGroupActions || $exports || $toolbar_buttons || $control->canHideColumns() || $inlineAdd" n:block="group-actions">
78
						<th colspan="{$control->getColumnsCount()}" class="ublaboo-datagrid-th-form-inline">
79
							{if $hasGroupActions}
80
								{block group_actions}
81
									{='ublaboo_datagrid.group_actions'|translate}:
82
									{foreach $filter['group_action']->getControls() as $form_control}
83
										{if $form_control instanceof \Nette\Forms\Controls\SubmitButton}
84
											{input $form_control, class => 'btn btn-primary btn-sm', style => 'display:none'}
85
										{elseif $form_control->getName() == 'group_action'}
86
											{input $form_control, class => 'form-control input-sm form-control-sm', disabled => TRUE}
87
										{else}
88
											{input $form_control, style => 'display:none'}
89
										{/if}
90
									{/foreach}
91
									{if $control->shouldShowSelectedRowsCount()}
92
										<span class="datagrid-selected-rows-count"></span>
93
									{/if}
94
								{/block}
95
							{/if}
96

  
97
							<div class="datagrid-toolbar" n:if="$control->canHideColumns() || $inlineAdd || $exports || $toolbar_buttons">
98
								<span n:if="$toolbar_buttons">
99
									{foreach $toolbar_buttons as $toolbar_button}{$toolbar_button->renderButton()}{/foreach}
100
								</span>
101

  
102
								<span class="datagrid-exports" n:if="$exports" n:snippet="exports" n:block="exports">
103
									{foreach $exports as $export}{$export->render()}{/foreach}
104
								</span>
105

  
106
								<div class="datagrid-settings" n:block="settings" n:if="$control->canHideColumns() || $inlineAdd">
107
									{**
108
									 * Inline add
109
									 *}
110
									{if $inlineAdd}
111
										{$inlineAdd->renderButtonAdd()}
112
									{/if}
113

  
114
									{**
115
									 * Hideable columns
116
									 *}
117
									<div class="btn-group">
118
										<button type="button" class="btn btn-xs btn-default btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" n:if="$control->canHideColumns()">
119
											<i n:block = "icon-gear" class="{$icon_prefix}cog"></i>
120
										</button>
121
										<ul class="dropdown-menu dropdown-menu-right dropdown-menu--grid">
122
											<li n:foreach="$columns_visibility as $v_key => $visibility">
123
												{if $visibility['visible']}
124
													<a n:href="hideColumn!, column => $v_key" class="ajax dropdown-item">
125
														<i n:block = "icon-checked" class="{$icon_prefix}check-square"></i>
126
														{include #column-header, column => $visibility['column']}
127
													</a>
128
												{else}
129
													<a n:href="showColumn!, column => $v_key" class="ajax dropdown-item">
130
														<i n:block = "icon-unchecked" class="{$icon_prefix}square"></i>
131
														{include #column-header, column => $visibility['column']}
132
													</a>
133
												{/if}
134
											</li>
135
											<li role="separator" class="divider dropdown-divider"></li>
136
											<li>
137
												<a n:href="showAllColumns!" class="ajax dropdown-item"><i n:block = "icon-eye" class="{$icon_prefix}eye"></i> {='ublaboo_datagrid.show_all_columns'|translate}</a>
138
											</li>
139
											<li n:if="$control->hasSomeColumnDefaultHide()">
140
												<a n:href="showDefaultColumns!" class="ajax dropdown-item"><i n:block = "icon-repeat" class="{$icon_prefix}redo"></i> {='ublaboo_datagrid.show_default_columns'|translate}</a>
141
											</li>
142
										</ul>
143
									</div>
144
								</div>
145
							</div>
146
						</th>
147
					</tr>
148
					<tr n:block="header-column-row">
149
						<th n:snippet="thead-group-action" n:if="$hasGroupActions" n:attr="'rowspan=2' => !empty($filters) && !$control->hasOuterFilterRendering()" class="col-checkbox">
150
							<input n:if="$hasGroupActionOnRows" n:class="$control->useHappyComponents() ? 'happy gray-border' , primary" name="{$control->getName()|lower}-toggle-all" type="checkbox" data-check="{$control->getName()}" data-check-all="{$control->getName()}">
151
						</th>
152
						{foreach $columns as $key => $column}
153
							{var $th = $column->getElementForRender('th', $key)}
154
							{$th->startTag()|noescape}
155
								{var $col_header = 'col-' . $key . '-header'}
156

  
157
								{**
158
								 * Column header can be defined also with block {col-<key>-header}
159
								 *}
160
								{ifset #$col_header}
161
									{include #$col_header, column => $column}
162
								{else}
163
									{if $column->isSortable()}
164
										<a n:class="$column->isSortedBy() ? 'sort' : '', 'ajax', 'success'" href="{link sort!, sort => $control->getSortNext($column)}" id="datagrid-sort-{$key}">
165
											{include #column-header, column => $column}
166

  
167
											{if $column->isSortedBy()}
168
												{if $column->isSortAsc()}
169
													<i n:block="icon-sort-up" class="{$icon_prefix}caret-up"></i>
170
												{else}
171
													<i n:block="icon-sort-down" class="{$icon_prefix}caret-down"></i>
172
												{/if}
173
											{else}
174
												<i n:block="icon-sort" class="{$icon_prefix}sort"></i>
175
											{/if}
176
										</a>
177
									{else}
178
										{include #column-header, column => $column}
179
									{/if}
180
								{/ifset}
181

  
182
								<div class="datagrid-column-header-additions">
183
									<div class="btn-group column-settings-menu" n:if="$control->canHideColumns()">
184
										<a class="dropdown-toggle success" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" href="">
185
											<i n:block="icon-caret-down" class="{$icon_prefix}caret-down"></i>
186
										</a>
187
										<ul class="dropdown-menu dropdown-menu--grid">
188
											<li>
189
												<a n:href="hideColumn!, column => $key" class="ajax dropdown-item">
190
													<i n:block = "icon-eye-slash" class="{$icon_prefix}eye-slash"></i> {='ublaboo_datagrid.hide_column'|translate}</a>
191
											</li>
192
										</ul>
193
									</div>
194

  
195
									{if $control->hasColumnReset()}
196
										<a data-datagrid-reset-filter-by-column="{$key}" n:href="resetColumnFilter!, key => $key" n:class="isset($filters[$key]) && $filters[$key]->isValueSet() ? '' : 'hidden', 'ajax'" title="{='ublaboo_datagrid.reset_filter'|translate}">
197
											<i n:block="icon-remove" class="{$icon_prefix}remove"></i>
198
										</a>
199
									{/if}
200
								</div>
201
							{$th->endTag()|noescape}
202
						{/foreach}
203
						<th n:if="$actions || $control->isSortable() || $items_detail || $inlineEdit || $inlineAdd" class="col-action text-center">
204
							{='ublaboo_datagrid.action'|translate}
205
						</th>
206
					</tr>
207
					<tr n:block="header-filters" n:if="!empty($filters) && !$control->hasOuterFilterRendering()">
208
						{foreach $columns as $key => $column}
209
							{var $th = $column->getElementForRender('th', $key)}
210
							{$th->startTag()|noescape}
211
							{var $col_header = 'col-filter-' . $key . '-header'}
212
							{if !$control->hasOuterFilterRendering() && isset($filters[$key])}
213
								{var $i = $filter['filter'][$key]}
214

  
215
									{var $filter_block = 'filter-' . $filters[$key]->getKey()}
216
									{var $filter_type_block = 'filtertype-' . $filters[$key]->getType()}
217

  
218
								{ifset #$filter_block}
219
									{include #$filter_block, filter => $filters[$key], input => $i, outer => FALSE}
220
								{else}
221
									{ifset #$filter_type_block}
222
										{include #$filter_type_block, filter => $filters[$key], input => $i, outer => FALSE}
223
									{else}
224
										{include $filters[$key]->getTemplate(), filter => $filters[$key], input => $i, outer => FALSE}
225
									{/ifset}
226
								{/ifset}
227

  
228
							{/if}
229
							{$th->endTag()|noescape}
230
						{/foreach}
231
						<th n:if="$actions || $control->isSortable() || $items_detail || $inlineEdit || $inlineAdd" class="col-action text-center">
232
							{if !$control->hasAutoSubmit() && !$control->hasOuterFilterRendering()}
233
								{input $filter['filter']['submit']}
234
							{/if}
235
						</th>
236
					</tr>
237
				</thead>
238

  
239
				{block tbody}
240
				<tbody n:snippet="tbody" {if $control->isSortable()}data-sortable data-sortable-url="{plink $control->getSortableHandler()}" data-sortable-parent-path="{$control->getSortableParentPath()}"{/}>
241
					{snippetArea items}
242
						{if $inlineAdd && $inlineAdd->isPositionTop()}
243
							{include inlineAddRow, columns => $columns}
244
						{/if}
245

  
246
						{foreach $rows as $row}
247
							{var $item = $row->getItem()}
248

  
249
							{if !isset($toggle_detail)}
250
								{if $inlineEdit && $inlineEdit->getItemId() == $row->getId()}
251
									{php $inlineEdit->onSetDefaults($filter['inline_edit'], $item); }
252

  
253
									<tr data-id="{$row->getId()}" n:snippet="item-{$row->getId()}" n:class="$row->getControlClass()">
254
										<td n:if="$hasGroupActions" class="col-checkbox"></td>
255

  
256
										{foreach $columns as $key => $column}
257
											{var $col = 'col-' . $key}
258

  
259
											{var $td = $column->getElementForRender('td', $key, $row)}
260
											{var $td->class[] = 'datagrid-inline-edit'}
261
											{$td->startTag()|noescape}
262
												{if isset($filter['inline_edit'][$key])}
263
													{input $filter['inline_edit'][$key]}
264
												{elseif $inlineEdit->showNonEditingColumns()}
265
													{include column-value, column => $column, row => $row, key => $key}
266
												{/if}
267
											{$td->endTag()|noescape}
268
										{/foreach}
269

  
270
										<td class="col-action col-action-inline-edit">
271
											{input $filter['inline_edit']['cancel'], class => 'btn btn-xs btn-danger'}
272
											{input $filter['inline_edit']['submit'], class => 'btn btn-xs btn-primary'}
273
											{input $filter['inline_edit']['_id']}
274
											{input $filter['inline_edit']['_primary_where_column']}
275
										</td>
276
									</tr>
277
								{else}
278
									<tr data-id="{$row->getId()}" n:snippet="item-{$row->getId()}" n:class="$row->getControlClass()">
279
										<td n:if="$hasGroupActions" class="col-checkbox">
280
											{if $row->hasGroupAction()}
281
												<input n:class="$control->useHappyComponents() ? 'happy gray-border' , primary" type="checkbox" data-check="{$control->getName()}" data-check-all-{$control->getName()|noescape} name="{$control->getName()|lower}_group_action_item[{$row->getId()}]">
282
											{/if}
283
										</td>
284
										{foreach $columns as $key => $column}
285
											{php $column = $row->applyColumnCallback($key, clone $column)}
286

  
287
											{var $td = $column->getElementForRender('td', $key, $row)}
288
											{$td->startTag()|noescape}
289
												{include column-value, column => $column, row => $row, key => $key}
290
											{$td->endTag()|noescape}
291
										{/foreach}
292
										<td n:if="$actions || $control->isSortable() || $items_detail || $inlineEdit || $inlineAdd" class="col-action">
293
											{foreach $actions as $key => $action}
294
												{if $row->hasAction($key)}
295
													{if $action->hasTemplate()}
296
														{include $action->getTemplate(), item => $item, (expand) $action->getTemplateVariables(), row => $row}
297
													{else}
298
														{$action->render($row)|noescape}
299
													{/if}
300
												{/if}
301
											{/foreach}
302
											<span class="handle-sort btn btn-xs btn-default btn-secondary" n:if="$control->isSortable()">
303
												<i n:block = "icon-arrows-v" class="{$icon_prefix}arrows-v"></i>
304
											</span>
305
											{if $inlineEdit && $row->hasInlineEdit()}
306
												{$inlineEdit->renderButton($row)|noescape}
307
											{/if}
308
											{if $items_detail && $items_detail->shouldBeRendered($row)}
309
												{$items_detail->renderButton($row)|noescape}
310
											{/if}
311
										</td>
312
									</tr>
313
								{/if}
314
							{/if}
315

  
316
							{**
317
							 * Item detail
318
							 *}
319
							{if $items_detail && $items_detail->shouldBeRendered($row)}
320
								<tr class="row-item-detail item-detail-{$row->getId()}" n:snippet="item-{$row->getId()}-detail">
321
									{if isset($toggle_detail) && $toggle_detail == $row->getId()}
322
										{var $item_detail_params = ['item' => $item, '_form' => $filter] + $items_detail->getTemplateVariables()}
323

  
324
										{if isset($filter['items_detail_form'])}
325
											{var $item_detail_params['items_detail_form'] = $filter['items_detail_form']}
326
										{/if}
327

  
328
										{ifset #detail}
329
											<td colspan="{$control->getColumnsCount()}">
330
												<div class="item-detail-content">
331
													{include #detail, (expand) $item_detail_params}
332
												</div>
333
											</td>
334
										{elseif $items_detail}
335
											<td colspan="{$control->getColumnsCount()}">
336
												<div class="item-detail-content">
337
													{if $items_detail->getType() == 'template'}
338
														{include $items_detail->getTemplate(), (expand) $item_detail_params}
339
													{else}
340
														{$items_detail->render($item)|noescape}
341
													{/if}
342
												</div>
343
											</td>
344
										{/ifset}
345
									{/if}
346
								</tr>
347
								<tr class="row-item-detail-helper"></tr>
348
							{/if}
349
						{/foreach}
350

  
351
						{if $inlineAdd && $inlineAdd->isPositionBottom()}
352
							{include inlineAddRow, columns => $columns}
353
						{/if}
354

  
355
						<tr class="datagrid-row-columns-summary" n:if="!empty($rows) && ($columnsSummary || $control->hasSomeAggregationFunction())" n:snippet="summary">
356
							<td n:if="$hasGroupActions" class="col-checkbox"></td>
357

  
358
							{if $columnsSummary && $columnsSummary->someColumnsExist($columns)}
359
								{include columnsSummary, columns => $columns}
360
							{/if}
361

  
362
							{if $control->hasSomeAggregationFunction()}
363
								{include aggregationFunctions, columns => $columns}
364
							{/if}
365

  
366
							<td n:if="$actions || $control->isSortable() || $items_detail || $inlineEdit || $inlineAdd" class="col-action"></td>
367
						</tr>
368

  
369
						{block noItems}
370
							<tr n:if="!$rows">
371
								<td colspan="{$control->getColumnsCount()}">
372
									{if $filter_active}
373
										{='ublaboo_datagrid.no_item_found_reset'|translate} <a class="link ajax" n:href="resetFilter!">{='ublaboo_datagrid.here'|translate}</a>.
374
									{else}
375
										{='ublaboo_datagrid.no_item_found'|translate}
376
									{/if}
377
								</td>
378
							</tr>
379
						{/block}
380
					{/snippetArea}
381
				</tbody>
382
				{/block}
383
				{block tfoot}
384
					<tfoot n:snippet="pagination">
385
						{if $control->isPaginated() || $filter_active}
386
							<tr n:block="pagination">
387
								<td colspan="{$control->getColumnsCount()}" n:if="!$control->isTreeView()" class="row-grid-bottom">
388
									<div class="col-items">
389
										<small class="text-muted" n:if="$control->isPaginated()">
390
											({var $paginator = $control['paginator']->getPaginator()}
391

  
392
											{if $control->getPerPage() === 'all'}
393
												{='ublaboo_datagrid.items'|translate}: {='ublaboo_datagrid.all'|translate}
394
											{else}
395
												{='ublaboo_datagrid.items'|translate}: {$paginator->getOffset() > 0 ? $paginator->getOffset() + 1 : ($paginator->getItemCount() > 0 ? 1 : 0)} - {sizeof($rows) + $paginator->getOffset()}
396
												{='ublaboo_datagrid.from'|translate} {$paginator->getItemCount()}
397
											{/if})
398
										</small>
399
									</div>
400
									<div class="col-pagination text-center">
401
										{**
402
										* Pagination
403
										*}
404
										{control paginator}
405
									</div>
406
									<div class="col-per-page text-right">
407
										{**
408
										* Items per page form (display only beside paginated grido)
409
										*}
410
										<a n:if="$filter_active" n:href="resetFilter!" class="ajax btn btn-danger btn-sm reset-filter">{='ublaboo_datagrid.reset_filter'|translate}</a>
411
										{if $control->isPaginated()}
412
											{input $filter['per_page'], data-autosubmit-per-page => TRUE, class => 'form-control input-sm form-control-sm'}
413
											{input $filter['per_page_submit'], class => 'datagrid-per-page-submit'}
414
										{/if}
415
									</div>
416
								</td>
417
							</tr>
418
						{/if}
419
					</tfoot>
420
				{/block}
421
			</table>
422
		{/form}
423
	{/snippetArea}
424
	</div>
425
</div>
426

  
427

  
428
{define inlineAddRow}
429
	{php $inlineAdd->onSetDefaults($filter['inline_add']); }
430

  
431
	<tr class="datagrid-row-inline-add datagrid-row-inline-add-hidden">
432
		<td n:if="$hasGroupActions" class="col-checkbox"></td>
433

  
434
		{foreach $columns as $key => $column}
435
			{var $col = 'col-' . $key}
436

  
437
			{var $td = clone $column->getElementForRender('td', $key)}
438
			{var $td->class[] = 'datagrid-inline-edit'}
439
			{$td->startTag()|noescape}
440
				{if isset($filter['inline_add'][$key])}
441
					{input $filter['inline_add'][$key]}
442
				{/if}
443
			{$td->endTag()|noescape}
444
		{/foreach}
445

  
446
		<td class="col-action col-action-inline-edit">
447
			{input $filter['inline_add']['cancel']}
448
			{input $filter['inline_add']['submit']}
449
		</td>
450
	</tr>
451
{/define}
452

  
453

  
454
{define columnsSummary}
455

  
456
	{foreach $columns as $key => $column}
457
		{var $td = $column->getElementForRender('td', $key)}
458

  
459
		{$td->startTag()|noescape}
460
			{$columnsSummary->render($key)}
461
		{$td->endTag()|noescape}
462
	{/foreach}
463

  
464
{/define}
465

  
466

  
467
{define aggregationFunctions}
468

  
469
	{foreach $columns as $key => $column}
470
		{var $td = $column->getElementForRender('td', $key)}
471

  
472
		{$td->startTag()|noescape}
473
			{if $aggregation_functions}
474
				{ifset $aggregation_functions[$key]}
475
					{$aggregation_functions[$key]->renderResult()|noescape}
476
				{/ifset}
477
			{else}
478
				{$multiple_aggregation_function->renderResult($key)|noescape}
479
			{/if}
480
		{$td->endTag()|noescape}
481
	{/foreach}
482

  
483
{/define}
484

  
485

  
486
{define column-header}
487
	{if $column->isHeaderEscaped()}
488
		{if $column instanceof \Nette\Utils\Html || !$column->isTranslatableHeader()}
489
			{$column->getName()|noescape}
490
		{else}
491
			{$column->getName()|translate|noescape}
492
		{/if}
493
	{else}
494
		{if $column instanceof \Nette\Utils\Html || !$column->isTranslatableHeader()}
495
			{$column->getName()}
496
		{else}
497
			{$column->getName()|translate}
498
		{/if}
499
	{/if}
500
{/define}
501

  
502

  
503
{define column-value}
504
	{var $col = 'col-' . $key}
505
	{var $item = $row->getItem()}
506

  
507
	{if $column->hasTemplate()}
508
		{include $column->getTemplate(), row => $row, item => $item, (expand) $column->getTemplateVariables()}
509
	{else}
510
		{ifset #$col}
511
			{include #$col, item => $item}
512
		{else}
513
			{if $column->isTemplateEscaped()}
514
				{$column->render($row)}
515
			{else}
516
				{$column->render($row)|noescape}
517
			{/if}
518
		{/ifset}
519
	{/if}
520
{/define}
521

  
522
<link href="{$basePath}/css/datagrid.min.css" rel="stylesheet" type="text/css">
523
<link href="{$basePath}/css/datagrid-spinners.min.css" rel="stylesheet" type="text/css">
524

  
525
<script src="{$basePath}/js/datagrid.min.js"></script>
526
<script src="{$basePath}/js/datagrid-instant-url-refresh.min.js"></script>
527
<script src="{$basePath}/js/datagrid-spinners.min.js"></script>
app/utils/datagrid/templates/datagrid_filter_date.latte
1
{**
2
 * @param Filter                         $filter
3
 * @param Nette\Forms\Controls\TextInput $input
4
 * @param string                         $icon_prefix       Icon prefix (fa fa-)
5
 *}
6

  
7
{if $outer}
8
	<div class="row">
9
		{label $input class => 'col-sm-3 control-label' /}
10
		<div class="col-sm-9 form-inline">
11
			<div class="input-group input-group-sm datagrid-input-group-full-width">
12
				{input $input}
13
				<label n:name="$input" class="input-group-addon input-group-append">
14
					<i class="input-group-text {$icon_prefix}calendar"></i>
15
				</label>
16
			</div>
17
		</div>
18
	</div>
19
{else}
20
	<div class="form-inline">
21
		<div class="input-group input-group-sm">
22
			{input $input}
23
			<label n:name="$input" class="input-group-addon input-group-append">
24
				<i class="input-group-text {$icon_prefix}calendar"></i>
25
			</label>
26
		</div>
27
	</div>
28
{/if}
29

  
30

  
app/utils/datagrid/templates/datagrid_filter_daterange.latte
1
{**
2
 * @param Filter                $filter
3
 * @param Nette\Forms\Container $input
4
 * @param string                $icon_prefix       Icon prefix (fa fa-)
5
 *}
6

  
7
{var $container = $input}
8

  
9
{if $outer}
10
	<div class="row">
11
		{label $container['from'], class => 'col-sm-3 control-label' /}
12
		<div class="col-sm-4 form-inline">
13
			<div class="input-group input-group-sm">
14
				{input $container['from']}
15
				<label n:name="$container['from']" class="input-group-addon input-group-append">
16
					<i class="input-group-text {$icon_prefix}calendar"></i>
17
				</label>
18
			</div>
19
		</div>
20
		{label $container['to'], class => 'filter-range-delimiter col-sm-1 control-label' /}
21
		<div class="col-sm-4 form-inline">
22
			<div class="input-group input-group-sm">
23
				{input $container['to']}
24
				<label n:name="$container['to']" class="input-group-addon input-group-append">
25
					<i class="input-group-text {$icon_prefix}calendar"></i>
26
				</label>
27
			</div>
28
		</div>
29
	</div>
30
{else}
31
	<div class="datagrid-col-filter-date-range form-inline">
32
		<div class="input-group input-group-sm">
33
			{input $container['from']}
34
			<label n:name="$container['from']" class="input-group-addon input-group-append">
35
				<i class="input-group-text {$icon_prefix}calendar"></i>
36
			</label>
37
        </div>
38

  
39
        <div class="input-group input-group-sm">
40
			{input $container['to']}
41
			<label n:name="$container['to']" class="input-group-addon input-group-append">
42
				<i class="input-group-text {$icon_prefix}calendar"></i>
43
			</label>
44
		</div>
45
	</div>
46
{/if}
app/utils/datagrid/templates/datagrid_filter_range.latte
1
{**
2
 * @param Filter                $filter
3
 * @param Nette\Forms\Container $input
4
 *}
5

  
6
{var $container = $input}
7

  
8
{if $outer}
9
	<div class="row">
10
		{label $container['from'], class => 'col-sm-3 control-label' /}
11
		<div class="col-sm-4">
12
			{input $container['from']}
13
		</div>
14
		{label $container['to'], class => 'filter-range-delimiter col-sm-1 control-label' /}
15
		<div class="col-sm-4">
16
			{input $container['to']}
17
		</div>
18
	</div>
19
{else}
20
	<div class="datagrid-col-filter-range form-inline">
21
		<div class="input-group">
22
			{input $container['from']}
23

  
24
			<div class="input-group-addon datagrid-col-filter-datte-range-delimiter">-</div>
25

  
26
			{input $container['to']}
27
		</div>
28
	</div>
29
{/if}
app/utils/datagrid/templates/datagrid_filter_select.latte
1
{**
2
 * @param Filter                         $filter
3
 * @param Nette\Forms\Controls\SelectBox $input
4
 *}
5

  
6
{if $outer}
7
	<div class="row">
8
		{label $input class => 'col-sm-3 control-label' /}
9
		<div class="col-sm-9">
10
			{input $input}
11
		</div>
12
	</div>
13
{else}
14
	{input $input}
15
{/if}
app/utils/datagrid/templates/datagrid_filter_text.latte
1
{**
2
 * @param Filter                         $filter
3
 * @param Nette\Forms\Controls\TextInput $input
4
 *}
5

  
6
{if $outer}
7
	<div class="row">
8
		{label $input class => 'col-sm-3 control-label' /}
9
		<div class="col-sm-9">
10
			{input $input}
11
		</div>
12
	</div>
13
{else}
14
	{input $input}
15
{/if}
app/utils/datagrid/templates/datagrid_tree.latte
1
{**
2
 * @param array    $columns           Available columns
3
 * @param array    $actions           Available actions
4
 * @param array    $exports           Available exports
5
 * @param Row[]    $rows              List of rows (each contain a item from data source)
6
 * @param DataGrid $control           Parent (DataGrid)
7
 * @param string   $original_template Original template file path
8
 * @param string   $icon_prefix       Icon prefix (fa fa-)
9
 *}
10

  
11
{extends $original_template}
12

  
13
<div class="datagrid-tree-item-children datagrid-tree" n:snippet="table" n:block="data" {if $control->isSortable()}data-sortable-tree data-sortable-url="{plink $control->getSortableHandler()}" data-sortable-parent-path="{$control->getSortableParentPath()}"{/if}>
14
	{snippetArea items}
15
		<div class="datagrid-tree-item datagrid-tree-header" n:snippet="item-header">
16
			<div class="datagrid-tree-item-content" data-has-children="">
17
				<div class="datagrid-tree-item-left">
18
					{foreach $columns as $key => $column}
19
						<strong>{$column->getName()|translate}</strong>
20
						{breakIf TRUE}
21
					{/foreach}
22
				</div>
23

  
24
				<div class="datagrid-tree-item-right">
25
					<div class="datagrid-tree-item-right-columns">
26
						{foreach $columns as $key => $column}
27
							{continueIf $iterator->isFirst()}
28
							<div class="datagrid-tree-item-right-columns-column col-{$column->getColumnName()} text-{$column->hasAlign() ? $column->getAlign() : 'left'}">
29
								<strong>{$column->getName()|translate}</strong>
30
							</div>
31
						{/foreach}
32
					</div>
33
					<div class="datagrid-tree-item-right-actions" n:if="($actions || $control->isSortable()) && $rows">
34
						<div class="datagrid-tree-item-right-actions-action">
35
							{var $tmp_row = reset($rows)}
36

  
37
							{foreach $actions as $key => $action}
38
								{if $tmp_row->hasAction($key)}
39
									{if $action->hasTemplate()}
40
										{include $action->getTemplate(), item => $tmp_row->getItem(), (expand) $action->getTemplateVariables(), row => $tmp_row}
41
									{else}
42
										{$action->render($tmp_row)|noescape}
43
									{/if}
44
								{/if}
45
							{/foreach}
46

  
47
							<span class="handle-sort btn btn-xs btn-default btn-secondary" n:if="$control->isSortable()">
48
								<i class="{$icon_prefix}arrows"></i>
49
							</span>
50
						</div>
51
					</div>
52
				</div>
53
			</div>
54
		</div>
55

  
56
		{foreach $rows as $row}
57
			{var $has_children = $control->hasTreeViewChildrenCallback() ? $control->treeViewChildrenCallback($row->getItem()) : $row->getValue($tree_view_has_children_column)}
58
			{var $item = $row->getItem()}
59

  
60
			<div n:class="$has_children ? has-children, 'datagrid-tree-item'" data-id="{$row->getId()}" n:snippet="item-{$row->getId()}">
61
				<div n:class="datagrid-tree-item-content, $row->getControlClass()" data-id="{$row->getId()}" data-has-children="{$has_children ? true : false}">
62
					<div class="datagrid-tree-item-left">
63
						<a n:href="getChildren! parent => $row->getId()" data-toggle-tree="true" n:class="!$has_children ? hidden, 'chevron ajax'">
64
							<i n:block="icon-chevron" class="{$icon_prefix}chevron-right"></i>
65
						</a>
66
						{foreach $columns as $key => $column}
67
							{var $col = 'col-' . $key}
68
							{php $column = $row->applyColumnCallback($key, clone $column)}
69

  
70
							{if $column->hasTemplate()}
71
								{include $column->getTemplate(), item => $item, (expand) $column->getTemplateVariables()}
72
							{else}
73
								{ifset #$col}
74
									{include #$col, item => $item}
75
								{else}
76
									{if $column->isTemplateEscaped()}
77
										{$column->render($row)}
78
									{else}
79
										{$column->render($row)|noescape}
80
									{/if}
81
								{/ifset}
82
							{/if}
83

  
84
							{breakIf TRUE}
85
						{/foreach}
86
					</div>
87
					<div class="datagrid-tree-item-right">
88
						<div class="datagrid-tree-item-right-columns">
89
							{foreach $columns as $key => $column}
90
								{continueIf $iterator->isFirst()}
91

  
92
								<div class="datagrid-tree-item-right-columns-column text-{$column->hasAlign() ? $column->getAlign() : 'left'}">
93
									{var $col = 'col-' . $key}
94
									{php $column = $row->applyColumnCallback($key, clone $column)}
95

  
96
									{if $column->hasTemplate()}
97
										{include $column->getTemplate(), row => $row, item => $item, (expand) $column->getTemplateVariables()}
98
									{else}
99
										{ifset #$col}
100
											{include #$col, item => $item}
101
										{else}
102
											{if $column->isTemplateEscaped()}
103
												{$column->render($row)}
104
											{else}
105
												{$column->render($row)|noescape}
106
											{/if}
107
										{/ifset}
108
									{/if}
109
								</div>
110
							{/foreach}
111
						</div>
112
						<div class="datagrid-tree-item-right-actions">
113
							<div class="datagrid-tree-item-right-actions-action">
114
								{foreach $actions as $key => $action}
115
									{if $row->hasAction($key)}
116
										{if $action->hasTemplate()}
117
											{include $action->getTemplate(), item => $item, (expand) $action->getTemplateVariables(), row => $row}
118
										{else}
119
											{$action->render($row)|noescape}
120
										{/if}
121
									{/if}
122
								{/foreach}
123

  
124
								<span class="handle-sort btn btn-xs btn-default btn-secondary" n:if="$control->isSortable()">
125
									<i n:block = "icon-arrows" class="{$icon_prefix}arrows"></i>
126
								</span>
127
							</div>
128
						</div>
129
					</div>
130
				</div>
131
				<div class="datagrid-tree-item-children" {if $control->isSortable()}data-sortable-tree data-sortable-url="{plink $control->getSortableHandler()}"{/}></div>
132
			</div>
133
		{/foreach}
134
		{if !$rows}
135
			{='ublaboo_datagrid.no_item_found'|translate}
136
		{/if}
137
	{/snippetArea}
138
</div>
composer.json
19 19
		"nette/security": "^2.4",
20 20
		"nette/utils": "^2.4",
21 21
		"latte/latte": "^2.4",
22
		"tracy/tracy": "^2.4"
22
		"tracy/tracy": "^2.4",
23
		"ublaboo/datagrid": "^5.6"
23 24
	},
24 25
	"require-dev": {
25 26
		"nette/tester": "^2.0"
composer.lock
4 4
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 5
        "This file is @generated automatically"
6 6
    ],
7
    "content-hash": "29742b99e1ba0714587bf91cdbaecb4d",
7
    "content-hash": "6018197517a97474da6c1a7c8e26f4fc",
8 8
    "packages": [
9 9
        {
10 10
            "name": "latte/latte",
......
1180 1180
            ],
1181 1181
            "time": "2018-09-18T10:22:16+00:00"
1182 1182
        },
1183
        {
1184
            "name": "paragonie/random_compat",
1185
            "version": "v9.99.99",
1186
            "source": {
1187
                "type": "git",
1188
                "url": "https://github.com/paragonie/random_compat.git",
1189
                "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95"
1190
            },
1191
            "dist": {
1192
                "type": "zip",
1193
                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
1194
                "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
1195
                "shasum": ""
1196
            },
1197
            "require": {
1198
                "php": "^7"
1199
            },
1200
            "require-dev": {
1201
                "phpunit/phpunit": "4.*|5.*",
1202
                "vimeo/psalm": "^1"
1203
            },
1204
            "suggest": {
1205
                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
1206
            },
1207
            "type": "library",
1208
            "notification-url": "https://packagist.org/downloads/",
1209
            "license": [
1210
                "MIT"
1211
            ],
1212
            "authors": [
1213
                {
1214
                    "name": "Paragon Initiative Enterprises",
1215
                    "email": "security@paragonie.com",
1216
                    "homepage": "https://paragonie.com"
1217
                }
1218
            ],
1219
            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
1220
            "keywords": [
1221
                "csprng",
1222
                "polyfill",
1223
                "pseudorandom",
1224
                "random"
1225
            ],
1226
            "time": "2018-07-02T15:55:56+00:00"
1227
        },
1228
        {
1229
            "name": "symfony/inflector",
1230
            "version": "v3.3.6",
1231
            "source": {
1232
                "type": "git",
1233
                "url": "https://github.com/symfony/inflector.git",
1234
                "reference": "aed5a0874a3bcfd8d0393a2d91b4cf828f29c7fb"
1235
            },
1236
            "dist": {
1237
                "type": "zip",
1238
                "url": "https://api.github.com/repos/symfony/inflector/zipball/aed5a0874a3bcfd8d0393a2d91b4cf828f29c7fb",
1239
                "reference": "aed5a0874a3bcfd8d0393a2d91b4cf828f29c7fb",
1240
                "shasum": ""
1241
            },
1242
            "require": {
1243
                "php": ">=5.5.9"
1244
            },
1245
            "type": "library",
1246
            "extra": {
1247
                "branch-alias": {
1248
                    "dev-master": "3.3-dev"
1249
                }
1250
            },
1251
            "autoload": {
1252
                "psr-4": {
1253
                    "Symfony\\Component\\Inflector\\": ""
1254
                },
1255
                "exclude-from-classmap": [
1256
                    "/Tests/"
1257
                ]
1258
            },
1259
            "notification-url": "https://packagist.org/downloads/",
1260
            "license": [
1261
                "MIT"
1262
            ],
1263
            "authors": [
1264
                {
1265
                    "name": "Bernhard Schussek",
1266
                    "email": "bschussek@gmail.com"
1267
                },
1268
                {
1269
                    "name": "Symfony Community",
1270
                    "homepage": "https://symfony.com/contributors"
1271
                }
1272
            ],
1273
            "description": "Symfony Inflector Component",
1274
            "homepage": "https://symfony.com",
1275
            "keywords": [
1276
                "inflection",
1277
                "pluralize",
1278
                "singularize",
1279
                "string",
1280
                "symfony",
1281
                "words"
1282
            ],
1283
            "time": "2017-04-12T14:14:56+00:00"
1284
        },
1285
        {
1286
            "name": "symfony/polyfill-php70",
1287
            "version": "v1.11.0",
1288
            "source": {
1289
                "type": "git",
1290
                "url": "https://github.com/symfony/polyfill-php70.git",
1291
                "reference": "bc4858fb611bda58719124ca079baff854149c89"
1292
            },
1293
            "dist": {
1294
                "type": "zip",
1295
                "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/bc4858fb611bda58719124ca079baff854149c89",
1296
                "reference": "bc4858fb611bda58719124ca079baff854149c89",
1297
                "shasum": ""
1298
            },
1299
            "require": {
1300
                "paragonie/random_compat": "~1.0|~2.0|~9.99",
1301
                "php": ">=5.3.3"
1302
            },
1303
            "type": "library",
1304
            "extra": {
1305
                "branch-alias": {
1306
                    "dev-master": "1.11-dev"
1307
                }
1308
            },
1309
            "autoload": {
1310
                "psr-4": {
1311
                    "Symfony\\Polyfill\\Php70\\": ""
1312
                },
1313
                "files": [
1314
                    "bootstrap.php"
1315
                ],
1316
                "classmap": [
1317
                    "Resources/stubs"
1318
                ]
1319
            },
1320
            "notification-url": "https://packagist.org/downloads/",
1321
            "license": [
1322
                "MIT"
... Rozdílový soubor je zkrácen, protože jeho délka přesahuje max. limit.

Také k dispozici: Unified diff