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