Actualiser assets/js/app.js
CI / PHP Syntax Check (push) Has been cancelled
CI / JavaScript Lint (push) Has been cancelled
CI / Docker Build Test (push) Has been cancelled
CI / Validate Translation Files (push) Has been cancelled
CI / Auto-merge develop → main (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / PHP Syntax Check (push) Has been cancelled
CI / JavaScript Lint (push) Has been cancelled
CI / Docker Build Test (push) Has been cancelled
CI / Validate Translation Files (push) Has been cancelled
CI / Auto-merge develop → main (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
This commit is contained in:
+28
-4
@@ -1426,9 +1426,10 @@ function renderRecipeTagsConfigList(tags) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
container.innerHTML = tags.map(tag => `
|
container.innerHTML = tags.map(tag => `
|
||||||
<div class="loc-row" style="display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--border,#e2e8f0)">
|
<div class="loc-row" style="display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--border,#e2e8f0)">
|
||||||
<input type="text" class="form-input" style="max-width:60px;text-align:center" value="${escapeHtml(tag.icon)}" id="rtag-icon-${tag.key}" maxlength="4">
|
<input type="text" class="form-input" style="max-width:60px;text-align:center" value="${escapeHtml(tag.icon)}" id="rtag-icon-${tag.key}" maxlength="4">
|
||||||
<input type="text" class="form-input" style="flex:1" value="${escapeHtml(tag.label)}" id="rtag-label-${tag.key}">
|
<input type="text" class="form-input" style="flex:1;min-width:120px" value="${escapeHtml(tag.label)}" id="rtag-label-${tag.key}">
|
||||||
|
<input type="text" class="form-input" style="flex:2;min-width:160px" value="${escapeHtml(tag.keywords || '')}" id="rtag-keywords-${tag.key}" placeholder="Mots-clés (ex: citron, lime)">
|
||||||
<button class="btn btn-small btn-primary" onclick="updateRecipeTagConfig('${tag.key}')" title="Enregistrer">💾</button>
|
<button class="btn btn-small btn-primary" onclick="updateRecipeTagConfig('${tag.key}')" title="Enregistrer">💾</button>
|
||||||
<button class="btn btn-small btn-secondary" onclick="removeRecipeTagConfig('${tag.key}')" title="Supprimer">🗑️</button>
|
<button class="btn btn-small btn-secondary" onclick="removeRecipeTagConfig('${tag.key}')" title="Supprimer">🗑️</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -1438,8 +1439,10 @@ function renderRecipeTagsConfigList(tags) {
|
|||||||
async function addRecipeTagConfig() {
|
async function addRecipeTagConfig() {
|
||||||
const iconInput = document.getElementById('new-recipe-tag-icon');
|
const iconInput = document.getElementById('new-recipe-tag-icon');
|
||||||
const labelInput = document.getElementById('new-recipe-tag-label');
|
const labelInput = document.getElementById('new-recipe-tag-label');
|
||||||
|
const keywordsInput = document.getElementById('new-recipe-tag-keywords');
|
||||||
const icon = iconInput.value.trim() || '🏷️';
|
const icon = iconInput.value.trim() || '🏷️';
|
||||||
const label = labelInput.value.trim();
|
const label = labelInput.value.trim();
|
||||||
|
const keywords = keywordsInput ? keywordsInput.value.trim() : '';
|
||||||
|
|
||||||
if (!label) {
|
if (!label) {
|
||||||
showToast('Indique un nom pour le nouveau tag', 'warning');
|
showToast('Indique un nom pour le nouveau tag', 'warning');
|
||||||
@@ -1448,12 +1451,13 @@ async function addRecipeTagConfig() {
|
|||||||
|
|
||||||
showLoading(true);
|
showLoading(true);
|
||||||
try {
|
try {
|
||||||
const result = await api('recipe_tags_add', {}, 'POST', { label, icon });
|
const result = await api('recipe_tags_add', {}, 'POST', { label, icon, keywords });
|
||||||
showLoading(false);
|
showLoading(false);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
showToast(`Tag "${label}" ajouté`, 'success');
|
showToast(`Tag "${label}" ajouté`, 'success');
|
||||||
iconInput.value = '';
|
iconInput.value = '';
|
||||||
labelInput.value = '';
|
labelInput.value = '';
|
||||||
|
if (keywordsInput) keywordsInput.value = '';
|
||||||
_loadRecipeTagsConfigSection();
|
_loadRecipeTagsConfigSection();
|
||||||
} else {
|
} else {
|
||||||
showToast(result.error || 'Erreur lors de l\'ajout', 'error');
|
showToast(result.error || 'Erreur lors de l\'ajout', 'error');
|
||||||
@@ -1467,6 +1471,8 @@ async function addRecipeTagConfig() {
|
|||||||
async function updateRecipeTagConfig(key) {
|
async function updateRecipeTagConfig(key) {
|
||||||
const icon = document.getElementById(`rtag-icon-${key}`).value.trim() || '🏷️';
|
const icon = document.getElementById(`rtag-icon-${key}`).value.trim() || '🏷️';
|
||||||
const label = document.getElementById(`rtag-label-${key}`).value.trim();
|
const label = document.getElementById(`rtag-label-${key}`).value.trim();
|
||||||
|
const keywordsEl = document.getElementById(`rtag-keywords-${key}`);
|
||||||
|
const keywords = keywordsEl ? keywordsEl.value.trim() : '';
|
||||||
|
|
||||||
if (!label) {
|
if (!label) {
|
||||||
showToast('Le nom ne peut pas être vide', 'warning');
|
showToast('Le nom ne peut pas être vide', 'warning');
|
||||||
@@ -1475,7 +1481,7 @@ async function updateRecipeTagConfig(key) {
|
|||||||
|
|
||||||
showLoading(true);
|
showLoading(true);
|
||||||
try {
|
try {
|
||||||
const result = await api('recipe_tags_update', {}, 'POST', { key, label, icon });
|
const result = await api('recipe_tags_update', {}, 'POST', { key, label, icon, keywords });
|
||||||
showLoading(false);
|
showLoading(false);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
showToast('Tag mis à jour', 'success');
|
showToast('Tag mis à jour', 'success');
|
||||||
@@ -15428,10 +15434,28 @@ Ingrédients :
|
|||||||
document.getElementById('modal-overlay').style.display = 'flex';
|
document.getElementById('modal-overlay').style.display = 'flex';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _normalizeForMatch(s) {
|
||||||
|
return (s || '').toString().toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchRecipeTagsFromIngredients(ingredients) {
|
||||||
|
const norm = _normalizeForMatch(ingredients.map(i => i.name).join(' '));
|
||||||
|
const matched = [];
|
||||||
|
(RECIPE_TAGS || []).forEach(tag => {
|
||||||
|
const raw = (tag.keywords && tag.keywords.trim()) ? tag.keywords : tag.key;
|
||||||
|
const kws = raw.split(',').map(k => _normalizeForMatch(k.trim())).filter(Boolean);
|
||||||
|
if (kws.some(kw => kw.length > 1 && norm.includes(kw))) {
|
||||||
|
matched.push(tag.key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
function analyzeRawRecipeText() {
|
function analyzeRawRecipeText() {
|
||||||
const raw = document.getElementById('rl-import-raw').value;
|
const raw = document.getElementById('rl-import-raw').value;
|
||||||
if (!raw.trim()) { showToast('Colle un texte de recette', 'warning'); return; }
|
if (!raw.trim()) { showToast('Colle un texte de recette', 'warning'); return; }
|
||||||
const parsed = parseRawRecipeText(raw);
|
const parsed = parseRawRecipeText(raw);
|
||||||
|
parsed.tags = matchRecipeTagsFromIngredients(parsed.ingredients);
|
||||||
openRecipeLibraryForm(null, parsed);
|
openRecipeLibraryForm(null, parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user