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