diff options
58 files changed, 1106 insertions, 1720 deletions
diff --git a/app/Elements/NoteRecord.php b/app/Elements/NoteRecord.php index f9e884fb6f..5bbda35095 100644 --- a/app/Elements/NoteRecord.php +++ b/app/Elements/NoteRecord.php @@ -25,9 +25,9 @@ namespace Fisharebest\Webtrees\Elements; class NoteRecord extends AbstractElement { protected const SUBTAGS = [ + 'SOUR' => '0:M', 'REFN' => '0:1', 'RIN' => '0:1', - 'SOUR' => '0:M', 'CHAN' => '0:1', ]; } diff --git a/app/Elements/SubmissionRecord.php b/app/Elements/SubmissionRecord.php index 03c2429ed8..2265c34e71 100644 --- a/app/Elements/SubmissionRecord.php +++ b/app/Elements/SubmissionRecord.php @@ -33,6 +33,5 @@ class SubmissionRecord extends AbstractElement 'ORDI' => '0:1', 'RIN' => '0:1', 'NOTE' => '0:1', - 'CHAN' => '0:1', ]; } diff --git a/app/Factories/ElementFactory.php b/app/Factories/ElementFactory.php index 951010b83a..5a6177e011 100644 --- a/app/Factories/ElementFactory.php +++ b/app/Factories/ElementFactory.php @@ -687,7 +687,7 @@ class ElementFactory implements ElementFactoryInterface 'SOUR:DATA:AGNC' => new ResponsibleAgency(I18N::translate('Agency')), 'SOUR:DATA:EVEN' => new EventsRecorded(I18N::translate('Events')), 'SOUR:DATA:EVEN:DATE' => new DateValue(I18N::translate('Date range')), - 'SOUR:DATA:EVEN:PLAC' => new SourceJurisdictionPlace(I18N::translate('Place')), + 'SOUR:DATA:EVEN:PLAC' => new SourceJurisdictionPlace(I18N::translate('Place'), []), 'SOUR:DATA:NOTE' => new NoteStructure(I18N::translate('Note')), 'SOUR:NOTE' => new NoteStructure(I18N::translate('Note')), 'SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), diff --git a/app/Functions/FunctionsPrint.php b/app/Functions/FunctionsPrint.php index 3944dedec2..ce8bec4757 100644 --- a/app/Functions/FunctionsPrint.php +++ b/app/Functions/FunctionsPrint.php @@ -20,6 +20,7 @@ declare(strict_types=1); namespace Fisharebest\Webtrees\Functions; use Fisharebest\Webtrees\Age; +use Fisharebest\Webtrees\Auth; use Fisharebest\Webtrees\Date; use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Family; @@ -28,14 +29,11 @@ use Fisharebest\Webtrees\Gedcom; use Fisharebest\Webtrees\GedcomRecord; use Fisharebest\Webtrees\I18N; use Fisharebest\Webtrees\Individual; -use Fisharebest\Webtrees\Media; use Fisharebest\Webtrees\Module\ModuleMapLinkInterface; use Fisharebest\Webtrees\Note; use Fisharebest\Webtrees\Place; use Fisharebest\Webtrees\Registry; -use Fisharebest\Webtrees\Repository; use Fisharebest\Webtrees\Services\ModuleService; -use Fisharebest\Webtrees\Source; use Fisharebest\Webtrees\Tree; use Illuminate\Support\Collection; use Illuminate\Support\Str; @@ -497,18 +495,16 @@ class FunctionsPrint /** * Print a new fact box on details pages * - * @param GedcomRecord $record the person, family, source etc the fact will be added to - * @param Collection<Fact> $usedfacts an array of facts already used in this record - * @param string $type the type of record INDI, FAM, SOUR etc + * @param GedcomRecord $record the person, family, source etc the fact will be added to * * @return void */ - public static function printAddNewFact(GedcomRecord $record, Collection $usedfacts, string $type): void + public static function printAddNewFact(GedcomRecord $record): void { $tree = $record->tree(); - // -- Add from pick list - switch ($type) { + // Add from pick list + switch ($record->tag()) { case Individual::RECORD_TYPE: $addfacts = preg_split('/[, ;:]+/', $tree->getPreference('INDI_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('INDI_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); @@ -521,43 +517,26 @@ class FunctionsPrint $quickfacts = preg_split('/[, ;:]+/', $tree->getPreference('FAM_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); break; - case Source::RECORD_TYPE: - $addfacts = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); - $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); - $quickfacts = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); - break; - - case Note::RECORD_TYPE: - $addfacts = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); - $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); - $quickfacts = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); - break; - - case Repository::RECORD_TYPE: - $addfacts = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); - $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); - $quickfacts = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); - break; - - case Media::RECORD_TYPE: - $addfacts = ['NOTE']; - $uniquefacts = []; - $quickfacts = []; - break; default: return; } - $addfacts = array_merge(self::checkFactUnique($uniquefacts, $usedfacts), $addfacts); - $quickfacts = array_intersect($quickfacts, $addfacts); - $translated_addfacts = []; - foreach ($addfacts as $addfact) { - $translated_addfacts[$addfact] = Registry::elementFactory()->make($record->tag() . ':' . $addfact)->label(); + // Create a label for a subtag + $fn = fn ($subtag) => Registry::elementFactory()->make($record->tag() . ':' . $subtag)->label(); + + $addfacts = array_merge(self::checkFactUnique($uniquefacts, $record->facts()), $addfacts); + $quickfacts = array_intersect($quickfacts, $addfacts); + $quickfacts = array_combine($quickfacts, array_map($fn, $quickfacts)); + $addfacts = array_combine($addfacts, array_map($fn, $addfacts)); + + uasort($addfacts, I18N::comparator()); + + if ($record->tree()->getPreference('MEDIA_UPLOAD') < Auth::accessLevel($record->tree())) { + unset($addfacts['OBJE'], $quickfacts['OBJE']); } - uasort($translated_addfacts, I18N::comparator()); echo view('edit/add-fact-row', [ - 'add_facts' => $translated_addfacts, + 'add_facts' => $addfacts, 'quick_facts' => $quickfacts, 'record' => $record, 'tree' => $tree, diff --git a/app/GedcomRecord.php b/app/GedcomRecord.php index 48f76e89ab..3b19e3278e 100644 --- a/app/GedcomRecord.php +++ b/app/GedcomRecord.php @@ -33,6 +33,10 @@ use Illuminate\Support\Collection; use function addcslashes; use function app; +use function array_combine; +use function array_keys; +use function array_map; +use function array_search; use function array_shift; use function assert; use function count; @@ -48,6 +52,7 @@ use function preg_match_all; use function preg_replace; use function preg_replace_callback; use function preg_split; +use function range; use function route; use function str_contains; use function str_pad; @@ -792,7 +797,26 @@ class GedcomRecord } if ($sort) { - $facts = Fact::sortFacts($facts); + switch ($this->tag()) { + case Family::RECORD_TYPE: + case Individual::RECORD_TYPE: + $facts = Fact::sortFacts($facts); + break; + + default: + $subtags = Registry::elementFactory()->make($this->tag())->subtags(); + $subtags = array_map(fn (string $tag): string => $this->tag() . ':' . $tag, array_keys($subtags)); + $subtags = array_combine(range(1, count($subtags)), $subtags); + + $facts = $facts + ->sort(static function (Fact $x, Fact $y) use ($subtags): int { + $sort_x = array_search($x->tag(), $subtags, true) ?: PHP_INT_MAX; + $sort_y = array_search($y->tag(), $subtags, true) ?: PHP_INT_MAX; + + return $sort_x <=> $sort_y; + }); + break; + } } if ($ignore_deleted) { @@ -805,6 +829,35 @@ class GedcomRecord } /** + * @return array<string,string> + */ + public function missingFacts(): array + { + $missing_facts = []; + + foreach (Registry::elementFactory()->make($this->tag())->subtags() as $subtag => $repeat) { + [, $max] = explode(':', $repeat); + $max = $max === 'M' ? PHP_INT_MAX : (int) $max; + + if ($this->facts([$subtag])->count() < $max) { + $missing_facts[$subtag] = $subtag; + $missing_facts[$subtag] = Registry::elementFactory()->make($this->tag() . ':' . $subtag)->label(); + } + } + + uasort($missing_facts, I18N::comparator()); + + if ($this->tree->getPreference('MEDIA_UPLOAD') < Auth::accessLevel($this->tree)) { + unset($missing_facts['OBJE']); + } + + // We have special code for this. + unset($missing_facts['FILE']); + + return $missing_facts; + } + + /** * Get the last-change timestamp for this record * * @return Carbon diff --git a/app/Http/RequestHandlers/GedcomRecordPage.php b/app/Http/RequestHandlers/GedcomRecordPage.php index d2773d98d8..22d052eb61 100644 --- a/app/Http/RequestHandlers/GedcomRecordPage.php +++ b/app/Http/RequestHandlers/GedcomRecordPage.php @@ -33,6 +33,7 @@ use Fisharebest\Webtrees\Source; use Fisharebest\Webtrees\Submission; use Fisharebest\Webtrees\Submitter; use Fisharebest\Webtrees\Tree; +use Illuminate\Support\Collection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -85,18 +86,16 @@ class GedcomRecordPage implements RequestHandlerInterface return redirect($record->url()); } - $record_type = $record->tag(); - - return $this->viewResponse('gedcom-record-page', [ - 'facts' => $record->facts(), - 'families' => $record->linkedFamilies($record_type), - 'individuals' => $record->linkedIndividuals($record_type), - 'notes' => $record->linkedNotes($record_type), - 'media_objects' => $record->linkedMedia($record_type), - 'record' => $record, - 'sources' => $record->linkedSources($record_type), - 'title' => $record->fullName(), - 'tree' => $tree, + return $this->viewResponse('record-page', [ + 'clipboard_facts' => new Collection(), + 'linked_families' => $record->linkedFamilies($record->tag()), + 'linked_individuals' => $record->linkedIndividuals($record->tag()), + 'linked_media_objects' => $record->linkedMedia($record->tag()), + 'linked_notes' => $record->linkedNotes($record->tag()), + 'linked_sources' => $record->linkedSources($record->tag()), + 'record' => $record, + 'title' => $record->fullName(), + 'tree' => $tree, ]); } } diff --git a/app/Http/RequestHandlers/HeaderPage.php b/app/Http/RequestHandlers/HeaderPage.php index 11ba009bfc..59a6bca12d 100644 --- a/app/Http/RequestHandlers/HeaderPage.php +++ b/app/Http/RequestHandlers/HeaderPage.php @@ -21,8 +21,6 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers; use Fig\Http\Message\StatusCodeInterface; use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; -use Fisharebest\Webtrees\Header; use Fisharebest\Webtrees\Http\ViewResponseTrait; use Fisharebest\Webtrees\Registry; use Fisharebest\Webtrees\Tree; @@ -31,13 +29,10 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use function array_search; use function assert; use function is_string; use function redirect; -use const PHP_INT_MAX; - /** * Show a header's page. */ @@ -45,22 +40,6 @@ class HeaderPage implements RequestHandlerInterface { use ViewResponseTrait; - // Show the header's facts in this order: - private const FACT_ORDER = [ - 1 => 'HEAD:SOUR', - 'HEAD:DEST', - 'HEAD:DATE', - 'HEAD:SUBM', - 'HEAD:SUBN', - 'HEAD:FILE', - 'HEAD:COPR', - 'HEAD:GEDC', - 'HEAD:CHAR', - 'HEAD:LANG', - 'HEAD:PLAC', - 'HEAD:NOTE', - ]; - /** * @param ServerRequestInterface $request * @@ -84,34 +63,18 @@ class HeaderPage implements RequestHandlerInterface return redirect($header->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); } - return $this->viewResponse('gedcom-record-page', [ - 'facts' => $this->facts($header), - 'record' => $header, - 'families' => new Collection(), - 'individuals' => new Collection(), - 'media_objects' => new Collection(), - 'meta_description' => '', - 'meta_robots' => 'index,follow', - 'notes' => new Collection(), - 'sources' => new Collection(), - 'title' => $header->fullName(), - 'tree' => $tree, + return $this->viewResponse('record-page', [ + 'clipboard_facts' => new Collection(), + 'linked_families' => null, + 'linked_individuals' => null, + 'linked_media_objects' => null, + 'linked_notes' => null, + 'linked_sources' => null, + 'meta_description' => '', + 'meta_robots' => 'index,follow', + 'record' => $header, + 'title' => $header->fullName(), + 'tree' => $tree, ]); } - - /** - * @param Header $record - * - * @return Collection<Fact> - */ - private function facts(Header $record): Collection - { - return $record->facts() - ->sort(static function (Fact $x, Fact $y): int { - $sort_x = array_search($x->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - $sort_y = array_search($y->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - - return $sort_x <=> $sort_y; - }); - } } diff --git a/app/Http/RequestHandlers/IndividualPage.php b/app/Http/RequestHandlers/IndividualPage.php index 550a3e483a..725d2065a0 100644 --- a/app/Http/RequestHandlers/IndividualPage.php +++ b/app/Http/RequestHandlers/IndividualPage.php @@ -141,11 +141,11 @@ class IndividualPage implements RequestHandlerInterface return $this->viewResponse('individual-page', [ 'age' => $this->ageString($individual), 'clipboard_facts' => $this->clipboard_service->pastableFacts($individual), - 'individual' => $individual, 'individual_media' => $individual_media, 'meta_description' => $this->metaDescription($individual), 'meta_robots' => 'index,follow', 'name_records' => $name_records, + 'record' => $individual, 'sex_records' => $sex_records, 'shares' => $shares, 'sidebars' => $this->getSidebars($individual), diff --git a/app/Http/RequestHandlers/LocationPage.php b/app/Http/RequestHandlers/LocationPage.php index b8006e7640..4d2a9bfd87 100644 --- a/app/Http/RequestHandlers/LocationPage.php +++ b/app/Http/RequestHandlers/LocationPage.php @@ -73,42 +73,26 @@ class LocationPage implements RequestHandlerInterface $xref = $request->getAttribute('xref'); assert(is_string($xref)); - $location = Registry::locationFactory()->make($xref, $tree); - $location = Auth::checkLocationAccess($location, false); + $record = Registry::locationFactory()->make($xref, $tree); + $record = Auth::checkLocationAccess($record, false); // Redirect to correct xref/slug - $slug = Registry::slugFactory()->make($location); + $slug = Registry::slugFactory()->make($record); - if ($location->xref() !== $xref || $request->getAttribute('slug') !== $slug) { - return redirect($location->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); + if ($record->xref() !== $xref || $request->getAttribute('slug') !== $slug) { + return redirect($record->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); } - return $this->viewResponse('gedcom-record-page', [ - 'facts' => $this->facts($location), - 'families' => $location->linkedFamilies('_LOC'), - 'individuals' => $location->linkedIndividuals('_LOC'), - 'notes' => new Collection(), - 'media_objects' => new Collection(), - 'record' => $location, - 'sources' => new Collection(), - 'title' => $location->fullName(), - 'tree' => $tree, + return $this->viewResponse('record-page', [ + 'clipboard_facts' => new Collection(), + 'linked_families' => $record->linkedFamilies($record->tag()), + 'linked_individuals' => $record->linkedIndividuals($record->tag()), + 'linked_media_objects' => null, + 'linked_notes' => null, + 'linked_sources' => null, + 'record' => $record, + 'title' => $record->fullName(), + 'tree' => $tree, ]); } - - /** - * @param Location $location - * - * @return Collection<Fact> - */ - private function facts(Location $location): Collection - { - return $location->facts() - ->sort(static function (Fact $x, Fact $y): int { - $sort_x = array_search($x->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - $sort_y = array_search($y->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - - return $sort_x <=> $sort_y; - }); - } } diff --git a/app/Http/RequestHandlers/MediaPage.php b/app/Http/RequestHandlers/MediaPage.php index 03df46ee8a..2f4e616125 100644 --- a/app/Http/RequestHandlers/MediaPage.php +++ b/app/Http/RequestHandlers/MediaPage.php @@ -21,13 +21,10 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers; use Fig\Http\Message\StatusCodeInterface; use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Http\ViewResponseTrait; -use Fisharebest\Webtrees\Media; use Fisharebest\Webtrees\Registry; use Fisharebest\Webtrees\Services\ClipboardService; use Fisharebest\Webtrees\Tree; -use Illuminate\Support\Collection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -70,42 +67,28 @@ class MediaPage implements RequestHandlerInterface $xref = $request->getAttribute('xref'); assert(is_string($xref)); - $media = Registry::mediaFactory()->make($xref, $tree); - $media = Auth::checkMediaAccess($media); + $record = Registry::mediaFactory()->make($xref, $tree); + $record = Auth::checkMediaAccess($record); // Redirect to correct xref/slug - $slug = Registry::slugFactory()->make($media); + $slug = Registry::slugFactory()->make($record); - if ($media->xref() !== $xref || $request->getAttribute('slug') !== $slug) { - return redirect($media->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); + if ($record->xref() !== $xref || $request->getAttribute('slug') !== $slug) { + return redirect($record->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); } return $this->viewResponse('media-page', [ - 'clipboard_facts' => $this->clipboard_service->pastableFacts($media), - 'data_filesystem' => $data_filesystem, - 'families' => $media->linkedFamilies('OBJE'), - 'facts' => $this->facts($media), - 'individuals' => $media->linkedIndividuals('OBJE'), - 'media' => $media, - 'meta_description' => '', - 'meta_robots' => 'index,follow', - 'notes' => $media->linkedNotes('OBJE'), - 'sources' => $media->linkedSources('OBJE'), - 'title' => $media->fullName(), - 'tree' => $tree, + 'clipboard_facts' => $this->clipboard_service->pastableFacts($record), + 'data_filesystem' => $data_filesystem, + 'linked_families' => $record->linkedFamilies('OBJE'), + 'linked_individuals' => $record->linkedIndividuals('OBJE'), + 'linked_notes' => $record->linkedNotes('OBJE'), + 'linked_sources' => $record->linkedSources('OBJE'), + 'meta_description' => '', + 'meta_robots' => 'index,follow', + 'record' => $record, + 'title' => $record->fullName(), + 'tree' => $tree, ]); } - - /** - * @param Media $record - * - * @return Collection<Fact> - */ - private function facts(Media $record): Collection - { - return $record->facts() - ->filter(static function (Fact $fact): bool { - return $fact->tag() !== 'OBJE:FILE'; - }); - } } diff --git a/app/Http/RequestHandlers/NotePage.php b/app/Http/RequestHandlers/NotePage.php index a972c1390a..bd7499f460 100644 --- a/app/Http/RequestHandlers/NotePage.php +++ b/app/Http/RequestHandlers/NotePage.php @@ -21,14 +21,11 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers; use Fig\Http\Message\StatusCodeInterface; use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Filter; use Fisharebest\Webtrees\Http\ViewResponseTrait; -use Fisharebest\Webtrees\Note; use Fisharebest\Webtrees\Registry; use Fisharebest\Webtrees\Services\ClipboardService; use Fisharebest\Webtrees\Tree; -use Illuminate\Support\Collection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -69,42 +66,27 @@ class NotePage implements RequestHandlerInterface $xref = $request->getAttribute('xref'); assert(is_string($xref)); - $note = Registry::noteFactory()->make($xref, $tree); - $note = Auth::checkNoteAccess($note, false); + $record = Registry::noteFactory()->make($xref, $tree); + $record = Auth::checkNoteAccess($record, false); // Redirect to correct xref/slug - $slug = Registry::slugFactory()->make($note); + $slug = Registry::slugFactory()->make($record); - if ($note->xref() !== $xref || $request->getAttribute('slug') !== $slug) { - return redirect($note->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); + if ($record->xref() !== $xref || $request->getAttribute('slug') !== $slug) { + return redirect($record->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); } return $this->viewResponse('note-page', [ - 'clipboard_facts' => $this->clipboard_service->pastableFacts($note), - 'facts' => $this->facts($note), - 'families' => $note->linkedFamilies('NOTE'), - 'individuals' => $note->linkedIndividuals('NOTE'), - 'note' => $note, - 'media_objects' => $note->linkedMedia('NOTE'), - 'meta_description' => '', - 'meta_robots' => 'index,follow', - 'sources' => $note->linkedSources('NOTE'), - 'text' => Filter::formatText($note->getNote(), $tree), - 'title' => $note->fullName(), - 'tree' => $tree, + 'clipboard_facts' => $this->clipboard_service->pastableFacts($record), + 'linked_families' => $record->linkedFamilies('NOTE'), + 'linked_individuals' => $record->linkedIndividuals('NOTE'), + 'linked_media_objects' => $record->linkedMedia('NOTE'), + 'linked_sources' => $record->linkedSources('NOTE'), + 'meta_description' => '', + 'meta_robots' => 'index,follow', + 'record' => $record, + 'title' => $record->fullName(), + 'tree' => $tree, ]); } - - /** - * @param Note $record - * - * @return Collection<Fact> - */ - private function facts(Note $record): Collection - { - return $record->facts() - ->filter(static function (Fact $fact): bool { - return $fact->tag() !== 'NOTE:CONT'; - }); - } } diff --git a/app/Http/RequestHandlers/RepositoryPage.php b/app/Http/RequestHandlers/RepositoryPage.php index 265e7614f3..1be97fe9c4 100644 --- a/app/Http/RequestHandlers/RepositoryPage.php +++ b/app/Http/RequestHandlers/RepositoryPage.php @@ -21,24 +21,18 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers; use Fig\Http\Message\StatusCodeInterface; use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Http\ViewResponseTrait; use Fisharebest\Webtrees\Registry; -use Fisharebest\Webtrees\Repository; use Fisharebest\Webtrees\Services\ClipboardService; use Fisharebest\Webtrees\Tree; -use Illuminate\Support\Collection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use function array_search; use function assert; use function is_string; use function redirect; -use const PHP_INT_MAX; - /** * Show a repository's page. */ @@ -84,41 +78,28 @@ class RepositoryPage implements RequestHandlerInterface $xref = $request->getAttribute('xref'); assert(is_string($xref)); - $repository = Registry::repositoryFactory()->make($xref, $tree); - $repository = Auth::checkRepositoryAccess($repository, false); + $record = Registry::repositoryFactory()->make($xref, $tree); + $record = Auth::checkRepositoryAccess($record, false); // Redirect to correct xref/slug - $slug = Registry::slugFactory()->make($repository); + $slug = Registry::slugFactory()->make($record); - if ($repository->xref() !== $xref || $request->getAttribute('slug') !== $slug) { - return redirect($repository->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); + if ($record->xref() !== $xref || $request->getAttribute('slug') !== $slug) { + return redirect($record->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); } - return $this->viewResponse('repository-page', [ - 'clipboard_facts' => $this->clipboard_service->pastableFacts($repository), - 'facts' => $this->facts($repository), - 'meta_description' => '', - 'meta_robots' => 'index,follow', - 'repository' => $repository, - 'sources' => $repository->linkedSources('REPO'), - 'title' => $repository->fullName(), - 'tree' => $tree, + return $this->viewResponse('record-page', [ + 'clipboard_facts' => $this->clipboard_service->pastableFacts($record), + 'linked_families' => null, + 'linked_individuals' => null, + 'linked_media_objects' => null, + 'linked_notes' => null, + 'linked_sources' => $record->linkedSources('REPO'), + 'meta_description' => '', + 'meta_robots' => 'index,follow', + 'record' => $record, + 'title' => $record->fullName(), + 'tree' => $tree, ]); } - - /** - * @param Repository $record - * - * @return Collection<Fact> - */ - private function facts(Repository $record): Collection - { - return $record->facts() - ->sort(static function (Fact $x, Fact $y): int { - $sort_x = array_search($x->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - $sort_y = array_search($y->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - - return $sort_x <=> $sort_y; - }); - } } diff --git a/app/Http/RequestHandlers/SourcePage.php b/app/Http/RequestHandlers/SourcePage.php index e72568c8e0..11fcacc09d 100644 --- a/app/Http/RequestHandlers/SourcePage.php +++ b/app/Http/RequestHandlers/SourcePage.php @@ -21,24 +21,18 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers; use Fig\Http\Message\StatusCodeInterface; use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Http\ViewResponseTrait; use Fisharebest\Webtrees\Registry; use Fisharebest\Webtrees\Services\ClipboardService; -use Fisharebest\Webtrees\Source; use Fisharebest\Webtrees\Tree; -use Illuminate\Support\Collection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use function array_search; use function assert; use function is_string; use function redirect; -use const PHP_INT_MAX; - /** * Show a source's page. */ @@ -46,24 +40,6 @@ class SourcePage implements RequestHandlerInterface { use ViewResponseTrait; - // Show the source's facts in this order: - private const FACT_ORDER = [ - 1 => 'SOUR:TITL', - 'SOUR:ABBR', - 'SOUR:AUTH', - 'SOUR:DATA', - 'SOUR:PUBL', - 'SOUR:TEXT', - 'SOUR:REPO', - 'SOUR:NOTE', - 'SOUR:OBJE', - 'SOUR:REFN', - 'SOUR:RIN', - 'SOUR:_UID', - 'SOUR:CHAN', - 'SOUR:RESN', - ]; - private ClipboardService $clipboard_service; /** @@ -89,44 +65,28 @@ class SourcePage implements RequestHandlerInterface $xref = $request->getAttribute('xref'); assert(is_string($xref)); - $source = Registry::sourceFactory()->make($xref, $tree); - $source = Auth::checkSourceAccess($source, false); + $record = Registry::sourceFactory()->make($xref, $tree); + $record = Auth::checkSourceAccess($record, false); // Redirect to correct xref/slug - $slug = Registry::slugFactory()->make($source); + $slug = Registry::slugFactory()->make($record); - if ($source->xref() !== $xref || $request->getAttribute('slug') !== $slug) { - return redirect($source->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); + if ($record->xref() !== $xref || $request->getAttribute('slug') !== $slug) { + return redirect($record->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); } - return $this->viewResponse('source-page', [ - 'clipboard_facts' => $this->clipboard_service->pastableFacts($source), - 'facts' => $this->facts($source), - 'families' => $source->linkedFamilies('SOUR'), - 'individuals' => $source->linkedIndividuals('SOUR'), - 'meta_description' => '', - 'meta_robots' => 'index,follow', - 'notes' => $source->linkedNotes('SOUR'), - 'media_objects' => $source->linkedMedia('SOUR'), - 'source' => $source, - 'title' => $source->fullName(), - 'tree' => $tree, + return $this->viewResponse('record-page', [ + 'clipboard_facts' => $this->clipboard_service->pastableFacts($record), + 'linked_families' => $record->linkedFamilies('SOUR'), + 'linked_individuals' => $record->linkedIndividuals('SOUR'), + 'linked_media_objects' => $record->linkedMedia('SOUR'), + 'linked_notes' => $record->linkedNotes('SOUR'), + 'linked_sources' => null, + 'meta_description' => '', + 'meta_robots' => 'index,follow', + 'record' => $record, + 'title' => $record->fullName(), + 'tree' => $tree, ]); } - - /** - * @param Source $record - * - * @return Collection<Fact> - */ - private function facts(Source $record): Collection - { - return $record->facts() - ->sort(static function (Fact $x, Fact $y): int { - $sort_x = array_search($x->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - $sort_y = array_search($y->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - - return $sort_x <=> $sort_y; - }); - } } diff --git a/app/Http/RequestHandlers/SubmissionPage.php b/app/Http/RequestHandlers/SubmissionPage.php index 5e4e3b640f..3d90a651ea 100644 --- a/app/Http/RequestHandlers/SubmissionPage.php +++ b/app/Http/RequestHandlers/SubmissionPage.php @@ -21,23 +21,18 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers; use Fig\Http\Message\StatusCodeInterface; use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Http\ViewResponseTrait; use Fisharebest\Webtrees\Registry; -use Fisharebest\Webtrees\Submission; use Fisharebest\Webtrees\Tree; use Illuminate\Support\Collection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use function array_search; use function assert; use function is_string; use function redirect; -use const PHP_INT_MAX; - /** * Show a submission's page. */ @@ -45,20 +40,6 @@ class SubmissionPage implements RequestHandlerInterface { use ViewResponseTrait; - // Show the submission's facts in this order: - private const FACT_ORDER = [ - 1 => 'SUBN:SUBM', - 'SUBN:FAMF', - 'SUBN:TEMP', - 'SUBN:ANCE', - 'SUBN:DESC', - 'SUBN:ORDI', - 'SUBN:OBJE', - 'SUBN:RIN', - 'SUBN:NOTE', - 'SUBN:CHAN', - ]; - /** * @param ServerRequestInterface $request * @@ -72,44 +53,28 @@ class SubmissionPage implements RequestHandlerInterface $xref = $request->getAttribute('xref'); assert(is_string($xref)); - $submission = Registry::submissionFactory()->make($xref, $tree); - $submission = Auth::checkSubmissionAccess($submission, false); + $record = Registry::submissionFactory()->make($xref, $tree); + $record = Auth::checkSubmissionAccess($record, false); // Redirect to correct xref/slug - $slug = Registry::slugFactory()->make($submission); + $slug = Registry::slugFactory()->make($record); - if ($submission->xref() !== $xref || $request->getAttribute('slug') !== $slug) { - return redirect($submission->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); + if ($record->xref() !== $xref || $request->getAttribute('slug') !== $slug) { + return redirect($record->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); } - return $this->viewResponse('gedcom-record-page', [ - 'facts' => $this->facts($submission), - 'record' => $submission, - 'families' => new Collection(), - 'individuals' => new Collection(), - 'media_objects' => new Collection(), - 'meta_description' => '', - 'meta_robots' => 'index,follow', - 'notes' => new Collection(), - 'sources' => new Collection(), - 'title' => $submission->fullName(), - 'tree' => $tree, + return $this->viewResponse('record-page', [ + 'clipboard_facts' => new Collection(), + 'linked_families' => null, + 'linked_individuals' => null, + 'linked_media_objects' => null, + 'linked_notes' => null, + 'linked_sources' => null, + 'meta_description' => '', + 'meta_robots' => 'index,follow', + 'record' => $record, + 'title' => $record->fullName(), + 'tree' => $tree, ]); } - - /** - * @param Submission $record - * - * @return Collection<Fact> - */ - private function facts(Submission $record): Collection - { - return $record->facts() - ->sort(static function (Fact $x, Fact $y): int { - $sort_x = array_search($x->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - $sort_y = array_search($y->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - - return $sort_x <=> $sort_y; - }); - } } diff --git a/app/Http/RequestHandlers/SubmitterPage.php b/app/Http/RequestHandlers/SubmitterPage.php index 4b659267bf..b778e93352 100644 --- a/app/Http/RequestHandlers/SubmitterPage.php +++ b/app/Http/RequestHandlers/SubmitterPage.php @@ -21,23 +21,18 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers; use Fig\Http\Message\StatusCodeInterface; use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Http\ViewResponseTrait; use Fisharebest\Webtrees\Registry; -use Fisharebest\Webtrees\Submitter; use Fisharebest\Webtrees\Tree; use Illuminate\Support\Collection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use function array_search; use function assert; use function is_string; use function redirect; -use const PHP_INT_MAX; - /** * Show a submitter's page. */ @@ -45,21 +40,6 @@ class SubmitterPage implements RequestHandlerInterface { use ViewResponseTrait; - // Show the submitter's facts in this order: - private const FACT_ORDER = [ - 1 => 'SUBM:NAME', - 'SUBM:ADDR', - 'SUBM:PHON', - 'SUBM:EMAIL', - 'SUBM:WWW', - 'SUBM:LANG', - 'SUBM:OBJE', - 'SUBM:RFN', - 'SUBM:RIN', - 'SUBM:NOTE', - 'SUBM:CHAN', - ]; - /** * @param ServerRequestInterface $request * @@ -73,41 +53,28 @@ class SubmitterPage implements RequestHandlerInterface $xref = $request->getAttribute('xref'); assert(is_string($xref)); - $submitter = Registry::submitterFactory()->make($xref, $tree); - $submitter = Auth::checkSubmitterAccess($submitter, false); + $record = Registry::submitterFactory()->make($xref, $tree); + $record = Auth::checkSubmitterAccess($record, false); // Redirect to correct xref/slug - $slug = Registry::slugFactory()->make($submitter); + $slug = Registry::slugFactory()->make($record); - if ($submitter->xref() !== $xref || $request->getAttribute('slug') !== $slug) { - return redirect($submitter->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); + if ($record->xref() !== $xref || $request->getAttribute('slug') !== $slug) { + return redirect($record->url(), StatusCodeInterface::STATUS_MOVED_PERMANENTLY); } - return $this->viewResponse('submitter-page', [ - 'facts' => $this->facts($submitter), - 'submitter' => $submitter, - 'families' => $submitter->linkedFamilies('SUBM'), - 'individuals' => $submitter->linkedIndividuals('SUBM'), - 'meta_description' => '', - 'meta_robots' => 'index,follow', - 'title' => $submitter->fullName(), - 'tree' => $tree, + return $this->viewResponse('record-page', [ + 'clipboard_facts' => new Collection(), + 'linked_families' => $record->linkedFamilies('SUBM'), + 'linked_individuals' => $record->linkedIndividuals('SUBM'), + 'linked_media_objects' => null, + 'linked_notes' => null, + 'linked_sources' => null, + 'meta_description' => '', + 'meta_robots' => 'index,follow', + 'record' => $record, + 'title' => $record->fullName(), + 'tree' => $tree, ]); } - - /** - * @param Submitter $record - * - * @return Collection<Fact> - */ - private function facts(Submitter $record): Collection - { - return $record->facts() - ->sort(static function (Fact $x, Fact $y): int { - $sort_x = array_search($x->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - $sort_y = array_search($y->tag(), self::FACT_ORDER, true) ?: PHP_INT_MAX; - - return $sort_x <=> $sort_y; - }); - } } diff --git a/app/Http/RequestHandlers/TreePreferencesAction.php b/app/Http/RequestHandlers/TreePreferencesAction.php index 7756479356..b2aa3a2823 100644 --- a/app/Http/RequestHandlers/TreePreferencesAction.php +++ b/app/Http/RequestHandlers/TreePreferencesAction.php @@ -85,9 +85,6 @@ class TreePreferencesAction implements RequestHandlerInterface $tree->setPreference('PREFER_LEVEL2_SOURCES', $params['PREFER_LEVEL2_SOURCES'] ?? ''); $tree->setPreference('QUICK_REQUIRED_FACTS', implode(',', $params['QUICK_REQUIRED_FACTS'] ?? [])); $tree->setPreference('QUICK_REQUIRED_FAMFACTS', implode(',', $params['QUICK_REQUIRED_FAMFACTS'] ?? [])); - $tree->setPreference('REPO_FACTS_ADD', implode(',', $params['REPO_FACTS_ADD'] ?? [])); - $tree->setPreference('REPO_FACTS_QUICK', implode(',', $params['REPO_FACTS_QUICK'] ?? [])); - $tree->setPreference('REPO_FACTS_UNIQUE', implode(',', $params['REPO_FACTS_UNIQUE'] ?? [])); $tree->setPreference('SHOW_COUNTER', $params['SHOW_COUNTER'] ?? ''); $tree->setPreference('SHOW_EST_LIST_DATES', $params['SHOW_EST_LIST_DATES'] ?? ''); $tree->setPreference('SHOW_FACT_ICONS', $params['SHOW_FACT_ICONS'] ?? ''); @@ -100,9 +97,6 @@ class TreePreferencesAction implements RequestHandlerInterface $tree->setPreference('SHOW_PEDIGREE_PLACES', $params['SHOW_PEDIGREE_PLACES'] ?? ''); $tree->setPreference('SHOW_PEDIGREE_PLACES_SUFFIX', $params['SHOW_PEDIGREE_PLACES_SUFFIX'] ?? ''); $tree->setPreference('SHOW_RELATIVES_EVENTS', implode(',', $params['SHOW_RELATIVES_EVENTS'] ?? [])); - $tree->setPreference('SOUR_FACTS_ADD', implode(',', $params['SOUR_FACTS_ADD'] ?? [])); - $tree->setPreference('SOUR_FACTS_QUICK', implode(',', $params['SOUR_FACTS_QUICK'] ?? [])); - $tree->setPreference('SOUR_FACTS_UNIQUE', implode(',', $params['SOUR_FACTS_UNIQUE'] ?? [])); $tree->setPreference('SUBLIST_TRIGGER_I', $params['SUBLIST_TRIGGER_I'] ?? '200'); $tree->setPreference('SURNAME_LIST_STYLE', $params['SURNAME_LIST_STYLE'] ?? ''); $tree->setPreference('SURNAME_TRADITION', $params['SURNAME_TRADITION'] ?? ''); diff --git a/app/Http/RequestHandlers/TreePrivacyPage.php b/app/Http/RequestHandlers/TreePrivacyPage.php index 766d7f70d7..d37cae1562 100644 --- a/app/Http/RequestHandlers/TreePrivacyPage.php +++ b/app/Http/RequestHandlers/TreePrivacyPage.php @@ -142,12 +142,6 @@ class TreePrivacyPage implements RequestHandlerInterface explode(',', $tree->getPreference('INDI_FACTS_UNIQUE')), explode(',', $tree->getPreference('FAM_FACTS_ADD')), explode(',', $tree->getPreference('FAM_FACTS_UNIQUE')), - explode(',', $tree->getPreference('NOTE_FACTS_ADD')), - explode(',', $tree->getPreference('NOTE_FACTS_UNIQUE')), - explode(',', $tree->getPreference('SOUR_FACTS_ADD')), - explode(',', $tree->getPreference('SOUR_FACTS_UNIQUE')), - explode(',', $tree->getPreference('REPO_FACTS_ADD')), - explode(',', $tree->getPreference('REPO_FACTS_UNIQUE')), [ 'SOUR', 'REPO', diff --git a/app/Schema/SeedGedcomSettingTable.php b/app/Schema/SeedGedcomSettingTable.php index 151d10bcd3..8a8e1d2402 100644 --- a/app/Schema/SeedGedcomSettingTable.php +++ b/app/Schema/SeedGedcomSettingTable.php @@ -29,27 +29,18 @@ use Illuminate\Database\Capsule\Manager as DB; class SeedGedcomSettingTable implements SeedInterface { private const DEFAULT_SETTINGS = [ - 'ADVANCED_NAME_FACTS' => 'NICK,_AKA', + 'ADVANCED_NAME_FACTS' => 'NICK', 'ADVANCED_PLAC_FACTS' => '', 'CALENDAR_FORMAT' => 'gregorian', 'CHART_BOX_TAGS' => '', - 'COMMON_NAMES_ADD' => '', - 'COMMON_NAMES_REMOVE' => '', - 'COMMON_NAMES_THRESHOLD' => '40', - 'EXPAND_RELATIVES_EVENTS' => '0', 'EXPAND_SOURCES' => '0', - 'FAM_FACTS_ADD' => 'CENS,MARR,RESI,SLGS,RESN', - 'FAM_FACTS_QUICK' => 'MARR,DIV,_NMR', - 'FAM_FACTS_UNIQUE' => 'NCHI,MARL,DIV,ANUL,DIVF,ENGA,MARB,MARC,MARS,_NMR', - 'FAM_ID_PREFIX' => 'F', 'FORMAT_TEXT' => 'markdown', 'FULL_SOURCES' => '0', - 'GEDCOM_ID_PREFIX' => 'I', 'GEDCOM_MEDIA_PATH' => '', 'GENERATE_UIDS' => '0', 'HIDE_GEDCOM_ERRORS' => '1', 'HIDE_LIVE_PEOPLE' => '1', - 'INDI_FACTS_ADD' => 'AFN,BIRT,DEAT,BURI,CREM,ADOP,BAPM,BARM,BASM,BLES,CHRA,CONF,FCOM,ORDN,NATU,EMIG,IMMI,CENS,PROB,WILL,GRAD,RETI,DSCR,EDUC,IDNO,NATI,NCHI,NMR,OCCU,PROP,RELI,RESI,SSN,TITL,BAPL,CONL,ENDL,SLGC,_MILI,ASSO,RESN', + 'INDI_FACTS_ADD' => 'AFN,BIRT,DEAT,BURI,CREM,ADOP,BAPM,BARM,BASM,BLES,CHRA,CONF,FCOM,ORDN,NATU,EMIG,IMMI,CENS,PROB,WILL,GRAD,RETI,DSCR,EDUC,IDNO,NATI,NCHI,NMR,OCCU,PROP,RELI,RESI,SSN,TITL,BAPL,CONL,ENDL,SLGC,ASSO,RESN', 'INDI_FACTS_QUICK' => 'BIRT,BURI,BAPM,CENS,DEAT,OCCU,RESI', 'INDI_FACTS_UNIQUE' => '', 'KEEP_ALIVE_YEARS_BIRTH' => '', @@ -57,23 +48,14 @@ class SeedGedcomSettingTable implements SeedInterface 'LANGUAGE' => 'en-US', 'MAX_ALIVE_AGE' => '120', 'MEDIA_DIRECTORY' => 'media/', - 'MEDIA_ID_PREFIX' => 'M', 'MEDIA_UPLOAD' => Auth::PRIV_USER, 'META_DESCRIPTION' => '', 'META_TITLE' => Webtrees::NAME, - 'NOTE_FACTS_ADD' => 'SOUR,RESN', - 'NOTE_FACTS_QUICK' => '', - 'NOTE_FACTS_UNIQUE' => '', - 'NOTE_ID_PREFIX' => 'N', 'NO_UPDATE_CHAN' => '0', 'PEDIGREE_ROOT_ID' => '', 'PREFER_LEVEL2_SOURCES' => '1', 'QUICK_REQUIRED_FACTS' => 'BIRT,DEAT', 'QUICK_REQUIRED_FAMFACTS' => 'MARR', - 'REPO_FACTS_ADD' => 'PHON,EMAIL,FAX,WWW,RESN', - 'REPO_FACTS_QUICK' => '', - 'REPO_FACTS_UNIQUE' => 'NAME,ADDR', - 'REPO_ID_PREFIX' => 'R', 'REQUIRE_AUTHENTICATION' => '0', 'SAVE_WATERMARK_IMAGE' => '0', 'SHOW_AGE_DIFF' => '0', @@ -92,15 +74,10 @@ class SeedGedcomSettingTable implements SeedInterface 'SHOW_PEDIGREE_PLACES_SUFFIX' => '0', 'SHOW_PRIVATE_RELATIONSHIPS' => '1', 'SHOW_RELATIVES_EVENTS' => '_BIRT_CHIL,_BIRT_SIBL,_MARR_CHIL,_MARR_PARE,_DEAT_CHIL,_DEAT_PARE,_DEAT_GPAR,_DEAT_SIBL,_DEAT_SPOU', - 'SOURCE_ID_PREFIX' => 'S', - 'SOUR_FACTS_ADD' => 'NOTE,REPO,RESN', - 'SOUR_FACTS_QUICK' => 'TEXT,NOTE,REPO', - 'SOUR_FACTS_UNIQUE' => 'AUTH,ABBR,TITL,PUBL,TEXT', 'SUBLIST_TRIGGER_I' => '200', 'SURNAME_LIST_STYLE' => 'style2', 'SURNAME_TRADITION' => 'paternal', 'THUMBNAIL_WIDTH' => '100', - 'USE_RIN' => '0', 'USE_SILHOUETTE' => '1', 'WORD_WRAPPED_NOTES' => '0', ]; diff --git a/resources/views/admin/trees-preferences.phtml b/resources/views/admin/trees-preferences.phtml index 62e60f7231..3ce43ea160 100644 --- a/resources/views/admin/trees-preferences.phtml +++ b/resources/views/admin/trees-preferences.phtml @@ -785,88 +785,6 @@ use Illuminate\Support\Collection; </div> </div> - <h3><?= I18N::translate('Facts for source records') ?></h3> - - <!-- SOUR_FACTS_ADD --> - <div class="row form-group"> - <label class="col-sm-3 col-form-label" for="SOUR_FACTS_ADD"> - <?= I18N::translate('All source facts') ?> - </label> - <div class="col-sm-9"> - <?= view('components/select', ['name' => 'SOUR_FACTS_ADD[]', 'id' => 'SOUR_FACTS_ADD', 'selected' => explode(',', $tree->getPreference('SOUR_FACTS_ADD')), 'options' => $all_sour_facts, 'class' => 'select2']) ?> - <p class="small text-muted"> - <?= /* I18N: Help text for the “All source facts” configuration setting */ I18N::translate('This is the list of GEDCOM facts that your users can add to sources. You can modify this list by removing or adding fact names, even custom ones, as necessary. Fact names that appear in this list must not also appear in the “Unique source facts” list.') ?> - </p> - </div> - </div> - - <!-- SOUR_FACTS_UNIQUE --> - <div class="row form-group"> - <label class="col-sm-3 col-form-label" for="SOUR_FACTS_UNIQUE"> - <?= I18N::translate('Unique source facts') ?> - </label> - <div class="col-sm-9"> - <?= view('components/select', ['name' => 'SOUR_FACTS_UNIQUE[]', 'id' => 'SOUR_FACTS_UNIQUE', 'selected' => explode(',', $tree->getPreference('SOUR_FACTS_UNIQUE')), 'options' => $all_sour_facts, 'class' => 'select2']) ?> - <p class="small text-muted"> - <?= /* I18N: Help text for the “Unique source facts” configuration setting */ I18N::translate('This is the list of GEDCOM facts that your users can only add once to sources. For example, if TITL is in this list, users will not be able to add more than one TITL record to a source. Fact names that appear in this list must not also appear in the “All source facts” list.') ?> - </p> - </div> - </div> - - <!-- SOUR_FACTS_QUICK --> - <div class="row form-group"> - <label class="col-sm-3 col-form-label" for="SOUR_FACTS_QUICK"> - <?= I18N::translate('Quick source facts') ?> - </label> - <div class="col-sm-9"> - <?= view('components/select', ['name' => 'SOUR_FACTS_QUICK[]', 'id' => 'SOUR_FACTS_QUICK', 'selected' => explode(',', $tree->getPreference('SOUR_FACTS_QUICK')), 'options' => $all_sour_facts, 'class' => 'select2']) ?> - <p class="small text-muted"> - <?= /* I18N: Help text for the “Quick source facts” configuration setting */ I18N::translate('The most common source facts are listed separately, so that they can be added more easily.') ?> - </p> - </div> - </div> - - <h3><?= I18N::translate('Facts for repository records') ?></h3> - - <!-- REPO_FACTS_ADD --> - <div class="row form-group"> - <label class="col-sm-3 col-form-label" for="REPO_FACTS_ADD"> - <?= I18N::translate('All repository facts') ?> - </label> - <div class="col-sm-9"> - <?= view('components/select', ['name' => 'REPO_FACTS_ADD[]', 'id' => 'REPO_FACTS_ADD', 'selected' => explode(',', $tree->getPreference('REPO_FACTS_ADD')), 'options' => $all_repo_facts, 'class' => 'select2']) ?> - <p class="small text-muted"> - <?= /* I18N: Help text for the “All repository facts” configuration setting */ I18N::translate('This is the list of GEDCOM facts that your users can add to repositories. You can modify this list by removing or adding fact names, even custom ones, as necessary. Fact names that appear in this list must not also appear in the “Unique repository facts” list.') ?> - </p> - </div> - </div> - - <!-- REPO_FACTS_UNIQUE --> - <div class="row form-group"> - <label class="col-sm-3 col-form-label" for="REPO_FACTS_UNIQUE"> - <?= I18N::translate('Unique repository facts') ?> - </label> - <div class="col-sm-9"> - <?= view('components/select', ['name' => 'REPO_FACTS_UNIQUE[]', 'id' => 'REPO_FACTS_UNIQUE', 'selected' => explode(',', $tree->getPreference('REPO_FACTS_UNIQUE')), 'options' => $all_repo_facts, 'class' => 'select2']) ?> - <p class="small text-muted"> - <?= /* I18N: Help text for the “Unique repository facts” configuration setting */ I18N::translate('This is the list of GEDCOM facts that your users can only add once to repositories. For example, if NAME is in this list, users will not be able to add more than one NAME record to a repository. Fact names that appear in this list must not also appear in the “All repository facts” list.') ?> - </p> - </div> - </div> - - <!-- REPO_FACTS_QUICK --> - <div class="row form-group"> - <label class="col-sm-3 col-form-label" for="REPO_FACTS_QUICK"> - <?= I18N::translate('Quick repository facts') ?> - </label> - <div class="col-sm-9"> - <?= view('components/select', ['name' => 'REPO_FACTS_QUICK[]', 'id' => 'REPO_FACTS_QUICK', 'selected' => explode(',', $tree->getPreference('REPO_FACTS_QUICK')), 'options' => $all_repo_facts, 'class' => 'select2']) ?> - <p class="small text-muted"> - <?= /* I18N: Help text for the “Quick repository facts” configuration setting */ I18N::translate('The most common repository facts are listed separately, so that they can be added more easily.') ?> - </p> - </div> - </div> - <h3><?= I18N::translate('Advanced fact preferences') ?></h3> <!-- ADVANCED_NAME_FACTS --> diff --git a/resources/views/edit/add-fact-row.phtml b/resources/views/edit/add-fact-row.phtml index 848a0ea301..6dea56834c 100644 --- a/resources/views/edit/add-fact-row.phtml +++ b/resources/views/edit/add-fact-row.phtml @@ -19,46 +19,45 @@ use Fisharebest\Webtrees\Registry; <tr> <th scope="row"> <label for="add-fact"> - <?= I18N::translate('Fact or event') ?> + <?= I18N::translate('Add a fact') ?> </label> </th> <td> - <form method="post" action="<?= e(route(SelectNewFact::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>" onsubmit="if ($('#add-fact').val() === null) {event.preventDefault();}"> - <?= csrf_field() ?> + <?php if ($add_facts !== []) : ?> + <form method="post" action="<?= e(route(SelectNewFact::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>" onsubmit="if ($('#add-fact').val() === null) {event.preventDefault();}"> + <?= csrf_field() ?> - <div class="input-group"> - <select class="custom-select" id="add-fact" name="fact"> - <option value="" disabled selected> - <?= I18N::translate('<select>') ?> - </option> - <?php foreach ($add_facts as $fact => $fact_name) : ?> - <option value="<?= $fact ?>"><?= $fact_name ?></option> - <?php endforeach ?> - <?php if ($record->tag() === Individual::RECORD_TYPE || $record->tag() === Family::RECORD_TYPE) : ?> - <option value="FACT"> - <?= I18N::translate('Custom fact') ?> + <div class="input-group"> + <select class="custom-select" id="add-fact" name="fact"> + <option value="" disabled selected> + <?= I18N::translate('<select>') ?> </option> - <option value="EVEN"> - <?= I18N::translate('Custom event') ?> - </option> - <?php endif ?> - </select> - <div class="input-group-append"> - <button class="btn btn-light" type="submit"> - <?= /* I18N: A button label. */ I18N::translate('add') ?> - </button> + <?php foreach ($add_facts as $fact => $label) : ?> + <option value="<?= $fact ?>"><?= $label ?></option> + <?php endforeach ?> + <?php if ($record->tag() === Individual::RECORD_TYPE || $record->tag() === Family::RECORD_TYPE) : ?> + <option value="FACT"><?= I18N::translate('Custom fact') ?></option> + <option value="EVEN"><?= I18N::translate('Custom event') ?></option> + <?php endif ?> + </select> + + <div class="input-group-append"> + <button class="btn btn-light" type="submit"> + <?= /* I18N: A button label. */ I18N::translate('add') ?> + </button> + </div> </div> - </div> - </form> + </form> + <?php endif ?> <div class="wt-quick-facts"> - <?php foreach ($quick_facts as $fact) : ?> - <a class="btn btn-link btn-sm wt-quick-fact" href="<?= e(route(AddNewFact::class, [ + <?php foreach ($quick_facts as $fact => $label) : ?> + <a class="btn btn-link wt-quick-fact" href="<?= e(route(AddNewFact::class, [ 'fact' => $fact, 'xref' => $record->xref(), 'tree' => $record->tree()->name(), ])) ?>"> - <?= Registry::elementFactory()->make($record->tag() . ':' . $fact)->label() ?> + <?= $label ?> </a> <?php endforeach ?> </div> diff --git a/resources/views/edit/paste-fact-row.phtml b/resources/views/edit/paste-fact-row.phtml deleted file mode 100644 index 6cf3007856..0000000000 --- a/resources/views/edit/paste-fact-row.phtml +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Fact; -use Fisharebest\Webtrees\GedcomRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PasteFact; -use Fisharebest\Webtrees\I18N; -use Illuminate\Support\Collection; - -/** - * @var Collection<Fact> $facts - * @var GedcomRecord $record - */ - -?> - -<?php if ($facts->isNotEmpty()) : ?> -<tr> - <th scope="row"> - <label for="paste-fact"> - <?= I18N::translate('Add from clipboard') ?> - </label> - </th> - <td> - <form method="post" action="<?= route(PasteFact::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()]) ?>"> - <?= csrf_field() ?> - - <div class="input-group"> - <select class="custom-select" id="paste-fact" name="fact_id"> - <?php foreach ($facts as $fact) : ?> - <option value="<?= e($fact->id()) ?>"> - <?= $fact->label() ?> - <?php if ($fact->target() !== null) : ?> - – <?= strip_tags($fact->target()->fullName()) ?> - <?php elseif ($fact->value() !== '') : ?> - – <?= e($fact->value()) ?> - <?php endif ?> - <?php if ($fact->date()->isOK()) : ?> - – <?= $fact->date()->minimumDate()->format('%Y') ?> - <?php endif ?> - <?php if ($fact->place()->gedcomName() !== '') : ?> - – <?= $fact->place()->shortName() ?> - <?php endif ?> - </option> - <?php endforeach ?> - </select> - <div class="input-group-append"> - <button class="btn btn-light" type="submit"> - <?= /* I18N: A button label. */ I18N::translate('add') ?> - </button> - </div> - </div> - </form> - </td> -</tr> -<?php endif ?> diff --git a/resources/views/family-page-menu.phtml b/resources/views/family-page-menu.phtml index 5359b10a19..130358c7b1 100644 --- a/resources/views/family-page-menu.phtml +++ b/resources/views/family-page-menu.phtml @@ -1,6 +1,7 @@ <?php use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Family; use Fisharebest\Webtrees\Http\RequestHandlers\AddChildToFamilyPage; use Fisharebest\Webtrees\Http\RequestHandlers\AddSpouseToFamilyPage; @@ -9,9 +10,11 @@ use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; use Fisharebest\Webtrees\Http\RequestHandlers\EditRawRecordPage; use Fisharebest\Webtrees\Http\RequestHandlers\ReorderChildrenPage; use Fisharebest\Webtrees\I18N; +use Illuminate\Support\Collection; /** - * @var Family $record + * @var Collection<Fact> $clipboard_facts + * @var Family $record */ ?> @@ -54,6 +57,12 @@ use Fisharebest\Webtrees\I18N; </a> <?php endif ?> + <?php if ($clipboard_facts->isNotEmpty()) : ?> + <div class="dropdown-divider"></div> + + <?= view('record-page-menu-clipboard', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> + <?php endif ?> + <div class="dropdown-divider"></div> <a class="dropdown-item" href="#" data-confirm="<?= I18N::translate('Deleting the family will unlink all of the individuals from each other but will leave the individuals in place. Are you sure you want to delete this family?') ?>" data-post-url="<?= e(route(DeleteRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>"> diff --git a/resources/views/family-page-pending.phtml b/resources/views/family-page-pending.phtml new file mode 100644 index 0000000000..013ff583a3 --- /dev/null +++ b/resources/views/family-page-pending.phtml @@ -0,0 +1,27 @@ +<?php + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Family; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; +use Fisharebest\Webtrees\I18N; + +/** + * @var Family $record + */ + +?> + +<?php if ($record->isPendingDeletion()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This family has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This family has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php elseif ($record->isPendingAddition()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This family has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This family has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php endif ?> diff --git a/resources/views/family-page.phtml b/resources/views/family-page.phtml index 8a1fb4470a..641d5974d9 100644 --- a/resources/views/family-page.phtml +++ b/resources/views/family-page.phtml @@ -6,8 +6,6 @@ use Fisharebest\Webtrees\Family; use Fisharebest\Webtrees\Functions\FunctionsPrint; use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; use Fisharebest\Webtrees\I18N; use Illuminate\Support\Collection; @@ -19,26 +17,14 @@ use Illuminate\Support\Collection; ?> -<?php if ($record->isPendingDeletion()) : ?> - <?php if (Auth::isModerator($record->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This family has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($record->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This family has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php elseif ($record->isPendingAddition()) : ?> - <?php if (Auth::isModerator($record->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This family has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($record->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This family has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php endif ?> +<?= view('family-page-pending', ['record' => $record]) ?> <div class="d-flex mb-4"> <h2 class="wt-page-title mx-auto"> <?= $record->fullName() ?> </h2> <?php if ($record->canEdit()) : ?> - <?= view('family-page-menu', ['record' => $record]) ?> + <?= view('family-page-menu', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> <?php endif ?> </div> @@ -63,9 +49,7 @@ use Illuminate\Support\Collection; <?php endif ?> <?php if (Auth::isEditor($record->tree())) : ?> - <?= view('edit/paste-fact-row', ['record' => $record, 'facts' => $clipboard_facts]) ?> - - <?php FunctionsPrint::printAddNewFact($record, $facts, Family::RECORD_TYPE) ?> + <?php FunctionsPrint::printAddNewFact($record) ?> <tr> <th scope="row"> <?= I18N::translate('Note') ?> diff --git a/resources/views/gedcom-record-page-menu.phtml b/resources/views/gedcom-record-page-menu.phtml deleted file mode 100644 index 09447681cc..0000000000 --- a/resources/views/gedcom-record-page-menu.phtml +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -use Fisharebest\Webtrees\GedcomRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\EditRecordPage; -use Fisharebest\Webtrees\I18N; - -/** - * @var GedcomRecord $record - */ - -?> - -<div class="dropdown wt-page-menu"> - <button class="btn btn-primary dropdown-toggle wt-page-menu-button" type="button" id="page-menu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> - <?= view('icons/menu') ?> - <?= I18N::translate('edit') ?> - </button> - - <div class="dropdown-menu dropdown-menu-right wt-page-menu-items" aria-labelledby="page-menu"> - <a class="dropdown-item" href="<?= route(EditRecordPage::class, ['xref' => $record->xref(), 'tree' => $record->tree()->name()]) ?>"> - <?= view('icons/edit') ?> - <?= I18N::translate('Edit') ?> - </a> - - <a class="dropdown-item" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete “%s”?', strip_tags($record->fullName())) ?>" data-post-url="<?= e(route(DeleteRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>"> - <?= view('icons/delete') ?> - <?= I18N::translate('Delete') ?> - </a> - </div> -</div> - -<?php if ($record->canEdit()) : ?> -<?php endif ?> - diff --git a/resources/views/gedcom-record-page.phtml b/resources/views/gedcom-record-page.phtml deleted file mode 100644 index 450cb2d11d..0000000000 --- a/resources/views/gedcom-record-page.phtml +++ /dev/null @@ -1,149 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; -use Fisharebest\Webtrees\Family; -use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; -use Fisharebest\Webtrees\GedcomRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Individual; -use Fisharebest\Webtrees\Media; -use Fisharebest\Webtrees\Note; -use Fisharebest\Webtrees\Source; -use Fisharebest\Webtrees\Tree; -use Illuminate\Support\Collection; - -/** - * @var Collection<Fact> $facts - * @var Collection<Family> $families - * @var Collection<Individual> $individuals - * @var Collection<Media> $media_objects - * @var Collection<Note> $notes - * @var GedcomRecord $record - * @var Collection<Source> $sources - * @var Tree $tree - */ - -?> - -<?php if ($record->isPendingDeletion()) : ?> - <?php if (Auth::isModerator($record->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This record has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($record->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This record has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php elseif ($record->isPendingAddition()) : ?> - <?php if (Auth::isModerator($record->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This record has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($record->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This record has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php endif ?> - -<div class="d-flex mb-4"> - <h2 class="wt-page-title mx-auto"> - <?= $record->fullName() ?> - </h2> - <?php if ($record->canEdit()) : ?> - <?= view('gedcom-record-page-menu', ['record' => $record]) ?> - <?php endif ?> -</div> - -<div class="wt-page-content"> - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <a class="nav-link active" data-toggle="tab" role="tab" href="#details"> - <?= I18N::translate('Details') ?> - </a> - </li> - - <?php if ($individuals->isNotEmpty()) : ?> - <li class="nav-item" role="presentation"> - <a class="nav-link" data-toggle="tab" role="tab" href="#individuals"> - <?= I18N::translate('Individuals') ?> - <?= view('components/badge', ['count' => $individuals->count()]) ?> - </a> - </li> - <?php endif ?> - - <?php if ($families->isNotEmpty()) : ?> - <li class="nav-item" role="presentation"> - <a class="nav-link" data-toggle="tab" role="tab" href="#families"> - <?= I18N::translate('Families') ?> - <?= view('components/badge', ['count' => $families->count()]) ?> - </a> - </li> - <?php endif ?> - - <?php if ($media_objects->isNotEmpty()) : ?> - <li class="nav-item" role="presentation"> - <a class="nav-link" data-toggle="tab" role="tab" href="#media"> - <?= I18N::translate('Media objects') ?> - <?= view('components/badge', ['count' => $media_objects->count()]) ?> - </a> - </li> - <?php endif ?> - - <?php if ($sources->isNotEmpty()) : ?> - <li class="nav-item" role="presentation"> - <a class="nav-link" data-toggle="tab" role="tab" href="#sources"> - <?= I18N::translate('Sources') ?> - <?= view('components/badge', ['count' => $sources->count()]) ?> - </a> - </li> - <?php endif ?> - - <?php if ($notes->isNotEmpty()) : ?> - <li class="nav-item" role="presentation"> - <a class="nav-link" data-toggle="tab" role="tab" href="#notes"> - <?= I18N::translate('Notes') ?> - <?= view('components/badge', ['count' => $notes->count()]) ?> - </a> - </li> - <?php endif ?> - </ul> - - <div class="tab-content"> - <div class="tab-pane active fade show" role="tabpanel" id="details"> - <table class="table wt-facts-table"> - <?php foreach ($facts as $fact) : ?> - <?php FunctionsPrintFacts::printFact($fact, $record) ?> - <?php endforeach ?> - </table> - </div> - - <?php if ($individuals->isNotEmpty()) : ?> - <div class="tab-pane fade" role="tabpanel" id="individuals"> - <?= view('lists/individuals-table', ['individuals' => $individuals, 'sosa' => false, 'tree' => $tree]) ?> - </div> - <?php endif ?> - - <?php if ($families->isNotEmpty()) : ?> - <div class="tab-pane fade" role="tabpanel" id="families"> - <?= view('lists/families-table', ['families' => $families, 'tree' => $tree]) ?> - </div> - <?php endif ?> - - <?php if ($media_objects->isNotEmpty()) : ?> - <div class="tab-pane fade" role="tabpanel" id="media"> - <?= view('lists/media-table', ['media_objects' => $media_objects, 'tree' => $tree]) ?> - </div> - <?php endif ?> - - <?php if ($sources->isNotEmpty()) : ?> - <div class="tab-pane fade" role="tabpanel" id="sources"> - <?= view('lists/sources-table', ['sources' => $sources, 'tree' => $tree]) ?> - </div> - <?php endif ?> - - <?php if ($notes->isNotEmpty()) : ?> - <div class="tab-pane fade" role="tabpanel" id="notes"> - <?= view('lists/notes-table', ['notes' => $notes, 'tree' => $tree]) ?> - </div> - <?php endif ?> - </div> -</div> - -<?= view('modals/ajax') ?> diff --git a/resources/views/individual-page-images.phtml b/resources/views/individual-page-images.phtml new file mode 100644 index 0000000000..f1cb032fcf --- /dev/null +++ b/resources/views/individual-page-images.phtml @@ -0,0 +1,64 @@ +<?php + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Fact; +use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Individual; +use Fisharebest\Webtrees\Media; +use Fisharebest\Webtrees\Module\ModuleSidebarInterface; +use Fisharebest\Webtrees\Module\ModuleTabInterface; +use Fisharebest\Webtrees\Tree; +use Illuminate\Support\Collection; + +/** + * @var string $age + * @var Collection<Media> $individual_media + * @var Collection<Fact> $name_records + * @var Individual $record + * @var Collection<Fact> $sex_records + * @var Collection<string> $shares + * @var Collection<ModuleSidebarInterface> $sidebars + * @var Collection<ModuleTabInterface> $tabs + * @var Tree $tree + * @var string $user_link + */ +?> + +<?php if ($individual_media->isNotEmpty() || $tree->getPreference('USE_SILHOUETTE') === '1') : ?> + <div class="col-sm-3"> + <?php if ($individual_media->isEmpty()) : ?> + <div class="img-thumbnail"> + <i class="wt-individual-silhouette wt-individual-silhouette-<?= strtolower($record->sex()) ?>"></i> + </div> + <?php elseif ($individual_media->count() === 1) : ?> + <?= $individual_media->first()->displayImage(200, 260, 'crop', ['class' => 'img-thumbnail img-fluid w-100']) ?> + <?php else : ?> + <div id="individual-images" class="carousel slide" data-ride="carousel" data-interval="false"> + <div class="carousel-inner"> + <?php foreach ($individual_media as $n => $media_file) : ?> + <div class="carousel-item <?= $n === 0 ? 'active' : '' ?>"> + <?= $media_file->displayImage(200, 260, 'crop', ['class' => 'img-thumbnail img-fluid w-100']) ?> + </div> + <?php endforeach ?> + </div> + <a class="carousel-control-prev" href="#individual-images" role="button" data-slide="prev"> + <span class="carousel-control-prev-icon" aria-hidden="true"></span> + <span class="sr-only"><?= I18N::translate('previous') ?></span> + </a> + <a class="carousel-control-next" href="#individual-images" role="button" data-slide="next"> + <span class="carousel-control-next-icon" aria-hidden="true"></span> + <span class="sr-only"><?= I18N::translate('next') ?></span> + </a> + </div> + <?php endif ?> + + <?php if (Auth::isEditor($record->tree())) : ?> + <div class="text-center"> + <a href="<?= e(route(AddNewFact::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref(), 'fact' => 'OBJE'])) ?>"> + <?= I18N::translate('Add a media object') ?> + </a> + </div> + <?php endif ?> + </div> +<?php endif ?> diff --git a/resources/views/individual-page-menu.phtml b/resources/views/individual-page-menu.phtml index e93b576dd7..67d75c542f 100644 --- a/resources/views/individual-page-menu.phtml +++ b/resources/views/individual-page-menu.phtml @@ -1,6 +1,7 @@ <?php use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact; use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; use Fisharebest\Webtrees\Http\RequestHandlers\EditFactPage; @@ -13,6 +14,7 @@ use Fisharebest\Webtrees\Individual; use Illuminate\Support\Collection; /** + * @var Collection<Fact> $clipboard_facts * @var Individual $record * @var Collection<string> $shares */ @@ -103,6 +105,12 @@ use Illuminate\Support\Collection; </div> <?php endif ?> + <?php if ($clipboard_facts->isNotEmpty()) : ?> + <div class="dropdown-divider"></div> + + <?= view('record-page-menu-clipboard', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> + <?php endif ?> + <div class="dropdown-divider"></div> <a class="dropdown-item" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete “%s”?', strip_tags($record->fullName())) ?>" data-post-url="<?= e(route(DeleteRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>"> diff --git a/resources/views/individual-page-names.phtml b/resources/views/individual-page-names.phtml new file mode 100644 index 0000000000..e866a110b5 --- /dev/null +++ b/resources/views/individual-page-names.phtml @@ -0,0 +1,21 @@ +<?php + +use Fisharebest\Webtrees\Fact; +use Illuminate\Support\Collection; + +/** + * @var Collection<Fact> $name_records + * @var Collection<Fact> $sex_records + */ +?> + +<!-- Name accordion --> +<div class="col-sm accordion" id="individual-names"> + <?php foreach ($name_records as $name_record) : ?> + <?= $name_record ?> + <?php endforeach ?> + + <?php foreach ($sex_records as $sex_record) : ?> + <?= $sex_record ?> + <?php endforeach ?> +</div> diff --git a/resources/views/individual-page-pending.phtml b/resources/views/individual-page-pending.phtml new file mode 100644 index 0000000000..2a9e3d9dd9 --- /dev/null +++ b/resources/views/individual-page-pending.phtml @@ -0,0 +1,32 @@ +<?php + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Individual; + +/** + * @var Individual $record + */ +?> + +<?php if ($record->isPendingDeletion()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', [ + 'alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ + I18N::translate('This individual has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes']), + ]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This individual has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php elseif ($record->isPendingAddition()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', [ + 'alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ + I18N::translate('This individual has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes']), + ]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This individual has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php endif ?> diff --git a/resources/views/individual-page-sidebars.phtml b/resources/views/individual-page-sidebars.phtml new file mode 100644 index 0000000000..b567b25304 --- /dev/null +++ b/resources/views/individual-page-sidebars.phtml @@ -0,0 +1,33 @@ +<?php + +use Fisharebest\Webtrees\Individual; +use Fisharebest\Webtrees\Module\ModuleSidebarInterface; +use Illuminate\Support\Collection; + +/** + * @var Individual $record + * @var Collection<ModuleSidebarInterface> $sidebars + */ +?> + +<div class="col-sm-4 accordion" id="sidebar"> + <?php foreach ($sidebars as $sidebar) : ?> + <div class="card"> + <div class="card-header" role="tab" id="sidebar-header-<?= $sidebar->name() ?>"> + <div class="card-title mb-0"> + <a data-toggle="collapse" href="#sidebar-content-<?= $sidebar->name() ?>" aria-expanded="<?= $sidebar->name() === 'family_nav' ? 'true' : 'false' ?>" aria-controls="sidebar-content-<?= $sidebar->name() ?>"> + <?= view('icons/expand') ?> + <?= view('icons/collapse') ?> + <?= $sidebar->sidebarTitle() ?> + </a> + </div> + </div> + + <div id="sidebar-content-<?= $sidebar->name() ?>" class="collapse<?= $sidebar->name() === 'family_nav' ? ' show' : '' ?>" data-parent="#sidebar" aria-labelledby="sidebar-header-<?= $sidebar->name() ?>"> + <div class="card-body"> + <?= $sidebar->getSidebarContent($record) ?> + </div> + </div> + </div> + <?php endforeach ?> +</div> diff --git a/resources/views/individual-page-tabs.phtml b/resources/views/individual-page-tabs.phtml new file mode 100644 index 0000000000..39555e4f9b --- /dev/null +++ b/resources/views/individual-page-tabs.phtml @@ -0,0 +1,69 @@ +<?php + +use Fisharebest\Webtrees\Individual; +use Fisharebest\Webtrees\Module\ModuleTabInterface; +use Fisharebest\Webtrees\View; +use Illuminate\Support\Collection; + +/** + * @var Individual $record + * @var Collection<ModuleTabInterface> $tabs + */ +?> + +<div class="wt-tabs-individual" id="individual-tabs"> + <ul class="nav nav-tabs flex-wrap" role="tablist"> + <?php foreach ($tabs as $tab) : ?> + <li class="nav-item" role="presentation"> + <a class="nav-link<?= $tab->isGrayedOut($record) ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" data-href="<?= e(route('module', ['module' => $tab->name(), 'action' => 'Tab', 'tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>" href="#<?= $tab->name() ?>"> + <?= $tab->tabTitle() ?> + </a> + </li> + <?php endforeach ?> + </ul> + + <div class="tab-content"> + <?php foreach ($tabs as $tab) : ?> + <div id="<?= $tab->name() ?>" class="tab-pane fade wt-ajax-load" role="tabpanel"><?php if (!$tab->canLoadAjax()) : + ?><?= $tab->getTabContent($record) ?><?php + endif ?></div> + <?php endforeach ?> + </div> +</div> + +<?php View::push('javascript') ?> +<script> + "use strict"; + + // Bootstrap tabs - load content dynamically using AJAX + $('a[data-toggle="tab"][data-href]').on('show.bs.tab', function () { + let target = $(this.hash + ':empty'); + if (target.length > 0) { + // Start the download immediately... + let download = fetch(this.dataset.href); + + // ...but don't insert it until the tab is ready. + $(this).one('shown.bs.tab', () => { + download + .then(data => data.text()) + .then(data => target.html(data)); + }); + } + }); + + // If the URL contains a fragment, then activate the corresponding tab. + // Use a prefix on the fragment, to prevent scrolling to the element. + let target = window.location.hash.replace("tab-", ""); + let tab = $("#individual-tabs .nav-link[href='" + target + "']"); + // If not, then activate the first tab. + if (tab.length === 0) { + tab = $("#individual-tabs .nav-link:first"); + } + tab.tab("show"); + + // If the user selects a tab, update the URL to reflect this + $('#individual-tabs a[data-toggle="tab"]').on('shown.bs.tab', function (e) { + window.location.hash = "tab-" + e.target.href.substring(e.target.href.indexOf('#') + 1); + }); +</script> +<?php View::endpush() ?> diff --git a/resources/views/individual-page.phtml b/resources/views/individual-page.phtml index 892ed3fa54..7b57b9e1ed 100644 --- a/resources/views/individual-page.phtml +++ b/resources/views/individual-page.phtml @@ -1,197 +1,56 @@ <?php -use Fisharebest\Webtrees\Auth; use Fisharebest\Webtrees\Fact; -use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; use Fisharebest\Webtrees\I18N; use Fisharebest\Webtrees\Individual; use Fisharebest\Webtrees\Media; use Fisharebest\Webtrees\Module\ModuleSidebarInterface; use Fisharebest\Webtrees\Module\ModuleTabInterface; use Fisharebest\Webtrees\Tree; -use Fisharebest\Webtrees\View; use Illuminate\Support\Collection; /** * @var string $age - * @var Individual $individual - * @var string $user_link - * @var Collection<ModuleSidebarInterface> $sidebars + * @var Collection<Fact> $clipboard_facts * @var Collection<Media> $individual_media * @var Collection<Fact> $name_records + * @var Individual $record * @var Collection<Fact> $sex_records * @var Collection<string> $shares + * @var Collection<ModuleSidebarInterface> $sidebars * @var Collection<ModuleTabInterface> $tabs * @var Tree $tree + * @var string $user_link */ ?> -<?php if ($individual->isPendingDeletion()) : ?> - <?php if (Auth::isModerator($individual->tree())) : ?> - <?= view('components/alert-warning-dismissible', [ - 'alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ - I18N::translate('This individual has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $individual->tree()->name(), 'xref' => $individual->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $individual->tree()->name(), 'xref' => $individual->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes']), - ]) ?> - <?php elseif (Auth::isEditor($individual->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This individual has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php elseif ($individual->isPendingAddition()) : ?> - <?php if (Auth::isModerator($individual->tree())) : ?> - <?= view('components/alert-warning-dismissible', [ - 'alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ - I18N::translate('This individual has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $individual->tree()->name(), 'xref' => $individual->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $individual->tree()->name(), 'xref' => $individual->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes']), - ]) ?> - <?php elseif (Auth::isEditor($individual->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This individual has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php endif ?> +<?= view('individual-page-pending', ['record' => $record]) ?> <div class="d-flex mb-4"> <h2 class="wt-page-title mx-auto"> - <?= $individual->fullName() ?><?= $user_link ?>, <?= $individual->lifespan() ?> <?= $age ?> + <?= $record->fullName() ?><?= $user_link ?>, <?= $record->lifespan() ?> <?= $age ?> </h2> - <?php if ($individual->canEdit()) : ?> - <?= view('individual-page-menu', ['record' => $individual, 'shares' => $shares]) ?> + + <?php if ($record->canEdit()) : ?> + <?= view('individual-page-menu', ['clipboard_facts' => $clipboard_facts, 'record' => $record, 'shares' => $shares]) ?> <?php endif ?> </div> <div class="row"> - <div class="<?= $sidebars->isEmpty() ? 'col-sm-12' : 'col-sm-8' ?>"> + <div class="col"> <div class="row mb-4"> - <!-- Individual images --> - <?php if ($individual_media->isNotEmpty() || $tree->getPreference('USE_SILHOUETTE') === '1') : ?> - <div class="col-sm-3"> - <?php if ($individual_media->isEmpty()) : ?> - <div class="img-thumbnail"> - <i class="wt-individual-silhouette wt-individual-silhouette-<?= strtolower($individual->sex()) ?>"></i> - </div> - <?php elseif ($individual_media->count() === 1) : ?> - <?= $individual_media->first()->displayImage(200, 260, 'crop', ['class' => 'img-thumbnail img-fluid w-100']) ?> - <?php else : ?> - <div id="individual-images" class="carousel slide" data-ride="carousel" data-interval="false"> - <div class="carousel-inner"> - <?php foreach ($individual_media as $n => $media_file) : ?> - <div class="carousel-item <?= $n === 0 ? 'active' : '' ?>"> - <?= $media_file->displayImage(200, 260, 'crop', ['class' => 'img-thumbnail img-fluid w-100']) ?> - </div> - <?php endforeach ?> - </div> - <a class="carousel-control-prev" href="#individual-images" role="button" data-slide="prev"> - <span class="carousel-control-prev-icon" aria-hidden="true"></span> - <span class="sr-only"><?= I18N::translate('previous') ?></span> - </a> - <a class="carousel-control-next" href="#individual-images" role="button" data-slide="next"> - <span class="carousel-control-next-icon" aria-hidden="true"></span> - <span class="sr-only"><?= I18N::translate('next') ?></span> - </a> - </div> - <?php endif ?> - - <?php if (Auth::isEditor($individual->tree())) : ?> - <div class="text-center"> - <a href="<?= e(route(AddNewFact::class, ['tree' => $individual->tree()->name(), 'xref' => $individual->xref(), 'fact' => 'OBJE'])) ?>"> - <?= I18N::translate('Add a media object') ?> - </a> - </div> - <?php endif ?> - </div> - <?php endif ?> + <?= view('individual-page-images', ['individual_media' => $individual_media, 'record' => $record, 'tree' => $tree]) ?> - <!-- Name accordion --> - <div class="col-sm accordion" id="individual-names"> - <?php foreach ($name_records as $name_record) : ?> - <?= $name_record ?> - <?php endforeach ?> - - <?php foreach ($sex_records as $sex_record) : ?> - <?= $sex_record ?> - <?php endforeach ?> - </div> + <?= view('individual-page-names', ['name_records' => $name_records, 'sex_records' => $sex_records]) ?> </div> - <div class="wt-tabs-individual" id="individual-tabs"> - <ul class="nav nav-tabs flex-wrap" role="tablist"> - <?php foreach ($tabs as $tab) : ?> - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $tab->isGrayedOut($individual) ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" data-href="<?= e(route('module', ['module' => $tab->name(), 'action' => 'Tab', 'tree' => $individual->tree()->name(), 'xref' => $individual->xref()])) ?>" href="#<?= $tab->name() ?>"> - <?= $tab->tabTitle() ?> - </a> - </li> - <?php endforeach ?> - </ul> - - <div class="tab-content"> - <?php foreach ($tabs as $tab) : ?> - <div id="<?= $tab->name() ?>" class="tab-pane fade wt-ajax-load" role="tabpanel"><?php if (!$tab->canLoadAjax()) : - ?><?= $tab->getTabContent($individual) ?><?php - endif ?></div> - <?php endforeach ?> - </div> - </div> + <?= view('individual-page-tabs', ['record' => $record, 'tabs' => $tabs]) ?> </div> - <?php if ($sidebars->isNotEmpty()) : ?> - <div class="col-sm-4 accordion" id="sidebar"> - <?php foreach ($sidebars as $sidebar) : ?> - <div class="card"> - <div class="card-header" role="tab" id="sidebar-header-<?= $sidebar->name() ?>"> - <div class="card-title mb-0"> - <a data-toggle="collapse" href="#sidebar-content-<?= $sidebar->name() ?>" aria-expanded="<?= $sidebar->name() === 'family_nav' ? 'true' : 'false' ?>" aria-controls="sidebar-content-<?= $sidebar->name() ?>"> - <?= view('icons/expand') ?> - <?= view('icons/collapse') ?> - <?= $sidebar->sidebarTitle() ?> - </a> - </div> - </div> - <div id="sidebar-content-<?= $sidebar->name() ?>" class="collapse<?= $sidebar->name() === 'family_nav' ? ' show' : '' ?>" data-parent="#sidebar" aria-labelledby="sidebar-header-<?= $sidebar->name() ?>"> - <div class="card-body"> - <?= $sidebar->getSidebarContent($individual) ?> - </div> - </div> - </div> - <?php endforeach ?> - </div> + <?php if ($sidebars->isNotEmpty()) : ?> + <?= view('individual-page-sidebars', ['record' => $record, 'sidebars' => $sidebars]) ?> <?php endif ?> </div> -<?php View::push('javascript') ?> -<script> - "use strict"; - - // Bootstrap tabs - load content dynamically using AJAX - $('a[data-toggle="tab"][data-href]').on('show.bs.tab', function () { - let target = $(this.hash + ':empty'); - if (target.length > 0) { - // Start the download immediately... - let download = fetch(this.dataset.href); - - // ...but don't insert it until the tab is ready. - $(this).one('shown.bs.tab', () => { - download - .then(data => data.text()) - .then(data => target.html(data)); - }); - } - }); - - // If the URL contains a fragment, then activate the corresponding tab. - // Use a prefix on the fragment, to prevent scrolling to the element. - let target = window.location.hash.replace("tab-", ""); - let tab = $("#individual-tabs .nav-link[href='" + target + "']"); - // If not, then activate the first tab. - if (tab.length === 0) { - tab = $("#individual-tabs .nav-link:first"); - } - tab.tab("show"); - - // If the user selects a tab, update the URL to reflect this - $('#individual-tabs a[data-toggle="tab"]').on('shown.bs.tab', function (e) { - window.location.hash = "tab-" + e.target.href.substring(e.target.href.indexOf('#') + 1); - }); -</script> -<?php View::endpush() ?> - <?= view('modals/ajax') ?> -<?= view('modals/shares', ['shares' => $shares, 'title' => I18N::translate('Share') . ' — ' . $individual->fullName()]) ?> +<?= view('modals/shares', ['shares' => $shares, 'title' => I18N::translate('Share') . ' — ' . $record->fullName()]) ?> diff --git a/resources/views/media-page-details.phtml b/resources/views/media-page-details.phtml new file mode 100644 index 0000000000..52cbbab375 --- /dev/null +++ b/resources/views/media-page-details.phtml @@ -0,0 +1,97 @@ +<?php + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; +use Fisharebest\Webtrees\Http\RequestHandlers\DeleteFact; +use Fisharebest\Webtrees\Http\RequestHandlers\EditMediaFileModal; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Media; +use Fisharebest\Webtrees\Registry; +use Fisharebest\Webtrees\Tree; +use Illuminate\Support\Collection; +use League\Flysystem\FilesystemOperator; + +/** + * @var Collection $clipboard_facts + * @var FilesystemOperator $data_filesystem + * @var Media $record + * @var Tree $tree + */ + +?> + +<table class="table wt-facts-table"> + <?php foreach ($record->mediaFiles() as $media_file) : ?> + <tr class="<?= $media_file->isPendingAddition() ? 'wt-new' : '' ?><?= $media_file->isPendingDeletion() ? 'wt-old' : '' ?>"> + <th scope="row"> + <?= I18N::translate('Media file') ?> + <?php if ($record->canEdit()) : ?> + <div class="editfacts nowrap"> + <a class="btn btn-link" href="#" data-toggle="modal" data-backdrop="static" data-target="#wt-ajax-modal" data-href="<?= route(EditMediaFileModal::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref(), 'fact_id' => $media_file->factId()]) ?>" title="<?= I18N::translate('Edit') ?>"> + <?= view('icons/edit') ?> + <span class="sr-only"> + <?= I18N::translate('Edit') ?> + </span> + </a> + + <?php if (count($record->mediaFiles()) > 1) : ?> + <a class="btn btn-link" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete this fact?') ?>" data-post-url="<?= e(route(DeleteFact::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref(), 'fact_id' => $media_file->factId()])) ?>" title="<?= I18N::translate('Delete') ?>"> + <?= view('icons/delete') ?> + <span class="sr-only"> + <?= I18N::translate('Delete') ?> + </span> + </a> + + <?php endif ?> + </div> + <?php endif ?> + </th> + <td class="d-flex justify-content-between"> + <div> + <?php if ($media_file->isExternal()) : ?> + <?= Registry::elementFactory()->make('OBJE:FILE')->labelValue($media_file->filename(), $record->tree()) ?> + <?php elseif (Auth::isEditor($record->tree())) :?> + <?php if (!$media_file->fileExists($data_filesystem)) : ?> + <p class="alert alert-danger"> + <?= I18N::translate('The file “%s” does not exist.', e($media_file->filename())) ?> + </p> + <?php endif ?> + <?= Registry::elementFactory()->make('OBJE:FILE')->labelValue($media_file->filename(), $record->tree()) ?> + <?php endif ?> + + <?= Registry::elementFactory()->make('OBJE:FILE:TITL')->labelValue($media_file->title(), $record->tree()) ?> + <?= Registry::elementFactory()->make('OBJE:FILE:FORM:TYPE')->labelValue($media_file->type(), $record->tree()) ?> + <?= Registry::elementFactory()->make('OBJE:FILE:FORM')->labelValue($media_file->format(), $record->tree()) ?> + </div> + + <div> + <?php if (!$media_file->isExternal()) : ?> + <?php if (explode('/', $media_file->mimeType())[0] === 'audio') : ?> + <audio controls> + <source src="<?= e($media_file->downloadUrl('inline')) ?>" type="<?= $media_file->mimeType() ?>"> + </audio> + <?php elseif (explode('/', $media_file->mimeType())[0] === 'video') : ?> + <video controls width="300"> + <source src="<?= e($media_file->downloadUrl('inline')) ?>" type="<?= $media_file->mimeType() ?>"> + </video> + <?php else : ?> + <?= $media_file->displayImage(200, 150, 'contain', []) ?> + <?php endif ?> + <?php if ($record->tree()->getPreference('SHOW_MEDIA_DOWNLOAD') >= Auth::accessLevel($record->tree()) && $media_file->fileExists($data_filesystem)) : ?> + <br> + <a href="<?= e($media_file->downloadUrl('attachment')) ?>"> + <?= I18N::translate('Download file') ?> + </a> + <?php endif ?> + <?php endif ?> + </div> + </td> + </tr> + <?php endforeach ?> + + <?php foreach ($record->facts() as $fact) : ?> + <?php FunctionsPrintFacts::printFact($fact, $record) ?> + <?php endforeach ?> +</table> diff --git a/resources/views/media-page-menu.phtml b/resources/views/media-page-menu.phtml index 8268e1360a..1aabf430ef 100644 --- a/resources/views/media-page-menu.phtml +++ b/resources/views/media-page-menu.phtml @@ -1,15 +1,21 @@ <?php +use Fisharebest\Webtrees\Fact; +use Fisharebest\Webtrees\Http\RequestHandlers\AddMediaFileModal; +use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact; use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; use Fisharebest\Webtrees\Http\RequestHandlers\EditRecordPage; use Fisharebest\Webtrees\Http\RequestHandlers\LinkMediaToFamilyModal; use Fisharebest\Webtrees\Http\RequestHandlers\LinkMediaToIndividualModal; use Fisharebest\Webtrees\Http\RequestHandlers\LinkMediaToSourceModal; +use Fisharebest\Webtrees\Http\RequestHandlers\PasteFact; use Fisharebest\Webtrees\I18N; use Fisharebest\Webtrees\Media; +use Illuminate\Support\Collection; /** - * @var Media $record + * @var Collection<Fact> $clipboard_facts + * @var Media $record */ ?> @@ -21,10 +27,31 @@ use Fisharebest\Webtrees\Media; </button> <div class="dropdown-menu dropdown-menu-right wt-page-menu-items" aria-labelledby="page-menu"> + <!-- <a class="dropdown-item" href="<?= route(EditRecordPage::class, ['xref' => $record->xref(), 'tree' => $record->tree()->name()]) ?>"> <?= view('icons/edit') ?> <?= I18N::translate('Edit') ?> </a> + --> + + <a class="dropdown-item" href="#" data-href="<?= e(route(AddMediaFileModal::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>" data-target="#wt-ajax-modal" data-toggle="modal" data-backdrop="static"> + <?= view('icons/add') ?> + <?= I18N::translate('Add a media file') ?> + </a> + + <?php if ($record->missingFacts() !== []) : ?> + <div class="dropdown-divider"></div> + + <?= view('record-page-menu-facts', ['record' => $record]) ?> + <?php endif ?> + + <?php if ($clipboard_facts->isNotEmpty()) : ?> + <div class="dropdown-divider"></div> + + <?= view('record-page-menu-clipboard', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> + <?php endif ?> + + <div class="dropdown-divider"></div> <a class="dropdown-item" href="#" data-href="<?= e(route(LinkMediaToIndividualModal::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>" data-target="#wt-ajax-modal" data-toggle="modal" data-backdrop="static"> <?= view('icons/link') ?> diff --git a/resources/views/media-page-pending.phtml b/resources/views/media-page-pending.phtml new file mode 100644 index 0000000000..411c18ad0a --- /dev/null +++ b/resources/views/media-page-pending.phtml @@ -0,0 +1,26 @@ +<?php + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Media; + +/** + * @var Media $record + */ +?> + +<?php if ($record->isPendingDeletion()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This media object has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This media object has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php elseif ($record->isPendingAddition()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This media object has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This media object has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php endif ?> diff --git a/resources/views/media-page.phtml b/resources/views/media-page.phtml index f0475b7f8c..b221f50118 100644 --- a/resources/views/media-page.phtml +++ b/resources/views/media-page.phtml @@ -1,18 +1,6 @@ <?php -use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Functions\FunctionsPrint; -use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; -use Fisharebest\Webtrees\GedcomTag; -use Fisharebest\Webtrees\Http\RequestHandlers\AddMediaFileModal; -use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact; -use Fisharebest\Webtrees\Http\RequestHandlers\DeleteFact; -use Fisharebest\Webtrees\Http\RequestHandlers\EditMediaFileModal; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; -use Fisharebest\Webtrees\I18N; use Fisharebest\Webtrees\Media; -use Fisharebest\Webtrees\Registry; use Fisharebest\Webtrees\Tree; use Illuminate\Support\Collection; use League\Flysystem\FilesystemOperator; @@ -20,203 +8,37 @@ use League\Flysystem\FilesystemOperator; /** * @var Collection $clipboard_facts * @var FilesystemOperator $data_filesystem - * @var Collection $facts - * @var Collection $families - * @var Collection $individuals - * @var Media $media - * @var Collection $notes - * @var Collection $sources + * @var Collection $linked_families + * @var Collection $linked_individuals + * @var Collection $linked_notes + * @var Collection $linked_sources + * @var Media $record * @var Tree $tree */ + ?> -<?php if ($media->isPendingDeletion()) : ?> - <?php if (Auth::isModerator($media->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This media object has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($media->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This media object has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php elseif ($media->isPendingAddition()) : ?> - <?php if (Auth::isModerator($media->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This media object has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($media->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This media object has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php endif ?> +<?= view('media-page-pending', ['record' => $record]) ?> <div class="d-flex mb-4"> <h2 class="wt-page-title mx-auto"> - <?= $media->fullName() ?> + <?= $record->fullName() ?> </h2> - <?php if ($media->canEdit()) : ?> - <?= view('media-page-menu', ['record' => $media]) ?> + <?php if ($record->canEdit()) : ?> + <?= view('media-page-menu', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> <?php endif ?> </div> <div class="wt-page-content"> - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <a class="nav-link active" data-toggle="tab" role="tab" href="#details"> - <?= I18N::translate('Details') ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $individuals->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#individuals"> - <?= I18N::translate('Individuals') ?> - <?= view('components/badge', ['count' => $individuals->count()]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $families->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#families"> - <?= I18N::translate('Families') ?> - <?= view('components/badge', ['count' => $families->count()]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $sources->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#sources"> - <?= I18N::translate('Sources') ?> - <?= view('components/badge', ['count' => $sources->count()]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $notes->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#notes"> - <?= I18N::translate('Notes') ?> - <?= view('components/badge', ['count' => $notes->count()]) ?> - </a> - </li> - </ul> - - <div class="tab-content mt-4"> - <div class="tab-pane active fade show" role="tabpanel" id="details"> - <table class="table wt-facts-table"> - <?php foreach ($media->mediaFiles() as $media_file) : ?> - <tr class="<?= $media_file->isPendingAddition() ? 'wt-new' : '' ?><?= $media_file->isPendingDeletion() ? 'wt-old' : '' ?>"> - <th scope="row"> - <?= I18N::translate('Media file') ?> - <?php if ($media->canEdit()) : ?> - <div class="editfacts nowrap"> - <a class="btn btn-link" href="#" data-toggle="modal" data-backdrop="static" data-target="#wt-ajax-modal" data-href="<?= route(EditMediaFileModal::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref(), 'fact_id' => $media_file->factId()]) ?>" title="<?= I18N::translate('Edit') ?>"> - <?= view('icons/edit') ?> - <span class="sr-only"> - <?= I18N::translate('Edit') ?> - </span> - </a> - - <?php if (count($media->mediaFiles()) > 1) : ?> - <a class="btn btn-link" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete this fact?') ?>" data-post-url="<?= e(route(DeleteFact::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref(), 'fact_id' => $media_file->factId()])) ?>" title="<?= I18N::translate('Delete') ?>"> - <?= view('icons/delete') ?> - <span class="sr-only"> - <?= I18N::translate('Delete') ?> - </span> - </a> - - <?php endif ?> - </div> - <?php endif ?> - </th> - <td class="d-flex justify-content-between"> - <div> - <?php if ($media_file->isExternal()) : ?> - <?= Registry::elementFactory()->make('OBJE:FILE')->labelValue($media_file->filename(), $media->tree()) ?> - <?php elseif (Auth::isEditor($media->tree())) :?> - <?php if (!$media_file->fileExists($data_filesystem)) : ?> - <p class="alert alert-danger"> - <?= I18N::translate('The file “%s” does not exist.', e($media_file->filename())) ?> - </p> - <?php endif ?> - <?= Registry::elementFactory()->make('OBJE:FILE')->labelValue($media_file->filename(), $media->tree()) ?> - <?php endif ?> - - <?= Registry::elementFactory()->make('OBJE:FILE:TITL')->labelValue($media_file->title(), $media->tree()) ?> - <?= Registry::elementFactory()->make('OBJE:FILE:FORM:TYPE')->labelValue($media_file->type(), $media->tree()) ?> - <?= Registry::elementFactory()->make('OBJE:FILE:FORM')->labelValue($media_file->format(), $media->tree()) ?> - </div> - - <div> - <?php if (!$media_file->isExternal()) : ?> - <?php if (explode('/', $media_file->mimeType())[0] === 'audio') : ?> - <audio controls> - <source src="<?= e($media_file->downloadUrl('inline')) ?>" type="<?= $media_file->mimeType() ?>"> - </audio> - <?php elseif (explode('/', $media_file->mimeType())[0] === 'video') : ?> - <video controls width="300"> - <source src="<?= e($media_file->downloadUrl('inline')) ?>" type="<?= $media_file->mimeType() ?>"> - </video> - <?php else : ?> - <?= $media_file->displayImage(200, 150, 'contain', []) ?> - <?php endif ?> - <?php if ($media->tree()->getPreference('SHOW_MEDIA_DOWNLOAD') >= Auth::accessLevel($media->tree()) && $media_file->fileExists($data_filesystem)) : ?> - <br> - <a href="<?= e($media_file->downloadUrl('attachment')) ?>"> - <?= I18N::translate('Download file') ?> - </a> - <?php endif ?> - <?php endif ?> - </div> - </td> - </tr> - <?php endforeach ?> - <?php foreach ($facts as $fact) : ?> - <?php FunctionsPrintFacts::printFact($fact, $media) ?> - <?php endforeach ?> - <?php if ($media->canEdit()) : ?> - <?= view('edit/paste-fact-row', ['record' => $media, 'facts' => $clipboard_facts]) ?> - - <?php FunctionsPrint::printAddNewFact($media, $facts, Media::RECORD_TYPE) ?> - <tr> - <th> - <?= I18N::translate('Source') ?> - </th> - <td> - <a href="<?= e(route(AddNewFact::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref(), 'fact' => 'SOUR'])) ?>"> - <?= I18N::translate('Add a source citation') ?> - </a> - </td> - </tr> - <tr> - <th scope="row"> - <?= I18N::translate('Restriction') ?> - </th> - <td> - <a href="<?= e(route(AddNewFact::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref(), 'fact' => 'RESN'])) ?>"> - <?= I18N::translate('Add a restriction') ?> - </a> - </td> - </tr> - <tr> - <th scope="row"> - <?= I18N::translate('Media file') ?> - </th> - <td> - <a href="#" data-href="<?= e(route(AddMediaFileModal::class, ['tree' => $media->tree()->name(), 'xref' => $media->xref()])) ?>" data-target="#wt-ajax-modal" data-toggle="modal" data-backdrop="static"> - <?= I18N::translate('Add a media file') ?> - </a> - </td> - </tr> - <?php endif ?> - </table> - </div> - - <div class="tab-pane fade" role="tabpanel" id="individuals"> - <?= view('lists/individuals-table', ['individuals' => $individuals, 'sosa' => false, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="families"> - <?= view('lists/families-table', ['families' => $families, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="sources"> - <?= view('lists/sources-table', ['sources' => $sources, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="notes"> - <?= view('lists/notes-table', ['notes' => $notes, 'tree' => $tree]) ?> - </div> - </div> + <?= view('record-page-links', [ + 'details' => view('media-page-details', ['clipboard_facts' => $clipboard_facts, 'data_filesystem' => $data_filesystem, 'record' => $record]), + 'linked_families' => $linked_families, + 'linked_individuals' => $linked_individuals, + 'linked_media_objects' => null, + 'linked_notes' => $linked_notes, + 'linked_sources' => $linked_sources, + 'tree' => $tree, + ]) ?> </div> <?= view('modals/ajax') ?> diff --git a/resources/views/modules/media/tab.phtml b/resources/views/modules/media/tab.phtml index 3f4e3911ea..5482791b12 100644 --- a/resources/views/modules/media/tab.phtml +++ b/resources/views/modules/media/tab.phtml @@ -30,9 +30,5 @@ use Illuminate\Support\Collection; </td> </tr> <?php endif ?> - - <?php if ($can_edit) : ?> - <?= view('edit/paste-fact-row', ['record' => $individual, 'facts' => $clipboard_facts]) ?> - <?php endif ?> </table> </div> diff --git a/resources/views/modules/notes/tab.phtml b/resources/views/modules/notes/tab.phtml index a3acc5af2a..965a366437 100644 --- a/resources/views/modules/notes/tab.phtml +++ b/resources/views/modules/notes/tab.phtml @@ -44,8 +44,6 @@ use Illuminate\Support\Collection; <?php endif ?> <?php if ($can_edit) : ?> - <?= view('edit/paste-fact-row', ['record' => $individual, 'facts' => $clipboard_facts]) ?> - <tr> <th scope="row"> <?= I18N::translate('Note') ?> diff --git a/resources/views/modules/personal_facts/tab.phtml b/resources/views/modules/personal_facts/tab.phtml index a845847cf9..ed3ae5f302 100644 --- a/resources/views/modules/personal_facts/tab.phtml +++ b/resources/views/modules/personal_facts/tab.phtml @@ -61,9 +61,7 @@ use Illuminate\Support\Collection; <?php endif ?> <?php if ($individual->canEdit()) : ?> - <?= view('edit/paste-fact-row', ['record' => $individual, 'facts' => $clipboard_facts]) ?> - - <?php FunctionsPrint::printAddNewFact($individual, $facts, Individual::RECORD_TYPE) ?> + <?php FunctionsPrint::printAddNewFact($individual) ?> <?php endif ?> </tbody> </table> diff --git a/resources/views/modules/sources_tab/tab.phtml b/resources/views/modules/sources_tab/tab.phtml index ada4899584..efc7b81240 100644 --- a/resources/views/modules/sources_tab/tab.phtml +++ b/resources/views/modules/sources_tab/tab.phtml @@ -42,8 +42,6 @@ use Illuminate\Support\Collection; <?php endif ?> <?php if ($can_edit) : ?> - <?= view('edit/paste-fact-row', ['record' => $individual, 'facts' => $clipboard_facts]) ?> - <tr> <th scope="row"> <?= I18N::translate('Source') ?> diff --git a/resources/views/note-page-details.phtml b/resources/views/note-page-details.phtml new file mode 100644 index 0000000000..8b73378240 --- /dev/null +++ b/resources/views/note-page-details.phtml @@ -0,0 +1,41 @@ +<?php + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Fact; +use Fisharebest\Webtrees\Filter; +use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; +use Fisharebest\Webtrees\Http\RequestHandlers\EditNotePage; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Note; +use Illuminate\Support\Collection; + +/** + * @var Note $record + * @var Collection<Fact> $clipboard_facts + * @var string $text + */ + +?> + +<table class="table wt-facts-table"> + <tr> + <th scope="row"> + <?= I18N::translate('Shared note') ?> + <?php if (Auth::isEditor($record->tree())) : ?> + <div class="editfacts nowrap"> + <a class="btn btn-link" href="<?= e(route(EditNotePage::class, ['xref' => $record->xref(), 'tree' => $record->tree()->name()])) ?>" title="<?= I18N::translate('Edit') ?>"> + <?= view('icons/edit') ?> + <span class="sr-only"> + <?= I18N::translate('Edit') ?> + </span> + </a> + </div> + <?php endif ?> + </th> + <td><?= Filter::formatText($record->getNote(), $record->tree()) ?></td> + </tr> + + <?php foreach ($record->facts() as $fact) : ?> + <?php FunctionsPrintFacts::printFact($fact, $record) ?> + <?php endforeach ?> +</table> diff --git a/resources/views/note-page-menu.phtml b/resources/views/note-page-menu.phtml deleted file mode 100644 index 0be518729f..0000000000 --- a/resources/views/note-page-menu.phtml +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\EditRecordPage; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Note; - -/** - * @var Note $record - */ - -?> - -<div class="dropdown wt-page-menu"> - <button class="btn btn-primary dropdown-toggle wt-page-menu-button" type="button" id="page-menu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> - <?= view('icons/menu') ?> - <?= I18N::translate('edit') ?> - </button> - - <div class="dropdown-menu dropdown-menu-right wt-page-menu-items" aria-labelledby="page-menu"> - <a class="dropdown-item" href="<?= route(EditRecordPage::class, ['xref' => $record->xref(), 'tree' => $record->tree()->name()]) ?>"> - <?= view('icons/edit') ?> - <?= I18N::translate('Edit') ?> - </a> - - <a class="dropdown-item" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete “%s”?', strip_tags($record->fullName())) ?>" data-post-url="<?= e(route(DeleteRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>"> - <?= view('icons/delete') ?> - <?= I18N::translate('Delete') ?> - </a> - </div> -</div> diff --git a/resources/views/note-page-pending.phtml b/resources/views/note-page-pending.phtml new file mode 100644 index 0000000000..62d968e679 --- /dev/null +++ b/resources/views/note-page-pending.phtml @@ -0,0 +1,27 @@ +<?php + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Note; + +/** + * @var Note $record + */ + +?> + +<?php if ($record->isPendingDeletion()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This note has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This note has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php elseif ($record->isPendingAddition()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This note has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This note has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php endif ?> diff --git a/resources/views/note-page.phtml b/resources/views/note-page.phtml index 760fbcce0a..969ad09d5f 100644 --- a/resources/views/note-page.phtml +++ b/resources/views/note-page.phtml @@ -1,14 +1,7 @@ <?php -use Fisharebest\Webtrees\Auth; use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Family; -use Fisharebest\Webtrees\Functions\FunctionsPrint; -use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; -use Fisharebest\Webtrees\Http\RequestHandlers\EditNotePage; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; -use Fisharebest\Webtrees\I18N; use Fisharebest\Webtrees\Individual; use Fisharebest\Webtrees\Media; use Fisharebest\Webtrees\Note; @@ -17,126 +10,38 @@ use Fisharebest\Webtrees\Tree; use Illuminate\Support\Collection; /** - * @var Note $note + * @var Note $record * @var Collection<Fact> $clipboard_facts - * @var Collection<Fact> $facts - * @var Collection<Family> $families - * @var Collection<Individual> $individuals - * @var Collection<Media> $media_objects - * @var Collection<Source> $sources - * @var string $text + * @var Collection<Family> $linked_families + * @var Collection<Individual> $linked_individuals + * @var Collection<Media> $linked_media_objects + * @var Collection<Source> $linked_sources * @var Tree $tree */ ?> -<?php if ($note->isPendingDeletion()) : ?> - <?php if (Auth::isModerator($note->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This note has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $note->tree()->name(), 'xref' => $note->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $note->tree()->name(), 'xref' => $note->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($note->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This note has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php elseif ($note->isPendingAddition()) : ?> - <?php if (Auth::isModerator($note->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This note has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $note->tree()->name(), 'xref' => $note->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $note->tree()->name(), 'xref' => $note->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($note->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This note has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php endif ?> +<?= view('note-page-pending', ['record' => $record]) ?> <div class="d-flex mb-4"> <h2 class="wt-page-title mx-auto"> - <?= $note->fullName() ?> + <?= $record->fullName() ?> </h2> - <?php if ($note->canEdit()) : ?> - <?= view('note-page-menu', ['record' => $note]) ?> + <?php if ($record->canEdit()) : ?> + <?= view('record-page-menu', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> <?php endif ?> </div> <div class="wt-page-content"> - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <a class="nav-link active" data-toggle="tab" role="tab" href="#details"> - <?= I18N::translate('Details') ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $individuals->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#individuals"> - <?= I18N::translate('Individuals') ?> - <?= view('components/badge', ['count' => count($individuals)]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $families->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#families"> - <?= I18N::translate('Families') ?> - <?= view('components/badge', ['count' => count($families)]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $media_objects->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#media"> - <?= I18N::translate('Media objects') ?> - <?= view('components/badge', ['count' => count($media_objects)]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $sources->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#sources"> - <?= I18N::translate('Sources') ?> - <?= view('components/badge', ['count' => count($sources)]) ?> - </a> - </li> - </ul> - - <div class="tab-content"> - <div class="tab-pane active fade show" role="tabpanel" id="details"> - <table class="table wt-facts-table"> - <tr> - <th scope="row"> - <?= I18N::translate('Shared note') ?> - <?php if (Auth::isEditor($note->tree())) : ?> - <div class="editfacts nowrap"> - <a class="btn btn-link" href="<?= e(route(EditNotePage::class, ['xref' => $note->xref(), 'tree' => $note->tree()->name()])) ?>" title="<?= I18N::translate('Edit') ?>"> - <?= view('icons/edit') ?> - <span class="sr-only"> - <?= I18N::translate('Edit') ?> - </span> - </a> - </div> - <?php endif ?> - </th> - <td><?= $text ?></td> - </tr> - <?php foreach ($facts as $fact) : ?> - <?php FunctionsPrintFacts::printFact($fact, $note) ?> - <?php endforeach ?> - - <?php if ($note->canEdit()) : ?> - <?= view('edit/paste-fact-row', ['record' => $note, 'facts' => $clipboard_facts]) ?> - - <?php FunctionsPrint::printAddNewFact($note, $facts, Note::RECORD_TYPE) ?> - <?php endif ?> - </table> - </div> - - <div class="tab-pane fade" role="tabpanel" id="individuals"> - <?= view('lists/individuals-table', ['individuals' => $individuals, 'sosa' => false, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="families"> - <?= view('lists/families-table', ['families' => $families, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="media"> - <?= view('lists/media-table', ['media_objects' => $media_objects, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="sources"> - <?= view('lists/sources-table', ['sources' => $sources, 'tree' => $tree]) ?> - </div> - </div> + <?= view('record-page-links', [ + 'details' => view('note-page-details', ['clipboard_facts' => $clipboard_facts, 'record' => $record]), + 'linked_families' => $linked_families, + 'linked_individuals' => $linked_individuals, + 'linked_media_objects' => $linked_media_objects, + 'linked_notes' => null, + 'linked_sources' => $linked_sources, + 'tree' => $tree, + ]) ?> </div> <?= view('modals/ajax') ?> diff --git a/resources/views/record-page-details.phtml b/resources/views/record-page-details.phtml new file mode 100644 index 0000000000..e20e26f219 --- /dev/null +++ b/resources/views/record-page-details.phtml @@ -0,0 +1,16 @@ +<?php + +use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; +use Fisharebest\Webtrees\GedcomRecord; + +/** + * @var GedcomRecord $record + */ + +?> + +<table class="table wt-facts-table"> + <?php foreach ($record->facts([], true) as $fact) : ?> + <?php FunctionsPrintFacts::printFact($fact, $record) ?> + <?php endforeach ?> +</table> diff --git a/resources/views/record-page-links.phtml b/resources/views/record-page-links.phtml new file mode 100644 index 0000000000..84ba40ef35 --- /dev/null +++ b/resources/views/record-page-links.phtml @@ -0,0 +1,111 @@ +<?php + +use Fisharebest\Webtrees\Family; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Individual; +use Fisharebest\Webtrees\Media; +use Fisharebest\Webtrees\Note; +use Fisharebest\Webtrees\Source; +use Fisharebest\Webtrees\Tree; +use Illuminate\Support\Collection; + +/** + * @var string $details + * @var ?Collection<Family> $linked_families + * @var ?Collection<Individual> $linked_individuals + * @var ?Collection<Media> $linked_media_objects + * @var ?Collection<Note> $linked_notes + * @var ?Collection<Source> $linked_sources + * @var Tree $tree + */ + +?> + +<ul class="nav nav-tabs" role="tablist"> + <li class="nav-item" role="presentation"> + <a class="nav-link active" data-toggle="tab" role="tab" href="#details"> + <?= I18N::translate('Details') ?> + </a> + </li> + + <?php if ($linked_individuals instanceof Collection) : ?> + <li class="nav-item" role="presentation"> + <a class="nav-link" data-toggle="tab" role="tab" href="#individuals"> + <?= I18N::translate('Individuals') ?> + <?= view('components/badge', ['count' => $linked_individuals->count()]) ?> + </a> + </li> + <?php endif ?> + + <?php if ($linked_families instanceof Collection) : ?> + <li class="nav-item" role="presentation"> + <a class="nav-link" data-toggle="tab" role="tab" href="#families"> + <?= I18N::translate('Families') ?> + <?= view('components/badge', ['count' => $linked_families->count()]) ?> + </a> + </li> + <?php endif ?> + + <?php if ($linked_media_objects instanceof Collection) : ?> + <li class="nav-item" role="presentation"> + <a class="nav-link" data-toggle="tab" role="tab" href="#media"> + <?= I18N::translate('Media objects') ?> + <?= view('components/badge', ['count' => $linked_media_objects->count()]) ?> + </a> + </li> + <?php endif ?> + + <?php if ($linked_sources instanceof Collection) : ?> + <li class="nav-item" role="presentation"> + <a class="nav-link" data-toggle="tab" role="tab" href="#sources"> + <?= I18N::translate('Sources') ?> + <?= view('components/badge', ['count' => $linked_sources->count()]) ?> + </a> + </li> + <?php endif ?> + + <?php if ($linked_notes instanceof Collection) : ?> + <li class="nav-item" role="presentation"> + <a class="nav-link" data-toggle="tab" role="tab" href="#notes"> + <?= I18N::translate('Notes') ?> + <?= view('components/badge', ['count' => $linked_notes->count()]) ?> + </a> + </li> + <?php endif ?> +</ul> + +<div class="tab-content"> + <div class="tab-pane fade show active" role="tabpanel" id="details"> + <?= $details ?> + </div> + + <?php if ($linked_individuals instanceof Collection) : ?> + <div class="tab-pane fade" role="tabpanel" id="individuals"> + <?= view('lists/individuals-table', ['individuals' => $linked_individuals, 'sosa' => false, 'tree' => $tree]) ?> + </div> + <?php endif ?> + + <?php if ($linked_families instanceof Collection) : ?> + <div class="tab-pane fade" role="tabpanel" id="families"> + <?= view('lists/families-table', ['families' => $linked_families, 'tree' => $tree]) ?> + </div> + <?php endif ?> + + <?php if ($linked_media_objects instanceof Collection) : ?> + <div class="tab-pane fade" role="tabpanel" id="media"> + <?= view('lists/media-table', ['media_objects' => $linked_media_objects, 'tree' => $tree]) ?> + </div> + <?php endif ?> + + <?php if ($linked_sources instanceof Collection) : ?> + <div class="tab-pane fade" role="tabpanel" id="sources"> + <?= view('lists/sources-table', ['sources' => $linked_sources, 'tree' => $tree]) ?> + </div> + <?php endif ?> + + <?php if ($linked_notes instanceof Collection) : ?> + <div class="tab-pane fade" role="tabpanel" id="notes"> + <?= view('lists/notes-table', ['notes' => $linked_notes, 'tree' => $tree]) ?> + </div> + <?php endif ?> +</div> diff --git a/resources/views/record-page-menu-clipboard.phtml b/resources/views/record-page-menu-clipboard.phtml new file mode 100644 index 0000000000..23ab44e561 --- /dev/null +++ b/resources/views/record-page-menu-clipboard.phtml @@ -0,0 +1,40 @@ +<?php + +use Fisharebest\Webtrees\Fact; +use Fisharebest\Webtrees\GedcomRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\PasteFact; +use Fisharebest\Webtrees\I18N; +use Illuminate\Support\Collection; + +/** + * @var Collection<Fact> $clipboard_facts + * @var GedcomRecord $record + */ + +?> + +<div class="dropdown-header"> + <?= I18N::translate('Add from clipboard') ?> +</div> + +<?php foreach ($clipboard_facts as $fact) : ?> + <form method="post" class="form-inline dropdown-item" action="<?= route(PasteFact::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()]) ?>"> + <?= view('icons/copy') ?> + <input type="hidden" name="fact_id" value="<?= e($fact->id()) ?>"> + <button type="submit" class="btn btn-text p-0" style="max-width:10rem"> + <?= csrf_field() ?> + <?= $fact->label() ?> + <?php if ($fact->target() !== null) : ?> + – <?= strip_tags($fact->target()->fullName()) ?> + <?php elseif ($fact->value() !== '') : ?> + – <?= e($fact->value()) ?> + <?php endif ?> + <?php if ($fact->date()->isOK()) : ?> + – <?= $fact->date()->minimumDate()->format('%Y') ?> + <?php endif ?> + <?php if ($fact->place()->gedcomName() !== '') : ?> + – <?= $fact->place()->shortName() ?> + <?php endif ?> + </button> + </form> +<?php endforeach ?> diff --git a/resources/views/record-page-menu-facts.phtml b/resources/views/record-page-menu-facts.phtml new file mode 100644 index 0000000000..16852921b4 --- /dev/null +++ b/resources/views/record-page-menu-facts.phtml @@ -0,0 +1,26 @@ +<?php + +use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact; +use Fisharebest\Webtrees\GedcomRecord; +use Fisharebest\Webtrees\I18N; + +/** + * @var GedcomRecord $record + */ + +?> + +<span class="dropdown-header"> + <?= I18N::translate('Add a fact') ?> + </span> + +<?php foreach ($record->missingFacts() as $fact => $label) : ?> + <a class="dropdown-item" href="<?= e(route(AddNewFact::class, [ + 'fact' => $fact, + 'xref' => $record->xref(), + 'tree' => $record->tree()->name(), + ])) ?>"> + <?= view('icons/add') ?> + <?= $label ?> + </a> +<?php endforeach ?> diff --git a/resources/views/record-page-menu.phtml b/resources/views/record-page-menu.phtml new file mode 100644 index 0000000000..a04323f5bc --- /dev/null +++ b/resources/views/record-page-menu.phtml @@ -0,0 +1,52 @@ +<?php + +use Fisharebest\Webtrees\Elements\HeaderRecord; +use Fisharebest\Webtrees\Fact; +use Fisharebest\Webtrees\GedcomRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\EditRecordPage; +use Fisharebest\Webtrees\I18N; +use Illuminate\Support\Collection; + +/** + * @var Collection<Fact> $clipboard_facts + * @var GedcomRecord $record + */ + +?> + +<div class="dropdown wt-page-menu"> + <button class="btn btn-primary dropdown-toggle wt-page-menu-button" type="button" id="page-menu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + <?= view('icons/menu') ?> + <?= I18N::translate('edit') ?> + </button> + + <div class="dropdown-menu dropdown-menu-right wt-page-menu-items" aria-labelledby="page-menu"> + <a class="dropdown-item" href="<?= route(EditRecordPage::class, ['xref' => $record->xref(), 'tree' => $record->tree()->name()]) ?>"> + <?= view('icons/edit') ?> + <?= I18N::translate('Edit') ?> + </a> + + <?php if ($record->missingFacts() !== []) : ?> + <div class="dropdown-divider"></div> + + <?= view('record-page-menu-facts', ['record' => $record]) ?> + <?php endif ?> + + <?php if ($clipboard_facts->isNotEmpty()) : ?> + <div class="dropdown-divider"></div> + + <?= view('record-page-menu-clipboard', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> + <?php endif ?> + + <?php if (!$record instanceof HeaderRecord) : ?> + <div class="dropdown-divider"></div> + + <a class="dropdown-item" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete “%s”?', strip_tags($record->fullName())) ?>" data-post-url="<?= e(route(DeleteRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>"> + <?= view('icons/delete') ?> + <?= I18N::translate('Delete') ?> + </a> + <?php endif ?> + </div> +</div> + diff --git a/resources/views/record-page-pending.phtml b/resources/views/record-page-pending.phtml new file mode 100644 index 0000000000..05f3d38869 --- /dev/null +++ b/resources/views/record-page-pending.phtml @@ -0,0 +1,27 @@ +<?php + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\GedcomRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; +use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; +use Fisharebest\Webtrees\I18N; + +/** + * @var GedcomRecord $record + */ + +?> + +<?php if ($record->isPendingDeletion()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This record has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This record has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php elseif ($record->isPendingAddition()) : ?> + <?php if (Auth::isModerator($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This record has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php elseif (Auth::isEditor($record->tree())) : ?> + <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This record has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> + <?php endif ?> +<?php endif ?> diff --git a/resources/views/record-page.phtml b/resources/views/record-page.phtml new file mode 100644 index 0000000000..c0afca5b56 --- /dev/null +++ b/resources/views/record-page.phtml @@ -0,0 +1,53 @@ +<?php + +use Fisharebest\Webtrees\Fact; +use Fisharebest\Webtrees\Family; +use Fisharebest\Webtrees\GedcomRecord; +use Fisharebest\Webtrees\Individual; +use Fisharebest\Webtrees\Media; +use Fisharebest\Webtrees\Note; +use Fisharebest\Webtrees\Source; +use Fisharebest\Webtrees\Tree; +use Illuminate\Support\Collection; + +/** + * @var Collection<Fact> $clipboard_facts + * @var Collection<Family> $linked_families + * @var Collection<Individual> $linked_individuals + * @var Collection<Media> $linked_media_objects + * @var Collection<Note> $linked_notes + * @var Collection<Source> $linked_sources + * @var GedcomRecord $record + * @var Tree $tree + */ + +?> + +<?= view('record-page-pending', ['record' => $record]) ?> + +<div class="d-flex mb-4"> + <h2 class="wt-page-title mx-auto"> + <?= $record->fullName() ?> + </h2> + <?php if ($record->canEdit()) : ?> + <?= view('record-page-menu', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> + <?php endif ?> +</div> + +<div class="wt-page-content"> + <?php if ($linked_families instanceof Collection || $linked_individuals instanceof Collection || $linked_media_objects instanceof Collection || $linked_notes instanceof Collection || $linked_sources instanceof Collection) : ?> + <?= view('record-page-links', [ + 'details' => view('record-page-details', ['record' => $record]), + 'linked_families' => $linked_families, + 'linked_individuals' => $linked_individuals, + 'linked_media_objects' => $linked_media_objects, + 'linked_notes' => $linked_notes, + 'linked_sources' => $linked_sources, + 'tree' => $tree, + ]) ?> + <?php else : ?> + <?= view('record-page-details', ['clipboard_facts' => $clipboard_facts, 'record' => $record]) ?> + <?php endif ?> +</div> + +<?= view('modals/ajax') ?> diff --git a/resources/views/repository-page-menu.phtml b/resources/views/repository-page-menu.phtml deleted file mode 100644 index 014e450ef3..0000000000 --- a/resources/views/repository-page-menu.phtml +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\EditRecordPage; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Repository; - -/** - * @var Repository $record - */ - -?> - -<div class="dropdown wt-page-menu"> - <button class="btn btn-primary dropdown-toggle wt-page-menu-button" type="button" id="page-menu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> - <?= view('icons/menu') ?> - <?= I18N::translate('edit') ?> - </button> - - <div class="dropdown-menu dropdown-menu-right wt-page-menu-items" aria-labelledby="page-menu"> - <a class="dropdown-item" href="<?= route(EditRecordPage::class, ['xref' => $record->xref(), 'tree' => $record->tree()->name()]) ?>"> - <?= view('icons/edit') ?> - <?= I18N::translate('Edit') ?> - </a> - - <a class="dropdown-item" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete “%s”?', strip_tags($record->fullName())) ?>" data-post-url="<?= e(route(DeleteRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>"> - <?= view('icons/delete') ?> - <?= I18N::translate('Delete') ?> - </a> - </div> -</div> diff --git a/resources/views/repository-page.phtml b/resources/views/repository-page.phtml deleted file mode 100644 index 7b4fe1b977..0000000000 --- a/resources/views/repository-page.phtml +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; -use Fisharebest\Webtrees\Functions\FunctionsPrint; -use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Repository; -use Fisharebest\Webtrees\Source; -use Fisharebest\Webtrees\Tree; -use Illuminate\Support\Collection; - -/** - * @var Collection<Fact> $clipboard_facts - * @var Collection<Fact> $facts - * @var Collection<Source> $sources - * @var Repository $repository - * @var Tree $tree - */ - -?> - -<?php if ($repository->isPendingDeletion()) : ?> - <?php if (Auth::isModerator($repository->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This repository has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $repository->tree()->name(), 'xref' => $repository->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $repository->tree()->name(), 'xref' => $repository->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($repository->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This repository has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php elseif ($repository->isPendingAddition()) : ?> - <?php if (Auth::isModerator($repository->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This repository has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $repository->tree()->name(), 'xref' => $repository->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $repository->tree()->name(), 'xref' => $repository->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($repository->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This repository has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php endif ?> - -<div class="d-flex mb-4"> - <h2 class="wt-page-title mx-auto"> - <?= $repository->fullName() ?> - </h2> - <?php if ($repository->canEdit()) : ?> - <?= view('repository-page-menu', ['record' => $repository]) ?> - <?php endif ?> -</div> - -<div class="wt-page-content"> - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <a class="nav-link active" data-toggle="tab" role="tab" href="#details"> - <?= I18N::translate('Details') ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $sources->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#sources"> - <?= I18N::translate('Sources') ?> - <?= view('components/badge', ['count' => count($sources)]) ?> - </a> - </li> - </ul> - - <div class="tab-content"> - <div class="tab-pane fade show active" role="tabpanel" id="details"> - <table class="table wt-facts-table"> - <?php foreach ($facts as $fact) : ?> - <?php FunctionsPrintFacts::printFact($fact, $repository) ?> - <?php endforeach ?> - - <?php if ($repository->canEdit()) : ?> - <?= view('edit/paste-fact-row', ['record' => $repository, 'facts' => $clipboard_facts]) ?> - - <?php FunctionsPrint::printAddNewFact($repository, $facts, Repository::RECORD_TYPE) ?> - <?php endif ?> - </table> - </div> - - <div class="tab-pane fade" role="tabpanel" id="sources"> - <?= view('lists/sources-table', ['sources' => $sources, 'tree' => $tree]) ?> - </div> - </div> -</div> - -<?= view('modals/ajax') ?> diff --git a/resources/views/source-page-menu.phtml b/resources/views/source-page-menu.phtml deleted file mode 100644 index e6d32b41cf..0000000000 --- a/resources/views/source-page-menu.phtml +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\EditRecordPage; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Source; - -/** - * @var Source $record - */ - -?> - -<div class="dropdown wt-page-menu"> - <button class="btn btn-primary dropdown-toggle wt-page-menu-button" type="button" id="page-menu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> - <?= view('icons/menu') ?> - <?= I18N::translate('edit') ?> - </button> - - <div class="dropdown-menu dropdown-menu-right wt-page-menu-items" aria-labelledby="page-menu"> - <a class="dropdown-item" href="<?= route(EditRecordPage::class, ['xref' => $record->xref(), 'tree' => $record->tree()->name()]) ?>"> - <?= view('icons/edit') ?> - <?= I18N::translate('Edit') ?> - </a> - - <a class="dropdown-item" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete “%s”?', strip_tags($record->fullName())) ?>" data-post-url="<?= e(route(DeleteRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>"> - <?= view('icons/delete') ?> - <?= I18N::translate('Delete') ?> - </a> - </div> -</div> - diff --git a/resources/views/source-page.phtml b/resources/views/source-page.phtml deleted file mode 100644 index d6bc76d007..0000000000 --- a/resources/views/source-page.phtml +++ /dev/null @@ -1,134 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; -use Fisharebest\Webtrees\Functions\FunctionsPrint; -use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; -use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Source; -use Fisharebest\Webtrees\Tree; -use Illuminate\Support\Collection; - -/** - * @var Collection<Fact> $clipboard_facts - * @var Collection<Fact> $facts - * @var Collection $families - * @var Collection $individuals - * @var Collection $media_objects - * @var Collection $notes - * @var Source $source - * @var Tree $tree - */ - -?> - -<?php if ($source->isPendingDeletion()) : ?> - <?php if (Auth::isModerator($source->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This source has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $source->tree()->name(), 'xref' => $source->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $source->tree()->name(), 'xref' => $source->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($source->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This source has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php elseif ($source->isPendingAddition()) : ?> - <?php if (Auth::isModerator($source->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This source has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $source->tree()->name(), 'xref' => $source->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $source->tree()->name(), 'xref' => $source->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($source->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This source has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php endif ?> - -<div class="d-flex mb-4"> - <h2 class="wt-page-title mx-auto"> - <?= $source->fullName() ?> - </h2> - <?php if ($source->canEdit()) : ?> - <?= view('source-page-menu', ['record' => $source]) ?> - <?php endif ?> -</div> - -<div class="wt-page-content"> - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <a class="nav-link active" data-toggle="tab" role="tab" href="#details"> - <?= I18N::translate('Details') ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $individuals->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#individuals"> - <?= I18N::translate('Individuals') ?> - <?= view('components/badge', ['count' => count($individuals)]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $families->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#families"> - <?= I18N::translate('Families') ?> - <?= view('components/badge', ['count' => count($families)]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $media_objects->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#media"> - <?= I18N::translate('Media objects') ?> - <?= view('components/badge', ['count' => count($media_objects)]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $notes->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#notes"> - <?= I18N::translate('Notes') ?> - <?= view('components/badge', ['count' => count($notes)]) ?> - </a> - </li> - </ul> - - <div class="tab-content"> - <div class="tab-pane fade show active" role="tabpanel" id="details"> - <table class="table wt-facts-table"> - <?php foreach ($facts as $fact) : ?> - <?php FunctionsPrintFacts::printFact($fact, $source) ?> - <?php endforeach ?> - - <?php if ($source->canEdit()) : ?> - <?= view('edit/paste-fact-row', ['record' => $source, 'facts' => $clipboard_facts]) ?> - - <?php FunctionsPrint::printAddNewFact($source, $facts, Source::RECORD_TYPE) ?> - - <?php if ($source->tree()->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($source->tree())) : ?> - <tr> - <th scope="row"> - <?= I18N::translate('Media object') ?> - </th> - <td> - <a href="<?= e(route(AddNewFact::class, ['tree' => $source->tree()->name(), 'xref' => $source->xref(), 'fact' => 'OBJE'])) ?>"> - <?= I18N::translate('Add a media object') ?> - </a> - </td> - </tr> - <?php endif ?> - <?php endif ?> - </table> - </div> - - <div class="tab-pane fade" role="tabpanel" id="individuals"> - <?= view('lists/individuals-table', ['individuals' => $individuals, 'sosa' => false, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="families"> - <?= view('lists/families-table', ['families' => $families, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="media"> - <?= view('lists/media-table', ['media_objects' => $media_objects, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="notes"> - <?= view('lists/notes-table', ['notes' => $notes, 'tree' => $tree]) ?> - </div> - </div> -</div> - -<?= view('modals/ajax') ?> diff --git a/resources/views/submitter-page-menu.phtml b/resources/views/submitter-page-menu.phtml deleted file mode 100644 index bcfeef0bfe..0000000000 --- a/resources/views/submitter-page-menu.phtml +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Http\RequestHandlers\DeleteRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\EditRecordPage; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Submitter; - -/** - * @var Submitter $record - */ - -?> - -<div class="dropdown wt-page-menu"> - <button class="btn btn-primary dropdown-toggle wt-page-menu-button" type="button" id="page-menu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> - <?= view('icons/menu') ?> - <?= I18N::translate('edit') ?> - </button> - - <div class="dropdown-menu dropdown-menu-right wt-page-menu-items" aria-labelledby="page-menu"> - <a class="dropdown-item" href="<?= route(EditRecordPage::class, ['xref' => $record->xref(), 'tree' => $record->tree()->name()]) ?>"> - <?= view('icons/edit') ?> - <?= I18N::translate('Edit') ?> - </a> - - <a class="dropdown-item" href="#" data-confirm="<?= I18N::translate('Are you sure you want to delete “%s”?', strip_tags($record->fullName())) ?>" data-post-url="<?= e(route(DeleteRecord::class, ['tree' => $record->tree()->name(), 'xref' => $record->xref()])) ?>"> - <?= view('icons/delete') ?> - <?= I18N::translate('Delete') ?> - </a> - </div> -</div> - -<?php if ($record->canEdit()) : ?> -<?php endif ?> - diff --git a/resources/views/submitter-page.phtml b/resources/views/submitter-page.phtml deleted file mode 100644 index 1e01a2e432..0000000000 --- a/resources/views/submitter-page.phtml +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Fact; -use Fisharebest\Webtrees\Family; -use Fisharebest\Webtrees\Functions\FunctionsPrintFacts; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesAcceptRecord; -use Fisharebest\Webtrees\Http\RequestHandlers\PendingChangesRejectRecord; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Individual; -use Fisharebest\Webtrees\Submitter; -use Fisharebest\Webtrees\Tree; -use Illuminate\Support\Collection; - -/** - * @var Collection<Fact> $facts - * @var Collection<Family> $families - * @var Collection<Individual> $individuals - * @var Submitter $submitter - * @var Tree $tree - */ - -?> - -<?php if ($submitter->isPendingDeletion()) : ?> - <?php if (Auth::isModerator($submitter->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This record has been deleted. You should review the deletion and then %1$s or %2$s it.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $submitter->tree()->name(), 'xref' => $submitter->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $submitter->tree()->name(), 'xref' => $submitter->xref()])) . '">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($submitter->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This record has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php elseif ($submitter->isPendingAddition()) : ?> - <?php if (Auth::isModerator($submitter->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => /* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate('This record has been edited. You should review the changes and then %1$s or %2$s them.', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesAcceptRecord::class, ['tree' => $submitter->tree()->name(), 'xref' => $submitter->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" class="alert-link" data-post-url="' . e(route(PendingChangesRejectRecord::class, ['tree' => $submitter->tree()->name(), 'xref' => $submitter->xref()])) . '">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php elseif (Auth::isEditor($submitter->tree())) : ?> - <?= view('components/alert-warning-dismissible', ['alert' => I18N::translate('This record has been edited. The changes need to be reviewed by a moderator.') . ' ' . view('help/link', ['topic' => 'pending_changes'])]) ?> - <?php endif ?> -<?php endif ?> - -<div class="d-flex mb-4"> - <h2 class="wt-page-title mx-auto"> - <?= $submitter->fullName() ?> - </h2> - <?php if ($submitter->canEdit()) : ?> - <?= view('submitter-page-menu', ['record' => $submitter]) ?> - <?php endif ?> -</div> - -<div class="wt-page-content"> - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <a class="nav-link active" data-toggle="tab" role="tab" href="#details"> - <?= I18N::translate('Details') ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $individuals->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#individuals"> - <?= I18N::translate('Individuals') ?> - <?= view('components/badge', ['count' => $individuals->count()]) ?> - </a> - </li> - - <li class="nav-item" role="presentation"> - <a class="nav-link<?= $families->isEmpty() ? ' text-muted' : '' ?>" data-toggle="tab" role="tab" href="#families"> - <?= I18N::translate('Families') ?> - <?= view('components/badge', ['count' => $families->count()]) ?> - </a> - </li> - </ul> - - <div class="tab-content"> - <div class="tab-pane active fade show" role="tabpanel" id="details"> - <table class="table wt-facts-table"> - <?php foreach ($facts as $fact) : ?> - <?php FunctionsPrintFacts::printFact($fact, $submitter) ?> - <?php endforeach ?> - </table> - </div> - - <div class="tab-pane fade" role="tabpanel" id="individuals"> - <?= view('lists/individuals-table', ['individuals' => $individuals, 'sosa' => false, 'tree' => $tree]) ?> - </div> - - <div class="tab-pane fade" role="tabpanel" id="families"> - <?= view('lists/families-table', ['families' => $families, 'tree' => $tree]) ?> - </div> - </div> -</div> - -<?= view('modals/ajax') ?> |
