feat: stockage articles en fichiers Markdown, SSO intégré, URLs propres
This commit is contained in:
+85
-28
@@ -1,64 +1,121 @@
|
||||
<?php
|
||||
ob_start();
|
||||
|
||||
// Valeur par défaut pour le champ datetime-local
|
||||
$dateValue = $published_at ?? date('Y-m-d\TH:i');
|
||||
$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 le post' : 'Créer un nouveau post' ?></h1>
|
||||
<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>
|
||||
<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) ?>">
|
||||
<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> – <a href="https://www.markdownguide.org/cheat-sheet/" target="_blank">guide rapide</a>
|
||||
Écris en <strong>Markdown</strong> — les fichiers uploadés sont référençables dans le contenu :
|
||||
<code></code>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="content" class="form-label">Contenu</label>
|
||||
<textarea class="form-control" id="content" name="content" rows="6"><?= htmlspecialchars($content) ?></textarea>
|
||||
<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 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>
|
||||
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="files" class="form-label">Fichiers</label>
|
||||
<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>
|
||||
<ul class="list-unstyled">
|
||||
<?php foreach ($existingFiles as $f): ?>
|
||||
<li>
|
||||
<code><?= htmlspecialchars($f['name']) ?></code>
|
||||
<small class="text-muted ms-2"><?= htmlspecialchars(number_format($f['size'] / 1024, 1)) ?> Ko</small>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<button type="submit" class="btn btn-success">Enregistrer</button>
|
||||
<a href="route.php" class="btn btn-secondary">Annuler</a>
|
||||
<a href="/" class="btn btn-secondary">Annuler</a>
|
||||
</form>
|
||||
|
||||
<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;
|
||||
})();
|
||||
</script>
|
||||
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
$title = $action === 'edit' ? 'Modifier le post' : 'Nouveau post';
|
||||
$title = $action === 'edit' ? 'Modifier l\'article' : 'Nouvel article';
|
||||
include __DIR__ . '/layout.php';
|
||||
|
||||
Reference in New Issue
Block a user