Skip to content

Commit ff9e03e

Browse files
authored
Merge pull request #6212 from WoltLab/6.2-TemplateListPage-to-grid-view
Migrate `TemplateListPage` to grid view
2 parents dbf99ec + df36664 commit ff9e03e

File tree

9 files changed

+368
-282
lines changed

9 files changed

+368
-282
lines changed

wcfsetup/install/files/acp/templates/templateList.tpl

Lines changed: 4 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<header class="contentHeader">
44
<div class="contentHeaderTitle">
5-
<h1 class="contentTitle">{lang}wcf.acp.template.list{/lang}{if $items} <span class="badge badgeInverse">{#$items}</span>{/if}</h1>
5+
<h1 class="contentTitle">{lang}wcf.acp.template.list{/lang} <span class="badge badgeInverse">{#$gridView->countRows()}</span></h1>
66
</div>
77

88
<nav class="contentHeaderNavigation">
@@ -14,136 +14,8 @@
1414
</nav>
1515
</header>
1616

17-
{include file='shared_formError'}
18-
19-
<form method="post" action="{link controller='TemplateList'}{/link}">
20-
<section class="section">
21-
<h2 class="sectionTitle">{lang}wcf.global.filter{/lang}</h2>
22-
23-
<div class="row rowColGap formGrid">
24-
{if $availableTemplateGroups|count}
25-
<dl class="col-xs-12 col-md-4">
26-
<dt></dt>
27-
<dd>
28-
<select name="templateGroupID" id="templateGroupID">
29-
<option value="0">{lang}wcf.acp.template.group.default{/lang}</option>
30-
{htmlOptions options=$availableTemplateGroups selected=$templateGroupID disableEncoding=true}
31-
</select>
32-
</dd>
33-
</dl>
34-
{/if}
35-
36-
{if $availableApplications|count > 1}
37-
<dl class="col-xs-12 col-md-4">
38-
<dt></dt>
39-
<dd>
40-
<select name="application" id="application">
41-
<option value="">{lang}wcf.acp.template.application{/lang}</option>
42-
{foreach from=$availableApplications key=abbreviation item=availableApplication}
43-
<option value="{$abbreviation}"{if $abbreviation == $application} selected{/if}>{$availableApplication}</option>
44-
{/foreach}
45-
</select>
46-
</dd>
47-
</dl>
48-
{/if}
49-
50-
<dl class="col-xs-12 col-md-4">
51-
<dt></dt>
52-
<dd>
53-
<input type="text" id="searchTemplateName" name="searchTemplateName" value="{$searchTemplateName}" placeholder="{lang}wcf.global.name{/lang}" class="long">
54-
</dd>
55-
</dl>
56-
57-
{event name='filterFields'}
58-
</div>
59-
60-
<div class="formSubmit">
61-
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
62-
{csrfToken}
63-
</div>
64-
</section>
65-
</form>
66-
67-
{hascontent}
68-
<div class="paginationTop">
69-
{content}
70-
{assign var='linkParameters' value=''}
71-
{if $templateGroupID}{capture append=linkParameters}&templateGroupID={@$templateGroupID}{/capture}{/if}
72-
{if $searchTemplateName}{capture append=linkParameters}&searchTemplateName={@$searchTemplateName|rawurlencode}{/capture}{/if}
73-
{if $application}{capture append=linkParameters}&application={$application}{/capture}{/if}
74-
75-
{pages print=true assign=pagesLinks controller="TemplateList" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder$linkParameters"}
76-
{/content}
77-
</div>
78-
{/hascontent}
79-
80-
{if $objects|count}
81-
<div id="templateTableContainer" class="section tabularBox">
82-
<table class="table jsObjectActionContainer" data-object-action-class-name="wcf\data\template\TemplateAction">
83-
<thead>
84-
<tr>
85-
<th class="columnID columnTemplateID{if $sortField == 'templateID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link controller='TemplateList'}pageNo={@$pageNo}&sortField=templateID&sortOrder={if $sortField == 'templateID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
86-
<th class="columnTitle columnTemplateName{if $sortField == 'templateName'} active {@$sortOrder}{/if}"><a href="{link controller='TemplateList'}pageNo={@$pageNo}&sortField=templateName&sortOrder={if $sortField == 'templateName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.global.name{/lang}</a></th>
87-
<th class="columnDate columnLastModificationTime{if $sortField == 'lastModificationTime'} active {@$sortOrder}{/if}"><a href="{link controller='TemplateList'}pageNo={@$pageNo}&sortField=lastModificationTime&sortOrder={if $sortField == 'lastModificationTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.acp.template.lastModificationTime{/lang}</a></th>
88-
89-
{event name='columnHeads'}
90-
</tr>
91-
</thead>
92-
93-
<tbody class="jsReloadPageWhenEmpty">
94-
{foreach from=$objects item=template}
95-
{if $template->canCopy()}
96-
<tr class="jsTemplateRow jsObjectActionObject" data-object-id="{@$template->getObjectID()}">
97-
<td class="columnIcon">
98-
<a href="{link controller='TemplateAdd'}copy={@$template->templateID}{/link}" title="{lang}wcf.acp.template.copy{/lang}" class="jsTooltip">{icon name='copy'}</a>
99-
100-
{if $template->templateGroupID}
101-
<a href="{link controller='TemplateDiff' id=$template->templateID}{/link}" title="{lang}wcf.acp.template.diff{/lang}" class="jsTooltip">{icon name='right-left'}</a>
102-
<a href="{link controller='TemplateEdit' id=$template->templateID}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
103-
{objectAction action="delete" objectTitle=$template->templateName}
104-
{else}
105-
<span class="disabled" title="{lang}wcf.acp.template.diff{/lang}">
106-
{icon name='arrow-right-arrow-left'}
107-
</span>
108-
<span class="disabled" title="{lang}wcf.global.button.edit{/lang}">
109-
{icon name='pencil'}
110-
</span>
111-
<span class="disabled" title="{lang}wcf.global.button.delete{/lang}">
112-
{icon name='xmark'}
113-
</span>
114-
{/if}
115-
116-
{event name='rowButtons'}
117-
</td>
118-
<td class="columnID">{@$template->templateID}</td>
119-
<td class="columnTitle columnTemplateName">{if $template->application != 'wcf'}<span class="badge label">{$template->application}</span> {/if}{if $template->templateGroupID}<a href="{link controller='TemplateEdit' id=$template->templateID}{/link}">{$template->templateName}</a>{else}{$template->templateName}{/if}</td>
120-
<td class="columnDate columnLastModificationTime">{@$template->lastModificationTime|time}</td>
121-
122-
{event name='columns'}
123-
</tr>
124-
{/if}
125-
{/foreach}
126-
</tbody>
127-
</table>
128-
</div>
129-
130-
<footer class="contentFooter">
131-
{hascontent}
132-
<div class="paginationBottom">
133-
{content}{@$pagesLinks}{/content}
134-
</div>
135-
{/hascontent}
136-
137-
<nav class="contentFooterNavigation">
138-
<ul>
139-
<li><a href="{link controller='TemplateAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.template.add{/lang}</span></a></li>
140-
141-
{event name='contentFooterNavigation'}
142-
</ul>
143-
</nav>
144-
</footer>
145-
{else}
146-
<woltlab-core-notice type="info">{lang}wcf.global.noItems{/lang}</woltlab-core-notice>
147-
{/if}
17+
<div class="section">
18+
{unsafe:$gridView->render()}
19+
</div>
14820

14921
{include file='footer'}

wcfsetup/install/files/lib/acp/page/TemplateListPage.class.php

Lines changed: 11 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,20 @@
22

33
namespace wcf\acp\page;
44

5-
use wcf\data\package\Package;
6-
use wcf\data\package\PackageCache;
7-
use wcf\data\template\group\TemplateGroup;
8-
use wcf\data\template\TemplateList;
9-
use wcf\page\SortablePage;
10-
use wcf\system\application\ApplicationHandler;
11-
use wcf\system\WCF;
12-
use wcf\util\StringUtil;
5+
use wcf\page\AbstractGridViewPage;
6+
use wcf\system\gridView\AbstractGridView;
7+
use wcf\system\gridView\admin\TemplateGridView;
138

149
/**
1510
* Shows a list of templates.
1611
*
17-
* @author Marcel Werk
18-
* @copyright 2001-2019 WoltLab GmbH
19-
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
12+
* @author Olaf Braun, Marcel Werk
13+
* @copyright 2001-2025 WoltLab GmbH
14+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
2015
*
21-
* @property TemplateList $objectList
16+
* @property TemplateGridView $gridView
2217
*/
23-
class TemplateListPage extends SortablePage
18+
class TemplateListPage extends AbstractGridViewPage
2419
{
2520
/**
2621
* @inheritDoc
@@ -32,142 +27,9 @@ class TemplateListPage extends SortablePage
3227
*/
3328
public $neededPermissions = ['admin.template.canManageTemplate'];
3429

35-
/**
36-
* @inheritDoc
37-
*/
38-
public $objectListClassName = TemplateList::class;
39-
40-
/**
41-
* @inheritDoc
42-
*/
43-
public $itemsPerPage = 100;
44-
45-
/**
46-
* @inheritDoc
47-
*/
48-
public $defaultSortField = 'templateName';
49-
50-
/**
51-
* @inheritDoc
52-
*/
53-
public $validSortFields = ['templateID', 'templateName', 'lastModificationTime'];
54-
55-
/**
56-
* template group id
57-
* @var int
58-
*/
59-
public $templateGroupID = 0;
60-
61-
/**
62-
* template name
63-
* @var string
64-
*/
65-
public $searchTemplateName = '';
66-
67-
/**
68-
* application
69-
* @var string
70-
*/
71-
public $application = '';
72-
73-
/**
74-
* available template groups
75-
* @var array
76-
*/
77-
public $availableTemplateGroups = [];
78-
79-
/**
80-
* available applications
81-
* @var array
82-
*/
83-
public $availableApplications = [];
84-
85-
/**
86-
* @inheritDoc
87-
*/
88-
public function readParameters()
89-
{
90-
parent::readParameters();
91-
92-
if (isset($_REQUEST['templateGroupID'])) {
93-
$this->templateGroupID = \intval($_REQUEST['templateGroupID']);
94-
}
95-
if (isset($_REQUEST['searchTemplateName'])) {
96-
$this->searchTemplateName = StringUtil::trim($_REQUEST['searchTemplateName']);
97-
}
98-
if (isset($_REQUEST['application'])) {
99-
$this->application = StringUtil::trim($_REQUEST['application']);
100-
}
101-
}
102-
103-
/**
104-
* @inheritDoc
105-
*/
106-
protected function initObjectList()
107-
{
108-
parent::initObjectList();
109-
110-
if ($this->templateGroupID) {
111-
$this->objectList->getConditionBuilder()->add('template.templateGroupID = ?', [$this->templateGroupID]);
112-
} else {
113-
$this->objectList->getConditionBuilder()->add('template.templateGroupID IS NULL');
114-
}
115-
116-
if ($this->searchTemplateName) {
117-
$this->objectList->getConditionBuilder()->add(
118-
'templateName LIKE ?',
119-
['%' . $this->searchTemplateName . '%']
120-
);
121-
}
122-
if ($this->application) {
123-
$this->objectList->getConditionBuilder()->add('application = ?', [$this->application]);
124-
}
125-
126-
$this->objectList->getConditionBuilder()->add('templateName <> ?', ['.htac']);
127-
}
128-
129-
/**
130-
* @inheritDoc
131-
*/
132-
public function readData()
30+
#[\Override]
31+
protected function createGridViewController(): AbstractGridView
13332
{
134-
parent::readData();
135-
136-
// get template groups
137-
$this->availableTemplateGroups = TemplateGroup::getSelectList([], 1);
138-
139-
// get applications
140-
$applications = ApplicationHandler::getInstance()->getApplications();
141-
$applications[] = ApplicationHandler::getInstance()->getWCF();
142-
foreach ($applications as $application) {
143-
$package = PackageCache::getInstance()->getPackage($application->packageID);
144-
$this->availableApplications[ApplicationHandler::getInstance()->getAbbreviation($package->packageID)] = $package;
145-
146-
// issues with the language cache would cause the uasort() below to throw a
147-
// misleading error message, calling it here just reveals the real error
148-
$package->getName();
149-
}
150-
151-
$collator = new \Collator(WCF::getLanguage()->getLocale());
152-
\uasort(
153-
$this->availableApplications,
154-
static fn (Package $a, Package $b) => $collator->compare($a->getName(), $b->getName())
155-
);
156-
}
157-
158-
/**
159-
* @inheritDoc
160-
*/
161-
public function assignVariables()
162-
{
163-
parent::assignVariables();
164-
165-
WCF::getTPL()->assign([
166-
'templateGroupID' => $this->templateGroupID,
167-
'searchTemplateName' => $this->searchTemplateName,
168-
'application' => $this->application,
169-
'availableTemplateGroups' => $this->availableTemplateGroups,
170-
'availableApplications' => $this->availableApplications,
171-
]);
33+
return new TemplateGridView(TemplateGridView::DEFAULT_TEMPLATE_GROUP_ID);
17234
}
17335
}

wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
197197
$event->register(new \wcf\system\endpoint\controller\core\paid\subscriptions\DisableSubscription());
198198
$event->register(new \wcf\system\endpoint\controller\core\paid\subscriptions\EnableSubscription());
199199
$event->register(new \wcf\system\endpoint\controller\core\paid\subscriptions\users\DeleteSubscriptionUser());
200+
$event->register(new \wcf\system\endpoint\controller\core\templates\DeleteTemplate());
200201
}
201202
);
202203

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace wcf\event\gridView\admin;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\gridView\admin\TemplateGridView;
7+
8+
/**
9+
* Indicates that the template grid view has been initialized.
10+
*
11+
* @author Olaf Braun
12+
* @copyright 2001-2025 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
final class TemplateGridViewInitialized implements IPsr14Event
17+
{
18+
public function __construct(public readonly TemplateGridView $param)
19+
{
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace wcf\event\interaction\admin;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\interaction\admin\TemplateInteractions;
7+
8+
/**
9+
* Indicates that the provider for template interactions is collecting interactions.
10+
*
11+
* @author Olaf Braun
12+
* @copyright 2001-2025 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
final class TemplateInteractionCollecting implements IPsr14Event
17+
{
18+
public function __construct(public readonly TemplateInteractions $param)
19+
{
20+
}
21+
}

0 commit comments

Comments
 (0)