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