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