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