summaryrefslogtreecommitdiff
path: root/resources/views/modules/statistics-chart
diff options
context:
space:
mode:
authorGreg Roach <fisharebest@webtrees.net>2019-01-23 11:23:32 +0000
committerGreg Roach <fisharebest@webtrees.net>2019-01-23 11:23:32 +0000
commitc6266a774b6e10cd51a0a871f89a19a4a21a59d5 (patch)
tree6f539b0e6e866a6396a9e8561f54b8400c330d56 /resources/views/modules/statistics-chart
parente2b8114de32f4ac3319ef4ec97dceddeff185499 (diff)
downloadwebtrees-c6266a774b6e10cd51a0a871f89a19a4a21a59d5.tar.gz
webtrees-c6266a774b6e10cd51a0a871f89a19a4a21a59d5.tar.bz2
webtrees-c6266a774b6e10cd51a0a871f89a19a4a21a59d5.zip
Merge chart controllers into chart modules
Diffstat (limited to 'resources/views/modules/statistics-chart')
-rw-r--r--resources/views/modules/statistics-chart/chart-page.phtml50
-rw-r--r--resources/views/modules/statistics-chart/custom.phtml283
-rw-r--r--resources/views/modules/statistics-chart/families.phtml144
-rw-r--r--resources/views/modules/statistics-chart/individuals.phtml136
-rw-r--r--resources/views/modules/statistics-chart/other.phtml85
5 files changed, 698 insertions, 0 deletions
diff --git a/resources/views/modules/statistics-chart/chart-page.phtml b/resources/views/modules/statistics-chart/chart-page.phtml
new file mode 100644
index 0000000000..a78f389ab2
--- /dev/null
+++ b/resources/views/modules/statistics-chart/chart-page.phtml
@@ -0,0 +1,50 @@
+<?php use Fisharebest\Webtrees\I18N; ?>
+<?php use Fisharebest\Webtrees\View; ?>
+
+<h2 class="wt-page-title">
+ <?= $title ?>
+</h2>
+
+<div class="wt-page-content wt-chart wt-statistics-chart" id="statistics-tabs">
+ <ul class="nav nav-tabs" role="tablist">
+ <?php foreach ($tabs as $label => $url) : ?>
+ <li class="nav-item">
+ <a class="nav-link" href="#tab-<?= e(md5($url)) ?>" data-toggle="tab" data-href="<?= e($url) ?>" role="tab">
+ <?= $label ?>
+ </a>
+ </li>
+ <?php endforeach ?>
+ </ul>
+
+ <div class="tab-content">
+ <?php foreach ($tabs as $label => $url) : ?>
+ <div class="tab-pane fade wt-ajax-load" role="tabpanel" id="tab-<?= e(md5($url)) ?>"></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 () {
+ $(this.getAttribute('href') + ':empty').load($(this).data('href'));
+ });
+
+ // If the URL contains a fragment, then activate the corresponding tab.
+ // Use a prefix on the fragment, to prevent scrolling to the element.
+ var target = window.location.hash.replace("tab-", "");
+ var tab = $("#statistics-tabs .nav-link[href='" + target + "']");
+ // If not, then activate the first tab.
+ if (tab.length === 0) {
+ tab = $("#statistics-tabs .nav-link:first");
+ }
+ tab.tab("show");
+
+ // If the user selects a tab, update the URL to reflect this
+ $('#statistics-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/modules/statistics-chart/custom.phtml b/resources/views/modules/statistics-chart/custom.phtml
new file mode 100644
index 0000000000..7fb3fe9369
--- /dev/null
+++ b/resources/views/modules/statistics-chart/custom.phtml
@@ -0,0 +1,283 @@
+<?php use Fisharebest\Webtrees\Bootstrap4; ?>
+<?php use Fisharebest\Webtrees\I18N; ?>
+
+<script>
+ function statusDisable(sel) {
+ var cbox = document.getElementById(sel);
+ cbox.checked = false;
+ cbox.disabled = true;
+ }
+
+ function statusEnable(sel) {
+ var cbox = document.getElementById(sel);
+ cbox.disabled = false;
+ }
+
+ function statusHide(sel) {
+ var box = document.getElementById(sel);
+ box.style.display = "none";
+ var box_m = document.getElementById(sel + "_m");
+ if (box_m) {
+ box_m.style.display = "none";
+ }
+ if (sel === "map_opt") {
+ var box_axes = document.getElementById("axes");
+ if (box_axes) {
+ box_axes.style.display = "";
+ }
+ var box_zyaxes = document.getElementById("zyaxes");
+ if (box_zyaxes) {
+ box_zyaxes.style.display = "";
+ }
+ }
+ }
+
+ function statusShow(sel) {
+ var box = document.getElementById(sel);
+ box.style.display = "";
+ var box_m = document.getElementById(sel + "_m");
+ if (box_m) {
+ box_m.style.display = "none";
+ }
+ if (sel === "map_opt") {
+ var box_axes = document.getElementById("axes");
+ if (box_axes) {
+ box_axes.style.display = "none";
+ }
+ var box_zyaxes = document.getElementById("zyaxes");
+ if (box_zyaxes) {
+ box_zyaxes.style.display = "none";
+ }
+ }
+ }
+
+ function statusChecked(sel) {
+ var cbox = document.getElementById(sel);
+ cbox.checked = true;
+ }
+
+ function statusShowSurname(x) {
+ if (x.value === "surname_distribution_chart") {
+ document.getElementById("surname_opt").style.display = "";
+ } else if (x.value !== "surname_distribution_chart") {
+ document.getElementById("surname_opt").style.display = "none";
+ }
+ }
+
+ function loadCustomChart() {
+ $("#custom-chart").html("");
+ var form = $("#own-stats-form");
+ jQuery.get(form.attr("action"), form.serialize())
+ .done(function (data) {
+ $("#custom-chart").html(data);
+ })
+ .fail(function (jqXHR, textStatus) {
+ // Server error? Show something to get rid of the spinner.
+ $("#custom-chart").html(textStatus);
+ });
+ return false;
+ }
+</script>
+
+<h3>
+ <?= I18N::translate('Create your own chart') ?>
+</h3>
+
+<form id="own-stats-form" action="index.php" onsubmit="return loadCustomChart();" class="wt-page-options wt-page-options-statistics">
+ <input type="hidden" name="route" value="module">
+ <input type="hidden" name="module" value="<?= e($module->name()) ?>">
+ <input type="hidden" name="action" value="CustomChart">
+ <input type="hidden" name="ged" value="<?= e($tree->name()) ?>">
+ <div class="form-group row">
+ <div class="col-sm-2 wt-page-options-label">
+ <?= I18N::translate('Chart type') ?>
+ </div>
+
+ <div class="col-sm-4 wt-page-options-value">
+ <fieldset>
+ <legend><?= I18N::translate('Individual') ?></legend>
+
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_BIRTH_MONTH => I18N::translate('Month of birth')], $module::X_AXIS_BIRTH_MONTH, false, ['onchange' => 'statusEnable("z_sex"); statusHide("x_years");; statusHide("map_opt");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_DEATH_MONTH => I18N::translate('Month of death')], '', false, ['onchange' => 'statusEnable("z_sex"); statusHide("x_years");; statusHide("map_opt");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_FIRST_CHILD_MONTH => I18N::translate('Month of birth of first child in a relation')], '', false, ['onchange' => 'statusEnable("z_sex"); statusHide("x_years");; statusHide("map_opt");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_AGE_AT_DEATH => I18N::translate('Average age at death')], '', false, ['onchange' => 'statusEnable("z_sex"); statusShow("x_years");; statusHide("map_opt");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_AGE_AT_MARRIAGE => I18N::translate('Age in year of marriage')], '', false, ['onchange' => 'statusEnable("z_sex"); statusHide("x_years"); statusShow("x_years_m");; statusHide("map_opt");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_AGE_AT_FIRST_MARRIAGE => I18N::translate('Age in year of first marriage')], '', false, ['onchange' => 'statusEnable("z_sex"); statusHide("x_years"); statusShow("x_years_m");; statusHide("map_opt");']) ?>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= I18N::translate('Family') ?></legend>
+
+ <?= Bootstrap4::radioButtons('x-as', [
+ $module::X_AXIS_MARRIAGE_MONTH => I18N::translate('Month of marriage'),
+ $module::X_AXIS_FIRST_MARRIAGE_MONTH => I18N::translate('Month of first marriage'),
+ ], '', false, ['onchange' => 'statusChecked("z_none"); statusDisable("z_sex"); statusHide("x_years");; statusHide("map_opt");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_NUMBER_OF_CHILDREN => I18N::translate('Number of children')], '', false, ['onchange' => 'statusChecked("z_none"); statusDisable("z_sex"); statusHide("x_years");; statusHide("map_opt");']) ?>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= I18N::translate('Map') ?></legend>
+
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_INDIVIDUAL_MAP => I18N::translate('Individuals')], '', false, ['onchange' => 'statusHide("x_years");; statusShow("map_opt"); statusShow("chart_type");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_BIRTH_MAP => I18N::translate('Births')], '', false, ['onchange' => 'statusHide("x_years");; statusShow("map_opt"); statusHide("chart_type"); statusHide("surname_opt");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_MARRIAGE_MAP => I18N::translate('Marriages')], '', false, ['onchange' => 'statusHide("x_years");; statusShow("map_opt"); statusHide("chart_type"); statusHide("surname_opt");']) ?>
+ <?= Bootstrap4::radioButtons('x-as', [$module::X_AXIS_DEATH_MAP => I18N::translate('Deaths')], '', false, ['onchange' => 'statusHide("x_years");; statusShow("map_opt"); statusHide("chart_type"); statusHide("surname_opt");']) ?>
+ </fieldset>
+ </div>
+
+ <div class="col-sm-2 wt-page-options-label">
+ <?= I18N::translate('Details') ?>
+ </div>
+
+ <div class="col-sm-4 wt-page-options-value">
+ <fieldset id="axes">
+ <legend><?= I18N::translate('Categories') ?></legend>
+
+ <label>
+ <input type="radio" id="z_none" name="z-as" value="<?= $module::Z_AXIS_ALL ?>" onclick="statusDisable('z-axis-boundaries-periods');">
+ <?= I18N::translate('none') ?>
+ </label>
+ <br>
+ <label>
+ <input type="radio" id="z_sex" name="z-as" value="<?= $module::Z_AXIS_SEX ?>" onclick="statusDisable('z-axis-boundaries-periods');">
+ <?= I18N::translate('gender') ?>
+ </label>
+ <br>
+ <label>
+ <input type="radio" id="z_time" name="z-as" value="<?= $module::Z_AXIS_TIME ?>" checked onclick="statusEnable('z-axis-boundaries-periods');">
+ <?= I18N::translate('date periods') ?>
+ </label>
+ <label for="z-axis-boundaries-periods" class="sr-only">
+ <?= I18N::translate('Date range') ?>
+ </label>
+ <select id="z-axis-boundaries-periods" class="form-control" name="z-axis-boundaries-periods">
+ <option value="1700,1750,1800,1850,1900,1950,2000" selected>
+ <?= /* I18N: from 1700 interval 50 years */
+ I18N::plural('from %1$s interval %2$s year', 'from %1$s interval %2$s years', 50, I18N::digits(1700), I18N::number(50)) ?>
+ </option>
+ <option value="1800,1840,1880,1920,1950,1970,2000">
+ <?= I18N::plural('from %1$s interval %2$s year', 'from %1$s interval %2$s years', 40, I18N::digits(1800), I18N::number(40)) ?>
+ </option>
+ <option value="1800,1850,1900,1950,2000">
+ <?= I18N::plural('from %1$s interval %2$s year', 'from %1$s interval %2$s years', 50, I18N::digits(1800), I18N::number(50)) ?>
+ </option>
+ <option value="1900,1920,1940,1960,1980,1990,2000">
+ <?= I18N::plural('from %1$s interval %2$s year', 'from %1$s interval %2$s years', 20, I18N::digits(1900), I18N::number(20)) ?>
+ </option>
+ <option value="1900,1925,1950,1975,2000">
+ <?= I18N::plural('from %1$s interval %2$s year', 'from %1$s interval %2$s years', 25, I18N::digits(1900), I18N::number(25)) ?>
+ </option>
+ <option value="1940,1950,1960,1970,1980,1990,2000">
+ <?= I18N::plural('from %1$s interval %2$s year', 'from %1$s interval %2$s years', 10, I18N::digits(1940), I18N::number(10)) ?>
+ </option>
+ </select>
+ </fieldset>
+
+ <fieldset id="zyaxes">
+ <legend><?= I18N::translate('Results') ?></legend>
+
+ <label>
+ <input type="radio" name="y-as" value="<?= $module::Y_AXIS_NUMBERS ?>" checked>
+ <?= I18N::translate('numbers') ?>
+ </label>
+ <br>
+ <label>
+ <input type="radio" name="y-as" value="<?= $module::Y_AXIS_PERCENT ?>">
+ <?= I18N::translate('percentage') ?>
+ </label>
+ </fieldset>
+
+ <fieldset id="x_years" style="display:none;">
+ <legend><?= I18N::translate('Age interval') ?></legend>
+
+ <label for="x-axis-boundaries-ages" class="sr-only">
+ <?= I18N::translate('Age interval') ?>
+ </label>
+ <?= Bootstrap4::select([
+ '1,5,10,20,30,40,50,60,70,80,90,100' => I18N::plural('%s year', '%s years', 10, I18N::number(10)),
+ '5,20,40,60,75,80,85,90' => I18N::plural('%s year', '%s years', 20, I18N::number(20)),
+ '10,25,50,75,100' => I18N::plural('%s year', '%s years', 25, I18N::number(25)),
+ ], '1,5,10,20,30,40,50,60,70,80,90,100', [
+ 'id' => 'x-axis-boundaries-ages',
+ 'name' => 'x-axis-boundaries-ages',
+ ]) ?>
+ </fieldset>
+
+ <fieldset id="x_years_m" style="display:none;">
+ <legend><?= I18N::translate('Age interval') ?></legend>
+
+ <label for="x-axis-boundaries-ages_m" class="sr-only">
+ <?= I18N::translate('Select the desired age interval') ?>
+ </label>
+ <?= Bootstrap4::select([
+ '16,18,20,22,24,26,28,30,32,35,40,50' => I18N::plural('%s year', '%s years', 2, I18N::number(2)),
+ '20,25,30,35,40,45,50' => I18N::plural('%s year', '%s years', 5, I18N::number(5)),
+ ], '16,18,20,22,24,26,28,30,32,35,40,50', [
+ 'id' => 'x-axis-boundaries-ages_m',
+ 'name' => 'x-axis-boundaries-ages_m',
+ ]) ?>
+ </fieldset>
+
+ <div id="map_opt" style="display:none;">
+ <fieldset id="chart_type">
+ <legend><?= I18N::translate('Chart type') ?></legend>
+
+ <label for="chart_type" class="sr-only"><?= I18N::translate('Chart type') ?></label>
+ <select name="chart_type" class="form-control" onchange="statusShowSurname(this);">
+ <option value="indi_distribution_chart" selected>
+ <?= I18N::translate('Individuals') ?>
+ </option>
+ <option value="surname_distribution_chart">
+ <?= I18N::translate('Surnames') ?>
+ </option>
+ </select>
+
+ <div id="surname_opt" class="form-group" style="display:none;">
+ <label for="SURN"><?= I18N::translate('Surname') ?></label>
+ <input data-autocomplete-type="SURN" class="form-control" type="text" id="SURN" name="SURN">
+ </div>
+ </fieldset>
+
+ <fieldset>
+ <legend id="label-area"><?= I18N::translate('Geographic area') ?></legend>
+
+ <label for="chart_shows" class="sr-only"><?= I18N::translate('Geographic area') ?></label>
+ <select id="chart_shows" class="form-control" name="chart_shows">
+ <option value="world" selected>
+ <?= I18N::translate('World') ?>
+ </option>
+ <option value="europe">
+ <?= I18N::translate('Europe') ?>
+ </option>
+ <option value="usa">
+ <?= I18N::translate('United States') ?>
+ </option>
+ <option value="south_america">
+ <?= I18N::translate('South America') ?>
+ </option>
+ <option value="asia">
+ <?= I18N::translate('Asia') ?>
+ </option>
+ <option value="middle_east">
+ <?= I18N::translate('Middle East') ?>
+ </option>
+ <option value="africa">
+ <?= I18N::translate('Africa') ?>
+ </option>
+ </select>
+ </fieldset>
+ </div>
+ </div>
+ </div>
+
+ <p class="center">
+ <button type="submit" class="btn btn-primary">
+ <?= view('icons/save') ?>
+ <?= I18N::translate('show the chart') ?>
+ </button>
+ </p>
+</form>
+
+<div id="custom-chart" class="wt-ajax-load">
+ <!-- Not initially empty, to disable spinner -->
+</div>
diff --git a/resources/views/modules/statistics-chart/families.phtml b/resources/views/modules/statistics-chart/families.phtml
new file mode 100644
index 0000000000..9097fa3bd7
--- /dev/null
+++ b/resources/views/modules/statistics-chart/families.phtml
@@ -0,0 +1,144 @@
+<?php use Fisharebest\Webtrees\I18N; ?>
+
+<h3>
+ <?= I18N::translate('Total families: %s', $stats->totalFamilies()) ?>
+</h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Total marriages') ?></td>
+ <td><?= I18N::translate('Total divorces') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->totalMarriages() ?></td>
+ <td><?= $stats->totalDivorces() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Marriages by century') ?></td>
+ <td><?= I18N::translate('Divorces by century') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->statsMarr() ?></td>
+ <td><?= $stats->statsDiv() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Earliest marriage') ?></td>
+ <td><?= I18N::translate('Earliest divorce') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->firstMarriage() ?></td>
+ <td><?= $stats->firstDivorce() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Latest marriage') ?></td>
+ <td><?= I18N::translate('Latest divorce') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->lastMarriage() ?></td>
+ <td><?= $stats->lastDivorce() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Length of marriage') ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Longest marriage'), ' - ', $stats->topAgeOfMarriage() ?></td>
+ <td><?= I18N::translate('Shortest marriage'), ' - ', $stats->minAgeOfMarriage() ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->topAgeOfMarriageFamily() ?></td>
+ <td><?= $stats->minAgeOfMarriageFamily() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Age in year of marriage') ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Youngest male'), ' - ', $stats->youngestMarriageMaleAge(true) ?></td>
+ <td><?= I18N::translate('Youngest female'), ' - ', $stats->youngestMarriageFemaleAge(true) ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->youngestMarriageMale() ?></td>
+ <td><?= $stats->youngestMarriageFemale() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Oldest male'), ' - ', $stats->oldestMarriageMaleAge(true) ?></td>
+ <td><?= I18N::translate('Oldest female'), ' - ', $stats->oldestMarriageFemaleAge(true) ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->oldestMarriageMale() ?></td>
+ <td><?= $stats->oldestMarriageFemale() ?></td>
+ </tr>
+ <tr>
+ <td colspan="2"><?= $stats->statsMarrAge() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Age at birth of child') ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Youngest father'), ' - ', $stats->youngestFatherAge(true) ?></td>
+ <td><?= I18N::translate('Youngest mother'), ' - ', $stats->youngestMotherAge(true) ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->youngestFather() ?></td>
+ <td><?= $stats->youngestMother() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Oldest father'), ' - ', $stats->oldestFatherAge(true) ?></td>
+ <td><?= I18N::translate('Oldest mother'), ' - ', $stats->oldestMotherAge(true) ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->oldestFather() ?></td>
+ <td><?= $stats->oldestMother() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Children in family') ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Average number of children per family') ?></td>
+ <td><?= I18N::translate('Number of families without children') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->averageChildren() ?></td>
+ <td><?= $stats->noChildrenFamilies() ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->statsChildren() ?></td>
+ <td><?= $stats->chartNoChildrenFamilies() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Largest families') ?></td>
+ <td><?= I18N::translate('Largest number of grandchildren') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->topTenLargestFamilyList() ?></td>
+ <td><?= $stats->topTenLargestGrandFamilyList() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Age difference') ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Age between siblings') ?></td>
+ <td><?= I18N::translate('Greatest age between siblings') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->topAgeBetweenSiblingsList() ?></td>
+ <td><?= $stats->topAgeBetweenSiblingsFullName() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Age between husband and wife') ?></td>
+ <td><?= I18N::translate('Age between wife and husband') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->ageBetweenSpousesMFList() ?></td>
+ <td><?= $stats->ageBetweenSpousesFMList() ?></td>
+ </tr>
+</table>
diff --git a/resources/views/modules/statistics-chart/individuals.phtml b/resources/views/modules/statistics-chart/individuals.phtml
new file mode 100644
index 0000000000..7980441272
--- /dev/null
+++ b/resources/views/modules/statistics-chart/individuals.phtml
@@ -0,0 +1,136 @@
+<?php use Fisharebest\Webtrees\I18N; ?>
+
+<h3>
+ <?= I18N::translate('Total individuals: %s', $stats->totalIndividuals()) ?>
+</h3>
+
+<table class="table table-sm table-bordered">
+ <thead>
+ <tr>
+ <th><?= I18N::translate('Total males') ?></th>
+ <th><?= I18N::translate('Total females') ?></th>
+ <th><?= I18N::translate('Total living') ?></th>
+ <th><?= I18N::translate('Total dead') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><?= $stats->totalSexMales() ?></td>
+ <td><?= $stats->totalSexFemales() ?></td>
+ <td><?= $stats->totalLiving() ?></td>
+ <td><?= $stats->totalDeceased() ?></td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2"><?= $stats->chartSex() ?></td>
+ <td colspan="2"><?= $stats->chartMortality() ?></td>
+ </tr>
+ </tfoot>
+</table>
+
+<h3><?= I18N::translate('Events') ?></h3>
+
+<table class="table table-sm table-bordered">
+ <tbody>
+ <tr>
+ <th><?= I18N::translate('Total births') ?></th>
+ <th><?= I18N::translate('Total deaths') ?></th>
+ </tr>
+ <tr>
+ <td><?= $stats->totalBirths() ?></td>
+ <td><?= $stats->totalDeaths() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Births by century') ?></td>
+ <td><?= I18N::translate('Deaths by century') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->statsBirth() ?></td>
+ <td><?= $stats->statsDeath() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Earliest birth') ?></td>
+ <td><?= I18N::translate('Earliest death') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->firstBirth() ?></td>
+ <td><?= $stats->firstDeath() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Latest birth') ?></td>
+ <td><?= I18N::translate('Latest death') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->lastBirth() ?></td>
+ <td><?= $stats->lastDeath() ?></td>
+ </tr>
+ </tbody>
+</table>
+
+<h3><?= I18N::translate('Lifespan') ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Average age at death') ?></td>
+ <td><?= I18N::translate('Males') ?></td>
+ <td><?= I18N::translate('Females') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->averageLifespan(true) ?></td>
+ <td><?= $stats->averageLifespanMale(true) ?></td>
+ <td><?= $stats->averageLifespanFemale(true) ?></td>
+ </tr>
+ <tr>
+ <td colspan="3"><?= $stats->statsAge() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Greatest age at death') ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Males') ?></td>
+ <td><?= I18N::translate('Females') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->topTenOldestMaleList() ?></td>
+ <td><?= $stats->topTenOldestFemaleList() ?></td>
+ </tr>
+</table>
+
+<?php if ($show_oldest_living) : ?>
+ <h3><?= I18N::translate('Oldest living individuals') ?></h3>
+
+ <table>
+ <tr>
+ <td><?= I18N::translate('Males') ?></td>
+ <td><?= I18N::translate('Females') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->topTenOldestMaleListAlive() ?></td>
+ <td><?= $stats->topTenOldestFemaleListAlive() ?></td>
+ </tr>
+ </table>
+<?php endif ?>
+
+<h3><?= I18N::translate('Names') ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Total surnames') ?></td>
+ <td><?= I18N::translate('Total given names') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->totalSurnames() ?></td>
+ <td><?= $stats->totalGivennames() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Top surnames') ?></td>
+ <td><?= I18N::translate('Top given names') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->chartCommonSurnames() ?></td>
+ <td><?= $stats->chartCommonGiven() ?></td>
+ </tr>
+</table>
diff --git a/resources/views/modules/statistics-chart/other.phtml b/resources/views/modules/statistics-chart/other.phtml
new file mode 100644
index 0000000000..d30979de96
--- /dev/null
+++ b/resources/views/modules/statistics-chart/other.phtml
@@ -0,0 +1,85 @@
+<?php use Fisharebest\Webtrees\I18N; ?>
+
+<h3>
+ <?= I18N::translate('Records') ?>: <?= $stats->totalRecords() ?>
+</h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Media objects') ?></td>
+ <td><?= I18N::translate('Sources') ?></td>
+ <td><?= I18N::translate('Notes') ?></td>
+ <td><?= I18N::translate('Repositories') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->totalMedia() ?></td>
+ <td><?= $stats->totalSources() ?></td>
+ <td><?= $stats->totalNotes() ?></td>
+ <td><?= $stats->totalRepositories() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Total events'), ': ', $stats->totalEvents() ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('First event'), ' - ', $stats->firstEventType() ?></td>
+ <td><?= I18N::translate('Last event'), ' - ', $stats->lastEventType() ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->firstEvent() ?></td>
+ <td><?= $stats->lastEvent() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Media objects'), ': ', $stats->totalMedia() ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Media objects') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->chartMedia() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Sources'), ': ', $stats->totalSources() ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Individuals with sources') ?></td>
+ <td><?= I18N::translate('Families with sources') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->totalIndisWithSources() ?></td>
+ <td><?= $stats->totalFamsWithSources() ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->chartIndisWithSources() ?></td>
+ <td><?= $stats->chartFamsWithSources() ?></td>
+ </tr>
+</table>
+
+<h3><?= I18N::translate('Places'), ': ', $stats->totalPlaces() ?></h3>
+
+<table>
+ <tr>
+ <td><?= I18N::translate('Birth places') ?></td>
+ <td><?= I18N::translate('Death places') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->commonBirthPlacesList() ?></td>
+ <td><?= $stats->commonDeathPlacesList() ?></td>
+ </tr>
+ <tr>
+ <td><?= I18N::translate('Marriage places') ?></td>
+ <td><?= I18N::translate('Events in countries') ?></td>
+ </tr>
+ <tr>
+ <td><?= $stats->commonMarriagePlacesList() ?></td>
+ <td><?= $stats->commonCountriesList() ?></td>
+ </tr>
+ <tr>
+ <td colspan="2"><?= $stats->chartDistribution() ?></td>
+ </tr>
+</table>