1<?php 2 3use Fisharebest\Webtrees\Auth; 4use Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel; 5use Fisharebest\Webtrees\Http\RequestHandlers\CreateMediaObjectModal; 6use Fisharebest\Webtrees\Http\RequestHandlers\CreateNoteModal; 7use Fisharebest\Webtrees\Http\RequestHandlers\CreateRepositoryModal; 8use Fisharebest\Webtrees\Http\RequestHandlers\CreateSourceModal; 9use Fisharebest\Webtrees\Http\RequestHandlers\CreateSubmitterModal; 10use Fisharebest\Webtrees\Http\RequestHandlers\DataFixChoose; 11use Fisharebest\Webtrees\Http\RequestHandlers\DeleteTreeAction; 12use Fisharebest\Webtrees\Http\RequestHandlers\ExportGedcomPage; 13use Fisharebest\Webtrees\Http\RequestHandlers\MergeRecordsPage; 14use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesLogPage; 15use Fisharebest\Webtrees\Http\RequestHandlers\SelectDefaultTree; 16use Fisharebest\Webtrees\Http\RequestHandlers\TreePage; 17use Fisharebest\Webtrees\Http\RequestHandlers\UnconnectedPage; 18use Fisharebest\Webtrees\I18N; 19use Fisharebest\Webtrees\Site; 20use Fisharebest\Webtrees\Tree; 21use Fisharebest\Webtrees\View; 22use Illuminate\Database\Capsule\Manager as DB; 23 24/** 25 * @var array<Tree> $all_trees 26 * @var array<string> $gedcom_files 27 * @var int $multiple_tree_threshold 28 * @var string $title 29 * @var Tree $tree 30 */ 31 32?> 33 34<?php if (!empty($all_trees)) : ?> 35 <?= view('components/breadcrumbs', ['links' => [route(ControlPanel::class) => I18N::translate('Control panel'), $title]]) ?> 36<?php endif ?> 37 38<h1><?= $title ?></h1> 39 40<?php if (empty($all_trees)) : ?> 41 <div class="alert alert-info"> 42 <?= I18N::translate('You need to create a family tree.') ?> 43 </div> 44<?php endif ?> 45 46<div id="accordion" role="tablist" aria-multiselectable="true"> 47 <?php foreach ($all_trees as $managed_tree) : ?> 48 <?php if (Auth::isManager($managed_tree)) : ?> 49 <div class="card"> 50 <div class="card-header" role="tab" id="card-tree-header-<?= $managed_tree->id() ?>"> 51 <h2 class="mb-0"> 52 <?= view('icons/tree') ?> 53 <a data-toggle="collapse" data-parent="#accordion" href="#card-tree-content-<?= $managed_tree->id() ?>" <?= $managed_tree == $tree || $managed_tree->getPreference('imported') === '0' ? 'aria-expanded="true"' : '' ?> aria-controls="card-tree-content-<?= $managed_tree->id() ?>"> 54 <?= e($managed_tree->name()) ?> — <?= e($managed_tree->title()) ?> 55 </a> 56 </h2> 57 </div> 58 <div id="card-tree-content-<?= $managed_tree->id() ?>" class="collapse<?= $managed_tree == $tree || $managed_tree->getPreference('imported') === '0' ? ' show' : '' ?>" role="tabpanel" aria-labelledby="panel-tree-header-<?= $managed_tree->id() ?>"> 59 <div class="card-body"> 60 <?php $importing = DB::table('gedcom_chunk')->where('gedcom_id', '=', $managed_tree->id())->where('imported', '=', 0)->exists() ?> 61 <?php if ($importing) : ?> 62 <div id="import<?= $managed_tree->id() ?>" class="col-12"> 63 <div class="progress"> 64 <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"> 65 <?= I18N::translate('Calculating…') ?> 66 </div> 67 </div> 68 </div> 69 <?php View::push('javascript'); ?> 70 <script> 71 $("#import<?= $managed_tree->id() ?>").load("<?= route('import', ['tree' => $managed_tree->name()]) ?>", {}); 72 </script> 73 <?php View::endpush() ?> 74 <?php endif ?> 75 <div class="row<?= $importing ? ' d-none' : '' ?>" id="actions<?= $managed_tree->id() ?>"> 76 <div class="col-sm-6 col-md-3"> 77 <h3> 78 <?= I18N::translate('Family tree') ?> 79 </h3> 80 <ul class="fa-ul"> 81 <li> 82 <span class="fa-li"><?= view('icons/tree') ?></span> 83 <a href="<?= e(route(TreePage::class, ['tree' => $managed_tree->name()])) ?>"> 84 <?= I18N::translate('Home page') ?> 85 </a> 86 </li> 87 </ul> 88 <ul class="fa-ul"> 89 <!-- PREFERENCES --> 90 <li> 91 <span class="fa-li"><?= view('icons/preferences') ?></span> 92 <a href="<?= e(route('admin-trees-preferences', ['tree' => $managed_tree->name()])) ?>"> 93 <?= I18N::translate('Preferences') ?> 94 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 95 </a> 96 </li> 97 <!-- PRIVACY --> 98 <li> 99 <span class="fa-li"><?= view('icons/lock') ?></span> 100 <a href="<?= e(route('tree-privacy', ['tree' => $managed_tree->name()])) ?>"> 101 <?= I18N::translate('Privacy') ?> 102 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 103 </a> 104 </li> 105 <!-- DELETE --> 106 <?php if (count($all_trees) > 1 && Auth::isAdmin()) : ?> 107 <li> 108 <span class="fa-li"><?= view('icons/delete') ?></span> 109 <a href="#" data-post-url="<?= e(route(DeleteTreeAction::class, ['tree' => $managed_tree->name()])) ?>" data-reload-url="<?= e(route(ControlPanel::class)) ?>" data-confirm="<?= I18N::translate('Are you sure you want to delete “%s”?', e($managed_tree->title())) ?>"> 110 <?= I18N::translate('Delete') ?> 111 </a> 112 </li> 113 <?php endif ?> 114 115 <!-- SET AS DEFAULT --> 116 <?php if (count($all_trees) > 1 && Auth::isAdmin()) : ?> 117 <li> 118 <span class="fa-li"><?= view('icons/favorite') ?></span> 119 <?php if ($managed_tree->name() === Site::getPreference('DEFAULT_GEDCOM')) : ?> 120 <?= I18N::translate('Default family tree') ?> 121 <?php else : ?> 122 <a href="#" onclick="document.defaultform<?= $managed_tree->id() ?>.submit();"> 123 <?= I18N::translate('Set as default') ?> 124 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 125 </a> 126 <form method="post" action="<?= route(SelectDefaultTree::class, ['tree' => $managed_tree->name()]) ?>" name="defaultform<?= $managed_tree->id() ?>"> 127 <?= csrf_field() ?> 128 <!-- A11Y - forms need submit buttons, but they look ugly here --> 129 <button class="sr-only" type="submit"> 130 <?= I18N::translate('Set as default') ?> 131 </button> 132 </form> 133 <?php endif ?> 134 </li> 135 <?php endif ?> 136 </ul> 137 138 <ul class="fa-ul"> 139 <!-- DATA FIXES --> 140 <li> 141 <span class="fa-li"><?= view('icons/data-fix') ?></span> 142 <a href="<?= e(route(DataFixChoose::class, ['tree' => $managed_tree->name()])) ?>"> 143 <?= I18N::translate('Data fixes') ?> 144 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 145 </a> 146 </li> 147 </ul> 148 </div> 149 <div class="col-sm-6 col-md-3"> 150 <h3> 151 <?= /* I18N: Individuals, sources, dates, places, etc. */ 152 I18N::translate('Genealogy data') ?> 153 </h3> 154 <ul class="fa-ul"> 155 <!-- FIND DUPLICATES --> 156 <li> 157 <span class="fa-li"><?= view('icons/copy') ?></span> 158 <a href="<?= e(route('admin-trees-duplicates', ['tree' => $managed_tree->name()])) ?>"> 159 <?= I18N::translate('Find duplicates') ?> 160 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 161 </a> 162 </li> 163 <!-- MERGE --> 164 <li> 165 <span class="fa-li"><?= view('icons/merge') ?></span> 166 <a href="<?= e(route(MergeRecordsPage::class, ['tree' => $managed_tree->name()])) ?>"> 167 <?= I18N::translate('Merge records') ?> 168 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 169 </a> 170 </li> 171 <!-- CHECK FOR ERRORS --> 172 <li> 173 <span class="fa-li"><?= view('icons/warning') ?></span> 174 <a href="<?= e(route('admin-trees-check', ['tree' => $managed_tree->name()])) ?>"> 175 <?= I18N::translate('Check for errors') ?> 176 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 177 </a> 178 </li> 179 <!-- UNCONNECTED INDIVIDUALS --> 180 <li> 181 <span class="fa-li"><?= view('icons/unlink') ?></span> 182 <a href="<?= e(route(UnconnectedPage::class, ['tree' => $managed_tree->name()])) ?>"> 183 <?= I18N::translate('Find unrelated individuals') ?> 184 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 185 </a> 186 </li> 187 <!-- RENUMBER --> 188 <li> 189 <span class="fa-li"><?= view('icons/sort') ?></span> 190 <a href="<?= e(route('admin-trees-renumber', ['tree' => $managed_tree->name()])) ?>"> 191 <?= I18N::translate('Renumber') ?> 192 <span class="sr-only"> 193 <?= e($managed_tree->title()) ?> 194 </span> 195 </a> 196 </li> 197 <!-- CHANGES --> 198 <li> 199 <span class="fa-li"><?= view('icons/edit') ?></span> 200 <a href="<?= route(PendingChangesLogPage::class, ['tree' => $managed_tree->name()]) ?>"> 201 <?= I18N::translate('Changes log') ?> 202 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 203 </a> 204 </li> 205 </ul> 206 </div> 207 <div class="clearfix visible-sm-block"></div> 208 <div class="col-sm-6 col-md-3"> 209 <h3> 210 <?= I18N::translate('Add unlinked records') ?> 211 </h3> 212 <ul class="fa-ul"> 213 <!-- UNLINKED INDIVIDUAL --> 214 <li> 215 <span class="fa-li"><?= view('icons/individual') ?></span> 216 <a href="<?= e(route('add-unlinked-individual', ['tree' => $managed_tree->name()])) ?>"> 217 <?= I18N::translate('Individual') ?> 218 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 219 </a> 220 </li> 221 <!-- UNLINKED SOURCE --> 222 <li> 223 <span class="fa-li"><?= view('icons/source') ?></span> 224 <a href="#" data-href="<?= e(route(CreateSourceModal::class, ['tree' => $managed_tree->name()])) ?>" data-target="#wt-ajax-modal" data-toggle="modal"> 225 <?= I18N::translate('Source') ?> 226 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 227 </a> 228 </li> 229 <!-- UNLINKED REPOSITORY --> 230 <li> 231 <span class="fa-li"><?= view('icons/repository') ?></span> 232 <a href="#" data-href="<?= e(route(CreateRepositoryModal::class, ['tree' => $managed_tree->name()])) ?>" data-target="#wt-ajax-modal" data-toggle="modal"> 233 <?= I18N::translate('Repository') ?> 234 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 235 </a> 236 </li> 237 <!-- UNLINKED MEDIA OBJECT --> 238 <li> 239 <span class="fa-li"><?= view('icons/media') ?></span> 240 <a href="#" data-href="<?= e(route(CreateMediaObjectModal::class, ['tree' => $managed_tree->name()])) ?>" data-target="#wt-ajax-modal" data-toggle="modal"> 241 242 <?= I18N::translate('Media object') ?> 243 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 244 </a> 245 </li> 246 <!-- UNLINKED NOTE --> 247 <li> 248 <span class="fa-li"><?= view('icons/note') ?></span> 249 <a href="#" data-href="<?= e(route(CreateNoteModal::class, ['tree' => $managed_tree->name()])) ?>" data-target="#wt-ajax-modal" data-toggle="modal"> 250 <?= I18N::translate('Shared note') ?> 251 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 252 </a> 253 </li> 254 <!-- UNLINKED SUBMITTER --> 255 <li> 256 <span class="fa-li"><?= view('icons/submitter') ?></span> 257 <a href="#" data-href="<?= e(route(CreateSubmitterModal::class, ['tree' => $managed_tree->name()])) ?>" data-target="#wt-ajax-modal" data-toggle="modal"> 258 <?= I18N::translate('Submitter') ?> 259 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 260 </a> 261 </li> 262 </ul> 263 </div> 264 <div class="col-sm-6 col-md-3"> 265 <h3> 266 <?= I18N::translate('GEDCOM file') ?> 267 </h3> 268 <ul class="fa-ul"> 269 <!-- DOWNLOAD/Export --> 270 <li> 271 <span class="fa-li"><?= view('icons/download') ?></span> 272 <a href="<?= e(route(ExportGedcomPage::class, ['tree' => $managed_tree->name()])) ?>"> 273 <?= I18N::translate('Export') ?> 274 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 275 </a> 276 </li> 277 <!-- UPLOAD/IMPORT --> 278 <li> 279 <span class="fa-li"><?= view('icons/upload') ?></span> 280 <a href="<?= e(route('admin-trees-import', ['tree' => $managed_tree->name()])) ?>"> 281 <?= I18N::translate('Import') ?> 282 <span class="sr-only"><?= e($managed_tree->title()) ?></span> 283 </a> 284 </li> 285 </ul> 286 </div> 287 </div> 288 </div> 289 </div> 290 </div> 291 <?php endif ?> 292 <?php endforeach ?> 293 294 <!-- BULK LOAD/SYNCHRONISE GEDCOM FILES --> 295 <?php if (count($gedcom_files) >= $multiple_tree_threshold) : ?> 296 <div class="card"> 297 <div class="card-header" id="card-tree-create-header"> 298 <h2 class="mb-0"> 299 <?= view('icons/sync') ?> 300 <a data-toggle="collapse" data-parent="#accordion" href="#synchronize-gedcom-files"> 301 <?= I18N::translate('Synchronize family trees with GEDCOM files') ?> 302 </a> 303 </h2> 304 </div> 305 306 <div id="synchronize-gedcom-files" class="panel-collapse collapse"> 307 <div class="card-body"> 308 <p> 309 <?= I18N::translate('Create, update, and delete a family tree for every GEDCOM file in the data folder.') ?> 310 </p> 311 <form method="post" action="<?= e(route('admin-trees-sync')) ?>" class="form form-horizontal"> 312 <?= csrf_field() ?> 313 <button type="submit" class="btn btn-danger"> 314 <?= view('icons/save') ?> 315 <?= /* I18N: A button label. */ 316 I18N::translate('continue') ?> 317 </button> 318 <p class="small text-muted"> 319 <?= I18N::translate('Caution! This may take a long time. Be patient.') ?> 320 </p> 321 </form> 322 </div> 323 </div> 324 </div> 325 <?php endif ?> 326</div> 327 328<?= view('modals/ajax') ?> 329