diff --git a/CouchLog/Components/Pages/GlobalList/Dialogs/AddNewGlobalEntityDialog.razor b/CouchLog/Components/Pages/GlobalList/Dialogs/AddNewGlobalEntityDialog.razor index 7b3515f..ede80ed 100644 --- a/CouchLog/Components/Pages/GlobalList/Dialogs/AddNewGlobalEntityDialog.razor +++ b/CouchLog/Components/Pages/GlobalList/Dialogs/AddNewGlobalEntityDialog.razor @@ -1,146 +1,279 @@ @using CouchLog.Data @using Microsoft.EntityFrameworkCore - @using Microsoft.AspNetCore.Authorization -@using CouchLog.Data @using Microsoft.AspNetCore.Identity -@using Microsoft.EntityFrameworkCore +@using System.ComponentModel.DataAnnotations @inject ApplicationDbContext CouchLogDB @inject UserManager UserManager @inject AuthenticationStateProvider AuthenticationStateProvider @inject NavigationManager NavigationManager +@inject ISnackbar Snackbar + + - - Add Global Entity - + Add Global Entity - - - - -
- - - -
-
- - -
- @*
- - - @if (!string.IsNullOrEmpty(ImageString)) - { - - } -
*@ -
- - @foreach(Genre Genre in Genres) - { - - } -
-
- -
- + + + + + + + + +
+ + @if (_imagePreviewUrl is not null) + { +
+ Preview +
+ + + + Replace Image + + +
+
+ } + else + { + + + + Bild hierher ziehen
oder klicken zum Auswählen +
+
+ } + +
+
+
+
+ + + + + + + + + @foreach (var type in _mediaTypes) + { + @type.Name + } + + + + @foreach (var genre in _genres) + { + @genre.Name + } + + + + @if (_isSaving) + { + + Saving... + } + else + { + Create Global Entity + } + + + +
- @*Dialog Footer*@ - Cancel + Cancel
@code { - private ApplicationUser AppUser = null!; - [CascadingParameter] - private IMudDialogInstance MudDialog { get; set; } - private void Cancel() => MudDialog.Cancel(); + private IMudDialogInstance MudDialog { get; set; } = null!; + private ApplicationUser? _appUser; + private EditContext _editContext = null!; - private List MediaTypes = new(); - private List Genres = new(); + private List _mediaTypes = new(); + private List _genres = new(); - #region ForNewGlobalEntity - private GlobalEntity newGlobalEntity = new(); - private IBrowserFile? Picture; - private int SelectedMediaTypeId; - private bool IsPrivate; - private List GenreIds = new (); - #endregion + private GlobalEntityFormModel _form = new(); + private MudFileUpload? _fileUpload; + private IBrowserFile? _picture; + private string? _imagePreviewUrl; + private bool _isDragOver; + private int _selectedMediaTypeId; + private bool _isPrivate; + private bool _isSaving; + private IEnumerable _selectedGenreIds = new HashSet(); + + private class GlobalEntityFormModel + { + [Required(ErrorMessage = "Title is required.")] + [MaxLength(200, ErrorMessage = "Title may not exceed 200 characters.")] + public string Title { get; set; } = string.Empty; + } + + private string GetDropZoneStyle() => + "width: 100%; height: 100%; min-height: 380px; border-radius: 6px; " + + $"border: 2px dashed {(_isDragOver ? "var(--mud-palette-primary)" : "var(--mud-palette-lines-default)")}; " + + $"background-color: {(_isDragOver ? "var(--mud-palette-primary-hover)" : "transparent")}; " + + "transition: border-color .2s ease, background-color .2s ease;"; + + private Task OpenFilePicker() => + _fileUpload?.OpenFilePickerAsync() ?? Task.CompletedTask; protected override async Task OnInitializedAsync() { - var AuthState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); - var User = AuthState.User; - AppUser = (await UserManager.GetUserAsync(User))!; + _editContext = new EditContext(_form); - if(AppUser == null) + var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); + _appUser = await UserManager.GetUserAsync(authState.User); + + if (_appUser is null) { - throw new Exception("Not Authenticated"); + Snackbar.Add("Not authenticated.", Severity.Error); + MudDialog.Cancel(); + return; } - MediaTypes = await CouchLogDB.MediaType.OrderBy(Type => Type.Id).ToListAsync(); - Genres = await CouchLogDB.Genres.OrderBy(Type => Type.Id).ToListAsync(); + _mediaTypes = await CouchLogDB.MediaType.OrderBy(t => t.Id).ToListAsync(); + _genres = await CouchLogDB.Genres.OrderBy(t => t.Id).ToListAsync(); + + if (_mediaTypes.Count > 0) + _selectedMediaTypeId = _mediaTypes.First().Id; } - private async Task CreateNewGlobalEntity() + private async Task OnPictureUploaded(IBrowserFile file) { - if (Picture is null) - { - throw new InvalidOperationException("No Picture selected."); - } + _picture = file; - if (AppUser is null) - { - throw new InvalidOperationException("User not loaded or not logged in."); - } + // Base64-Vorschau generieren (max. 5 MB) + const long maxPreviewSize = 5 * 1024 * 1024; + await using var stream = file.OpenReadStream(maxPreviewSize); + using var ms = new MemoryStream(); + await stream.CopyToAsync(ms); - //Save Picture and Name it - string NewFileName = $"{newGlobalEntity.Title.Replace(" ", "-")}-{Guid.NewGuid()}{Path.GetExtension(Picture.Name)}"; - string PicturePath = Path.Combine("wwwroot", "Pictures", NewFileName); - using FileStream FileStream = File.Create(PicturePath); - await Picture.OpenReadStream().CopyToAsync(FileStream); - //await Picture.OpenReadStream(maxAllowedSize: 10_000_000).CopyToAsync(FileStream); - - newGlobalEntity.PicturePath = $"Pictures/{NewFileName}"; - newGlobalEntity.CreatorId = AppUser.Id; - newGlobalEntity.TypeId = SelectedMediaTypeId; - newGlobalEntity.CreationTime = DateTime.Now; - newGlobalEntity.IsPrivate = IsPrivate; - - CouchLogDB.Add(newGlobalEntity); - await CouchLogDB.SaveChangesAsync(); - - foreach(int GenreId in GenreIds) - { - LinkTableGlobalGenre LinkTableGlobalGenre = new() { GenreId = GenreId, GlobalEntityId = newGlobalEntity.Id }; - CouchLogDB.Add(LinkTableGlobalGenre); - } - - await CouchLogDB.SaveChangesAsync(); - NavigationManager.NavigateTo(NavigationManager.Uri, true); + var base64 = Convert.ToBase64String(ms.ToArray()); + _imagePreviewUrl = $"data:{file.ContentType};base64,{base64}"; } - private void AddGenreIdToGenreIdList(int GenreId) + private void Cancel() => MudDialog.Cancel(); + + private async Task HandleSubmit(EditContext ctx) { - if (!GenreIds.Contains(GenreId)) + if (!ctx.Validate()) return; + + if (_picture is null) { - GenreIds.Add(GenreId); + Snackbar.Add("Please upload a picture.", Severity.Warning); + return; + } + + if (_selectedMediaTypeId == 0) + { + Snackbar.Add("Please select a media type.", Severity.Warning); + return; + } + + _isSaving = true; + + try + { + string safeTitle = _form.Title.Replace(" ", "-"); + string fileName = $"{safeTitle}-{Guid.NewGuid()}{Path.GetExtension(_picture.Name)}"; + string picturePath = Path.Combine("wwwroot", "Pictures", fileName); + + await using (var fs = File.Create(picturePath)) + { + await _picture.OpenReadStream(maxAllowedSize: 10_000_000).CopyToAsync(fs); + } + + var entity = new GlobalEntity + { + Title = _form.Title, + PicturePath = $"Pictures/{fileName}", + CreatorId = _appUser!.Id, + TypeId = _selectedMediaTypeId, + CreationTime = DateTime.UtcNow, + IsPrivate = _isPrivate + }; + + CouchLogDB.Add(entity); + await CouchLogDB.SaveChangesAsync(); + + foreach (int genreId in _selectedGenreIds) + { + CouchLogDB.Add(new LinkTableGlobalGenre + { + GenreId = genreId, + GlobalEntityId = entity.Id + }); + } + + await CouchLogDB.SaveChangesAsync(); + + Snackbar.Add("Global Entity created!", Severity.Success); + MudDialog.Close(DialogResult.Ok(entity.Id)); + } + catch (Exception ex) + { + Snackbar.Add($"Error: {ex.Message}", Severity.Error); + } + finally + { + _isSaving = false; } } -} \ No newline at end of file +}