xref: /webtrees/resources/views/admin/control-panel.phtml (revision b8c8582ab2a169215e9010c84703b6f7f9c8027d)
1<?php
2
3use Fisharebest\Webtrees\Http\RequestHandlers\BroadcastPage;
4use Fisharebest\Webtrees\Http\RequestHandlers\CleanDataFolder;
5use Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel;
6use Fisharebest\Webtrees\Http\RequestHandlers\CreateTreePage;
7use Fisharebest\Webtrees\Http\RequestHandlers\PendingChanges;
8use Fisharebest\Webtrees\Http\RequestHandlers\PhpInformation;
9use Fisharebest\Webtrees\Http\RequestHandlers\SiteLogsPage;
10use Fisharebest\Webtrees\Http\RequestHandlers\EmailPreferencesPage;
11use Fisharebest\Webtrees\Http\RequestHandlers\TreePageDefaultEdit;
12use Fisharebest\Webtrees\Http\RequestHandlers\UserPageDefaultEdit;
13use Fisharebest\Webtrees\Http\RequestHandlers\UsersCleanupPage;
14use Fisharebest\Webtrees\I18N;
15use Fisharebest\Webtrees\Module\FamilyListModule;
16use Fisharebest\Webtrees\Module\IndividualListModule;
17use Fisharebest\Webtrees\Module\MediaListModule;
18use Fisharebest\Webtrees\Module\ModuleConfigInterface;
19use Fisharebest\Webtrees\Module\ModuleCustomInterface;
20use Fisharebest\Webtrees\Module\NoteListModule;
21use Fisharebest\Webtrees\Module\RepositoryListModule;
22use Fisharebest\Webtrees\Module\SourceListModule;
23use Fisharebest\Webtrees\Module\SubmitterListModule;
24use Fisharebest\Webtrees\Webtrees;
25use Illuminate\Support\Collection;
26
27/**
28 * @var string     $latest_version
29 * @var string     $title
30 * @var Collection $server_errors
31 * @var Collection $server_warnings
32 */
33
34?>
35
36<h1><?= $title ?></h1>
37
38<!-- WEBSITE / WEBTREES -->
39<div class="card mb-4">
40    <div class="card-header">
41        <h2 class="mb-0">
42            <?= I18N::translate('Website') ?>
43            <span class="badge badge-secondary" dir="ltr">
44                <?= e(Webtrees::VERSION) ?>
45            </span>
46        </h2>
47    </div>
48    <div class="card-body">
49        <?php foreach ($server_errors as $server_error) : ?>
50            <p class="alert alert-danger"><?= $server_error ?></p>
51        <?php endforeach ?>
52
53        <?php foreach ($server_warnings as $server_warning) : ?>
54            <p class="alert alert-warning"><?= $server_warning ?></p>
55        <?php endforeach ?>
56
57        <p class="card-text">
58            <?= /* I18N: %s is a URL/link to the project website */
59            I18N::translate('Support and documentation can be found at %s.', '<a href="https://webtrees.net/">webtrees.net</a>') ?>
60        </p>
61        <p class="card-text">
62            <?php if ($latest_version === '') : ?>
63                <?= I18N::translate('No upgrade information is available.') ?>
64            <?php elseif (version_compare(Webtrees::VERSION, $latest_version) < 0) : ?>
65                <div class="alert alert-info">
66                    <?= I18N::translate('A new version of webtrees is available.') ?>
67                    <a href="<?= e(route('upgrade')) ?>" class="alert-link">
68                        <?= /* I18N: %s is a version number */
69                        I18N::translate('Upgrade to webtrees %s.', e($latest_version)) ?>
70                    </a>
71                </div>
72            <?php else : ?>
73                <?= I18N::translate('This is the latest version of webtrees. No upgrade is available.') ?>
74            <?php endif ?>
75        </p>
76
77        <div class="row">
78            <div class="col-sm-6">
79                <ul class="fa-ul">
80                    <li>
81                        <span class="fa-li"><?= view('icons/preferences') ?></span>
82                        <a href="<?= e(route('admin-site-preferences')) ?>">
83                            <?= I18N::translate('Website preferences') ?>
84                        </a>
85                    </li>
86                    <li>
87                        <span class="fa-li"><?= view('icons/email') ?></span>
88                        <a href="<?= e(route(EmailPreferencesPage::class)) ?>">
89                            <?= I18N::translate('Sending email') ?>
90                        </a>
91                    </li>
92                    <li>
93                        <span class="fa-li"><?= view('icons/user') ?></span>
94                        <a href="<?= e(route('admin-site-registration')) ?>">
95                            <?= I18N::translate('Sign-in and registration') ?>
96                        </a>
97                    </li>
98                </ul>
99            </div>
100            <div class="col-sm-6">
101                <ul class="fa-ul">
102                    <li>
103                        <span class="fa-li"><?= view('icons/list') ?></span>
104                        <a href="<?= e(route(SiteLogsPage::class)) ?>">
105                            <?= I18N::translate('Website logs') ?>
106                        </a>
107                    </li>
108                    <li>
109                        <span class="fa-li"><?= view('icons/delete') ?></span>
110                        <a href="<?= e(route(CleanDataFolder::class)) ?>">
111                            <?= I18N::translate('Clean up data folder') ?>
112                        </a>
113                    </li>
114                    <li>
115                        <span class="fa-li"><?= view('icons/help') ?></span>
116                        <a href="<?= e(route(PhpInformation::class)) ?>">
117                            <?= I18N::translate('Server information') ?>
118                        </a>
119                    </li>
120                </ul>
121            </div>
122        </div>
123    </div>
124</div>
125
126<!-- FAMILY TREES -->
127<div class="card mb-4 <?= array_sum($changes) ? 'card-outline-danger' : '' ?>">
128    <div class="card-header">
129        <h2 class="mb-0">
130            <?= I18N::translate('Family trees') ?>
131            <span class="badge badge-secondary">
132                    <?= I18N::number(count($all_trees)) ?>
133                </span>
134        </h2>
135    </div>
136    <div class="card-body">
137        <?php if ($all_trees->isEmpty()) : ?>
138            <p class="alert alert-info">
139                <?= I18N::translate('You need to create a family tree.') ?>
140            </p>
141        <?php endif ?>
142
143        <ul class="fa-ul">
144            <li>
145                <span class="fa-li"><?= view('icons/add') ?></span>
146                <a href="<?= e(route(CreateTreePage::class)) ?>">
147                    <?= I18N::translate('Create a family tree') ?>
148                </a>
149            </li>
150            <li>
151                <span class="fa-li"><?= view('icons/block') ?></span>
152                <a href="<?= e(route(TreePageDefaultEdit::class)) ?>">
153                    <?= I18N::translate('Set the default blocks for new family trees') ?>
154                </a>
155            </li>
156            <?php if (count($all_trees) > 1) : ?>
157                <li>
158                    <span class="fa-li"><?= view('icons/merge') ?></span>
159                    <a href="<?= e(route('admin-trees-merge')) ?>">
160                        <?= I18N::translate('Merge family trees') ?>
161                    </a>
162                </li>
163            <?php endif ?>
164        </ul>
165
166        <table class="table table-sm">
167            <caption class="sr-only">
168                <?= I18N::translate('Family trees') ?>
169            </caption>
170            <thead>
171                <tr>
172                    <th><?= I18N::translate('Family tree') ?></th>
173                    <th class="align-digits"><?= I18N::translate('Pending changes') ?></th>
174                    <th class="d-none d-sm-table-cell align-digits"><?= I18N::translate('Individuals') ?></th>
175                    <th class="d-none d-lg-table-cell align-digits"><?= I18N::translate('Families') ?></th>
176                    <th class="d-none d-sm-table-cell align-digits"><?= I18N::translate('Sources') ?></th>
177                    <th class="d-none d-lg-table-cell align-digits"><?= I18N::translate('Repositories') ?></th>
178                    <th class="d-none d-sm-table-cell align-digits"><?= I18N::translate('Media') ?></th>
179                    <th class="d-none d-lg-table-cell align-digits"><?= I18N::translate('Notes') ?></th>
180                    <th class="d-none d-lg-table-cell align-digits"><?= I18N::translate('Submitters') ?></th>
181                </tr>
182            </thead>
183            <tbody>
184                <?php foreach ($all_trees as $tree) : ?>
185                    <tr class="<?= $changes[$tree->id()] ? 'danger' : '' ?>">
186                        <th scope="row">
187                            <a href="<?= e(route('manage-trees', ['tree' => $tree->name()])) ?>">
188                                <?= view('icons/preferences') ?>
189                                <?= e($tree->name()) ?>
190                                -
191                                <?= e($tree->title()) ?>
192                            </a>
193                        </th>
194                        <td style="text-align: right;">
195                            <?php if ($changes[$tree->id()]) : ?>
196                                <a href="<?= e(route(PendingChanges::class, ['tree' => $tree->name(), 'url' => route(ControlPanel::class)])) ?>">
197                                    <?= I18N::number($changes[$tree->id()]) ?>
198                                    <span class="sr-only"><?= I18N::translate('Pending changes') ?> <?= e($tree->title()) ?></span>
199                                </a>
200                            <?php else : ?>
201                                -
202                            <?php endif ?>
203                        </td>
204                        <td class="d-none d-sm-table-cell align-digits">
205                            <?php if ($individuals[$tree->id()] > 0) : ?>
206                                <?php if ($individual_list_module instanceof IndividualListModule) : ?>
207                                    <a href="<?= e($individual_list_module->listUrl($tree)) ?>"><?= I18N::number($individuals[$tree->id()]) ?></a>
208                                <?php else : ?>
209                                    <?= I18N::number($individuals[$tree->id()]) ?>
210                                <?php endif ?>
211                            <?php else : ?>
212                                -
213                            <?php endif ?>
214                        </td>
215                        <td class="d-none d-lg-table-cell align-digits">
216                            <?php if ($families[$tree->id()] > 0) : ?>
217                                <?php if ($family_list_module instanceof FamilyListModule) : ?>
218                                    <a href="<?= e($family_list_module->listUrl($tree)) ?>"><?= I18N::number($families[$tree->id()]) ?></a>
219                                <?php else : ?>
220                                    <?= I18N::number($families[$tree->id()]) ?>
221                                <?php endif ?>
222                            <?php else : ?>
223                                -
224                            <?php endif ?>
225                        </td>
226                        <td class="d-none d-sm-table-cell align-digits">
227                            <?php if ($sources[$tree->id()] > 0) : ?>
228                                <?php if ($source_list_module instanceof SourceListModule) : ?>
229                                    <a href="<?= e($source_list_module->listUrl($tree)) ?>"><?= I18N::number($sources[$tree->id()]) ?></a>
230                                <?php else : ?>
231                                    <?= I18N::number($sources[$tree->id()]) ?>
232                                <?php endif ?>
233                            <?php else : ?>
234                                -
235                            <?php endif ?>
236                        </td>
237                        <td class="d-none d-lg-table-cell align-digits">
238                            <?php if ($repositories[$tree->id()] > 0) : ?>
239                                <?php if ($repository_list_module instanceof RepositoryListModule) : ?>
240                                    <a href="<?= e($repository_list_module->listUrl($tree)) ?>"><?= I18N::number($repositories[$tree->id()]) ?></a>
241                                <?php else : ?>
242                                    <?= I18N::number($repositories[$tree->id()]) ?>
243                                <?php endif ?>
244                            <?php else : ?>
245                                -
246                            <?php endif ?>
247                        </td>
248                        <td class="d-none d-sm-table-cell align-digits">
249                            <?php if ($media[$tree->id()] > 0) : ?>
250                                <?php if ($media_list_module instanceof MediaListModule) : ?>
251                                    <a href="<?= e($media_list_module->listUrl($tree)) ?>"><?= I18N::number($media[$tree->id()]) ?></a>
252                                <?php else : ?>
253                                    <?= I18N::number($media[$tree->id()]) ?>
254                                <?php endif ?>
255                            <?php else : ?>
256                                -
257                            <?php endif ?>
258                        </td>
259                        <td class="d-none d-lg-table-cell align-digits">
260                            <?php if ($notes[$tree->id()] > 0) : ?>
261                                <?php if ($note_list_module instanceof NoteListModule) : ?>
262                                    <a href="<?= e($note_list_module->listUrl($tree)) ?>"><?= I18N::number($notes[$tree->id()]) ?></a>
263                                <?php else : ?>
264                                    <?= I18N::number($notes[$tree->id()]) ?>
265                                <?php endif ?>
266                            <?php else : ?>
267                                -
268                            <?php endif ?>
269                        </td>
270                         <td class="d-none d-lg-table-cell align-digits">
271                            <?php if ($submitters[$tree->id()] > 0) : ?>
272                                <?php if ($submitter_list_module instanceof SubmitterListModule) : ?>
273                                    <a href="<?= e($submitter_list_module->listUrl($tree)) ?>"><?= I18N::number($submitters[$tree->id()]) ?></a>
274                                <?php else : ?>
275                                    <?= I18N::number($submitters[$tree->id()]) ?>
276                                <?php endif ?>
277                            <?php else : ?>
278                                -
279                            <?php endif ?>
280                        </td>
281                    </tr>
282                <?php endforeach ?>
283            </tbody>
284            <tfoot>
285                <tr>
286                    <th scope="row">
287                        <?= I18N::translate('Total') ?>
288                    </th>
289                    <td class="align-digits">
290                        <?= I18N::number(array_sum($changes)) ?>
291                    </td>
292                    <td class="d-none d-sm-table-cell align-digits">
293                        <?= I18N::number($individuals->sum()) ?>
294                    </td>
295                    <td class="d-none d-lg-table-cell align-digits">
296                        <?= I18N::number($families->sum()) ?>
297                    </td>
298                    <td class="d-none d-sm-table-cell align-digits">
299                        <?= I18N::number($sources->sum()) ?>
300                    </td>
301                    <td class="d-none d-lg-table-cell align-digits">
302                        <?= I18N::number($repositories->sum()) ?>
303                    </td>
304                    <td class="d-none d-sm-table-cell align-digits">
305                        <?= I18N::number($media->sum()) ?>
306                    </td>
307                    <td class="d-none d-lg-table-cell align-digits">
308                        <?= I18N::number($notes->sum()) ?>
309                    </td>
310                </tr>
311            </tfoot>
312        </table>
313    </div>
314</div>
315
316<!-- USERS -->
317<div class="card mb-4 <?= $unapproved || $unverified ? 'card-outline-danger' : '' ?>">
318    <div class="card-header">
319        <h2 class="mb-0">
320            <?= I18N::translate('Users') ?>
321            <span class="badge badge-secondary">
322                    <?= I18N::number(count($all_users)) ?>
323                </span>
324        </h2>
325    </div>
326    <div class="card-body">
327        <dl class="row">
328            <?php foreach ([I18N::translate('Administrators') => $administrators, I18N::translate('Managers') => $managers, I18N::translate('Moderators') => $moderators, I18N::translate('Not verified by the user') => $unverified, I18N::translate('Not approved by an administrator') => $unapproved] as $label => $list) : ?>
329                <?php if (!empty($list)) : ?>
330                    <dt class="col-sm-6">
331                        <?= $label ?>
332                    </dt>
333                    <dd class="col-sm-6">
334                        <?php foreach ($list as $n => $user) : ?>
335                            <?= $n ? I18N::$list_separator : '' ?>
336                            <a href="<?= e(route('admin-users-edit', ['user_id' => $user->id()])) ?>" dir="auto">
337                                <?= e($user->realName()) ?>
338                            </a>
339                        <?php endforeach ?>
340                        <?php if ($list->isEmpty()) : ?>
341342                        <?php endif ?>
343                    </dd>
344                <?php endif ?>
345            <?php endforeach ?>
346        </dl>
347
348        <div class="row">
349            <div class="col-sm-6">
350                <ul class="fa-ul">
351                    <li>
352                        <span class="fa-li"><?= view('icons/preferences') ?></span>
353                        <a href="<?= e(route('admin-users')) ?>">
354                            <?= I18N::translate('User administration') ?>
355                        </a>
356                    </li>
357                    <li>
358                        <span class="fa-li"><?= view('icons/add') ?></span>
359                        <a href="<?= e(route('admin-users-create')) ?>">
360                            <?= I18N::translate('Add a user') ?>
361                        </a>
362                    </li>
363                    <li>
364                        <span class="fa-li"><?= view('icons/delete') ?></span>
365                        <a href="<?= e(route(UsersCleanupPage::class)) ?>">
366                            <?= I18N::translate('Delete inactive users') ?>
367                        </a>
368                    </li>
369                    <li>
370                        <span class="fa-li"><?= view('icons/block') ?></span>
371                        <a href="<?= e(route(UserPageDefaultEdit::class)) ?>">
372                            <?= I18N::translate('Set the default blocks for new users') ?>
373                        </a>
374                    </li>
375                </ul>
376            </div>
377            <div class="col-sm-6">
378                <ul class="fa-ul">
379                    <li>
380                        <span class="fa-li"><?= view('icons/email') ?></span>
381                        <a href="<?= e(route(BroadcastPage::class, ['to' => 'all'])) ?>">
382                            <?= I18N::translate('Send a message to all users') ?>
383                        </a>
384                    </li>
385                    <li>
386                        <span class="fa-li"><?= view('icons/email') ?></span>
387                        <a href="<?= e(route(BroadcastPage::class, ['to' => 'never_logged'])) ?>">
388                            <?= I18N::translate('Send a message to users who have never signed in') ?>
389                        </a>
390                    </li>
391                    <li>
392                        <span class="fa-li"><?= view('icons/email') ?></span>
393                        <a href="<?= e(route(BroadcastPage::class, ['to' => 'last_6mo'])) ?>">
394                            <?= I18N::translate('Send a message to users who have not signed in for 6 months') ?>
395                        </a>
396                    </li>
397                </ul>
398            </div>
399        </div>
400    </div>
401</div>
402
403<!-- MODULES -->
404<div class="card mb-4">
405    <div class="card-header">
406        <h2 class="mb-0">
407            <?= I18N::translate('Modules') ?>
408            <?= view('components/badge', ['count' => $all_modules_enabled->count(), 'total' => $all_modules_disabled->count(), 'context' => 'secondary']) ?>
409        </h2>
410    </div>
411
412    <div class="card-body">
413        <ul class="fa-ul">
414            <li>
415                <span class="fa-li"><?= view('icons/module') ?></span>
416                <a href="<?= e(route('modules')) ?>">
417                    <?= I18N::translate('All modules') ?>
418                </a>
419                <?= view('components/badge', ['count' => $all_modules_enabled->count(), 'total' => $all_modules_disabled->count(), 'context' => 'primary']) ?>
420            </li>
421        </ul>
422
423        <div class="row">
424            <div class="col-sm-4">
425                <h3>
426                    <?= I18N::translate('Genealogy') ?>
427                </h3>
428
429                <ul class="fa-ul">
430                    <li>
431                        <span class="fa-li"><?= view('icons/menu') ?></span>
432                        <a href="<?= e(route('menus')) ?>">
433                            <?= I18N::translate('Menus') ?>
434                        </a>
435                        <?= view('components/badge', ['count' => $menu_modules_enabled->count(), 'total' => $menu_modules_disabled->count(), 'context' => 'primary']) ?>
436                    </li>
437                    <li>
438                        <span class="fa-li"><?= view('icons/chart') ?></span>
439                        <a href="<?= e(route('charts')) ?>">
440                            <?= I18N::translate('Charts') ?>
441                        </a>
442                        <?= view('components/badge', ['count' => $chart_modules_enabled->count(), 'total' => $chart_modules_disabled->count(), 'context' => 'primary']) ?>
443                    </li>
444                    <li>
445                        <span class="fa-li"><?= view('icons/list') ?></span>
446                        <a href="<?= e(route('lists')) ?>">
447                            <?= I18N::translate('Lists') ?>
448                        </a>
449                        <?= view('components/badge', ['count' => $list_modules_enabled->count(), 'total' => $list_modules_disabled->count(), 'context' => 'primary']) ?>
450                    </li>
451                    <li>
452                        <span class="fa-li"><?= view('icons/report') ?></span>
453                        <a href="<?= e(route('reports')) ?>">
454                            <?= I18N::translate('Reports') ?>
455                        </a>
456                        <?= view('components/badge', ['count' => $report_modules_enabled->count(), 'total' => $report_modules_disabled->count(), 'context' => 'primary']) ?>
457                    </li>
458                    <li>
459                        <span class="fa-li"><?= view('icons/data-fix') ?></span>
460                        <a href="<?= e(route('data-fixes')) ?>">
461                            <?= I18N::translate('Data fixes') ?>
462                        </a>
463                        <?= view('components/badge', ['count' => $data_fix_modules_enabled->count(), 'total' => $data_fix_modules_disabled->count(), 'context' => 'primary']) ?>
464                    </li>
465                </ul>
466
467                <h3>
468                    <?= I18N::translate('Website') ?>
469                </h3>
470
471                <ul class="fa-ul">
472                    <li>
473                        <span class="fa-li"><?= view('icons/footer') ?></span>
474                        <a href="<?= e(route('footers')) ?>">
475                            <?= I18N::translate('Footers') ?>
476                        </a>
477                        <?= view('components/badge', ['count' => $footer_modules_enabled->count(), 'total' => $footer_modules_disabled->count(), 'context' => 'primary']) ?>
478                    </li>
479                    <li>
480                        <span class="fa-li"><?= view('icons/analytics') ?></span>
481                        <a href="<?= e(route('analytics')) ?>">
482                            <?= I18N::translate('Tracking and analytics') ?>
483                        </a>
484                        <?= view('components/badge', ['count' => $analytics_modules_enabled->count(), 'total' => $analytics_modules_disabled->count(), 'context' => 'primary']) ?>
485                    </li>
486                    <li>
487                        <span class="fa-li"><?= view('icons/theme') ?></span>
488                        <a href="<?= e(route('themes')) ?>">
489                            <?= I18N::translate('Themes') ?>
490                        </a>
491                        <?= view('components/badge', ['count' => $theme_modules_enabled->count(), 'total' => $theme_modules_disabled->count(), 'context' => 'primary']) ?>
492                    </li>
493                    <li>
494                        <span class="fa-li"><?= view('icons/language') ?></span>
495                        <a href="<?= e(route('languages')) ?>">
496                            <?= I18N::translate('Languages') ?>
497                        </a>
498                        <?= view('components/badge', ['count' => $language_modules_enabled->count(), 'total' => $language_modules_disabled->count(), 'context' => 'primary']) ?>
499                    </li>
500                </ul>
501
502            </div>
503
504            <div class="col-sm-4">
505
506                <h3>
507                    <?= I18N::translate('Home page') ?>
508                </h3>
509
510                <ul class="fa-ul">
511                    <li>
512                        <span class="fa-li"><?= view('icons/block') ?></span>
513                        <a href="<?= e(route('blocks')) ?>">
514                            <?= I18N::translate('Blocks') ?>
515                        </a>
516                        <?= view('components/badge', ['count' => $block_modules_enabled->count(), 'total' => $block_modules_disabled->count(), 'context' => 'primary']) ?>
517                    </li>
518                </ul>
519
520                <h3>
521                    <?= I18N::translate('Individual page') ?>
522                </h3>
523
524                <ul class="fa-ul">
525                    <li>
526                        <span class="fa-li"><?= view('icons/tab') ?></span>
527                        <a href="<?= e(route('tabs')) ?>">
528                            <?= I18N::translate('Tabs') ?>
529                            <?= view('components/badge', ['count' => $tab_modules_enabled->count(), 'total' => $tab_modules_disabled->count(), 'context' => 'primary']) ?>
530                        </a>
531                    </li>
532                    <li>
533                        <span class="fa-li"><?= view('icons/sidebar') ?></span>
534                        <a href="<?= e(route('sidebars')) ?>">
535                            <?= I18N::translate('Sidebars') ?>
536                        </a>
537                        <?= view('components/badge', ['count' => $sidebar_modules_enabled->count(), 'total' => $sidebar_modules_disabled->count(), 'context' => 'primary']) ?>
538                    </li>
539                    <li>
540                        <span class="fa-li"><?= view('icons/history') ?></span>
541                        <a href="<?= e(route('history')) ?>">
542                            <?= I18N::translate('Historic events') ?>
543                        </a>
544                        <?= view('components/badge', ['count' => $history_modules_enabled->count(), 'total' => $history_modules_disabled->count(), 'context' => 'primary']) ?>
545                    </li>
546                </ul>
547
548            </div>
549
550            <div class="col-sm-4">
551
552                <h3>
553                    <?= I18N::translate('Other') ?>
554                </h3>
555
556                <ul class="fa-ul">
557                    <?php foreach ($other_modules as $module) : ?>
558                        <li>
559                            <span class="fa-li"><?= view('icons/module') ?></span>
560
561                            <?php if ($module->isEnabled()) : ?>
562                                <?php if ($module instanceof ModuleConfigInterface) : ?>
563                                    <a href="<?= e($module->getConfigLink()) ?>">
564                                    <?= $module->title() ?>
565                                    <?= view('icons/preferences') ?>
566                                    </a>
567                                <?php else : ?>
568                                    <?= $module->title() ?>
569                                <?php endif ?>
570                            <?php else : ?>
571                                <span class="text-muted">
572                                    <span class="fa-li"><?= view('icons/module') ?></span>
573                                     <?= $module->title() ?>
574                                    <?php if ($module instanceof ModuleConfigInterface) : ?>
575                                        <?= view('icons/preferences') ?>
576                                    <?php endif ?>
577                                    </span>
578                                </span>
579                            <?php endif ?>
580
581                            <?php if ($module instanceof ModuleCustomInterface) : ?>
582                                <?= view('admin/custom-module-info', ['module' => $module]) ?>
583                            <?php endif ?>
584                        </li>
585                    <?php endforeach ?>
586                </ul>
587            </div>
588        </div>
589    </div>
590</div>
591
592<!-- MEDIA -->
593<div class="card mb-4">
594    <div class="card-header">
595        <h2 class="mb-0">
596            <?= I18N::translate('Media') ?>
597        </h2>
598    </div>
599    <div class="card-body">
600        <ul class="fa-ul">
601            <li>
602                <span class="fa-li"><?= view('icons/preferences') ?></span>
603                <a href="<?= e(route('admin-media')) ?>">
604                    <?= I18N::translate('Manage media') ?>
605                </a>
606            </li>
607            <li>
608                <span class="fa-li"><?= view('icons/upload') ?></span>
609                <a href="<?= e(route('admin-media-upload')) ?>">
610                    <?= I18N::translate('Upload media files') ?>
611                </a>
612            </li>
613            <li>
614                <span class="fa-li"><?= view('icons/link') ?></span>
615                <a href="<?= e(route('admin-fix-level-0-media')) ?>">
616                    <?= I18N::translate('Link media objects to facts and events') ?>
617                </a>
618            </li>
619            <li>
620                <span class="fa-li"><?= view('icons/upload') ?></span>
621                <a href="<?= e(route('admin-webtrees1-thumbs')) ?>">
622                    <?= I18N::translate('Import custom thumbnails from webtrees version 1') ?>
623                </a>
624            </li>
625        </ul>
626    </div>
627</div>
628
629<!-- MAPS -->
630<div class="card mb-4">
631    <div class="card-header">
632        <h2 class="mb-0">
633            <?= I18N::translate('Map') ?>
634        </h2>
635    </div>
636    <div class="card-body">
637        <div class="row">
638            <div class="col-sm-6">
639                <ul class="fa-ul">
640                    <li>
641                        <span class="fa-li"><?= view('icons/location') ?></span>
642                        <a href="<?= e(route('map-data')) ?>">
643                            <?= I18N::translate('Geographic data') ?>
644                        </a>
645                    </li>
646                </ul>
647            </div>
648            <div class="col-sm-6">
649                <ul class="fa-ul">
650                    <li>
651                        <span class="fa-li"><?= view('icons/map') ?></span>
652                        <a href="<?= e(route('map-provider')) ?>">
653                            <?= I18N::translate('Map provider') ?>
654                        </a>
655                    </li>
656                </ul>
657            </div>
658        </div>
659    </div>
660</div>
661
662<!-- OLD FILES -->
663<?php if (!empty($files_to_delete)) : ?>
664    <div class="card mb-4 card-outline-danger">
665        <div class="card-header">
666            <h2 class="mb-0">
667                <?= I18N::translate('Old files found') ?>
668            </h2>
669        </div>
670        <div class="card-body">
671            <p>
672                <?= I18N::translate('Files have been found from a previous version of webtrees. Old files can sometimes be a security risk. You should delete them.') ?>
673            </p>
674            <ul class="list-unstyled">
675                <?php foreach ($files_to_delete as $file_to_delete) : ?>
676                    <li dir="ltr">
677                        <code><?= e($file_to_delete) ?></code>
678                    </li>
679                <?php endforeach ?>
680            </ul>
681        </div>
682    </div>
683<?php endif ?>
684