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