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