191 lines
7.3 KiB
Plaintext
191 lines
7.3 KiB
Plaintext
@page "/artikelen/nieuw"
|
|
@attribute [Authorize(Policy = "Editor")]
|
|
@using System.ComponentModel.DataAnnotations
|
|
@inject ArticleService Artikelen
|
|
@inject SeasonService Seizoenen
|
|
@inject UserService Gebruikers
|
|
@inject UploadService Uploads
|
|
|
|
<PageTitle>Nieuw artikel — ProostenKrant</PageTitle>
|
|
|
|
<section class="card">
|
|
<h1 class="headline">Nieuw artikel</h1>
|
|
<p class="muted">Artikel voor de redactie aanmaken en eventueel direct publiceren.</p>
|
|
|
|
@if (_fout is not null)
|
|
{
|
|
<p class="alert alert-error">@_fout</p>
|
|
}
|
|
|
|
<EditForm FormName="artikel-nieuw" Method="post" Model="Input" OnValidSubmit="Opslaan"
|
|
class="krant-form" enctype="multipart/form-data">
|
|
<div class="form-group">
|
|
<label for="title">Titel</label>
|
|
<InputText @bind-Value="Input.Title" id="title" class="form-control" placeholder="De kop boven het artikel" />
|
|
<ValidationMessage For="() => Input.Title" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="content">Tekst</label>
|
|
<InputTextArea @bind-Value="Input.Content" id="content" rows="10" class="form-control" placeholder="Schrijf hier de inhoud van je artikel…" />
|
|
<ValidationMessage For="() => Input.Content" />
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="writer">Schrijver</label>
|
|
<InputSelect @bind-Value="Input.WriterId" id="writer" class="form-control">
|
|
<option value="0">— Kies schrijver —</option>
|
|
@foreach (var gebruiker in _gebruikers)
|
|
{
|
|
<option value="@gebruiker.Id">@gebruiker.DisplayName</option>
|
|
}
|
|
</InputSelect>
|
|
<ValidationMessage For="() => Input.WriterId" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="eventdate">Datum van de gebeurtenis</label>
|
|
<InputDate @bind-Value="Input.EventDate" id="eventdate" class="form-control" />
|
|
<ValidationMessage For="() => Input.EventDate" />
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="season">Seizoen</label>
|
|
<InputSelect @bind-Value="Input.SeasonId" id="season" class="form-control">
|
|
<option value="0">— Kies seizoen —</option>
|
|
@foreach (var seizoen in _seizoenen)
|
|
{
|
|
<option value="@seizoen.Id">@seizoen.Name</option>
|
|
}
|
|
</InputSelect>
|
|
<ValidationMessage For="() => Input.SeasonId" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="status">Status</label>
|
|
<InputSelect @bind-Value="Input.Status" id="status" class="form-control">
|
|
<option value="draft">Klad</option>
|
|
<option value="published">Gepubliceerd</option>
|
|
</InputSelect>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Deelnemers</label>
|
|
<div class="checkbox-group">
|
|
@foreach (var gebruiker in _gebruikers)
|
|
{
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" name="Participants" value="@gebruiker.Id"
|
|
checked="@(_geselecteerd.Contains(gebruiker.Id))" />
|
|
<span>@gebruiker.DisplayName</span>
|
|
</label>
|
|
}
|
|
</div>
|
|
@if (_participantsFout is not null)
|
|
{
|
|
<span class="error-message">@_participantsFout</span>
|
|
}
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="image">Afbeelding (optioneel)</label>
|
|
<input type="file" name="Afbeelding" id="image" class="form-control" accept="image/*" />
|
|
<span class="help-text">JPG, PNG, GIF of WEBP, maximaal 25 MB.</span>
|
|
@if (_afbeeldingFout is not null)
|
|
{
|
|
<span class="error-message">@_afbeeldingFout</span>
|
|
}
|
|
</div>
|
|
<div class="form-actions">
|
|
<button type="submit" class="btn btn-primary">Artikel opslaan</button>
|
|
<a class="btn" href="/artikelen">Annuleren</a>
|
|
</div>
|
|
</EditForm>
|
|
</section>
|
|
|
|
@code {
|
|
[CascadingParameter]
|
|
private HttpContext HttpContext { get; set; } = default!;
|
|
|
|
[SupplyParameterFromForm(FormName = "artikel-nieuw")]
|
|
private ArtikelInput Input { get; set; } = new();
|
|
|
|
private List<User> _gebruikers = new();
|
|
private List<Season> _seizoenen = new();
|
|
private List<int> _geselecteerd = new();
|
|
private string? _fout;
|
|
private string? _participantsFout;
|
|
private string? _afbeeldingFout;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
Input ??= new();
|
|
_gebruikers = await Gebruikers.GetAllAsync();
|
|
_seizoenen = await Seizoenen.GetAllAsync();
|
|
var huidig = await Seizoenen.GetCurrentAsync();
|
|
Input.SeasonId ??= huidig?.Id ?? (_seizoenen.FirstOrDefault()?.Id ?? 0);
|
|
Input.EventDate ??= DateTime.Today;
|
|
Input.Status ??= "published";
|
|
}
|
|
|
|
private async Task Opslaan()
|
|
{
|
|
Input ??= new();
|
|
var form = HttpContext.Request.Form;
|
|
_geselecteerd = form["Participants"].SelectMany(v => (v ?? "").Split(','))
|
|
.Select(s => int.TryParse(s, out var id) ? id : 0).Where(id => id > 0).ToList();
|
|
if (Input.WriterId <= 0)
|
|
{
|
|
_fout = "Kies een schrijver.";
|
|
return;
|
|
}
|
|
if (!_geselecteerd.Contains(Input.WriterId))
|
|
{
|
|
_geselecteerd.Insert(0, Input.WriterId);
|
|
}
|
|
if (_geselecteerd.Count == 0)
|
|
{
|
|
_participantsFout = "Selecteer minstens één deelnemer.";
|
|
return;
|
|
}
|
|
|
|
var (webPad, fout) = await Uploads.SaveArticleImageAsync(HttpContext.Request.Form.Files["Afbeelding"]);
|
|
if (fout is not null)
|
|
{
|
|
_afbeeldingFout = fout;
|
|
return;
|
|
}
|
|
|
|
var artikel = new Article
|
|
{
|
|
Title = Input.Title,
|
|
Content = Input.Content,
|
|
AuthorId = Input.WriterId,
|
|
Participants = string.Join(",", _geselecteerd),
|
|
EventDate = Input.EventDate,
|
|
SeasonId = Input.SeasonId,
|
|
ArticleImage = webPad,
|
|
Status = Input.Status == "published" ? "published" : "draft",
|
|
};
|
|
await Artikelen.CreateAsync(artikel);
|
|
Nav.NavigateTo("/artikelen?melding=" + Uri.EscapeDataString("Artikel succesvol opgeslagen."), forceLoad: true);
|
|
}
|
|
|
|
private sealed class ArtikelInput
|
|
{
|
|
[Required(ErrorMessage = "Geef het artikel een titel (minstens 5 tekens).")]
|
|
[MinLength(5, ErrorMessage = "De titel moet minstens 5 tekens bevatten.")]
|
|
[MaxLength(255)]
|
|
public string Title { get; set; } = "";
|
|
|
|
[Required(ErrorMessage = "Schrijf de tekst van het artikel (minstens 10 tekens).")]
|
|
[MinLength(10, ErrorMessage = "De tekst moet minstens 10 tekens bevatten.")]
|
|
public string Content { get; set; } = "";
|
|
|
|
public int WriterId { get; set; }
|
|
|
|
public DateTime? EventDate { get; set; }
|
|
|
|
public int? SeasonId { get; set; }
|
|
|
|
public string? Status { get; set; }
|
|
}
|
|
}
|