Implemented simple image upload in ArticleEditor
This commit is contained in:
		
							parent
							
								
									06ce7e995c
								
							
						
					
					
						commit
						4dac73c564
					
				| 
						 | 
				
			
			@ -20,17 +20,6 @@
 | 
			
		|||
	</ul>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="my-3 flex flex-wrap gap-4">
 | 
			
		||||
	@foreach (var image in Article.Images) {
 | 
			
		||||
		<figure>
 | 
			
		||||
			<img src="/images/@(image.Id)?size=400" width="400" alt="@image.ImageDescription"/>
 | 
			
		||||
			<figcaption>
 | 
			
		||||
				@image.ImageDescription
 | 
			
		||||
			</figcaption>
 | 
			
		||||
		</figure>
 | 
			
		||||
	}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<EditForm method="post" FormName="article-editor" Model="@Model" OnValidSubmit="OnValidSubmit">
 | 
			
		||||
	<DataAnnotationsValidator/>
 | 
			
		||||
	<input type="hidden" @bind-value="@Model.Id"/>
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +143,23 @@
 | 
			
		|||
		}
 | 
			
		||||
	</div>
 | 
			
		||||
</EditForm>
 | 
			
		||||
<CategoryPicker/>
 | 
			
		||||
 | 
			
		||||
<ImageModal Id="@ImageModal" ImageAdded="ImageAdded" />
 | 
			
		||||
<div class="my-3 flex flex-wrap gap-4 min-h-24">
 | 
			
		||||
	@foreach (var image in Article.Images) {
 | 
			
		||||
		<figure class="p-2 bg-base-200">
 | 
			
		||||
			<img class="w-40" src="/images/@(image.Id)?size=400" width="400"
 | 
			
		||||
			     title="@image.ImageDescription" alt="@image.ImageDescription"/>
 | 
			
		||||
			<figcaption>
 | 
			
		||||
				<button type="button" class="btn btn-info w-full mt-3"
 | 
			
		||||
						onclick="navigator.clipboard.writeText(')?size=400)')">
 | 
			
		||||
					@Localizer["Image_CopyLink"]
 | 
			
		||||
				</button>
 | 
			
		||||
			</figcaption>
 | 
			
		||||
		</figure>
 | 
			
		||||
	}
 | 
			
		||||
	<button type="button" class="btn" onclick="@(ImageModal).showModal()">@Localizer["Image_Add_Label"]</button>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<SectionContent SectionName="scripts">
 | 
			
		||||
	<script>
 | 
			
		||||
| 
						 | 
				
			
			@ -199,6 +204,8 @@
 | 
			
		|||
</SectionContent>
 | 
			
		||||
 | 
			
		||||
