xref: /webtrees/resources/views/admin/control-panel.phtml (revision aaafd355d2cee5330c9f89ee69ed12ba8ecc27fa)
1<?php
2
3use Fisharebest\Webtrees\I18N;
4use Fisharebest\Webtrees\Module\ModuleConfigInterface;
5use Fisharebest\Webtrees\Module\ModuleCustomInterface;
6use Fisharebest\Webtrees\Webtrees;
7use Illuminate\Support\Collection;
8
9/**
10 * @var string     $latest_version
11 * @var string     $title
12 * @var Collection $server_errors
13 * @var Collection $server_warnings
14 */
15
16?>
17
18<h1><?= $title ?></h1>
19
20<!-- WEBSITE / WEBTREES -->
21<div class="card mb-4">
22    <div class="card-header">
23        <h2 class="mb-0">
24            <?= I18N::translate('Website') ?>
25            <span class="badge badge-secondary">
26                <?= e(Webtrees::VERSION) ?>
27            </span>
28        </h2>
29    </div>
30    <div class="card-body">
31        <?php foreach ($server_errors as $server_error) : ?>
32            <p class="alert alert-danger"><?= $server_error ?></p>
33        <?php endforeach ?>
34
35        <?php foreach ($server_warnings as $server_warning) : ?>
36            <p class="alert alert-warning"><?= $server_warning ?></p>
37        <?php endforeach ?>
38
39        <p class="card-text">
40            <?= /* I18N: %s is a URL/link to the project website */
41            I18N::translate('Support and documentation can be found at %s.', '<a href="https://webtrees.net/">webtrees.net</a>') ?>
42        </p>
43        <p class="card-text ">
44            <?php if ($latest_version === '') : ?>
45                <?= I18N::translate('No upgrade information is available.') ?>
46            <?php elseif (version_compare(Webtrees::VERSION, $latest_version) < 0) : ?>
47                <?= I18N::translate('A new version of webtrees is available.') ?>
48                <a href="<?= e(route('upgrade')) ?>" class="error">
49                    <?= /* I18N: %s is a version number */
50                    I18N::translate('Upgrade to webtrees %s.', e($latest_version)) ?>
51                </a>
52            <?php else : ?>
53                <?= I18N::translate('This is the latest version of webtrees. No upgrade is available.') ?>
54            <?php endif ?>
55        </p>
56
57        <div class="row">
58            <div class="col-sm-6">
59                <ul class="fa-ul">
60                    <li>
61                        <span class="fa-li"><?= view('icons/preferences') ?></span>
62                        <a href="<?= e(route('admin-site-preferences')) ?>">
63                            <?= I18N::translate('Website preferences') ?>
64                        </a>
65                    </li>
66                    <li>
67                        <span class="fa-li"><?= view('icons/preferences') ?></span>
68                        <a href="<?= e(route('admin-site-mail')) ?>">
69                            <?= I18N::translate('Sending email') ?>
70                        </a>
71                    </li>
72                    <li>
73                        <span class="fa-li"><?= view('icons/preferences') ?></span>
74                        <a href="<?= e(route('admin-site-registration')) ?>">
75                            <?= I18N::translate('Sign-in and registration') ?>
76                        </a>
77                    </li>
78                    <li>
79                        <span class="fa-li"><?= view('icons/preferences') ?></span>
80                        <a href="<?= e(route('admin-site-languages')) ?>">
81                            <?= I18N::translate('Languages') ?>
82                        </a>
83                    </li>
84                </ul>
85            </div>
86            <div class="col-sm-6">
87                <ul class="fa-ul">
88                    <li>
89                        <span class="fa-li"><?= view('icons/preferences') ?></span>
90                        <a href="<?= e(route('admin-site-logs')) ?>">
91                            <?= I18N::translate('Website logs') ?>
92                        </a>
93                    </li>
94                    <li>
95                        <span class="fa-li"><?= view('icons/preferences') ?></span>
96                        <a href="<?= e(route('admin-clean-data')) ?>">
97                            <?= I18N::translate('Clean up data folder') ?>
98                        </a>
99                    </li>
100                    <li>
101                        <span class="fa-li"><?= view('icons/preferences') ?></span>
102                        <a href="<?= e(route('admin-site-information')) ?>">
103                            <?= I18N::translate('Server information') ?>
104                        </a>
105                    </li>
106                </ul>
107            </div>
108        </div>
109    </div>
110</div>
111
112<!-- FAMILY TREES -->
113<div class="card mb-4 <?= array_sum($changes) ? 'card-outline-danger' : '' ?>">
114    <div class="card-header">
115        <h2 class="mb-0">
116            <?= I18N::translate('Family trees') ?>
117            <span class="badge badge-secondary">
118                    <?= I18N::number(count($all_trees)) ?>
119                </span>
120        </h2>
121    </div>
122    <div class="card-body">
123        <table class="table table-sm">
124            <caption class="sr-only">
125                <?= I18N::translate('Family trees') ?>
126            </caption>
127            <thead>
128                <tr>
129                    <th><?= I18N::translate('Family tree') ?></th>
130                    <th>
131                        <span class="sr-only"><?= I18N::translate('Manage family trees') ?></span>
132                    </th>
133                    <th class="text-right"><?= I18N::translate('Pending changes') ?></th>
134                    <th class="d-none d-sm-table-cell text-right"><?= I18N::translate('Individuals') ?></th>
135                    <th class="d-none d-lg-table-cell text-right"><?= I18N::translate('Families') ?></th>
136                    <th class="d-none d-sm-table-cell text-right"><?= I18N::translate('Sources') ?></th>
137                    <th class="d-none d-lg-table-cell text-right"><?= I18N::translate('Repositories') ?></th>
138                    <th class="d-none d-sm-table-cell text-right"><?= I18N::translate('Media') ?></th>
139                    <th class="d-none d-lg-table-cell text-right"><?= I18N::translate('Notes') ?></th>
140                </tr>
141            </thead>
142            <tbody>
143                <?= view('admin/control-panel-tree-list', [
144                    'all_trees'              => $all_trees,
145                    'changes'                => $changes,
146                    'families'               => $families,
147                    'individuals'            => $individuals,
148                    'media'                  => $media,
149                    'notes'                  => $notes,
150                    'repositories'           => $repositories,
151                    'sources'                => $sources,
152                    'family_list_module'     => $family_list_module,
153                    'individual_list_module' => $individual_list_module,
154                    'media_list_module'      => $media_list_module,
155                    'note_list_module'       => $note_list_module,
156                    'repository_list_module' => $repository_list_module,
157                    'source_list_module'     => $source_list_module,
158                ]); ?>
159            </tbody>
160            <tfoot>
161                <tr>
162                    <th scope="row">
163                        <?= I18N::translate('Total') ?>
164                    </th>
165                    <td></td>
166                    <td class="text-right">
167                        <?= I18N::number(array_sum($changes)) ?>
168                    </td>
169                    <td class="d-none d-sm-table-cell text-right">
170                        <?= I18N::number($individuals->sum()) ?>
171                    </td>
172                    <td class="d-none d-lg-table-cell text-right">
173                        <?= I18N::number($families->sum()) ?>
174                    </td>
175                    <td class="d-none d-sm-table-cell text-right">
176                        <?= I18N::number($sources->sum()) ?>
177                    </td>
178                    <td class="d-none d-lg-table-cell text-right">
179                        <?= I18N::number($repositories->sum()) ?>
180                    </td>
181                    <td class="d-none d-sm-table-cell text-right">
182                        <?= I18N::number($media->sum()) ?>
183                    </td>
184                    <td class="d-none d-lg-table-cell text-right">
185                        <?= I18N::number($notes->sum()) ?>
186                    </td>
187                </tr>
188            </tfoot>
189        </table>
190
191        <ul class="fa-ul">
192            <li>
193                <span class="fa-li"><?= view('icons/preferences') ?></span>
194                <a href="<?= e(route('admin-trees')) ?>">
195                    <?= I18N::translate('Manage family trees') ?>
196                </a>
197            </li>
198            <li>
199                <span class="fa-li"><?= view('icons/preferences') ?></span>
200                <a href="<?= e(route('tree-page-default-edit')) ?>">
201                    <?= I18N::translate('Set the default blocks for new family trees') ?>
202                </a>
203            </li>
204            <?php if (count($all_trees) > 1) : ?>
205                <li>
206                    <span class="fa-li"><?= view('icons/preferences') ?></span>
207                    <a href="<?= e(route('admin-trees-merge')) ?>">
208                        <?= I18N::translate('Merge family trees') ?>
209                    </a>
210                </li>
211            <?php endif ?>
212        </ul>
213    </div>
214</div>
215
216<!-- USERS -->
217<div class="card mb-4 <?= $unapproved || $unverified ? 'card-outline-danger' : '' ?>">
218    <div class="card-header">
219        <h2 class="mb-0">
220            <?= I18N::translate('Users') ?>
221            <span class="badge badge-secondary">
222                    <?= I18N::number(count($all_users)) ?>
223                </span>
224        </h2>
225    </div>
226    <div class="card-body">
227        <dl class="row">
228            <?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) : ?>
229                <?php if (!empty($list)) : ?>
230                    <dt class="col-sm-3">
231                        <?= $label ?>
232                    </dt>
233                    <dd class="col-sm-9">
234                        <?php foreach ($list as $n => $user) : ?>
235                            <?= $n ? I18N::$list_separator : '' ?>
236                            <a href="<?= e(route('admin-users-edit', ['user_id' => $user->id()])) ?>" dir="auto">
237                                <?= e($user->realName()) ?>
238                            </a>
239                        <?php endforeach ?>
240                    </dd>
241                <?php endif ?>
242            <?php endforeach ?>
243        </dl>
244
245        <div class="row">
246            <div class="col-sm-6">
247                <ul class="fa-ul">
248                    <li>
249                        <span class="fa-li"><?= view('icons/preferences') ?></span>
250                        <a href="<?= e(route('admin-users')) ?>">
251                            <?= I18N::translate('User administration') ?>
252                        </a>
253                    </li>
254                    <li>
255                        <span class="fa-li"><?= view('icons/preferences') ?></span>
256                        <a href="<?= e(route('admin-users-create')) ?>">
257                            <?= I18N::translate('Add a user') ?>
258                        </a>
259                    </li>
260                    <li>
261                        <span class="fa-li"><?= view('icons/preferences') ?></span>
262                        <a href="<?= e(route('admin-users-cleanup')) ?>">
263                            <?= I18N::translate('Delete inactive users') ?>
264                        </a>
265                    </li>
266                    <li>
267                        <span class="fa-li"><?= view('icons/preferences') ?></span>
268                        <a href="<?= e(route('user-page-default-edit')) ?>">
269                            <?= I18N::translate('Set the default blocks for new users') ?>
270                        </a>
271                    </li>
272                </ul>
273            </div>
274            <div class="col-sm-6">
275                <ul class="fa-ul">
276                    <li>
277                        <span class="fa-li"><?= view('icons/email') ?></span>
278                        <a href="<?= e(route('broadcast', ['to' => 'all'])) ?>">
279                            <?= I18N::translate('Send a message to all users') ?>
280                        </a>
281                    </li>
282                    <li>
283                        <span class="fa-li"><?= view('icons/email') ?></span>
284                        <a href="<?= e(route('broadcast', ['to' => 'never_logged'])) ?>">
285                            <?= I18N::translate('Send a message to users who have never signed in') ?>
286                        </a>
287                    </li>
288                    <li>
289                        <span class="fa-li"><?= view('icons/email') ?></span>
290                        <a href="<?= e(route('broadcast', ['to' => 'last_6mo'])) ?>">
291                            <?= I18N::translate('Send a message to users who have not signed in for 6 months') ?>
292                        </a>
293                    </li>
294                </ul>
295            </div>
296        </div>
297    </div>
298</div>
299
300<!-- MODULES -->
301<div class="card mb-4">
302    <div class="card-header">
303        <h2 class="mb-0">
304            <?= I18N::translate('Modules') ?>
305            <?= view('components/badge', ['count' => $all_modules_enabled->count(), 'total' => $all_modules_disabled->count(), 'context' => 'secondary']) ?>
306        </h2>
307    </div>
308
309    <div class="card-body">
310        <ul class="fa-ul">
311            <li>
312                <span class="fa-li"><?= view('icons/module') ?></span>
313                <a href="<?= e(route('modules')) ?>">
314                    <?= I18N::translate('All modules') ?>
315                </a>
316                <?= view('components/badge', ['count' => $all_modules_enabled->count(), 'total' => $all_modules_disabled->count(), 'context' => 'primary']) ?>
317            </li>
318        </ul>
319
320        <div class="row">
321            <div class="col-sm-6">
322                <h3>
323                    <?= I18N::translate('Genealogy') ?>
324                </h3>
325
326                <ul class="fa-ul">
327                    <li>
328                        <span class="fa-li"><?= view('icons/menu') ?></span>
329                        <a href="<?= e(route('menus')) ?>">
330                            <?= I18N::translate('Menus') ?>
331                        </a>
332                        <?= view('components/badge', ['count' => $menu_modules_enabled->count(), 'total' => $menu_modules_disabled->count(), 'context' => 'primary']) ?>
333                    </li>
334                    <li>
335                        <span class="fa-li"><?= view('icons/chart') ?></span>
336                        <a href="<?= e(route('charts')) ?>">
337                            <?= I18N::translate('Charts') ?>
338                        </a>
339                        <?= view('components/badge', ['count' => $chart_modules_enabled->count(), 'total' => $chart_modules_disabled->count(), 'context' => 'primary']) ?>
340                    </li>
341                    <li>
342                        <span class="fa-li"><?= view('icons/list') ?></span>
343                        <a href="<?= e(route('lists')) ?>">
344                            <?= I18N::translate('Lists') ?>
345                        </a>
346                        <?= view('components/badge', ['count' => $list_modules_enabled->count(), 'total' => $list_modules_disabled->count(), 'context' => 'primary']) ?>
347                    </li>
348                    <li>
349                        <span class="fa-li"><?= view('icons/report') ?></span>
350                        <a href="<?= e(route('reports')) ?>">
351                            <?= I18N::translate('Reports') ?>
352                        </a>
353                        <?= view('components/badge', ['count' => $report_modules_enabled->count(), 'total' => $report_modules_disabled->count(), 'context' => 'primary']) ?>
354                    </li>
355                </ul>
356
357                <h3>
358                    <?= I18N::translate('Website') ?>
359                </h3>
360
361                <ul class="fa-ul">
362                    <li>
363                        <span class="fa-li"><?= view('icons/footer') ?></span>
364                        <a href="<?= e(route('footers')) ?>">
365                            <?= I18N::translate('Footers') ?>
366                        </a>
367                        <?= view('components/badge', ['count' => $footer_modules_enabled->count(), 'total' => $footer_modules_disabled->count(), 'context' => 'primary']) ?>
368                    </li>
369                    <li>
370                        <span class="fa-li"><?= view('icons/analytics') ?></span>
371                        <a href="<?= e(route('analytics')) ?>">
372                            <?= I18N::translate('Tracking and analytics') ?>
373                        </a>
374                        <?= view('components/badge', ['count' => $analytics_modules_enabled->count(), 'total' => $analytics_modules_disabled->count(), 'context' => 'primary']) ?>
375                    </li>
376                    <li>
377                        <span class="fa-li"><?= view('icons/theme') ?></span>
378                        <a href="<?= e(route('themes')) ?>">
379                            <?= I18N::translate('Themes') ?>
380                        </a>
381                        <?= view('components/badge', ['count' => $theme_modules_enabled->count(), 'total' => $theme_modules_disabled->count(), 'context' => 'primary']) ?>
382                    </li>
383                    <li>
384                        <span class="fa-li"><?= view('icons/language') ?></span>
385                        <a href="<?= e(route('languages')) ?>">
386                            <?= I18N::translate('Languages') ?>
387                        </a>
388                        <?= view('components/badge', ['count' => $language_modules_enabled->count(), 'total' => $language_modules_disabled->count(), 'context' => 'primary']) ?>
389                    </li>
390                </ul>
391
392                <h3>
393                    <?= I18N::translate('Home page') ?>
394                </h3>
395
396                <ul class="fa-ul">
397                    <li>
398                        <span class="fa-li"><?= view('icons/block') ?></span>
399                        <a href="<?= e(route('blocks')) ?>">
400                            <?= I18N::translate('Blocks') ?>
401                        </a>
402                        <?= view('components/badge', ['count' => $block_modules_enabled->count(), 'total' => $block_modules_disabled->count(), 'context' => 'primary']) ?>
403                    </li>
404                </ul>
405            </div>
406
407            <div class="col-sm-6">
408                <h3>
409                    <?= I18N::translate('Individual page') ?>
410                </h3>
411
412                <ul class="fa-ul">
413                    <li>
414                        <span class="fa-li"><?= view('icons/tab') ?></span>
415                        <a href="<?= e(route('tabs')) ?>">
416                            <?= I18N::translate('Tabs') ?>
417                            <?= view('components/badge', ['count' => $tab_modules_enabled->count(), 'total' => $tab_modules_disabled->count(), 'context' => 'primary']) ?>
418                        </a>
419                    </li>
420                    <li>
421                        <span class="fa-li"><?= view('icons/sidebar') ?></span>
422                        <a href="<?= e(route('sidebars')) ?>">
423                            <?= I18N::translate('Sidebars') ?>
424                        </a>
425                        <?= view('components/badge', ['count' => $sidebar_modules_enabled->count(), 'total' => $sidebar_modules_disabled->count(), 'context' => 'primary']) ?>
426                    </li>
427                    <li>
428                        <span class="fa-li"><?= view('icons/history') ?></span>
429                        <a href="<?= e(route('history')) ?>">
430                            <?= I18N::translate('Historic events') ?>
431                        </a>
432                        <?= view('components/badge', ['count' => $history_modules_enabled->count(), 'total' => $history_modules_disabled->count(), 'context' => 'primary']) ?>
433                    </li>
434                </ul>
435
436                <h3>
437                    <?= I18N::translate('Other') ?>
438                </h3>
439
440                <ul class="fa-ul">
441                    <?php foreach ($other_modules as $module) : ?>
442                        <li>
443                            <span class="fa-li"><?= view('icons/module') ?></span>
444                            <?php if ($module->isEnabled() && $module instanceof ModuleConfigInterface): ?>
445                                <a href="<?= e($module->getConfigLink()) ?>">
446                                    <?= $module->title() ?>
447                                    <span class="fa"><?= view('icons/preferences') ?></span>
448                                </a>
449                            <?php elseif ($module->isEnabled()) : ?>
450                                <?= $module->title() ?>
451                            <?php else : ?>
452                                <del class="text-muted"><?= $module->title() ?></del>
453                            <?php endif ?>
454                            <?php if ($module instanceof ModuleCustomInterface): ?>
455                                <?= view('admin/custom-module-info', ['module' => $module]) ?>
456                            <?php endif ?>
457                        </li>
458                    <?php endforeach ?>
459                </ul>
460            </div>
461        </div>
462    </div>
463</div>
464
465<!-- MEDIA -->
466<div class="card mb-4">
467    <div class="card-header">
468        <h2 class="mb-0">
469            <?= I18N::translate('Media') ?>
470        </h2>
471    </div>
472    <div class="card-body">
473        <ul class="fa-ul">
474            <li>
475                <span class="fa-li"><?= view('icons/preferences') ?></span>
476                <a href="<?= e(route('admin-media')) ?>">
477                    <?= I18N::translate('Manage media') ?>
478                </a>
479            </li>
480            <li>
481                <span class="fa-li"><?= view('icons/preferences') ?></span>
482                <a href="<?= e(route('admin-media-upload')) ?>">
483                    <?= I18N::translate('Upload media files') ?>
484                </a>
485            </li>
486            <li>
487                <span class="fa-li"><?= view('icons/preferences') ?></span>
488                <a href="<?= e(route('admin-fix-level-0-media')) ?>">
489                    <?= I18N::translate('Link media objects to facts and events') ?>
490                </a>
491            </li>
492            <li>
493                <span class="fa-li"><?= view('icons/preferences') ?></span>
494                <a href="<?= e(route('admin-webtrees1-thumbs')) ?>">
495                    <?= I18N::translate('Import custom thumbnails from webtrees version 1') ?>
496                </a>
497            </li>
498        </ul>
499    </div>
500</div>
501
502<!-- MAPS -->
503<div class="card mb-4">
504    <div class="card-header">
505        <h2 class="mb-0">
506            <?= I18N::translate('Map') ?>
507        </h2>
508    </div>
509    <div class="card-body">
510        <div class="row">
511            <div class="col-sm-6">
512                <ul class="fa-ul">
513                    <li>
514                        <span class="fa-li"><?= view('icons/location') ?></span>
515                        <a href="<?= e(route('map-data')) ?>">
516                            <?= I18N::translate('Geographic data') ?>
517                        </a>
518                    </li>
519                </ul>
520            </div>
521            <div class="col-sm-6">
522                <ul class="fa-ul">
523                    <li>
524                        <span class="fa-li"><?= view('icons/map') ?></span>
525                        <a href="<?= e(route('map-provider')) ?>">
526                            <?= I18N::translate('Map provider') ?>
527                        </a>
528                    </li>
529                </ul>
530            </div>
531        </div>
532    </div>
533</div>
534
535<!-- OLD FILES -->
536<?php if (!empty($files_to_delete)) : ?>
537    <div class="card mb-4 card-outline-danger">
538        <div class="card-header">
539            <h2 class="mb-0">
540                <?= I18N::translate('Old files found') ?>
541            </h2>
542        </div>
543        <div class="card-body">
544            <p>
545                <?= I18N::translate('Files have been found from a previous version of webtrees. Old files can sometimes be a security risk. You should delete them.') ?>
546            </p>
547            <ul class="list-unstyled">
548                <?php foreach ($files_to_delete as $file_to_delete) : ?>
549                    <li dir="ltr">
550                        <code><?= e($file_to_delete) ?></code>
551                    </li>
552                <?php endforeach ?>
553            </ul>
554        </div>
555    </div>
556<?php endif ?>
557