Réparer les scripts intégrés aux vues

This commit is contained in:
Alexandre NOEL 2026-09-03 23:08:03 +02:00
commit 64ce1285aa
12 changed files with 112 additions and 97 deletions

View file

@ -138,9 +138,9 @@ $today = date('Y-m-d');
select.required = !opening;
name.required = opening;
button.setAttribute('aria-expanded', opening ? 'true' : 'false');
button.textContent = opening ? < ? = json_encode(t('common.choose_from_list'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > : '+ ' + < ? = json_encode(t(
'common.add'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ;
button.textContent = opening ? <?= json_encode(t('common.choose_from_list'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> : '+ ' + <?= json_encode(t(
'common.add'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
if (opening) name.focus();
});
});
@ -746,10 +746,10 @@ $today = date('Y-m-d');
const kind = sterilizedCheckbox.form.querySelector('select[name="kind"]');
const reason = document.getElementById('medicalReason');
if (kind) kind.value = 'acte';
if (reason && reason.value.trim() === '') reason.value = < ? = json_encode(t(
'animal.sterilization_label'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ;
if (reason && reason.value.trim() === '') reason.value = <?= json_encode(t(
'animal.sterilization_label'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
});
const animalId = < ? = (int) $animal['id'] ? > ;
const animalId = <?= (int) $animal['id'] ?> ;
const legacyKey = 'animal_show_active_tab_' + animalId;
// L'ancien comportement mémorisait le dernier onglet par animal. Une
// ouverture normale doit désormais toujours revenir sur Identité.
@ -822,8 +822,8 @@ $today = date('Y-m-d');
select = document.getElementById('labTemplate');
if (!body) return;
const presets = {};
const references = < ? = json_encode($labReferenceSets ?? [], JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ? > ;
const references = <?= json_encode($labReferenceSets ?? [], JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ?> ;
Object.entries(references).forEach(([key, set]) => presets['ref:' + key] = (set.parameters || []).map(p => [
p.code + ' — ' + p.name, p.unit, p.min, p.max
]));
@ -882,16 +882,16 @@ $today = date('Y-m-d');
pointRadius: 4,
tension: .2
}, {
label: < ? = json_encode(t('medical_document.reference_min'),
JSON_UNESCAPED_UNICODE) ? > ,
label: <?= json_encode(t('medical_document.reference_min'),
JSON_UNESCAPED_UNICODE) ?> ,
data: points.map(p => p.min),
borderColor: '#74c0fc',
borderDash: [5, 5],
pointRadius: 0,
spanGaps: true
}, {
label: < ? = json_encode(t('medical_document.reference_max'),
JSON_UNESCAPED_UNICODE) ? > ,
label: <?= json_encode(t('medical_document.reference_max'),
JSON_UNESCAPED_UNICODE) ?> ,
data: points.map(p => p.max),
borderColor: '#ffa8a8',
borderDash: [5, 5],
@ -921,7 +921,7 @@ $today = date('Y-m-d');
x: {
title: {
display: true,
text: < ? = json_encode(t('chart.date'), JSON_UNESCAPED_UNICODE) ? >
text: <?= json_encode(t('chart.date'), JSON_UNESCAPED_UNICODE) ?>
}
}
}
@ -936,7 +936,7 @@ $today = date('Y-m-d');
const el = document.getElementById('weightChart');
if (!el) return;
const rows = < ? = json_encode($weights ?? [], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ? > ;
const rows = <?= json_encode($weights ?? [], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?> ;
// labels = dates, data = poids
const labels = rows.map(r => (r.measured_at || '').slice(0, 10)); // YYYY-MM-DD
@ -948,7 +948,7 @@ $today = date('Y-m-d');
data: {
labels,
datasets: [{
label: < ? = json_encode(t('chart.weight'), JSON_UNESCAPED_UNICODE) ? > ,
label: <?= json_encode(t('chart.weight'), JSON_UNESCAPED_UNICODE) ?> ,
data,
tension: 0.25,
pointRadius: 2
@ -972,7 +972,7 @@ $today = date('Y-m-d');
x: {
title: {
display: true,
text: < ? = json_encode(t('chart.date'), JSON_UNESCAPED_UNICODE) ? >
text: <?= json_encode(t('chart.date'), JSON_UNESCAPED_UNICODE) ?>
}
}
}
@ -985,14 +985,14 @@ $today = date('Y-m-d');
(function() {
const btn = document.getElementById('btn-icad-refresh');
const body = document.getElementById('icad-card-body');
const tr = < ? = json_encode(['error' => t('animal.icad_error'), 'empty' => t('animal.no_icad'), 'date' =>
const tr = <?= json_encode(['error' => t('animal.icad_error'), 'empty' => t('animal.no_icad'), 'date' =>
t('common.date'), 'recorded' => t('animal.recorded'), 'noEvent' => t('animal.no_event'),
'holder' => t('animal.holder_internal'), 'name' => t('common.name'), 'phone' => t(
'common.phone'), 'email' => t('common.email'), 'icadName' => t('animal.icad_name'),
'microchip' => t('animal.microchip'), 'sex' => t('animal.sex'), 'birth' => t('animal.birth'),
'appearance' => t('animal.appearance'), 'history' => t('animal.icad_history'), 'fetching' => t(
'animal.icad_fetching'), 'fetchError' => t('animal.icad_fetch_error')
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ;
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
if (!btn || !body) return;
function esc(s) {
@ -1082,7 +1082,7 @@ ${ownerHtml}
body: new URLSearchParams({
id,
force: '1',
csrf: < ? = json_encode(Auth::csrf()) ? >
csrf: <?= json_encode(Auth::csrf()) ?>
})
});
const j = await r.json();

View file

@ -44,14 +44,14 @@
document.addEventListener('DOMContentLoaded', () => {
const s = document.getElementById('expenseTariff'),
h = document.getElementById('expenseHint'),
template = < ? = json_encode(t('expense.unit_estimate'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ? > ,
empty = < ? = json_encode(t('expense.price_after_discount'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ? > ;
template = <?= json_encode(t('expense.unit_estimate'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ?> ,
empty = <?= json_encode(t('expense.price_after_discount'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ?> ;
s?.addEventListener('change', () => {
const o = s.selectedOptions[0],
price = (Number(o?.dataset.price || 0) / 100).toLocaleString( < ? = json_encode(I18n::
locale() === 'fr' ? 'fr-FR' : 'en-GB') ? > , {
price = (Number(o?.dataset.price || 0) / 100).toLocaleString( <?= json_encode(I18n::
locale() === 'fr' ? 'fr-FR' : 'en-GB') ?> , {
minimumFractionDigits: 2
});
h.textContent = o?.value ? template.replace(':price', price).replace(':discount', o.dataset

View file

@ -327,7 +327,7 @@ foreach ($volunteers as $v): ?><option value="<?= (int)$v['id'] ?>"
const params = new URLSearchParams(new FormData(form));
['view', 'date', 'month'].forEach(key => params.delete(key));
document.querySelectorAll('a[href^="/agenda?"] , a[href^="/agenda/export.ics?"]').forEach(link => {
if (link.title === < ? = json_encode(t('common.reset')) ? > ) return;
if (link.title === <?= json_encode(t('common.reset')) ?> ) return;
const url = new URL(link.href, location.origin);
params.forEach((value, key) => url.searchParams.set(key, value));
link.href = url.pathname + '?' + url.searchParams.toString();
@ -335,20 +335,20 @@ foreach ($volunteers as $v): ?><option value="<?= (int)$v['id'] ?>"
}
const modal = document.getElementById('agendaModal');
const addButton = document.getElementById('agendaAddButton');
if (modal && addButton && < ? = (!$edit && PermissionService::can('agenda', 'edit')) ? 'true' :
'false' ? > ) {
const month = < ? = json_encode($cursor - > format('Y-m')) ? > ;
const weekDates = < ? = json_encode(array_map(static fn($i) => $weekStart - > modify('+'.$i.
' days') - > format('Y-m-d'), range(0, 6))) ? > ;
if (modal && addButton && <?= (!$edit && PermissionService::can('agenda', 'edit')) ? 'true' :
'false' ?> ) {
const month = <?= json_encode($cursor->format('Y-m')) ?> ;
const weekDates = <?= json_encode(array_map(static fn($i) => $weekStart->modify('+'.$i.
' days')->format('Y-m-d'), range(0, 6))) ?> ;
document.querySelectorAll('.agenda-calendar .agenda-day:not(.muted)').forEach((cell, index) => {
const number = cell.querySelector('.agenda-number')?.textContent.trim();
const date = < ? = $viewMode === 'week' ? 'weekDates[index]' :
'month+\'-\'+String(parseInt(number,10)).padStart(2,\'0\')' ? > ;
const date = <?= $viewMode === 'week' ? 'weekDates[index]' :
'month+\'-\'+String(parseInt(number,10)).padStart(2,\'0\')' ?> ;
if (!date) return;
cell.classList.add('agenda-day-clickable');
cell.tabIndex = 0;
cell.setAttribute('role', 'button');
cell.setAttribute('aria-label', < ? = json_encode(t('agenda.add_on_date')) ? > +' ' +
cell.setAttribute('aria-label', <?= json_encode(t('agenda.add_on_date')) ?> +' ' +
date.split('-').reverse().join('/'));
const open = event => {
if (event.target.closest('.agenda-event,button,a,input,select,textarea,label'))

View file

@ -846,11 +846,11 @@ $mosaicQs['view'] = 'mosaic';
</div>
<script>
const animalListTranslations = < ? = json_encode(['medicalPreview' => t('animals.medical_preview'),
const animalListTranslations = <?= json_encode(['medicalPreview' => t('animals.medical_preview'),
'neverProvided' => t('animals.never_provided'), 'lastUpdate' => t('animals.last_update', ['date' =>
'__DATE__'
])
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ;
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
(() => {
const zoom = document.getElementById('animalPhotoZoom');
const image = zoom?.querySelector('img');

View file

@ -185,19 +185,19 @@
summary = document.getElementById('formValidationError');
function frenchMessage(field) {
if (field.validity.valueMissing) return < ? = json_encode(t('auth.required'), JSON_UNESCAPED_UNICODE) ? > ;
if (field.validity.tooShort) return < ? = json_encode(t('auth.password_min', ['count' => '__COUNT__']),
JSON_UNESCAPED_UNICODE) ? > .replace('__COUNT__', field.minLength);
if (field.validity.patternMismatch) return < ? = json_encode(t('auth.invalid_format'),
JSON_UNESCAPED_UNICODE) ? > ;
return < ? = json_encode(t('auth.check_field'), JSON_UNESCAPED_UNICODE) ? > ;
if (field.validity.valueMissing) return <?= json_encode(t('auth.required'), JSON_UNESCAPED_UNICODE) ?> ;
if (field.validity.tooShort) return <?= json_encode(t('auth.password_min', ['count' => '__COUNT__']),
JSON_UNESCAPED_UNICODE) ?> .replace('__COUNT__', field.minLength);
if (field.validity.patternMismatch) return <?= json_encode(t('auth.invalid_format'),
JSON_UNESCAPED_UNICODE) ?> ;
return <?= json_encode(t('auth.check_field'), JSON_UNESCAPED_UNICODE) ?> ;
}
form.addEventListener('submit', event => {
form.querySelectorAll('.is-invalid').forEach(el => el.classList.remove('is-invalid'));
const password = form.elements.password,
confirmation = form.elements.password_confirm;
if (confirmation) confirmation.setCustomValidity(password.value !== confirmation.value ? < ? =
json_encode(t('auth.password_mismatch'), JSON_UNESCAPED_UNICODE) ? > : '');
if (confirmation) confirmation.setCustomValidity(password.value !== confirmation.value ? <?=
json_encode(t('auth.password_mismatch'), JSON_UNESCAPED_UNICODE) ?> : '');
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();

View file

@ -81,15 +81,15 @@ if ($pageDescription === '') {
<script>
(function() {
const rescue = {
lat: < ? = $hasRescue ? (float) $rescueLat : 'null' ? > ,
lng: < ? = $hasRescue ? (float) $rescueLng : 'null' ? > ,
addr: < ? = json_encode($rescueAddr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? >
lat: <?= $hasRescue ? (float) $rescueLat : 'null' ?> ,
lng: <?= $hasRescue ? (float) $rescueLng : 'null' ?> ,
addr: <?= json_encode($rescueAddr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>
};
const cur = {
lat: < ? = $hasCurrent ? (float) $currentLat : 'null' ? > ,
lng: < ? = $hasCurrent ? (float) $currentLng : 'null' ? > ,
addr: < ? = json_encode($currentAddr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? >
lat: <?= $hasCurrent ? (float) $currentLat : 'null' ?> ,
lng: <?= $hasCurrent ? (float) $currentLng : 'null' ?> ,
addr: <?= json_encode($currentAddr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>
};
const el = document.getElementById('mapJourney');
@ -102,16 +102,16 @@ if ($pageDescription === '') {
className: '',
iconSize: [18, 18],
iconAnchor: [9, 9],
html: '<div class="twix-pin rescue" title="' + < ? = json_encode(t('map.rescue'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > +'"></div>'
html: '<div class="twix-pin rescue" title="' + <?= json_encode(t('map.rescue'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> +'"></div>'
});
const iconCurrent = L.divIcon({
className: '',
iconSize: [18, 18],
iconAnchor: [9, 9],
html: '<div class="twix-pin current" title="' + < ? = json_encode(t('map.current'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > +'"></div>'
html: '<div class="twix-pin current" title="' + <?= json_encode(t('map.current'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> +'"></div>'
});
const map = L.map('mapJourney', {
@ -144,8 +144,8 @@ if ($pageDescription === '') {
icon: iconRescue
})
.addTo(map)
.bindPopup(safePopup( < ? = json_encode(t('map.rescue'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ? > , rescue.addr), {
.bindPopup(safePopup( <?= json_encode(t('map.rescue'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ?> , rescue.addr), {
autoPan: false, // <-- stop le déplacement
closeButton: false
});
@ -158,8 +158,8 @@ if ($pageDescription === '') {
icon: iconCurrent
})
.addTo(map)
.bindPopup(safePopup( < ? = json_encode(t('map.current'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ? > , cur.addr), {
.bindPopup(safePopup( <?= json_encode(t('map.current'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ?> , cur.addr), {
autoPan: false, // <-- stop le déplacement
closeButton: false
});
@ -169,8 +169,8 @@ if ($pageDescription === '') {
map.setView(fallback, 8);
L.popup({
autoPan: false
}).setLatLng(fallback).setContent( < ? = json_encode(t('map.missing_coordinates'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ).openOn(map);
}).setLatLng(fallback).setContent( <?= json_encode(t('map.missing_coordinates'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ).openOn(map);
} else if (pts.length === 1) {
map.setView(pts[0], 14);
} else {
@ -246,8 +246,8 @@ if ($pageDescription === '') {
settingsMenu.classList.add('settings-menu-wide');
}
}
const globinoursPermissions = < ? = json_encode(PermissionService::currentPermissions(),
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ? > ;
const globinoursPermissions = <?= json_encode(PermissionService::currentPermissions(),
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?> ;
const permissionModuleForPath = path => {
if (path === '/' || path.startsWith('/dashboard')) return 'dashboard';
if (path.startsWith('/animal/documents')) return 'medical';
@ -323,11 +323,11 @@ if ($pageDescription === '') {
form.appendChild(input);
});
const validationMessages = {
required: < ? = json_encode(t('validation.required'), JSON_UNESCAPED_UNICODE) ? > ,
passwordMin: count => < ? = json_encode(t('validation.password_min'), JSON_UNESCAPED_UNICODE) ? >
required: <?= json_encode(t('validation.required'), JSON_UNESCAPED_UNICODE) ?> ,
passwordMin: count => <?= json_encode(t('validation.password_min'), JSON_UNESCAPED_UNICODE) ?>
.replace(':count', count),
invalidFormat: < ? = json_encode(t('validation.invalid_format'), JSON_UNESCAPED_UNICODE) ? > ,
checkField: < ? = json_encode(t('validation.check_field'), JSON_UNESCAPED_UNICODE) ? >
invalidFormat: <?= json_encode(t('validation.invalid_format'), JSON_UNESCAPED_UNICODE) ?> ,
checkField: <?= json_encode(t('validation.check_field'), JSON_UNESCAPED_UNICODE) ?>
};
document.querySelectorAll('form').forEach(form => {
if (!form.querySelector('input[type="password"]')) return;
@ -358,7 +358,7 @@ if ($pageDescription === '') {
});
document.querySelectorAll('input[type="date"]').forEach(input => {
flatpickr(input, {
locale: < ? = json_encode(I18n::locale() === 'fr' ? 'fr' : 'default') ? > ,
locale: <?= json_encode(I18n::locale() === 'fr' ? 'fr' : 'default') ?> ,
altInput: true,
altFormat: 'd/m/Y',
dateFormat: 'Y-m-d',

View file

@ -56,8 +56,8 @@ if (!empty($litter['birth_date'])) {
</form>
<script>
document.getElementById('litterAnimalSearch')?.addEventListener('input', event => {
const query = event.target.value.trim().toLocaleLowerCase( < ? = json_encode(I18n::locale() === 'fr' ?
'fr' : 'en') ? > );
const query = event.target.value.trim().toLocaleLowerCase( <?= json_encode(I18n::locale() === 'fr' ?
'fr' : 'en') ?> );
document.querySelectorAll('.litter-animal-choice').forEach(choice => {
choice.classList.toggle('d-none', query !== '' && !choice.dataset.search.includes(query));
});

View file

@ -170,8 +170,8 @@ $prefillCount = max(0, min(20, (int)($_GET['count'] ?? 4)));
if (target < list.children.length) {
const removedRows = [...list.children].slice(target);
if (confirmRemoval && removedRows.some(hasValues) &&
!window.confirm( < ? = json_encode(t('litter.reduce_confirm'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ? > )) {
!window.confirm( <?= json_encode(t('litter.reduce_confirm'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ?> )) {
countInput.value = list.children.length;
return;
}
@ -190,8 +190,8 @@ $prefillCount = max(0, min(20, (int)($_GET['count'] ?? 4)));
const mother = document.getElementById('motherId');
const father = document.getElementById('fatherId');
const syncExistingChoices = () => {
const query = existingSearch?.value.trim().toLocaleLowerCase( < ? = json_encode(I18n::locale() ===
'fr' ? 'fr' : 'en') ? > ) || '';
const query = existingSearch?.value.trim().toLocaleLowerCase( <?= json_encode(I18n::locale() ===
'fr' ? 'fr' : 'en') ?> ) || '';
document.querySelectorAll('.existing-kitten-choice').forEach(choice => {
const isParent = choice.dataset.animalId === mother?.value || choice.dataset
.animalId === father?.value;

View file

@ -32,17 +32,17 @@ $obfuscate = static fn (string$value): string => implode('', array_reverse(mb_st
(() => {
const map = L.map('association-map', {
scrollWheelZoom: false
}).setView([ < ? = json_encode($lat) ? > , < ? = json_encode($lng) ? > ], 15);
}).setView([ <?= json_encode($lat) ?> , <?= json_encode($lng) ?> ], 15);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; OpenStreetMap'
}).addTo(map);
const popup = document.createElement('div');
const name = document.createElement('strong');
name.textContent = < ? = json_encode($association, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ;
popup.append(name, document.createElement('br'), document.createTextNode( < ? = json_encode($fullAddress,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ));
L.marker([ < ? = json_encode($lat) ? > , < ? = json_encode($lng) ? > ]).addTo(map).bindPopup(popup)
name.textContent = <?= json_encode($association, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
popup.append(name, document.createElement('br'), document.createTextNode( <?= json_encode($fullAddress,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ));
L.marker([ <?= json_encode($lat) ?> , <?= json_encode($lng) ?> ]).addTo(map).bindPopup(popup)
.openPopup();
})();

View file

@ -79,13 +79,13 @@
document.querySelectorAll('#asm3Form<?= (int)$job['
id '] ?> input[name="mode"]').forEach(el => el.addEventListener('change', () => {
const replace = el.form.mode.value === 'replace';
el.form.confirmation.placeholder = replace ? < ? = json_encode(t('asm3.type_replace'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > : < ? = json_encode(t(
'asm3.type_import'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ;
el.form.querySelector('.confirmation-hint strong').textContent = replace ? < ? =
el.form.confirmation.placeholder = replace ? <?= json_encode(t('asm3.type_replace'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> : <?= json_encode(t(
'asm3.type_import'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
el.form.querySelector('.confirmation-hint strong').textContent = replace ? <?=
json_encode(t('asm3.confirm_replace_phrase'), JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ? > : < ? = json_encode(t('asm3.confirm_import_phrase'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ? > ;
JSON_UNESCAPED_SLASHES) ?> : <?= json_encode(t('asm3.confirm_import_phrase'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
}));
</script><?php elseif ($result):?><details>

View file

@ -334,29 +334,28 @@ if (empty($costs['by_clinic'])):?><span class="text-muted"><?= h(t('statistics.n
new Chart(canvas, {
type: 'line',
data: {
labels: < ? = json_encode(array_map('strval', array_keys($timeline)),
JSON_UNESCAPED_UNICODE) ? > ,
labels: <?= json_encode(array_map('strval', array_keys($timeline)),
JSON_UNESCAPED_UNICODE) ?> ,
datasets: [{
label: < ? = json_encode(t('statistics.handled'), JSON_UNESCAPED_UNICODE) ?
> ,
data: < ? = json_encode(array_values(array_map(static fn($s) => (int) $s[
'handled'], $timeline))) ? > ,
label: <?= json_encode(t('statistics.handled'), JSON_UNESCAPED_UNICODE) ?> ,
data: <?= json_encode(array_values(array_map(static fn($s) => (int) $s[
'handled'], $timeline))) ?> ,
borderColor: '#0ca678',
backgroundColor: 'rgba(12,166,120,.12)',
tension: .3
}, {
label: < ? = json_encode(t('statistics.adoptions'),
JSON_UNESCAPED_UNICODE) ? > ,
data: < ? = json_encode(array_values(array_map(static fn($s) => (int) $s[
'adoptions'], $timeline))) ? > ,
label: <?= json_encode(t('statistics.adoptions'),
JSON_UNESCAPED_UNICODE) ?> ,
data: <?= json_encode(array_values(array_map(static fn($s) => (int) $s[
'adoptions'], $timeline))) ?> ,
borderColor: '#206bc4',
backgroundColor: 'rgba(32,107,196,.12)',
tension: .3
}, {
label: < ? = json_encode(t('statistics.deaths'), JSON_UNESCAPED_UNICODE) ? >
label: <?= json_encode(t('statistics.deaths'), JSON_UNESCAPED_UNICODE) ?>
,
data: < ? = json_encode(array_values(array_map(static fn($s) => (int) $s[
'deaths'], $timeline))) ? > ,
data: <?= json_encode(array_values(array_map(static fn($s) => (int) $s[
'deaths'], $timeline))) ?> ,
borderColor: '#343a40',
backgroundColor: 'rgba(52,58,64,.10)',
tension: .3