@code {
 | 
			
		||||
	private const string ImageModal = "AddImage";
 | 
			
		||||
 | 
			
		||||
	[Parameter] 
 | 
			
		||||
    public Guid? Id { get; set; }
 | 
			
		||||
	[Parameter] 
 | 
			
		||||
| 
						 | 
				
			
			@ -281,6 +288,14 @@
 | 
			
		|||
 | 
			
		||||
			Model.Categories ??= [];
 | 
			
		||||
			context.Update(Article);
 | 
			
		||||
 | 
			
		||||
			var existingImages = await context.Set<Article>().Where(a => a.Id == Article.Id)
 | 
			
		||||
				.SelectMany(a => a.Images).ToListAsync();
 | 
			
		||||
			foreach (var image in Article.Images) {
 | 
			
		||||
				context.Entry(image).State = 
 | 
			
		||||
					existingImages.Any(i => i.Id == image.Id) ? 
 | 
			
		||||
						EntityState.Modified : EntityState.Added;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			var relations = await context.Set<ArticleCategory>()
 | 
			
		||||
				.IgnoreQueryFilters().IgnoreAutoIncludes()
 | 
			
		||||
| 
						 | 
				
			
			@ -335,6 +350,11 @@
 | 
			
		|||
		Model.Categories = selected?.Select(Guid.Parse).ToArray();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private async Task ImageAdded(ArticleImage image) {
 | 
			
		||||
		Article.Images.Add(image);
 | 
			
		||||
		await InvokeAsync(StateHasChanged);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private sealed class InputModel {
 | 
			
		||||
		public Guid? Id { get; set; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -346,5 +366,4 @@
 | 
			
		|||
		public Guid[]? Categories { get; set; }
 | 
			
		||||
		public DateTimeOffset? PublishDate { get; set; }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								Wave/Components/Pages/Partials/ImageModal.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								Wave/Components/Pages/Partials/ImageModal.razor
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,69 @@
 | 
			
		|||
@using Wave.Services
 | 
			
		||||
@using Wave.Data
 | 
			
		||||
 | 
			
		||||
@inject ImageService Images
 | 
			
		||||
@inject IStringLocalizer<ArticleEditor> Localizer
 | 
			
		||||
 | 
			
		||||
<ModalComponent Id="@Id" ShowCloseButton="false">
 | 
			
		||||
	<ChildContent>
 | 
			
		||||
		@if (Image != null) {
 | 
			
		||||
			<figure>
 | 
			
		||||
				<img src="/images/@(Image)" alt=""/>
 | 
			
		||||
			</figure>
 | 
			
		||||
		}
 | 
			
		||||
		<FileUploadComponent FileUploadedCallback="FileChanged"/>
 | 
			
		||||
		
 | 
			
		||||
		<InputLabelComponent LabelText="@Localizer["Image_Description_Label"]">
 | 
			
		||||
			<InputText class="input input-bordered w-full" maxlength="2048"
 | 
			
		||||
			           @bind-Value="@ImageDescription" 
 | 
			
		||||
			           placeholder="@Localizer["Image_Description_Placeholder"]" 
 | 
			
		||||
			           autocomplete="off" />
 | 
			
		||||
		</InputLabelComponent>
 | 
			
		||||
	</ChildContent>
 | 
			
		||||
	<Actions>
 | 
			
		||||
		<button class="btn btn-primary" @onclick="Save">@Localizer["Image_Add_Submit"]</button>
 | 
			
		||||
		<form method="dialog">
 | 
			
		||||
			<button type="submit" class="btn btn-error" @onclick="Cancel">@Localizer["Image_Add_Abort"]</button>
 | 
			
		||||
		</form>
 | 
			
		||||
	</Actions>
 | 
			
		||||
</ModalComponent>
 | 
			
		||||
 | 
			
		||||
@code {
 | 
			
		||||
	[Parameter]
 | 
			
		||||
	public required string Id { get; set; }
 | 
			
		||||
	[Parameter]
 | 
			
		||||
	public required EventCallback<ArticleImage> ImageAdded { get; set; }
 | 
			
		||||
 | 
			
		||||
	private Guid? Image { get; set; }
 | 
			
		||||
	private string ImageDescription { get; set; } = string.Empty;
 | 
			
		||||
	
 | 
			
		||||
	private async Task FileChanged(string tempPath) {
 | 
			
		||||
		if (Image is { } img) {
 | 
			
		||||
			Image = null;
 | 
			
		||||
			Images.Delete(img);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Image = await Images.StoreImageAsync(tempPath);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private async Task Save() {
 | 
			
		||||
		if (Image is null) return;
 | 
			
		||||
 | 
			
		||||
		await ImageAdded.InvokeAsync(new ArticleImage {
 | 
			
		||||
			Id = Image.Value,
 | 
			
		||||
			ImageDescription = ImageDescription
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		Image = null;
 | 
			
		||||
		ImageDescription = string.Empty;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void Cancel() {
 | 
			
		||||
		if (Image is { } img) {
 | 
			
		||||
			Image = null;
 | 
			
		||||
			Images.Delete(img);
 | 
			
		||||
		}
 | 
			
		||||
		ImageDescription = string.Empty;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -191,4 +191,31 @@
 | 
			
		|||
  <data name="Tools_Mark_Tooltip" xml:space="preserve">
 | 
			
		||||
    <value>Den selektierten Text markieren</value>
 | 
			
		||||
  </data>
 | 
			
		||||
    <data name="Categories_Label" xml:space="preserve">
 | 
			
		||||
        <value>Kategorie</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Add_Label" xml:space="preserve">
 | 
			
		||||
        <value>Bild Hochladen</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Description_Label" xml:space="preserve">
 | 
			
		||||
        <value>Bildbeschreibung</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Description_Placeholder" xml:space="preserve">
 | 
			
		||||
        <value>Ein Bild eines Käsekuchen</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Add_Submit" xml:space="preserve">
 | 
			
		||||
        <value>Hinzufügen</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Add_Abort" xml:space="preserve">
 | 
			
		||||
        <value>Schließen</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Save_Success" xml:space="preserve">
 | 
			
		||||
        <value>Artikel Gespeichert</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Save_Error" xml:space="preserve">
 | 
			
		||||
        <value>Unbekannter fehler beim speichern des Artikels</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_CopyLink" xml:space="preserve">
 | 
			
		||||
        <value>Link Kopieren</value>
 | 
			
		||||
    </data>
 | 
			
		||||
</root>
 | 
			
		||||
| 
						 | 
				
			
			@ -197,4 +197,31 @@
 | 
			
		|||
  <data name="Tools_Mark_Tooltip" xml:space="preserve">
 | 
			
		||||
    <value>Mark the selected text</value>
 | 
			
		||||
  </data>
 | 
			
		||||
    <data name="Categories_Label" xml:space="preserve">
 | 
			
		||||
        <value>Category</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Add_Label" xml:space="preserve">
 | 
			
		||||
        <value>Upload Image</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Description_Label" xml:space="preserve">
 | 
			
		||||
        <value>Image Description</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Description_Placeholder" xml:space="preserve">
 | 
			
		||||
        <value>A picture of a cheesecake</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Add_Submit" xml:space="preserve">
 | 
			
		||||
        <value>Add</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_Add_Abort" xml:space="preserve">
 | 
			
		||||
        <value>Close</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Save_Success" xml:space="preserve">
 | 
			
		||||
        <value>Article Saved</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Save_Error" xml:space="preserve">
 | 
			
		||||
        <value>Unknown error saving article</value>
 | 
			
		||||
    </data>
 | 
			
		||||
    <data name="Image_CopyLink" xml:space="preserve">
 | 
			
		||||
        <value>Copy Link</value>
 | 
			
		||||
    </data>
 | 
			
		||||
</root>
 | 
			
		||||
							
								
								
									
										2
									
								
								Wave/wwwroot/css/main.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								Wave/wwwroot/css/main.min.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
		Reference in a new issue