Files
cedricAbonnel 298f18dabe feat & fix : intégration IA éditeur + onglet admin IA + corrections CSP (v1.6.24-25)
- #96 : boutons IA sidebar éditeur (analyse critique / réécriture) via Anthropic API
- #97 : onglet admin /admin/ia — provider anthropic/claude_code, modèle, procédure CLI
- #95 : extraction scripts inline vers fichiers JS (comments.js, post_confirm.js, admin.js)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 12:18:38 +02:00

268 lines
13 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
ob_start();
$CONTEXT = 3;
$base = rtrim(APP_URL, '/');
$effectiveTitle = ($seoTitle !== '') ? $seoTitle : $title;
$effectiveDesc = ($seoDescription !== '') ? $seoDescription : $autoSeoDesc;
$effectiveSlug = $postSlug;
$coverFilename = ($newCover ?? '') !== '' ? $newCover : ($article['cover'] ?? '');
$suggestedOgImage = $coverFilename !== ''
? $base . '/file?uuid=' . rawurlencode($uuid) . '&name=' . rawurlencode($coverFilename)
: '';
?>
<div class="d-flex align-items-center gap-3 mb-4 flex-wrap">
<a href="/edit/<?= htmlspecialchars($uuid) ?>" class="btn btn-outline-secondary">← Retour à l'édition</a>
<h1 class="h4 mb-0">Confirmer les modifications</h1>
</div>
<form method="POST" action="/edit/<?= htmlspecialchars($uuid) ?>">
<input type="hidden" name="_confirm" value="1">
<input type="hidden" name="title" value="<?= htmlspecialchars($title) ?>">
<input type="hidden" name="content" value="<?= htmlspecialchars($content) ?>">
<?php if ($published): ?>
<input type="hidden" name="published" value="1">
<?php endif; ?>
<input type="hidden" name="published_at" value="<?= htmlspecialchars($published_at) ?>">
<!-- seo_title et seo_description sont des champs visibles dans la colonne droite -->
<!-- og_image est calculé depuis la couverture côté serveur -->
<input type="hidden" name="category" value="<?= htmlspecialchars($category) ?>">
<?php foreach ($confirmTags ?? [] as $_ctk => $_ctv): ?>
<input type="hidden" name="tags[<?= htmlspecialchars($_ctk) ?>]" value="<?= htmlspecialchars($_ctv) ?>">
<?php endforeach; ?>
<?php if (($newCover ?? '') !== ''): ?>
<input type="hidden" name="cover_file" value="<?= htmlspecialchars($newCover) ?>">
<?php endif; ?>
<?php foreach ($fmetaNames as $fi => $fname): ?>
<input type="hidden" name="fmeta_name[]" value="<?= htmlspecialchars($fname) ?>">
<input type="hidden" name="fmeta_author[]" value="<?= htmlspecialchars($fmetaAuthors[$fi] ?? '') ?>">
<input type="hidden" name="fmeta_source[]" value="<?= htmlspecialchars($fmetaSources[$fi] ?? '') ?>">
<?php endforeach; ?>
<div class="row g-4">
<div class="col-lg-8">
<?php if (!empty($changes)): ?>
<div class="alert alert-info py-2 mb-3">
<?= htmlspecialchars(ucfirst(implode(' · ', $changes))) ?>
</div>
<?php else: ?>
<div class="alert alert-secondary py-2 mb-3">Aucune modification détectée.</div>
<?php endif; ?>
<!-- ─── Diff ─────────────────────────────────────────────────────────────── -->
<div class="mb-4">
<h2 class="h6 fw-semibold mb-2">Diff du contenu</h2>
<?php if ($diffLines === []): ?>
<div class="text-muted small">Contenu identique.</div>
<?php else:
$total = count($diffLines);
$show = [];
for ($i = 0; $i < $total; $i++) {
if ($diffLines[$i][0] !== '=') {
for ($c = max(0, $i - $CONTEXT); $c <= min($total - 1, $i + $CONTEXT); $c++) {
$show[$c] = true;
}
}
}
$hasChanges = false;
foreach ($diffLines as [$op]) {
if ($op !== '=') {
$hasChanges = true;
break;
}
}
?>
<div class="d-flex gap-3 mb-1 small">
<span class="diff-del px-2 py-1 rounded"> Supprimé</span>
<span class="diff-ins px-2 py-1 rounded">+ Ajouté</span>
</div>
<div class="diff-view font-monospace small">
<?php $inEllipsis = false;
for ($i = 0; $i < $total; $i++): ?>
<?php [$op, $line] = $diffLines[$i]; ?>
<?php if (!isset($show[$i])): ?>
<?php if (!$inEllipsis): $inEllipsis = true; ?>
<div class="diff-ellipsis text-muted px-2">⋯</div>
<?php endif;
continue; ?>
<?php else: $inEllipsis = false; endif; ?>
<?php if ($op === '!'): ?>
<div class="diff-warning text-warning px-2"><?= htmlspecialchars($line) ?></div>
<?php elseif ($op === '-'): ?>
<div class="diff-del px-2">&nbsp;<?= htmlspecialchars($line) ?></div>
<?php elseif ($op === '+'): ?>
<div class="diff-ins px-2">+&nbsp;<?= htmlspecialchars($line) ?></div>
<?php else: ?>
<div class="diff-eq px-2 text-muted">&nbsp;&nbsp;<?= htmlspecialchars($line) ?></div>
<?php endif; ?>
<?php endfor; ?>
</div>
<?php endif; ?>
</div>
<!-- ─── Slug ─────────────────────────────────────────────────────────────── -->
<?php
$slugDefault = ($titleChanged && $autoSlug !== $postSlug) ? $autoSlug : $postSlug;
$slugOriginal = $postSlug;
?>
<div class="mb-3">
<label for="confirm-slug" class="form-label fw-semibold">
Slug (URL permanente)
<small class="text-muted fw-normal">— /post/<span id="slug-display"><?= htmlspecialchars($slugDefault) ?></span></small>
</label>
<input type="text" class="form-control form-control-sm font-monospace" id="confirm-slug" name="slug"
value="<?= htmlspecialchars($slugDefault) ?>"
pattern="[a-z0-9][a-z0-9\-]*">
<?php if ($titleChanged && $autoSlug !== $slugOriginal): ?>
<div class="mt-2 d-flex align-items-center gap-2 flex-wrap">
<small class="text-muted">Slug recalculé depuis le nouveau titre. Slug initial :</small>
<code class="small"><?= htmlspecialchars($slugOriginal) ?></code>
<button type="button" id="slug-btn-keep" class="btn btn-sm btn-outline-secondary py-0"
data-slug-keep="<?= htmlspecialchars($slugOriginal) ?>">
Conserver
</button>
</div>
<?php endif; ?>
</div>
<!-- ─── Commentaire de révision ──────────────────────────────────────────── -->
<div class="mb-4">
<label for="revision_comment" class="form-label fw-semibold">
Commentaire de révision <small class="text-muted fw-normal">(optionnel)</small>
</label>
<input type="text" class="form-control" id="revision_comment" name="revision_comment"
value="<?= htmlspecialchars($autoRevisionComment) ?>"
placeholder="ex. Correction typos, ajout section X…">
</div>
<div class="d-flex gap-3 flex-wrap">
<button type="submit" class="btn btn-success">Confirmer et enregistrer</button>
<a href="/edit/<?= htmlspecialchars($uuid) ?>" class="btn btn-outline-secondary">← Retour</a>
</div>
</div><!-- /col-lg-8 -->
<!-- ─── SEO ───────────────────────────────────────────────────────────────── -->
<div class="col-lg-4">
<div class="card border-secondary mb-3">
<div class="card-header bg-transparent py-2">
<span class="fw-semibold small">SEO — titre, description, image</span>
</div>
<div class="card-body">
<div class="mb-3">
<label for="seo_title" class="form-label small">
Titre SEO <small class="text-muted">(og:title, &lt;title&gt;)</small>
</label>
<input type="text" class="form-control form-control-sm" id="seo_title" name="seo_title"
maxlength="70"
value="<?= htmlspecialchars($seoTitle) ?>"
placeholder="<?= htmlspecialchars($title) ?>">
<div class="d-flex justify-content-between mt-1">
<small class="text-muted">Idéal : 3060 car.</small>
<small id="seo_title_counter" class="text-muted">0 / 60</small>
</div>
</div>
<div class="mb-3">
<label for="seo_description" class="form-label small">
Description SEO <small class="text-muted">(meta description)</small>
</label>
<textarea class="form-control form-control-sm" id="seo_description" name="seo_description"
rows="3" maxlength="200"
placeholder="<?= htmlspecialchars(mb_strimwidth($autoSeoDesc, 0, 80, '…')) ?>"><?= htmlspecialchars($seoDescription) ?></textarea>
<div class="d-flex justify-content-between mt-1">
<small class="text-muted">Idéal : 120155 car.</small>
<small id="seo_desc_counter" class="text-muted">0 / 155</small>
</div>
</div>
</div>
</div>
<div class="card border-secondary">
<div class="card-header bg-transparent py-2">
<span class="fw-semibold small">Aperçu dans les moteurs de recherche</span>
</div>
<div class="card-body p-3">
<?php
$pubTs = strtotime((string)($published_at ?? $article['published_at'] ?? ''));
$modTs = time(); // sera mis à jour à la sauvegarde
$pubFmt = $pubTs ? date('d/m/Y H:i', $pubTs) : '—';
$modFmt = date('d/m/Y H:i', $modTs);
$catVal = trim($category ?? '');
?>
<div class="seo-preview mb-3">
<div class="seo-preview-url small text-truncate mb-1" id="preview-url">
<?= htmlspecialchars(rtrim($base, '/') . '/post/' . $effectiveSlug) ?>
</div>
<div class="seo-preview-title mb-1" id="preview-title">
<?= htmlspecialchars($effectiveTitle) ?>
</div>
<div class="seo-preview-desc small" id="preview-desc">
<?= htmlspecialchars($effectiveDesc) ?>
</div>
</div>
<table class="table table-sm table-borderless mb-0 small">
<tbody>
<tr>
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap" style="width:1%">Auteur</th>
<td><?= htmlspecialchars(currentUserName() ?: (currentUserEmail() ?? '—')) ?></td>
</tr>
<tr>
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Publication</th>
<td><?= htmlspecialchars($pubFmt) ?></td>
</tr>
<tr>
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Modification</th>
<td><?= htmlspecialchars($modFmt) ?> <small class="text-muted">(après enreg.)</small></td>
</tr>
<tr>
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Langue</th>
<td>fr-FR</td>
</tr>
<tr>
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">Catégorie</th>
<td><?= $catVal !== '' ? htmlspecialchars($catVal) : '<span class="text-muted">—</span>' ?></td>
</tr>
<tr>
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap">og:image</th>
<td class="text-truncate" style="max-width:0">
<?= $suggestedOgImage !== '' ? '<span title="' . htmlspecialchars($suggestedOgImage) . '">' . htmlspecialchars($coverFilename) . '</span>' : '<span class="text-muted">— (pas de couverture)</span>' ?>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div><!-- /row -->
</form>
<style>
.diff-view { border: 1px solid var(--bs-border-color, #dee2e6); border-radius: 6px; overflow-x: auto; }
.diff-view > div { padding: 1px 8px; white-space: pre; line-height: 1.5; }
.diff-del { background: #ffeef0; color: #b91c1c; }
.diff-ins { background: #e6ffec; color: #15803d; }
.diff-eq { }
.diff-ellipsis { background: #f8f9fa; padding: 2px 8px; user-select: none; }
.seo-preview { border: 1px solid #dee2e6; border-radius: 6px; padding: 10px 12px; background: #fff; }
.seo-preview-url { color: #006621; font-size: .78rem; }
.seo-preview-title { color: #1a0dab; font-size: 1.05rem; font-weight: 500; line-height: 1.3; word-break: break-word; }
.seo-preview-desc { color: #545454; line-height: 1.5; }
</style>
<div id="pc-data" hidden
data-default-title="<?= htmlspecialchars($effectiveTitle) ?>"
data-default-desc="<?= htmlspecialchars($effectiveDesc) ?>"
data-base-url="<?= htmlspecialchars(rtrim($base, '/') . '/post/') ?>"></div>
<script src="/assets/js/post_confirm.js"></script>
<?php
$content = ob_get_clean();
$title = 'Confirmer — ' . $title;
include __DIR__ . '/layout.php';