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