Add Full Diagram as a tab on individual pages
Implement ModuleTabInterface so the diagram can be shown as a tab on person views. Uses 500px fixed height, AJAX-loadable, tab order 9.
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Fisharebest\Webtrees\I18N;
|
||||||
|
use Fisharebest\Webtrees\Individual;
|
||||||
|
use Fisharebest\Webtrees\Module\ModuleChartInterface;
|
||||||
|
use Fisharebest\Webtrees\Tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ModuleChartInterface $module
|
||||||
|
* @var Individual $individual
|
||||||
|
* @var Tree $tree
|
||||||
|
* @var string $tree_data
|
||||||
|
* @var string $javascript_url
|
||||||
|
* @var string $stylesheet_url
|
||||||
|
* @var int $ancestor_generations
|
||||||
|
* @var int $descendant_generations
|
||||||
|
* @var bool $show_siblings
|
||||||
|
*/
|
||||||
|
|
||||||
|
$containerId = 'full-diagram-tab-' . $individual->xref();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="<?= e($stylesheet_url) ?>">
|
||||||
|
|
||||||
|
<div id="<?= $containerId ?>" class="full-diagram-container full-diagram-block wt-chart" data-tree-name="<?= e($tree->name()) ?>" style="height:500px;">
|
||||||
|
<div class="full-diagram-chart"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
if (!window.fullDiagramI18n) {
|
||||||
|
window.fullDiagramI18n = <?= json_encode([
|
||||||
|
'Born' => I18N::translate('Born'),
|
||||||
|
'Baptism' => I18N::translate('Baptism'),
|
||||||
|
'Marriage' => I18N::translate('Marriage'),
|
||||||
|
'Died' => I18N::translate('Died'),
|
||||||
|
'Occupation' => I18N::translate('Occupation'),
|
||||||
|
'Residence' => I18N::translate('Residence'),
|
||||||
|
'View profile' => I18N::translate('View profile'),
|
||||||
|
'Died at age %s' => I18N::translate('Died at age %s', '__AGE__'),
|
||||||
|
'Deceased' => I18N::translate('Deceased'),
|
||||||
|
'Age ~%s' => I18N::translate('Age ~%s', '__AGE__'),
|
||||||
|
], JSON_THROW_ON_ERROR) ?>;
|
||||||
|
}
|
||||||
|
var data = <?= $tree_data ?>;
|
||||||
|
var baseUrl = <?= json_encode(route($module::ROUTE_NAME, [
|
||||||
|
'tree' => $tree->name(),
|
||||||
|
'xref' => '__XREF__',
|
||||||
|
'ancestor_generations' => $ancestor_generations,
|
||||||
|
'descendant_generations' => $descendant_generations,
|
||||||
|
'show_siblings' => $show_siblings ? '1' : '0',
|
||||||
|
]), JSON_THROW_ON_ERROR) ?>;
|
||||||
|
|
||||||
|
function initTab() {
|
||||||
|
if (typeof window.FullDiagramChart === 'undefined') {
|
||||||
|
setTimeout(initTab, 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var chart = new window.FullDiagramChart('#<?= $containerId ?>', data, baseUrl);
|
||||||
|
chart.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initTab);
|
||||||
|
} else {
|
||||||
|
initTab();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<script src="<?= e($javascript_url) ?>"></script>
|
||||||
@@ -23,6 +23,8 @@ use Fisharebest\Webtrees\Module\ModuleChartInterface;
|
|||||||
use Fisharebest\Webtrees\Module\ModuleChartTrait;
|
use Fisharebest\Webtrees\Module\ModuleChartTrait;
|
||||||
use Fisharebest\Webtrees\Module\ModuleCustomInterface;
|
use Fisharebest\Webtrees\Module\ModuleCustomInterface;
|
||||||
use Fisharebest\Webtrees\Module\ModuleCustomTrait;
|
use Fisharebest\Webtrees\Module\ModuleCustomTrait;
|
||||||
|
use Fisharebest\Webtrees\Module\ModuleTabInterface;
|
||||||
|
use Fisharebest\Webtrees\Module\ModuleTabTrait;
|
||||||
use Fisharebest\Webtrees\Registry;
|
use Fisharebest\Webtrees\Registry;
|
||||||
use Fisharebest\Webtrees\Tree;
|
use Fisharebest\Webtrees\Tree;
|
||||||
use Fisharebest\Webtrees\Validator;
|
use Fisharebest\Webtrees\Validator;
|
||||||
@@ -33,11 +35,12 @@ use Psr\Http\Message\ResponseInterface;
|
|||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
class Module extends AbstractModule implements ModuleChartInterface, ModuleCustomInterface, ModuleBlockInterface, RequestHandlerInterface
|
class Module extends AbstractModule implements ModuleChartInterface, ModuleCustomInterface, ModuleBlockInterface, ModuleTabInterface, RequestHandlerInterface
|
||||||
{
|
{
|
||||||
use ModuleChartTrait;
|
use ModuleChartTrait;
|
||||||
use ModuleCustomTrait;
|
use ModuleCustomTrait;
|
||||||
use ModuleBlockTrait;
|
use ModuleBlockTrait;
|
||||||
|
use ModuleTabTrait;
|
||||||
|
|
||||||
public const ROUTE_NAME = 'full-diagram';
|
public const ROUTE_NAME = 'full-diagram';
|
||||||
public const ROUTE_URL = '/tree/{tree}/full-diagram/{xref}';
|
public const ROUTE_URL = '/tree/{tree}/full-diagram/{xref}';
|
||||||
@@ -274,6 +277,57 @@ class Module extends AbstractModule implements ModuleChartInterface, ModuleCusto
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Tab interface ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
public function tabTitle(): string
|
||||||
|
{
|
||||||
|
return I18N::translate('Full Diagram');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defaultTabOrder(): int
|
||||||
|
{
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasTabContent(Individual $individual): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isGrayedOut(Individual $individual): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canLoadAjax(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTabContent(Individual $individual): string
|
||||||
|
{
|
||||||
|
$configuration = new Configuration(
|
||||||
|
self::DEFAULT_ANCESTOR_GENERATIONS,
|
||||||
|
self::DEFAULT_DESCENDANT_GENERATIONS,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
$dataFacade = new DataFacade();
|
||||||
|
$treeData = $dataFacade->buildFullTree($individual, $configuration);
|
||||||
|
|
||||||
|
return view($this->name() . '::modules/full-diagram/tab', [
|
||||||
|
'module' => $this,
|
||||||
|
'individual' => $individual,
|
||||||
|
'tree' => $individual->tree(),
|
||||||
|
'tree_data' => json_encode($treeData, JSON_THROW_ON_ERROR),
|
||||||
|
'javascript_url' => $this->assetUrl('js/full-diagram.min.js'),
|
||||||
|
'stylesheet_url' => $this->assetUrl('css/full-diagram.css'),
|
||||||
|
'ancestor_generations' => self::DEFAULT_ANCESTOR_GENERATIONS,
|
||||||
|
'descendant_generations' => self::DEFAULT_DESCENDANT_GENERATIONS,
|
||||||
|
'show_siblings' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Route handler ───────────────────────────────────────────────
|
// ─── Route handler ───────────────────────────────────────────────
|
||||||
|
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Fisharebest\Webtrees\I18N;
|
||||||
|
use Fisharebest\Webtrees\Individual;
|
||||||
|
use Fisharebest\Webtrees\Module\ModuleChartInterface;
|
||||||
|
use Fisharebest\Webtrees\Tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ModuleChartInterface $module
|
||||||
|
* @var Individual $individual
|
||||||
|
* @var Tree $tree
|
||||||
|
* @var string $tree_data
|
||||||
|
* @var string $javascript_url
|
||||||
|
* @var string $stylesheet_url
|
||||||
|
* @var int $ancestor_generations
|
||||||
|
* @var int $descendant_generations
|
||||||
|
* @var bool $show_siblings
|
||||||
|
*/
|
||||||
|
|
||||||
|
$containerId = 'full-diagram-tab-' . $individual->xref();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="<?= e($stylesheet_url) ?>">
|
||||||
|
|
||||||
|
<div id="<?= $containerId ?>" class="full-diagram-container full-diagram-block wt-chart" data-tree-name="<?= e($tree->name()) ?>" style="height:500px;">
|
||||||
|
<div class="full-diagram-chart"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
if (!window.fullDiagramI18n) {
|
||||||
|
window.fullDiagramI18n = <?= json_encode([
|
||||||
|
'Born' => I18N::translate('Born'),
|
||||||
|
'Baptism' => I18N::translate('Baptism'),
|
||||||
|
'Marriage' => I18N::translate('Marriage'),
|
||||||
|
'Died' => I18N::translate('Died'),
|
||||||
|
'Occupation' => I18N::translate('Occupation'),
|
||||||
|
'Residence' => I18N::translate('Residence'),
|
||||||
|
'View profile' => I18N::translate('View profile'),
|
||||||
|
'Died at age %s' => I18N::translate('Died at age %s', '__AGE__'),
|
||||||
|
'Deceased' => I18N::translate('Deceased'),
|
||||||
|
'Age ~%s' => I18N::translate('Age ~%s', '__AGE__'),
|
||||||
|
], JSON_THROW_ON_ERROR) ?>;
|
||||||
|
}
|
||||||
|
var data = <?= $tree_data ?>;
|
||||||
|
var baseUrl = <?= json_encode(route($module::ROUTE_NAME, [
|
||||||
|
'tree' => $tree->name(),
|
||||||
|
'xref' => '__XREF__',
|
||||||
|
'ancestor_generations' => $ancestor_generations,
|
||||||
|
'descendant_generations' => $descendant_generations,
|
||||||
|
'show_siblings' => $show_siblings ? '1' : '0',
|
||||||
|
]), JSON_THROW_ON_ERROR) ?>;
|
||||||
|
|
||||||
|
function initTab() {
|
||||||
|
if (typeof window.FullDiagramChart === 'undefined') {
|
||||||
|
setTimeout(initTab, 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var chart = new window.FullDiagramChart('#<?= $containerId ?>', data, baseUrl);
|
||||||
|
chart.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initTab);
|
||||||
|
} else {
|
||||||
|
initTab();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<script src="<?= e($javascript_url) ?>"></script>
|
||||||
+55
-1
@@ -23,6 +23,8 @@ use Fisharebest\Webtrees\Module\ModuleChartInterface;
|
|||||||
use Fisharebest\Webtrees\Module\ModuleChartTrait;
|
use Fisharebest\Webtrees\Module\ModuleChartTrait;
|
||||||
use Fisharebest\Webtrees\Module\ModuleCustomInterface;
|
use Fisharebest\Webtrees\Module\ModuleCustomInterface;
|
||||||
use Fisharebest\Webtrees\Module\ModuleCustomTrait;
|
use Fisharebest\Webtrees\Module\ModuleCustomTrait;
|
||||||
|
use Fisharebest\Webtrees\Module\ModuleTabInterface;
|
||||||
|
use Fisharebest\Webtrees\Module\ModuleTabTrait;
|
||||||
use Fisharebest\Webtrees\Registry;
|
use Fisharebest\Webtrees\Registry;
|
||||||
use Fisharebest\Webtrees\Tree;
|
use Fisharebest\Webtrees\Tree;
|
||||||
use Fisharebest\Webtrees\Validator;
|
use Fisharebest\Webtrees\Validator;
|
||||||
@@ -33,11 +35,12 @@ use Psr\Http\Message\ResponseInterface;
|
|||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
class Module extends AbstractModule implements ModuleChartInterface, ModuleCustomInterface, ModuleBlockInterface, RequestHandlerInterface
|
class Module extends AbstractModule implements ModuleChartInterface, ModuleCustomInterface, ModuleBlockInterface, ModuleTabInterface, RequestHandlerInterface
|
||||||
{
|
{
|
||||||
use ModuleChartTrait;
|
use ModuleChartTrait;
|
||||||
use ModuleCustomTrait;
|
use ModuleCustomTrait;
|
||||||
use ModuleBlockTrait;
|
use ModuleBlockTrait;
|
||||||
|
use ModuleTabTrait;
|
||||||
|
|
||||||
public const ROUTE_NAME = 'full-diagram';
|
public const ROUTE_NAME = 'full-diagram';
|
||||||
public const ROUTE_URL = '/tree/{tree}/full-diagram/{xref}';
|
public const ROUTE_URL = '/tree/{tree}/full-diagram/{xref}';
|
||||||
@@ -274,6 +277,57 @@ class Module extends AbstractModule implements ModuleChartInterface, ModuleCusto
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Tab interface ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
public function tabTitle(): string
|
||||||
|
{
|
||||||
|
return I18N::translate('Full Diagram');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defaultTabOrder(): int
|
||||||
|
{
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasTabContent(Individual $individual): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isGrayedOut(Individual $individual): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canLoadAjax(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTabContent(Individual $individual): string
|
||||||
|
{
|
||||||
|
$configuration = new Configuration(
|
||||||
|
self::DEFAULT_ANCESTOR_GENERATIONS,
|
||||||
|
self::DEFAULT_DESCENDANT_GENERATIONS,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
$dataFacade = new DataFacade();
|
||||||
|
$treeData = $dataFacade->buildFullTree($individual, $configuration);
|
||||||
|
|
||||||
|
return view($this->name() . '::modules/full-diagram/tab', [
|
||||||
|
'module' => $this,
|
||||||
|
'individual' => $individual,
|
||||||
|
'tree' => $individual->tree(),
|
||||||
|
'tree_data' => json_encode($treeData, JSON_THROW_ON_ERROR),
|
||||||
|
'javascript_url' => $this->assetUrl('js/full-diagram.min.js'),
|
||||||
|
'stylesheet_url' => $this->assetUrl('css/full-diagram.css'),
|
||||||
|
'ancestor_generations' => self::DEFAULT_ANCESTOR_GENERATIONS,
|
||||||
|
'descendant_generations' => self::DEFAULT_DESCENDANT_GENERATIONS,
|
||||||
|
'show_siblings' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Route handler ───────────────────────────────────────────────
|
// ─── Route handler ───────────────────────────────────────────────
|
||||||
|
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
|||||||
Reference in New Issue
Block a user