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