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