Améliore les réglages et la documentation

Refs #7 #8 #11 #14 #15 #19
This commit is contained in:
Alexandre NOEL 2026-09-08 00:07:40 +02:00
commit 6bda723f22
14 changed files with 52 additions and 10 deletions

View file

@ -95,3 +95,12 @@ Toutes les modifications importantes du projet sont consignées ici. Le format s
[1.0.0]: https://nnsprod.com/git/oversu/Globinours
[0.1.0]: https://nnsprod.com/git/oversu/Globinours
## [1.0.0-rc.9] — 2026-09-08
### Troisième lot de tickets
- ajout de liens publics facultatifs vers WhatsApp, LinkedIn, X et Snapchat, sans ressource chargée depuis un service tiers (`#7`) ;
- clarification de la conservation de l’historique lors de la désactivation d’une salle (`#11`) ;
- distinction explicite entre les frais d’adoption et le catalogue des coûts vétérinaires (`#14`) ;
- rappel du routeur requis par le serveur PHP local pour rendre la recherche universelle disponible (`#19`) ;
- vérification des correctifs déjà livrés pour le lien du pied de page et l’ajout d’espèces aux références biologiques (`#8`, `#15`).

View file

@ -41,3 +41,7 @@ Fiabilisation du géocodage et des formulaires de configuration, amélioration d
## `1.0.0-rc.8` — Deuxième lot de tickets
Clarification du diagnostic système et de la santé des sauvegardes, validation des identifiants administratifs et encadrement des longueurs de noms.
## `1.0.0-rc.9` — Troisième lot de tickets
Extension des liens sociaux du site public, clarification des salles et des tarifs, et documentation du routage nécessaire à la recherche locale.

View file

@ -94,6 +94,8 @@ php -d upload_max_filesize=250M -d post_max_size=260M \
-S 127.0.0.1:8000 -t public public/router.php
```
Le dernier argument, `public/router.php`, est indispensable : sans lui, les routes telles que la recherche universelle (`/search.json`) renvoient une page introuvable avec le serveur PHP intégré.
Ouvrez ensuite `http://127.0.0.1:8000/setup`. L’assistant vérifie l’environnement, recueille l’identité de l’association et crée le premier compte administrateur.
Les migrations sont appliquées automatiquement. Elles peuvent aussi être exécutées explicitement :

View file

@ -1 +1 @@
1.0.0-rc.8
1.0.0-rc.9

View file

