00478e2466
Admin-facing simplification:
- Dropped separate \"lookahead\" and \"historical lookahead\" tree
prefs (and the once-per-month historical gate). A single
\"send every N days\" number now drives both the cron cadence
and the window each issue looks ahead for living + deceased
events.
- Default 14, range 1–90, applies uniformly.
User-facing addition:
- The /my-account/{tree} subscription card gained an \"Email
frequency\" select with options: use site default, weekly,
every 2 weeks, monthly, every 2 months, quarterly. Stored as
a per-tree-per-user preference.
- Dispatch now checks each recipient's own cadence against
their own last-sent timestamp. Admin-added external addresses
with no webtrees account always receive every run (no
per-user state).
- Newsletter footer now reads \"You can change how often you
receive this email, or unsubscribe entirely, in the Newsletter
subscription section on your My account page\" — true now
that the control exists.
German translations updated for the new strings; stale ones
removed.
184 lines
8.7 KiB
PHTML
184 lines
8.7 KiB
PHTML
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use EmailNewsletter\Configuration;
|
|
use EmailNewsletter\Module;
|
|
use Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel;
|
|
use Fisharebest\Webtrees\Http\RequestHandlers\ModulesAllPage;
|
|
use Fisharebest\Webtrees\I18N;
|
|
use Fisharebest\Webtrees\Tree;
|
|
use Illuminate\Support\Collection;
|
|
|
|
/**
|
|
* @var Module $module
|
|
* @var Collection<int,Tree> $all_trees
|
|
* @var string $cron_token
|
|
* @var string $cron_url
|
|
* @var string $title
|
|
*/
|
|
|
|
?>
|
|
|
|
<?= view('components/breadcrumbs', [
|
|
'links' => [
|
|
route(ControlPanel::class) => I18N::translate('Control panel'),
|
|
route(ModulesAllPage::class) => I18N::translate('Modules'),
|
|
$title,
|
|
],
|
|
]) ?>
|
|
|
|
<h1><?= e($title) ?></h1>
|
|
|
|
<p>
|
|
<?= I18N::translate('Configure newsletter dispatch on a per-tree basis. The sender is the contact user of each tree (falling back to the site webmaster).') ?>
|
|
</p>
|
|
|
|
<form method="post">
|
|
<?= csrf_field() ?>
|
|
|
|
<?php foreach ($all_trees as $tree) : ?>
|
|
<?php
|
|
$id = $tree->id();
|
|
$enabled = Configuration::isEnabled($tree);
|
|
$frequency = Configuration::frequencyDays($tree);
|
|
$annivs = Configuration::includeAnniversaries($tree);
|
|
$subject = Configuration::subjectPrefix($tree);
|
|
$extras = $tree->getPreference(Configuration::PREF_EXTRA_RECIPIENTS, '');
|
|
$lineal = Configuration::linealDepth($tree);
|
|
$last_sent = Configuration::lastSentAt($tree);
|
|
?>
|
|
|
|
<fieldset class="card mb-4">
|
|
<legend class="card-header h4"><?= e($tree->title()) ?></legend>
|
|
|
|
<div class="card-body">
|
|
<div class="row mb-3">
|
|
<div class="offset-sm-3 col-sm-9">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox"
|
|
id="enabled-<?= $id ?>" name="enabled-<?= $id ?>"
|
|
value="1" <?= $enabled ? 'checked' : '' ?>>
|
|
<label class="form-check-label" for="enabled-<?= $id ?>">
|
|
<?= I18N::translate('Enable newsletter for this tree') ?>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<label class="col-sm-3 col-form-label" for="frequency-<?= $id ?>">
|
|
<?= I18N::translate('Send newsletters every') ?>
|
|
</label>
|
|
<div class="col-sm-9">
|
|
<div class="input-group" style="max-width: 18rem;">
|
|
<input class="form-control" type="number"
|
|
id="frequency-<?= $id ?>" name="frequency-<?= $id ?>"
|
|
value="<?= e((string) $frequency) ?>"
|
|
min="<?= Configuration::MIN_FREQUENCY_DAYS ?>"
|
|
max="<?= Configuration::MAX_FREQUENCY_DAYS ?>" required>
|
|
<span class="input-group-text"><?= I18N::translate('days') ?></span>
|
|
</div>
|
|
<small class="form-text text-muted">
|
|
<?= I18N::translate('Each issue looks the same number of days ahead, for both living relatives and historical events of those who have passed away. Default 14.') ?>
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="offset-sm-3 col-sm-9">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox"
|
|
id="anniversaries-<?= $id ?>" name="anniversaries-<?= $id ?>"
|
|
value="1" <?= $annivs ? 'checked' : '' ?>>
|
|
<label class="form-check-label" for="anniversaries-<?= $id ?>">
|
|
<?= I18N::translate('Include marriage anniversaries') ?>
|
|
</label>
|
|
</div>
|
|
<small class="form-text text-muted">
|
|
<?= I18N::translate('Only intact marriages of still-living couples are included.') ?>
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<label class="col-sm-3 col-form-label" for="lineal-<?= $id ?>">
|
|
<?= I18N::translate('Detailed view distance') ?>
|
|
</label>
|
|
<div class="col-sm-9">
|
|
<input class="form-control" type="number" style="max-width: 18rem;"
|
|
id="lineal-<?= $id ?>" name="lineal-<?= $id ?>"
|
|
value="<?= e((string) $lineal) ?>"
|
|
min="<?= Configuration::MIN_LINEAL_DEPTH ?>"
|
|
max="<?= Configuration::MAX_LINEAL_DEPTH ?>" required>
|
|
<small class="form-text text-muted">
|
|
<?= I18N::translate('A person is shown in detail (avatar, icon, timeline) when they sit within this many descent-steps of the recipient\'s direct lineage. Examples relative to the recipient: a sibling is distance 1 (one step down from the recipient\'s parent), a great-aunt is distance 1 (one step down from a great-grandparent), a nephew is distance 2, a first cousin is distance 2. Spouses share their partner\'s distance. Everyone outside this radius appears as a compact text bullet at the bottom of each section. Set to 0 to render the whole newsletter as text; recipients with no linked tree record always see the full detailed view.') ?>
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<label class="col-sm-3 col-form-label" for="subject-<?= $id ?>">
|
|
<?= I18N::translate('Subject prefix') ?>
|
|
</label>
|
|
<div class="col-sm-9">
|
|
<input class="form-control" type="text"
|
|
id="subject-<?= $id ?>" name="subject-<?= $id ?>"
|
|
value="<?= e($subject) ?>">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<label class="col-sm-3 col-form-label" for="extras-<?= $id ?>">
|
|
<?= I18N::translate('Extra recipient email addresses (one per line)') ?>
|
|
</label>
|
|
<div class="col-sm-9">
|
|
<textarea class="form-control" rows="4"
|
|
id="extras-<?= $id ?>" name="extras-<?= $id ?>"><?= e($extras) ?></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($last_sent > 0) : ?>
|
|
<div class="row mb-3">
|
|
<div class="offset-sm-3 col-sm-9">
|
|
<small class="text-muted">
|
|
<?= I18N::translate('Last sent: %s', date('Y-m-d H:i', $last_sent)) ?>
|
|
</small>
|
|
</div>
|
|
</div>
|
|
<?php endif ?>
|
|
</div>
|
|
</fieldset>
|
|
<?php endforeach ?>
|
|
|
|
<fieldset class="card mb-4">
|
|
<legend class="card-header h4"><?= I18N::translate('Cron token') ?></legend>
|
|
<div class="card-body">
|
|
<p>
|
|
<?= I18N::translate('Configure your system cron, systemd timer, or any external scheduler to call the URL below. The schedule decides when newsletters are actually due — calling more frequently is safe.') ?>
|
|
</p>
|
|
<pre class="bg-light p-2"><?= e($cron_url) ?></pre>
|
|
<div class="form-check mb-2">
|
|
<input class="form-check-input" type="checkbox" id="regenerate_token"
|
|
name="regenerate_token" value="1">
|
|
<label class="form-check-label" for="regenerate_token">
|
|
<?= I18N::translate('Regenerate token') ?>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<button type="submit" class="btn btn-primary">
|
|
<?= view('icons/save') ?>
|
|
<?= I18N::translate('Save') ?>
|
|
</button>
|
|
</form>
|
|
|
|
<form method="post" action="<?= e(route('module', ['module' => $module->name(), 'action' => 'SendNowAdmin'])) ?>" class="mt-3">
|
|
<?= csrf_field() ?>
|
|
<button type="submit" class="btn btn-secondary"
|
|
onclick="return confirm('<?= e(I18N::translate('Send the newsletter now for every enabled tree?')) ?>');">
|
|
<?= I18N::translate('Send now') ?>
|
|
</button>
|
|
</form>
|