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()) : ?> 496 — 497 <?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