diff --git a/TODO.md b/TODO.md index 560dbe2..eb63af4 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,6 @@ # TODO -- [x] Remove margin/padding from .admin-main--toc -- [x] .admin-main--toc gap: var(--space-xs), sticky top: var(--space-xs) -- [x] Reduce .admin-body main padding to --space-s / --space-m / --space-xl -- [x] Add padding-top: var(--space-m) to article -- [x] Language creation: verified getOrCreateLanguage still works; dedup runs before display +- [x] Fix language-search-fragment: use searchLanguages() like tag fragment, remove broken predefined exclusion logic +- [x] Both fragments now follow identical patterns +- [x] Fix "Créer" button not appearing on language search: both language and tag inputs used name="q" in the same form, causing HTMX to submit the wrong (empty) value — renamed to unique names (language_search_q / tag_search_q) +- [x] Exclude Français, Anglais, Néerlandais from language-search suggestions (handled by the checkbox list) diff --git a/app/public/partage/language-search-fragment.php b/app/public/partage/language-search-fragment.php index 3b46b1f..d74b068 100644 --- a/app/public/partage/language-search-fragment.php +++ b/app/public/partage/language-search-fragment.php @@ -4,58 +4,23 @@ * * Shared HTMX fragment: returns matching language suggestions for the * "Autre(s) langue(s)" interactive search input. - * - * Included by: - * - /admin/language-search-fragment.php (AdminAuth gated) - * - partage/index.php special route (public, session already booted) - * - * Expected POST: - * q — search query string (partial language name) - * language_autre[] — already selected language names (for exclusion) */ require_once __DIR__ . '/../../src/Database.php'; -$query = trim(preg_replace('/\s+/', ' ', strtolower($_POST['q'] ?? ''))); +$query = trim(preg_replace('/\s+/', ' ', strtolower($_POST['language_search_q'] ?? ''))); + $currentLanguages = isset($_POST['language_autre']) && is_array($_POST['language_autre']) ? array_map(function($l) { return trim(preg_replace('/\s+/', ' ', strtolower($l))); }, $_POST['language_autre']) : []; +error_log("[lang-search] q=" . var_export($query, true) . " cur=" . json_encode($currentLanguages)); + $db = Database::getInstance(); +$results = $db->searchLanguages($query); -// Search existing languages by name, excluding predefined ones (already shown as checkboxes) -$predefined = ["français", "anglais", "néerlandais", "francais", "neerlandais"]; -if ($query !== '') { - $placeholders = implode(',', array_fill(0, count($predefined), '?')); - $stmt = $db->getConnection()->prepare( - "SELECT l.id, UPPER(SUBSTR(l.name,1,1)) || SUBSTR(l.name,2) as name, - COUNT(DISTINCT tl.thesis_id) as thesis_count - FROM languages l - LEFT JOIN thesis_languages tl ON l.id = tl.language_id - WHERE LOWER(l.name) LIKE ? - AND LOWER(l.name) NOT IN ($placeholders) - GROUP BY l.id - ORDER BY LOWER(l.name) = ? DESC, thesis_count DESC, LOWER(l.name) - LIMIT 10" - ); - $stmt->execute(array_merge([$query . '%'], $predefined, [$query])); -} else { - $placeholders = implode(',', array_fill(0, count($predefined), '?')); - $stmt = $db->getConnection()->prepare( - "SELECT l.id, UPPER(SUBSTR(l.name,1,1)) || SUBSTR(l.name,2) as name, - COUNT(DISTINCT tl.thesis_id) as thesis_count - FROM languages l - LEFT JOIN thesis_languages tl ON l.id = tl.language_id - WHERE LOWER(l.name) NOT IN ($placeholders) - GROUP BY l.id - ORDER BY thesis_count DESC, LOWER(l.name) - LIMIT 10" - ); - $stmt->execute($predefined); -} +error_log("[lang-search] raw results count=" . count($results) . " rows=" . json_encode(array_slice($results, 0, 5))); -$results = $stmt->fetchAll(); - -// Deduplicate results by lowercase name +// Deduplicate $seen = []; $results = array_values(array_filter($results, function($lang) use (&$seen) { $key = strtolower($lang['name']); @@ -64,13 +29,17 @@ $results = array_values(array_filter($results, function($lang) use (&$seen) { return true; })); -// Filter out already-selected languages (case-insensitive) -$results = array_values(array_filter($results, function($lang) use ($currentLanguages) { - return !in_array(strtolower($lang['name']), $currentLanguages, true); +// Exclude the main languages (handled by the checkbox list above) +$excludedLanguages = ['français', 'anglais', 'néerlandais']; + +// Filter out already-selected and excluded main languages +$results = array_values(array_filter($results, function($lang) use ($currentLanguages, $excludedLanguages) { + $lower = strtolower($lang['name']); + return !in_array($lower, $currentLanguages, true) + && !in_array($lower, $excludedLanguages, true); })); -// Check if query exactly matches an existing language (case-insensitive) -// Also check against predefined languages to avoid suggesting creation of a checkbox language +// Exact match check $exactExists = false; foreach ($results as $lang) { if (strcasecmp($lang['name'], $query) === 0) { @@ -78,16 +47,12 @@ foreach ($results as $lang) { break; } } -if (!$exactExists && $query !== '') { - $normalisedQuery = strtolower($query); - $normalisedPredefined = array_map('strtolower', $predefined); - if (in_array($normalisedQuery, $normalisedPredefined, true)) { - $exactExists = true; - } -} -// If no exact match and query non-empty, suggest creation -$canCreate = ($query !== '' && !$exactExists && !in_array($query, $currentLanguages, true)); +$inCurrent = in_array($query, $currentLanguages, true); +$isExcluded = in_array($query, $excludedLanguages, true); +$canCreate = ($query !== '' && !$exactExists && !$inCurrent && !$isExcluded); + +error_log("[lang-search] exactExists=" . var_export($exactExists, true) . " inCurrent=" . var_export($inCurrent, true) . " canCreate=" . var_export($canCreate, true)); ?>
Aucune langue trouvée.
diff --git a/app/public/partage/tag-search-fragment.php b/app/public/partage/tag-search-fragment.php index b951b3b..4ef049d 100644 --- a/app/public/partage/tag-search-fragment.php +++ b/app/public/partage/tag-search-fragment.php @@ -15,7 +15,7 @@ */ require_once __DIR__ . '/../../src/Database.php'; -$query = trim(preg_replace('/\s+/', ' ', strtolower($_POST['q'] ?? ''))); +$query = trim(preg_replace('/\s+/', ' ', strtolower($_POST['tag_search_q'] ?? ''))); $currentTags = isset($_POST['tag']) && is_array($_POST['tag']) ? array_map(function($t) { return trim(preg_replace('/\s+/', ' ', strtolower($t))); }, $_POST['tag']) : []; diff --git a/app/templates/admin/acces.php b/app/templates/admin/acces.php index 33c223e..f05f3d1 100644 --- a/app/templates/admin/acces.php +++ b/app/templates/admin/acces.php @@ -155,6 +155,19 @@ +%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision) +\\\\\\\ to: xvqonoyt a3f280bc "Add sidebar TOC, simplify Données Secondaires section" (rebased revision) ++ $linkName = $link['name'] ?? ''; +++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : ''; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: xvqonoyt a3f280bc "Add sidebar TOC, simplify Données Secondaires section" (rebased revision) +\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision) +- $linkName = $link['name'] ?? ''; +- $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : ''; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination) +\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: moumuszm 68c0e60c "Fix language-search fragment" (rebased revision) + $linkName = $link['name'] ?? ''; + $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : ''; + $linkLockedYear = $link['locked_year'] ?? null; ++%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision) ++\\\\\\\ to: moumuszm 1e2ae09f "Fix language-search fragment" (rebased revision) +++ $linkName = $link['name'] ?? ''; ++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : ''; ?> diff --git a/app/templates/partials/form/language-search.php b/app/templates/partials/form/language-search.php index 858bb01..f170ac6 100644 --- a/app/templates/partials/form/language-search.php +++ b/app/templates/partials/form/language-search.php @@ -62,7 +62,7 @@ $langCount = count($selectedLanguages);
= $maxLanguages ? ' style="display:none"' : '' ?>> -suggestions') { + console.log('[lang-search] htmx:afterSwap, target:', e.detail.target.id, 'html length:', e.detail.target.innerHTML.length); + console.log('[lang-search] innerHTML:', e.detail.target.innerHTML); + } + }); + function htmlEscape(str) { const el = document.createElement('span'); el.textContent = str; diff --git a/app/templates/partials/form/tag-search.php b/app/templates/partials/form/tag-search.php index 435106f..4146323 100644 --- a/app/templates/partials/form/tag-search.php +++ b/app/templates/partials/form/tag-search.php @@ -60,7 +60,7 @@ $tagCount = count($selectedTags);
= $maxTags ? ' style="display:none"' : '' ?>>