show note if no entries exist for a listing
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor\UI;
|
||||
|
||||
use Froxlor\UI\Panel\UI;
|
||||
@@ -20,142 +21,143 @@ use Froxlor\UI\Panel\UI;
|
||||
*/
|
||||
class Listing
|
||||
{
|
||||
public static function format(Collection $collection, array $tabellisting): array
|
||||
{
|
||||
$collection = $collection->get();
|
||||
public static function format(Collection $collection, array $tabellisting): array
|
||||
{
|
||||
$collection = $collection->get();
|
||||
|
||||
return [
|
||||
'title' => $tabellisting['title'],
|
||||
'icon' => $tabellisting['icon'],
|
||||
'table' => [
|
||||
'th' => self::generateTableHeadings($tabellisting),
|
||||
'tr' => self::generateTableRows($collection['data']['list'], $tabellisting),
|
||||
],
|
||||
'pagination' => $collection['pagination'],
|
||||
];
|
||||
}
|
||||
return [
|
||||
'title' => $tabellisting['title'],
|
||||
'icon' => $tabellisting['icon'],
|
||||
'table' => [
|
||||
'th' => self::generateTableHeadings($tabellisting),
|
||||
'tr' => self::generateTableRows($collection['data']['list'], $tabellisting),
|
||||
],
|
||||
'pagination' => $collection['pagination'],
|
||||
'empty_msg' => $tabellisting['empty_msg'] ?? null
|
||||
];
|
||||
}
|
||||
|
||||
private static function generateTableHeadings(array $tabellisting): array
|
||||
{
|
||||
$heading = [];
|
||||
private static function generateTableHeadings(array $tabellisting): array
|
||||
{
|
||||
$heading = [];
|
||||
|
||||
// Table headings for columns
|
||||
foreach ($tabellisting['visible_columns'] as $visible_column) {
|
||||
if (isset($tabellisting['columns'][$visible_column]['visible']) && !$tabellisting['columns'][$visible_column]['visible']) {
|
||||
continue;
|
||||
}
|
||||
// Table headings for columns
|
||||
foreach ($tabellisting['visible_columns'] as $visible_column) {
|
||||
if (isset($tabellisting['columns'][$visible_column]['visible']) && !$tabellisting['columns'][$visible_column]['visible']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$heading[$visible_column] = [
|
||||
'text' => $tabellisting['columns'][$visible_column]['label'],
|
||||
'class' => $tabellisting['columns'][$visible_column]['class'] ?? null,
|
||||
];
|
||||
}
|
||||
$heading[$visible_column] = [
|
||||
'text' => $tabellisting['columns'][$visible_column]['label'],
|
||||
'class' => $tabellisting['columns'][$visible_column]['class'] ?? null,
|
||||
];
|
||||
}
|
||||
|
||||
// Table headings for actions
|
||||
if (isset($tabellisting['actions'])) {
|
||||
$heading['actions'] = [
|
||||
'text' => UI::getLng('panel.options'),
|
||||
'class' => 'text-end',
|
||||
];
|
||||
}
|
||||
// Table headings for actions
|
||||
if (isset($tabellisting['actions'])) {
|
||||
$heading['actions'] = [
|
||||
'text' => UI::getLng('panel.options'),
|
||||
'class' => 'text-end',
|
||||
];
|
||||
}
|
||||
|
||||
return $heading;
|
||||
}
|
||||
return $heading;
|
||||
}
|
||||
|
||||
private static function generateTableRows(array $list, array $tabellisting): array
|
||||
{
|
||||
$rows = [];
|
||||
private static function generateTableRows(array $list, array $tabellisting): array
|
||||
{
|
||||
$rows = [];
|
||||
|
||||
// Create new row from item
|
||||
foreach ($list as $row => $item) {
|
||||
// Generate columns from item
|
||||
foreach ($tabellisting['visible_columns'] as $col => $visible_column) {
|
||||
if (isset($tabellisting['columns'][$visible_column]['visible']) && !$tabellisting['columns'][$visible_column]['visible']) {
|
||||
continue;
|
||||
}
|
||||
// Create new row from item
|
||||
foreach ($list as $row => $item) {
|
||||
// Generate columns from item
|
||||
foreach ($tabellisting['visible_columns'] as $col => $visible_column) {
|
||||
if (isset($tabellisting['columns'][$visible_column]['visible']) && !$tabellisting['columns'][$visible_column]['visible']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$format_callback = $tabellisting['columns'][$visible_column]['format_callback'] ?? null;
|
||||
$column = $tabellisting['columns'][$visible_column]['field'];
|
||||
$data = self::getMultiArrayFromString($item, $column);
|
||||
$format_callback = $tabellisting['columns'][$visible_column]['format_callback'] ?? null;
|
||||
$column = $tabellisting['columns'][$visible_column]['field'];
|
||||
$data = self::getMultiArrayFromString($item, $column);
|
||||
|
||||
if ($format_callback) {
|
||||
$rows[$row]['td'][$col]['data'] = call_user_func($format_callback, ['data' => $data, 'fields' => $item]);
|
||||
} else {
|
||||
$rows[$row]['td'][$col]['data'] = $data;
|
||||
}
|
||||
if ($format_callback) {
|
||||
$rows[$row]['td'][$col]['data'] = call_user_func($format_callback, ['data' => $data, 'fields' => $item]);
|
||||
} else {
|
||||
$rows[$row]['td'][$col]['data'] = $data;
|
||||
}
|
||||
|
||||
$rows[$row]['td'][$col]['class'] = $tabellisting['columns'][$visible_column]['class'] ?? null;
|
||||
}
|
||||
$rows[$row]['td'][$col]['class'] = $tabellisting['columns'][$visible_column]['class'] ?? null;
|
||||
}
|
||||
|
||||
// Set row classes from format_callback
|
||||
if (isset($tabellisting['format_callback'])) {
|
||||
// Set row classes from format_callback
|
||||
if (isset($tabellisting['format_callback'])) {
|
||||
$class = [];
|
||||
foreach ($tabellisting['format_callback'] as $format_callback) {
|
||||
$class[] = call_user_func($format_callback, ['fields' => $item]);
|
||||
}
|
||||
$rows[$row]['class'] = implode(' ', $class);
|
||||
}
|
||||
$rows[$row]['class'] = implode(' ', $class);
|
||||
}
|
||||
|
||||
// Set all actions for row
|
||||
if (isset($tabellisting['actions'])) {
|
||||
$actions = self::setLinks($tabellisting['actions'], $item);
|
||||
// Set all actions for row
|
||||
if (isset($tabellisting['actions'])) {
|
||||
$actions = self::setLinks($tabellisting['actions'], $item);
|
||||
|
||||
$rows[$row]['td'][] = [
|
||||
'class' => 'text-end',
|
||||
'data' => [
|
||||
'type' => 'actions',
|
||||
'data' => $actions
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
$rows[$row]['td'][] = [
|
||||
'class' => 'text-end',
|
||||
'data' => [
|
||||
'type' => 'actions',
|
||||
'data' => $actions
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private static function setLinks(array $actions, array $item): array
|
||||
{
|
||||
$linker = UI::getLinker();
|
||||
private static function setLinks(array $actions, array $item): array
|
||||
{
|
||||
$linker = UI::getLinker();
|
||||
|
||||
// Check each action for a href
|
||||
foreach ($actions as $key => $action) {
|
||||
// Set link if href is an array
|
||||
if (isset($action['href']) && is_array($action['href'])) {
|
||||
// Search for "columns" in our href array
|
||||
foreach ($action['href'] as $href_key => $href_value) {
|
||||
$length = strlen(':');
|
||||
if (substr($href_value, 0, $length) === ':') {
|
||||
$column = ltrim($href_value, ':');
|
||||
$action['href'][$href_key] = $item[$column];
|
||||
}
|
||||
}
|
||||
// Check each action for a href
|
||||
foreach ($actions as $key => $action) {
|
||||
// Set link if href is an array
|
||||
if (isset($action['href']) && is_array($action['href'])) {
|
||||
// Search for "columns" in our href array
|
||||
foreach ($action['href'] as $href_key => $href_value) {
|
||||
$length = strlen(':');
|
||||
if (substr($href_value, 0, $length) === ':') {
|
||||
$column = ltrim($href_value, ':');
|
||||
$action['href'][$href_key] = $item[$column];
|
||||
}
|
||||
}
|
||||
|
||||
// Set actual link from linker
|
||||
$actions[$key]['href'] = $linker->getLink($action['href']);
|
||||
}
|
||||
}
|
||||
// Set actual link from linker
|
||||
$actions[$key]['href'] = $linker->getLink($action['href']);
|
||||
}
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
return $actions;
|
||||
}
|
||||
|
||||
public static function getVisibleColumnsForListing(string $listing, array $default_columns): array
|
||||
{
|
||||
// Hier käme dann die Logik, die das aus der DB zieht ...
|
||||
// alternativ nimmt er die $default_columns, wenn kein Eintrag
|
||||
// in der DB definiert ist
|
||||
public static function getVisibleColumnsForListing(string $listing, array $default_columns): array
|
||||
{
|
||||
// Hier käme dann die Logik, die das aus der DB zieht ...
|
||||
// alternativ nimmt er die $default_columns, wenn kein Eintrag
|
||||
// in der DB definiert ist
|
||||
|
||||
return $default_columns;
|
||||
}
|
||||
return $default_columns;
|
||||
}
|
||||
|
||||
public static function getMultiArrayFromString(array $arr, string $str)
|
||||
{
|
||||
foreach (explode('.', $str) as $key) {
|
||||
if (!array_key_exists($key, $arr)) {
|
||||
return null;
|
||||
}
|
||||
$arr = $arr[$key];
|
||||
}
|
||||
public static function getMultiArrayFromString(array $arr, string $str)
|
||||
{
|
||||
foreach (explode('.', $str) as $key) {
|
||||
if (!array_key_exists($key, $arr)) {
|
||||
return null;
|
||||
}
|
||||
$arr = $arr[$key];
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ return [
|
||||
'domain_list' => [
|
||||
'title' => $lng['admin']['domains'],
|
||||
'icon' => 'fa-solid fa-user',
|
||||
'empty_msg' => $lng['admin']['domain_nocustomeraddingavailable'],
|
||||
'columns' => [
|
||||
'd.domain_ace' => [
|
||||
'label' => $lng['domains']['domainname'],
|
||||
|
||||
@@ -24,22 +24,22 @@ return [
|
||||
'title' => $lng['admin']['plans']['plans'],
|
||||
'icon' => 'fa-solid fa-user',
|
||||
'columns' => [
|
||||
'p.name' => [
|
||||
'label' => $lng['admin']['plans']['name'],
|
||||
'field' => 'name',
|
||||
],
|
||||
'p.description' => [
|
||||
'label' => $lng['admin']['plans']['description'],
|
||||
'field' => 'description',
|
||||
],
|
||||
'p.adminname' => [
|
||||
'label' => $lng['admin']['admin'],
|
||||
'field' => 'adminname',
|
||||
],
|
||||
'p.ts' => [
|
||||
'label' => $lng['admin']['plans']['last_update'],
|
||||
'field' => 'ts',
|
||||
],
|
||||
'p.name' => [
|
||||
'label' => $lng['admin']['plans']['name'],
|
||||
'field' => 'name',
|
||||
],
|
||||
'p.description' => [
|
||||
'label' => $lng['admin']['plans']['description'],
|
||||
'field' => 'description',
|
||||
],
|
||||
'p.adminname' => [
|
||||
'label' => $lng['admin']['admin'],
|
||||
'field' => 'adminname',
|
||||
],
|
||||
'p.ts' => [
|
||||
'label' => $lng['admin']['plans']['last_update'],
|
||||
'field' => 'ts',
|
||||
],
|
||||
],
|
||||
'visible_columns' => Listing::getVisibleColumnsForListing('sslcertificates_list', [
|
||||
'p.name',
|
||||
@@ -47,26 +47,26 @@ return [
|
||||
'p.adminname',
|
||||
'p.ts',
|
||||
]),
|
||||
'actions' => [
|
||||
'edit' => [
|
||||
'icon' => 'fa fa-edit',
|
||||
'href' => [
|
||||
'section' => 'plans',
|
||||
'page' => 'overview',
|
||||
'action' => 'edit',
|
||||
'id' => ':id'
|
||||
],
|
||||
],
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'class' => 'text-danger',
|
||||
'href' => [
|
||||
'section' => 'plans',
|
||||
'page' => 'overview',
|
||||
'action' => 'delete',
|
||||
'id' => ':id'
|
||||
],
|
||||
],
|
||||
]
|
||||
'actions' => [
|
||||
'edit' => [
|
||||
'icon' => 'fa fa-edit',
|
||||
'href' => [
|
||||
'section' => 'plans',
|
||||
'page' => 'overview',
|
||||
'action' => 'edit',
|
||||
'id' => ':id'
|
||||
],
|
||||
],
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'class' => 'text-danger',
|
||||
'href' => [
|
||||
'section' => 'plans',
|
||||
'page' => 'overview',
|
||||
'action' => 'delete',
|
||||
'id' => ':id'
|
||||
],
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -2146,3 +2146,4 @@ $lng['ssl_certificates']['certificate_for'] = 'Certificate for';
|
||||
$lng['ssl_certificates']['valid_from'] = 'Valid from';
|
||||
$lng['ssl_certificates']['valid_until'] = 'Valid until';
|
||||
$lng['ssl_certificates']['issuer'] = 'Issuer';
|
||||
$lng['panel']['listing_empty'] = 'No entries found';
|
||||
|
||||
@@ -1788,3 +1788,4 @@ $lng['serversettings']['acmeshpath']['description'] = 'Installationspfad zu acme
|
||||
|
||||
$lng['panel']['usage_statistics'] = 'Resourcen-Verbrauch';
|
||||
$lng['panel']['security_question'] = 'Sicherheitsabfrage';
|
||||
$lng['panel']['listing_empty'] = 'Keine Einträge gefunden';
|
||||
|
||||
@@ -13,49 +13,56 @@
|
||||
</h3>
|
||||
{% endif %}
|
||||
|
||||
<div class="card table-responsive">
|
||||
<table class="table table-borderless table-striped table-sm mb-0 px-3">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for key,th in listing.table.th %}
|
||||
{{ pagination.titlesorting(listing.pagination, key, th) }}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for tr in listing.table.tr %}
|
||||
<tr {% if tr.class is defined %}class="{{ tr.class }}"{% endif %}>
|
||||
{% for td in tr.td %}
|
||||
<td class="px-3{% if td.class is defined %} {{ td.class }}{% endif %}">
|
||||
{% if td.data is iterable %}
|
||||
{% if td.data.type == 'progressbar' %}
|
||||
{{ callbacks.progressbar(td.data.data) }}
|
||||
{% elseif td.data.type == 'boolean' %}
|
||||
{{ callbacks.boolean(td.data.data) }}
|
||||
{% elseif td.data.type == 'booleanWithInfo' %}
|
||||
{{ callbacks.booleanWithInfo(td.data.data) }}
|
||||
{% elseif td.data.type == 'link' %}
|
||||
{{ callbacks.link(td.data.data) }}
|
||||
{% elseif td.data.type == 'domainWithSan' %}
|
||||
{{ callbacks.domainWithSan(td.data.data) }}
|
||||
{% elseif td.data.type == 'actions' %}
|
||||
{{ callbacks.actions(td.data.data) }}
|
||||
{% else %}
|
||||
Callback '{{ td|json_encode }}' is not implemented!
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ td.data|raw }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if listing.table.tr|length == 0 %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
<h4 class="alert-heading">{{ lng('admin.note') }}</h4>
|
||||
<p>{{ listing.empty_msg|default(lng('panel.listing_empty'))|raw }}</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card table-responsive">
|
||||
<table class="table table-borderless table-striped table-sm mb-0 px-3">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for key,th in listing.table.th %}
|
||||
{{ pagination.titlesorting(listing.pagination, key, th) }}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if listing.pagination is not empty %}
|
||||
{{ pagination.paging(listing.pagination) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for tr in listing.table.tr %}
|
||||
<tr {% if tr.class is defined %} class="{{ tr.class }}" {% endif %}>
|
||||
{% for td in tr.td %}
|
||||
<td class="px-3{% if td.class is defined %} {{ td.class }}{% endif %}">
|
||||
{% if td.data is iterable %}
|
||||
{% if td.data.type == 'progressbar' %}
|
||||
{{ callbacks.progressbar(td.data.data) }}
|
||||
{% elseif td.data.type == 'boolean' %}
|
||||
{{ callbacks.boolean(td.data.data) }}
|
||||
{% elseif td.data.type == 'booleanWithInfo' %}
|
||||
{{ callbacks.booleanWithInfo(td.data.data) }}
|
||||
{% elseif td.data.type == 'link' %}
|
||||
{{ callbacks.link(td.data.data) }}
|
||||
{% elseif td.data.type == 'domainWithSan' %}
|
||||
{{ callbacks.domainWithSan(td.data.data) }}
|
||||
{% elseif td.data.type == 'actions' %}
|
||||
{{ callbacks.actions(td.data.data) }}
|
||||
{% else %}
|
||||
Callback '{{ td|json_encode }}' is not implemented!
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ td.data|raw }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if listing.pagination is not empty %}
|
||||
{{ pagination.paging(listing.pagination) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% endmacro %}
|
||||
|
||||
Reference in New Issue
Block a user