@ -825,7 +825,20 @@ final class SettingsController
exit();
}
$values['public_site_custom_css'] = $customCss;
foreach (['public_site_donation_url', 'public_site_facebook_url', 'public_site_instagram_url', 'public_site_youtube_url', 'public_site_tiktok_url'] as $key) {
foreach (
[
'public_site_donation_url',
'public_site_facebook_url',
'public_site_instagram_url',
'public_site_youtube_url',
'public_site_tiktok_url',
'public_site_whatsapp_url',
'public_site_linkedin_url',
'public_site_x_url',
'public_site_snapchat_url',
]
as $key
) {
$url = trim((string) ($_POST[$key] ?? ''));
$scheme = strtolower((string) parse_url($url, PHP_URL_SCHEME));
if ($url !== '' && (!filter_var($url, FILTER_VALIDATE_URL) || $scheme !== 'https')) {

View file

@ -39,6 +39,10 @@ final class AppSettings
'public_site_instagram_url' => '',
'public_site_youtube_url' => '',
'public_site_tiktok_url' => '',
'public_site_whatsapp_url' => '',
'public_site_linkedin_url' => '',
'public_site_x_url' => '',
'public_site_snapchat_url' => '',
'notification_email_enabled' => '0',
'notification_email_frequency' => 'weekly',
'notification_email_recipient' => '',

View file

@ -31,10 +31,10 @@
<div class="col-lg-6">
<section class="card h-100">
<div class="card-body">
<span class="badge bg-blue-lt mb-2">1.0.0-rc.8</span>
<h3>Deuxième lot de tickets</h3>
<p class="text-muted">Diagnostic système clarifié, identifiants administratifs contrôlés et
longueurs des principaux noms encadrées.</p>
<span class="badge bg-blue-lt mb-2">1.0.0-rc.9</span>
<h3>Troisième lot de tickets</h3>
<p class="text-muted">Site public enrichi, salles et tarifs clarifiés, et lancement local de la
recherche mieux documenté.</p>
</div>
</section>
</div>

View file

@ -14,7 +14,7 @@ $obfuscate = static fn (string$value): string => implode('', array_reverse(mb_st
class="contact-obfuscated"><?= h($obfuscate($settings['association_email'])) ?></span></div>
<?php endif; ?></div>
<div class="chips" style="margin-top:25px">
<?php foreach (['facebook' => 'Facebook','instagram' => 'Instagram','youtube' => 'YouTube','tiktok' => 'TikTok'] as $network => $label):
<?php foreach (['facebook' => 'Facebook','instagram' => 'Instagram','youtube' => 'YouTube','tiktok' => 'TikTok','whatsapp' => 'WhatsApp','linkedin' => 'LinkedIn','x' => 'X','snapchat' => 'Snapchat'] as $network => $label):
$url = trim((string)($settings['public_site_' . $network . '_url'] ?? ''));
if ($url === '') continue; ?>
<a class="button secondary" href="<?= h($url) ?>" rel="noopener noreferrer"><?= h($label) ?></a>

View file

@ -10,7 +10,10 @@
<form class="card h-100" method="post" action="/settings/pricing/adoption">
<div class="card-status-top bg-green"></div>
<div class="card-header">
<h3 class="card-title"><?= h(t('pricing.adoption_fees')) ?></h3>
<div>
<h3 class="card-title"><?= h(t('pricing.adoption_fees')) ?></h3>
<div class="text-muted small"><?= h(t('pricing.adoption_fees_help')) ?></div>
</div>
</div>
<div class="card-body row g-3">
<div class="col-6"><label class="form-label"><?= h(t('pricing.sterilized')) ?></label>

View file

@ -137,7 +137,7 @@
name="public_site_facebook_url" value="<?= h($settings['public_site_facebook_url']) ?>"></div>
<div class="col-md-6"><label class="form-label">Instagram</label><input class="form-control" type="url"
name="public_site_instagram_url" value="<?= h($settings['public_site_instagram_url']) ?>"></div>
<?php foreach (['youtube' => 'YouTube','tiktok' => 'TikTok'] as $network => $label): ?>
<?php foreach (['youtube' => 'YouTube','tiktok' => 'TikTok','whatsapp' => 'WhatsApp','linkedin' => 'LinkedIn','x' => 'X','snapchat' => 'Snapchat'] as $network => $label): ?>
<div class="col-md-6"><label class="form-label"><?= h($label) ?></label><input class="form-control"
type="url" name="public_site_<?= h($network) ?>_url"
value="<?= h($settings['public_site_' . $network . '_url']) ?>" placeholder="https://..."></div>

View file

@ -2,7 +2,7 @@
<?php if ($saved): ?><div class="alert alert-success"><?= h(t('rooms.saved')) ?></div><?php endif; ?>
<?php if ($error): ?><div class="alert alert-danger"><?= h($error) ?></div><?php endif; ?>
<form method="post" action="/settings/rooms/save"><input type="hidden" name="csrf" value="<?= h(Auth::csrf()) ?>">
<div class="alert alert-info"><?= h(t('rooms.help')) ?></div>
<div class="alert alert-info"><?= h(t('rooms.inactive_help')) ?></div>
<div class="row row-cards">
<?php foreach ($rooms as $room):$boxNames = implode("\n", array_column(array_filter($room['boxes'], static fn ($box) => (int)$box['active'] === 1), 'name')); ?>
<div class="col-lg-6">

View file

@ -0,0 +1,5 @@
INSERT OR IGNORE INTO app_settings(setting_key, setting_value) VALUES
('public_site_whatsapp_url', ''),
('public_site_linkedin_url', ''),
('public_site_x_url', ''),
('public_site_snapchat_url', '');

View file

@ -123,4 +123,5 @@ return [
'public_site.image_library'=>'Image library','public_site.image_file'=>'Image to add','public_site.image_upload'=>'Upload image','public_site.image_help'=>'Upload an image, place the cursor in a text field, then choose “Insert”. Accepted formats: JPEG, PNG and WebP.','public_site.image_none'=>'No image uploaded.','public_site.image_insert'=>'Insert','public_site.image_invalid'=>'Choose a valid image.',
'rooms.duplicate'=>'A room with this name or code already exists.','settings.species_duplicate'=>'A species with this name or code already exists.',
'settings.invalid_rna'=>'The RNA number must start with W followed by 9 digits.','settings.invalid_siret'=>'The SIRET number must contain 14 digits and be valid.','rooms.name_too_long'=>'A room name cannot exceed 100 characters.','rooms.box_name_too_long'=>'A box name cannot exceed 100 characters.','animal.name_too_long'=>'An animal name cannot exceed 150 characters.',
'pricing.adoption_fees_help'=>'Indicative amounts shared by all animals, according to their sterilisation status.','rooms.inactive_help'=>'An unchecked room becomes inactive, while its previous assignments remain in the history. Its internal code never changes.',
];

View file

@ -123,4 +123,5 @@ return [
'public_site.image_library'=>'Bibliothèque d’images','public_site.image_file'=>'Image à ajouter','public_site.image_upload'=>'Ajouter l’image','public_site.image_help'=>'Ajoutez une image, placez le curseur dans un texte puis choisissez « Insérer ». Formats acceptés : JPEG, PNG et WebP.','public_site.image_none'=>'Aucune image ajoutée.','public_site.image_insert'=>'Insérer','public_site.image_invalid'=>'Choisissez une image valide.',
'rooms.duplicate'=>'Une salle portant ce nom ou ce code existe déjà.','settings.species_duplicate'=>'Une espèce portant ce nom ou ce code existe déjà.',
'settings.invalid_rna'=>'Le numéro RNA doit commencer par W et être suivi de 9 chiffres.','settings.invalid_siret'=>'Le numéro SIRET doit contenir 14 chiffres et être valide.','rooms.name_too_long'=>'Le nom d’une salle ne peut pas dépasser 100 caractères.','rooms.box_name_too_long'=>'Le nom d’un box ne peut pas dépasser 100 caractères.','animal.name_too_long'=>'Le nom d’un animal ne peut pas dépasser 150 caractères.',
'pricing.adoption_fees_help'=>'Montants indicatifs communs à tous les animaux, selon leur état de stérilisation.','rooms.inactive_help'=>'Une salle décochée devient inactive, mais ses anciennes affectations restent dans l’historique. Son code interne ne change jamais.',
];