Files
varlog/templates/post_form.php
T
2026-05-08 23:16:36 +02:00

235 lines
11 KiB
PHP
Raw 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();
$dateValue = isset($published_at)
? (str_contains($published_at, ' ')
? date('Y-m-d\TH:i', strtotime($published_at))
: $published_at)
: date('Y-m-d\TH:i');
?>
<h1 class="mb-4"><?= $action === 'edit' ? 'Modifier l\'article' : 'Nouvel article' ?></h1>
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<ul class="mb-0">
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="POST" action="<?= htmlspecialchars($formAction) ?>" enctype="multipart/form-data">
<div class="mb-3">
<label for="title" class="form-label">Titre</label>
<input type="text" class="form-control" id="title" name="title" required
value="<?= htmlspecialchars($title ?? '') ?>"
oninput="autoSlug(this.value)">
</div>
<div class="mb-3">
<label for="slug" class="form-label">
Slug <small class="text-muted">(URL : /post/<span id="slug-preview"><?= htmlspecialchars($postSlug ?? '') ?></span>)</small>
</label>
<input type="text" class="form-control form-control-sm font-monospace" id="slug" name="slug"
value="<?= htmlspecialchars($postSlug ?? '') ?>"
pattern="[a-z0-9][a-z0-9-]*"
placeholder="généré automatiquement depuis le titre">
</div>
<div class="mb-2">
<small class="text-muted">
Écris en <strong>Markdown</strong> — les fichiers uploadés sont référençables dans le contenu :
<code>![alt](nom-du-fichier.jpg)</code>
</small>
</div>
<div class="mb-3">
<label for="content" class="form-label">Contenu</label>
<textarea class="form-control font-monospace" id="content" name="content" rows="12"><?= htmlspecialchars($content ?? '') ?></textarea>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label for="published_at" class="form-label">Date de publication</label>
<input type="datetime-local" class="form-control" id="published_at" name="published_at" value="<?= $dateValue ?>">
</div>
<div class="col-md-6 d-flex align-items-end">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="published" name="published"
<?= ($published ?? false) ? 'checked' : '' ?>>
<label class="form-check-label" for="published">Publié</label>
</div>
</div>
</div>
<div class="mb-3">
<label for="files" class="form-label">Ajouter des fichiers</label>
<input type="file" class="form-control" id="files" name="files[]" multiple>
<div class="form-text">Images, vidéos, PDF… — intègre-les dans le contenu ou laisse-les en pièces jointes.</div>
</div>
<?php if ($action === 'edit' && !empty($existingFiles)): ?>
<div class="mb-3">
<p class="form-label">Fichiers existants</p>
<div class="list-group">
<?php foreach ($existingFiles as $i => $f): ?>
<?php $fileUrl = '/file?uuid=' . rawurlencode($uuid) . '&name=' . rawurlencode($f['name']); ?>
<div class="list-group-item d-flex align-items-center gap-3 py-2">
<?php if ($f['is_image']): ?>
<a href="<?= htmlspecialchars($fileUrl) ?>" target="_blank" rel="noopener">
<img src="<?= htmlspecialchars($fileUrl) ?>" alt=""
style="width:48px;height:48px;object-fit:cover;border-radius:4px;flex-shrink:0">
</a>
<?php else: ?>
<a href="<?= htmlspecialchars($fileUrl) ?>" target="_blank" rel="noopener"
style="width:48px;text-align:center;font-size:1.5rem;flex-shrink:0;text-decoration:none">
<?php
$icon = match(true) {
str_starts_with($f['mime'], 'video/') => '🎬',
str_starts_with($f['mime'], 'audio/') => '🎵',
$f['mime'] === 'application/pdf' => '📑',
default => '📄',
};
echo $icon;
?>
</a>
<?php endif; ?>
<div class="flex-grow-1 overflow-hidden">
<code class="d-block text-truncate"><?= htmlspecialchars($f['name']) ?></code>
<small class="text-muted">
<?= htmlspecialchars(number_format($f['size'] / 1024, 1)) ?> Ko
&mdash; <?= htmlspecialchars($f['mime']) ?>
</small>
</div>
<div class="d-flex gap-2 flex-shrink-0">
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="copyMdRef(<?= htmlspecialchars(json_encode($f['name'])) ?>, <?= $f['is_image'] ? 'true' : 'false' ?>, this)">
Référence MD
</button>
<button type="submit" form="del-file-<?= $i ?>"
class="btn btn-sm btn-outline-danger"
onclick="return confirm('Supprimer « <?= htmlspecialchars(addslashes($f['name'])) ?> » définitivement ?')">
Supprimer
</button>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<?php if ($action === 'edit'): ?>
<div class="mb-3">
<label for="revision_comment" class="form-label">Commentaire de révision <small class="text-muted">(optionnel)</small></label>
<input type="text" class="form-control" id="revision_comment" name="revision_comment"
placeholder="ex. Correction typos, ajout section X…">
</div>
<?php endif; ?>
<div class="card mb-3 border-secondary">
<div class="card-header bg-transparent py-2">
<button class="btn btn-sm btn-link text-secondary text-decoration-none p-0 fw-semibold"
type="button" data-bs-toggle="collapse" data-bs-target="#seoPanel" aria-expanded="false">
▸ SEO — titre, description, image
</button>
</div>
<div class="collapse" id="seoPanel">
<div class="card-body">
<div class="mb-3">
<label for="seo_title" class="form-label">
Titre SEO
<small class="text-muted">(balise &lt;title&gt; et og:title)</small>
</label>
<input type="text" class="form-control" id="seo_title" name="seo_title"
maxlength="70"
value="<?= htmlspecialchars($seoTitle ?? '') ?>"
placeholder="Généré automatiquement depuis le titre">
<div class="d-flex justify-content-between mt-1">
<small class="text-muted">Idéal : 3060 caractères</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">
Description SEO
<small class="text-muted">(meta description et og:description)</small>
</label>
<textarea class="form-control" id="seo_description" name="seo_description"
rows="3" maxlength="200"
placeholder="Générée automatiquement depuis le début du contenu"><?= htmlspecialchars($seoDescription ?? '') ?></textarea>
<div class="d-flex justify-content-between mt-1">
<small class="text-muted">Idéal : 120155 caractères</small>
<small id="seo_desc_counter" class="text-muted">0 / 155</small>
</div>
</div>
<div class="mb-2">
<label for="og_image" class="form-label">
Image Open Graph
<small class="text-muted">(URL absolue, optionnel)</small>
</label>
<input type="url" class="form-control font-monospace" id="og_image" name="og_image"
value="<?= htmlspecialchars($ogImage ?? '') ?>"
placeholder="https://varlog.a5l.fr/…">
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-success">Enregistrer</button>
<a href="/" class="btn btn-secondary">Annuler</a>
</form>
<?php if ($action === 'edit' && !empty($existingFiles)): ?>
<?php foreach ($existingFiles as $i => $f): ?>
<form id="del-file-<?= $i ?>" method="POST"
action="/?action=delete_file&uuid=<?= rawurlencode($uuid) ?>">
<input type="hidden" name="name" value="<?= htmlspecialchars($f['name']) ?>">
</form>
<?php endforeach; ?>
<?php endif; ?>
<script>
function slugify(s) {
const map = {'à':'a','â':'a','ä':'a','é':'e','è':'e','ê':'e','ë':'e','î':'i','ï':'i','ô':'o','ö':'o','ù':'u','û':'u','ü':'u','ç':'c','æ':'ae','œ':'oe'};
return s.toLowerCase().replace(/[àâäéèêëîïôöùûüçæœ]/g, c => map[c] || c)
.replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
}
function autoSlug(title) {
const slugField = document.getElementById('slug');
const preview = document.getElementById('slug-preview');
// N'écrase le slug que s'il est vide ou s'il correspond à la génération automatique
if (slugField._auto !== false) {
const generated = slugify(title);
slugField.value = generated;
preview.textContent = generated;
}
}
document.getElementById('slug').addEventListener('input', function() {
this._auto = (this.value === '');
document.getElementById('slug-preview').textContent = this.value;
});
// En mode édition le champ est pré-rempli : désactive l'auto-génération
(function() {
const s = document.getElementById('slug');
if (s.value !== '') s._auto = false;
})();
function copyMdRef(name, isImage, btn) {
const ref = isImage ? `![](${name})` : `[${name}](${name})`;
navigator.clipboard.writeText(ref).then(() => {
const orig = btn.textContent;
btn.textContent = 'Copié !';
setTimeout(() => { btn.textContent = orig; }, 1500);
});
}
</script>
<?php
$content = ob_get_clean();
$title = $action === 'edit' ? 'Modifier l\'article' : 'Nouvel article';
include __DIR__ . '/layout.php';