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