Compare commits
3
Commits
b704dbc30e
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ccbe8cf65 | ||
|
|
1e79620272 | ||
|
|
8435545bec |
No files matched your search
@@ -3,7 +3,7 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"dotnet-ef": {
|
"dotnet-ef": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.2",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-ef"
|
"dotnet-ef"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ namespace CocktailWeb.Data
|
|||||||
public DbSet<CocktailFlasche> CocktailFlaschen { get; set; }
|
public DbSet<CocktailFlasche> CocktailFlaschen { get; set; }
|
||||||
public DbSet<Cocktail> Cocktails { get; set; }
|
public DbSet<Cocktail> Cocktails { get; set; }
|
||||||
public DbSet<Filler> Fillers { get; set; }
|
public DbSet<Filler> Fillers { get; set; }
|
||||||
|
public DbSet<Glas> Glasses { get; set; }
|
||||||
public DbSet<Glas> Glaeser { get; set; }
|
|
||||||
|
|
||||||
public DbDataContext(IConfiguration configuration)
|
public DbDataContext(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,9 +3,13 @@
|
|||||||
public class Glas
|
public class Glas
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Name { get
|
public string? Name { get; set; }
|
||||||
|
public string DisplayName { get
|
||||||
{
|
{
|
||||||
return $"{Fuellmenge} ml";
|
string name = "";
|
||||||
|
if (Name != null) name += $"{Name} - ";
|
||||||
|
name += $"{Fuellmenge} ml";
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int Fuellmenge { get; set; }
|
public int Fuellmenge { get; set; }
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Whitespace-only changes.
@@ -2,8 +2,8 @@
|
|||||||
{
|
{
|
||||||
public class GeneralSettings
|
public class GeneralSettings
|
||||||
{
|
{
|
||||||
|
|
||||||
public int MaxAllowedUploadSizeInMB { get; set; } = 10;
|
public int MaxAllowedUploadSizeInMB { get; set; } = 10;
|
||||||
|
|
||||||
public string ImageUploadDir { get; set; } = "images";
|
public string ImageUploadDir { get; set; } = "images";
|
||||||
|
|
||||||
public string SerialPort { get; set; } = "COM5";
|
public string SerialPort { get; set; } = "COM5";
|
||||||
|
|||||||
@@ -31,15 +31,30 @@ else
|
|||||||
<h6>
|
<h6>
|
||||||
Stärke
|
Stärke
|
||||||
</h6>
|
</h6>
|
||||||
<div class="btn-group" role="group">
|
@if (!UseNewIntensityCalc)
|
||||||
<button @onclick="() => SetIntensity(-60)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -60 ? "" : "outline-")success"><i class="bi bi-peace fs-5"></i></button>
|
{
|
||||||
<button @onclick="() => SetIntensity(-40)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -40 ? "" : "outline-")success"><i class="bi bi-dash fs-5"></i></button>
|
<div class="btn-group" role="group">
|
||||||
<button @onclick="() => SetIntensity(-20)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -20 ? "" : "outline-")success"><i class="bi bi-dash"></i></button>
|
<button @onclick="() => SetIntensity(-60)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -60 ? "" : "outline-")success"><i class="bi bi-peace fs-5"></i></button>
|
||||||
<button @onclick="() => SetIntensity(0)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity == 0 ? "" : "")warning"><i class="bi bi-circle"></i></button>
|
<button @onclick="() => SetIntensity(-40)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -40 ? "" : "outline-")success"><i class="bi bi-dash fs-5"></i></button>
|
||||||
<button @onclick="() => SetIntensity(20)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 20 ? "" : "outline-")danger"><i class="bi bi-plus"></i></button>
|
<button @onclick="() => SetIntensity(-20)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -20 ? "" : "outline-")success"><i class="bi bi-dash"></i></button>
|
||||||
<button @onclick="() => SetIntensity(40)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 40 ? "" : "outline-")danger"><i class="bi bi-plus fs-5"></i></button>
|
<button @onclick="() => SetIntensity(0)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity == 0 ? "" : "")warning"><i class="bi bi-circle"></i></button>
|
||||||
<button @onclick="() => SetIntensity(60)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 60 ? "" : "outline-")danger"><i class="bi bi-radioactive fs-5"></i></button>
|
<button @onclick="() => SetIntensity(20)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 20 ? "" : "outline-")danger"><i class="bi bi-plus"></i></button>
|
||||||
</div>
|
<button @onclick="() => SetIntensity(40)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 40 ? "" : "outline-")danger"><i class="bi bi-plus fs-5"></i></button>
|
||||||
|
<button @onclick="() => SetIntensity(60)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 60 ? "" : "outline-")danger"><i class="bi bi-radioactive fs-5"></i></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<button @onclick="() => SetIntensityPercentual(-3)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -3 ? "" : "outline-")success"><i class="bi bi-peace fs-5"></i></button>
|
||||||
|
<button @onclick="() => SetIntensityPercentual(-2)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -2 ? "" : "outline-")success"><i class="bi bi-dash fs-5"></i></button>
|
||||||
|
<button @onclick="() => SetIntensityPercentual(-1)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity <= -1 ? "" : "outline-")success"><i class="bi bi-dash"></i></button>
|
||||||
|
<button @onclick="() => SetIntensityPercentual(0)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity == 0 ? "" : "")warning"><i class="bi bi-circle"></i></button>
|
||||||
|
<button @onclick="() => SetIntensityPercentual(1)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 1 ? "" : "outline-")danger"><i class="bi bi-plus"></i></button>
|
||||||
|
<button @onclick="() => SetIntensityPercentual(2)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 2 ? "" : "outline-")danger"><i class="bi bi-plus fs-5"></i></button>
|
||||||
|
<button @onclick="() => SetIntensityPercentual(3)" class="btn @(SelectedCocktail.IsAlcoholic ? "" : "disabled") btn-@(DrinkIntensity >= 3 ? "" : "outline-")danger"><i class="bi bi-radioactive fs-5"></i></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@if (ErrorMessage != null)
|
@if (ErrorMessage != null)
|
||||||
@@ -48,12 +63,12 @@ else
|
|||||||
@ErrorMessage
|
@ErrorMessage
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if(CocktailCode != null)
|
@if (CocktailCode != null)
|
||||||
{
|
{
|
||||||
<div class="alert alert-dark" style="white-space: pre-line" role="alert">
|
<div class="alert alert-dark" style="white-space: pre-line" role="alert">
|
||||||
@CocktailCode
|
@CocktailCode
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<button class="btn btn-primary" @onclick=CreateCocktailCode>Lets goooooo!</button>
|
<button class="btn btn-primary" @onclick=CreateCocktailCode>Lets goooooo!</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -120,6 +135,8 @@ else
|
|||||||
|
|
||||||
private int DrinkIntensity = 0;
|
private int DrinkIntensity = 0;
|
||||||
|
|
||||||
|
private bool UseNewIntensityCalc = false;
|
||||||
|
|
||||||
private string? ErrorMessage;
|
private string? ErrorMessage;
|
||||||
private string? CocktailCode;
|
private string? CocktailCode;
|
||||||
|
|
||||||
@@ -181,6 +198,9 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Erstellt den für die Arduino-Steuerung erforderlichen Code
|
||||||
|
/// </summary>
|
||||||
private void CreateCocktailCode()
|
private void CreateCocktailCode()
|
||||||
{
|
{
|
||||||
CocktailCode = null;
|
CocktailCode = null;
|
||||||
@@ -196,50 +216,93 @@ else
|
|||||||
if (Filler.Type == Filler.FillerType.Pump)
|
if (Filler.Type == Filler.FillerType.Pump)
|
||||||
{
|
{
|
||||||
line = $"P{Filler.Pos}={Zutat.Menge}";
|
line = $"P{Filler.Pos}={Zutat.Menge}";
|
||||||
} else if (Filler.Type == Filler.FillerType.Pourer)
|
}
|
||||||
|
else if (Filler.Type == Filler.FillerType.Pourer)
|
||||||
{
|
{
|
||||||
line = $"F{Filler.Pos}={Zutat.Menge}";
|
line = $"F{Filler.Pos}={Zutat.Menge}";
|
||||||
}
|
}
|
||||||
lines.Add(line);
|
lines.Add(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
lines.Add("ZIEL");
|
lines.Add("ZIEL");
|
||||||
CocktailCode = String.Join("\r\n", lines.ToArray());
|
CocktailCode = String.Join("\r\n", lines.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Setzt die Alkoholintensität
|
/// Setzt die Alkoholintensität und berechnet die Mengen für ModifiedCocktail entsprechend neu
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="intensity">Zugabe/Abzug von Alkohol in Prozent</param>
|
/// <param name="intensity">Zugabe/Abzug von Alkohol in Prozent</param>
|
||||||
private void SetIntensity(int intensity)
|
private void SetIntensity(int intensity)
|
||||||
{
|
{
|
||||||
DrinkIntensity = intensity;
|
DrinkIntensity = intensity;
|
||||||
if (ModifiedCocktail != null && SelectedCocktail != null)
|
if (ModifiedCocktail == null || SelectedCocktail == null) return;
|
||||||
|
|
||||||
|
foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen)
|
||||||
{
|
{
|
||||||
|
int OriginalMenge = SelectedCocktail.Cocktailflaschen.First(scf => scf.Id == cf.Id).Menge;
|
||||||
foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen)
|
if (cf.Flasche.Alkoholisch)
|
||||||
{
|
{
|
||||||
int OriginalMenge = SelectedCocktail.Cocktailflaschen.First(scf => scf.FlascheID == cf.FlascheID).Menge;
|
cf.Menge = OriginalMenge + (OriginalMenge * intensity / 100);
|
||||||
if (cf.Flasche.Alkoholisch)
|
|
||||||
{
|
|
||||||
cf.Menge = OriginalMenge + (OriginalMenge * intensity / 100);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cf.Menge = OriginalMenge - (OriginalMenge * intensity / 100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Durch das anteilige Umrechnen ändert sich die Gesamtmenge, daher passen wir die Mengen nochmal an
|
|
||||||
int AktGesMenge = ModifiedCocktail.Cocktailflaschen.Sum(cf => cf.Menge);
|
|
||||||
int OrigMenge = SelectedCocktail.Cocktailflaschen.Sum(cf => cf.Menge);
|
|
||||||
foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen)
|
|
||||||
{
|
{
|
||||||
cf.Menge = (int)((float)cf.Menge / AktGesMenge * OrigMenge);
|
cf.Menge = OriginalMenge - (OriginalMenge * intensity / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Durch das anteilige Umrechnen ändert sich die Gesamtmenge, daher passen wir die Mengen nochmal an
|
||||||
|
int AktGesMenge = ModifiedCocktail.Cocktailflaschen.Sum(cf => cf.Menge);
|
||||||
|
int OrigMenge = SelectedCocktail.Cocktailflaschen.Sum(cf => cf.Menge);
|
||||||
|
foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen)
|
||||||
|
{
|
||||||
|
cf.Menge = (int)((float)cf.Menge / AktGesMenge * OrigMenge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ToDo: Ggf. noch Rundungsfehler drin oder wirklich noch grobe Fehler in der Mathematik.. Gesamtmenge passt irgendwie nicht.
|
||||||
|
/// <summary>
|
||||||
|
/// Ändert die Alkoholintensität basierend auf den Prozentwerten anstatt der Menge
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="intensitylevel">Intensitätslevel (z.B. -1, 0, 1,2 ...)</param>
|
||||||
|
private void SetIntensityPercentual(int intensitylevel)
|
||||||
|
{
|
||||||
|
DrinkIntensity = intensitylevel;
|
||||||
|
if (ModifiedCocktail == null || SelectedCocktail == null) return;
|
||||||
|
int DivideParts = 4; // Gibt an, in wieviele Teile die nicht-alkoholische Gesamtmenge aufgeteilt wird. Sollte mindestens 1 oder 2 mehr als das Max.Intensitätslevel sein
|
||||||
|
float IncreasePerLevel_pct; // Gibt an, um welchen Anteil in % die alkoholischen Getränke steigen.
|
||||||
|
|
||||||
|
float SumAlcoholic_ml = SelectedCocktail.Cocktailflaschen.Where(cf => cf.Flasche.Alkoholisch).Sum(cf => cf.Menge); // Summe in ml der Alkoholhaltigen Zutaten
|
||||||
|
float SumNonAlcoholic_ml = SelectedCocktail.Cocktailflaschen.Where(cf => !cf.Flasche.Alkoholisch).Sum(cf => cf.Menge); // Summe in ml der Alkoholfreien Zutaten
|
||||||
|
float SumTotal = SumAlcoholic_ml + SumNonAlcoholic_ml;
|
||||||
|
float SumAlcoholic_pct = SumAlcoholic_ml / SumTotal * 100; //Prozentwert an alkoholhaltigen Zutaten
|
||||||
|
float SumNonAlcoholic_pct = SumNonAlcoholic_ml / SumTotal * 100; //Prozentwert an alkoholhaltigen Zutaten
|
||||||
|
float SumBasis_ml = intensitylevel >= 0 ? SumNonAlcoholic_ml : SumAlcoholic_ml; // Wenn Intensität > 0, dann ist Summenbasis nichtalkoholisch, ansonsten alkoholisch
|
||||||
|
if (intensitylevel >= 0)
|
||||||
|
{
|
||||||
|
/// Wenn alkoholhaltiges 30% ausmacht, teilen wir den Rest (alkoholfreis, 70%) durch die o.g. DivideParts, damit wir wissen um wieviel Prozent pro Stufe wir erhöhen können
|
||||||
|
IncreasePerLevel_pct = SumNonAlcoholic_pct / DivideParts;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cocktail abschwächen, daher teilen wir in die andere Richtung auf
|
||||||
|
IncreasePerLevel_pct = SumAlcoholic_pct / DivideParts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach (CocktailFlasche cf in ModifiedCocktail.Cocktailflaschen)
|
||||||
|
{
|
||||||
|
float OrigMenge = SelectedCocktail.Cocktailflaschen.First(f => f.Id == cf.Id).Menge;
|
||||||
|
// Herausfinden, wieviel Prozent die Zutat in ihrem Bereich (Alkoholisch/Nichtalkoholisch) ausmacht
|
||||||
|
float ZutatIncrease_pct = IncreasePerLevel_pct / SumBasis_ml * cf.Menge;
|
||||||
|
float ZutatMenge_pct = (float)OrigMenge / SumTotal * 100;
|
||||||
|
// Neue Menge in Prozent: ZutatMenge_pct + ZutatIncrease_pct
|
||||||
|
if (!cf.Flasche.Alkoholisch ^ intensitylevel < 0 )
|
||||||
|
{
|
||||||
|
ZutatIncrease_pct *= -1;
|
||||||
|
}
|
||||||
|
cf.Menge = (int)Math.Round(OrigMenge / ZutatMenge_pct * (ZutatMenge_pct + (ZutatIncrease_pct * intensitylevel)), 0, MidpointRounding.AwayFromZero);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
private string modalClass = "";
|
private string modalClass = "";
|
||||||
private bool showBackdrop = false;
|
private bool showBackdrop = false;
|
||||||
|
|
||||||
public async Task OpenModal()
|
public async Task ShowAsync()
|
||||||
{
|
{
|
||||||
modalDisplay = "block;";
|
modalDisplay = "block;";
|
||||||
await Task.Delay(100);//Delay allows bootstrap to perform nice fade animation
|
await Task.Delay(100);//Delay allows bootstrap to perform nice fade animation
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
showBackdrop = true;
|
showBackdrop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Close()
|
public async Task CloseAsync()
|
||||||
{
|
{
|
||||||
modalDisplay = "none";
|
modalDisplay = "none";
|
||||||
await Task.Delay(250);//Delay allows bootstrap to perform nice fade animation
|
await Task.Delay(250);//Delay allows bootstrap to perform nice fade animation
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ModalComponent @ref="modal">
|
<ModalComponent @ref="modal">
|
||||||
@@ -67,13 +66,13 @@
|
|||||||
private async Task ConfirmDelete(Cocktail c)
|
private async Task ConfirmDelete(Cocktail c)
|
||||||
{
|
{
|
||||||
SelectedCocktail = c;
|
SelectedCocktail = c;
|
||||||
await modal.OpenModal();
|
await modal.ShowAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CloseDialog()
|
private async Task CloseDialog()
|
||||||
{
|
{
|
||||||
SelectedCocktail = null;
|
SelectedCocktail = null;
|
||||||
await modal.Close();
|
await modal.CloseAsync();
|
||||||
}
|
}
|
||||||
private async Task DeleteCocktail(MouseEventArgs e)
|
private async Task DeleteCocktail(MouseEventArgs e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
@page "/settings/glasses/edit"
|
||||||
|
@page "/settings/glasses/edit/{id}"
|
||||||
|
@using CocktailWeb.Data
|
||||||
|
@using Microsoft.AspNetCore.Components.Sections
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using Microsoft.Extensions.Options
|
||||||
|
@inject IDbContextFactory<DbDataContext> DataContextFactory;
|
||||||
|
@inject NavigationManager nav;
|
||||||
|
@inject IWebHostEnvironment env;
|
||||||
|
@inject IOptions<GeneralSettings> Config;
|
||||||
|
|
||||||
|
<SectionContent SectionId="TopRow.Title">
|
||||||
|
<label>Glas bearbeiten</label>
|
||||||
|
</SectionContent>
|
||||||
|
|
||||||
|
<EditForm EditContext="editContext" OnValidSubmit="OnSubmit">
|
||||||
|
<div class="d-flex gap-3">
|
||||||
|
<div class="border border-2 rounded p-3 w-100">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="name">Name (optional)</label>
|
||||||
|
<input class="form-control" id="name" name="name" type="text" @bind=@curGlas.Name />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="menge">Füllmenge</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input class="form-control text-end" id="menge" name="menge" type="number" @bind=@curGlas.Fuellmenge />
|
||||||
|
<span class="input-group-text">ml</span>
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="() => ModifyAmount(-10)"><i class="bi bi-dash"></i></button>
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="() => ModifyAmount(10)"><i class="bi bi-plus"></i></button>
|
||||||
|
</div>
|
||||||
|
<div class="form-text"><ValidationMessage For="() => curGlas.Fuellmenge" /></div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="submit" class="btn btn-primary">Speichern</button>
|
||||||
|
<button type="button" @onclick="@(() => nav.NavigateTo(PrevPageURL))" class="btn btn-secondary">Abbrechen</button>
|
||||||
|
</div>
|
||||||
|
<div class="border border-2 rounded p-3 w-100">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="image">Bild</label>
|
||||||
|
<div class="mb-2">
|
||||||
|
@if (curGlas.ImageURL != null)
|
||||||
|
{
|
||||||
|
<img style="max-width:128px;" src="@curGlas.ImageURL" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div>Kein Bild vorhanden</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<label class="form-label" for="image">Neues Bild hochladen</label>
|
||||||
|
<InputFile OnChange="Bild_OnChange" class="form-control" id="image" name="image" accept=".jpg,.png,.jpeg,.gif,.webp" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</EditForm>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter]
|
||||||
|
public string? id { get; set; }
|
||||||
|
|
||||||
|
public Glas curGlas = null!;
|
||||||
|
|
||||||
|
public IBrowserFile? NewImage;
|
||||||
|
|
||||||
|
private DbDataContext? _DataContext;
|
||||||
|
|
||||||
|
private string PrevPageURL = "/settings/glasses";
|
||||||
|
|
||||||
|
EditContext? editContext;
|
||||||
|
ValidationMessageStore? valMessages;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (id != null)
|
||||||
|
{
|
||||||
|
_DataContext ??= await DataContextFactory.CreateDbContextAsync();
|
||||||
|
if (_DataContext != null) curGlas = _DataContext.Glasses.Single(f => f.Id == Convert.ToInt32(id));
|
||||||
|
}
|
||||||
|
curGlas ??= new(); // Falls keine ID angegeben wurde oder der Eintrag in der Datenbank nicht gefunden wurde, gehen wir davon aus dass ein neuer Eintrag erstellt wird.
|
||||||
|
|
||||||
|
editContext = new(curGlas);
|
||||||
|
editContext.OnValidationRequested += editContext_OnValidationRequested;
|
||||||
|
valMessages = new(editContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Bild_OnChange(InputFileChangeEventArgs e)
|
||||||
|
{
|
||||||
|
NewImage = e.GetMultipleFiles().FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ModifyAmount(int amount)
|
||||||
|
{
|
||||||
|
curGlas.Fuellmenge = Math.Max(curGlas.Fuellmenge + amount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void editContext_OnValidationRequested(object? sender, ValidationRequestedEventArgs args)
|
||||||
|
{
|
||||||
|
valMessages?.Clear();
|
||||||
|
if (curGlas.Fuellmenge <= 0) valMessages?.Add(() => curGlas.Fuellmenge, "Füllmenge muss größer 0 sein!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task OnSubmit()
|
||||||
|
{
|
||||||
|
_DataContext ??= await DataContextFactory.CreateDbContextAsync();
|
||||||
|
|
||||||
|
if (curGlas != null && _DataContext != null)
|
||||||
|
{
|
||||||
|
if (id != null)
|
||||||
|
{
|
||||||
|
_DataContext.Glasses.Update(curGlas);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_DataContext.Glasses.Add(curGlas);
|
||||||
|
}
|
||||||
|
await _DataContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
if (NewImage != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Bild hochladen
|
||||||
|
var relativeuploadpath = Path.Join(Config.Value.ImageUploadDir, $"glas_{curGlas.Id}{Path.GetExtension(NewImage.Name)}");
|
||||||
|
var fullpath = Path.Join(env.WebRootPath, relativeuploadpath);
|
||||||
|
string? folder = Path.GetDirectoryName(fullpath);
|
||||||
|
if (folder != null && !Path.Exists(folder)) Directory.CreateDirectory(folder);
|
||||||
|
|
||||||
|
Stream stream = NewImage.OpenReadStream(maxAllowedSize: Config.Value.MaxAllowedUploadSizeInMB * 1024 * 1024);
|
||||||
|
FileStream fs = File.Create(fullpath);
|
||||||
|
await stream.CopyToAsync(fs);
|
||||||
|
stream.Close();
|
||||||
|
fs.Close();
|
||||||
|
curGlas.ImageURL = relativeuploadpath;
|
||||||
|
// URL hinterlegen und wieder speichern
|
||||||
|
_DataContext.Glasses.Update(curGlas);
|
||||||
|
await _DataContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error uploading image: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nav.NavigateTo(PrevPageURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +1,90 @@
|
|||||||
@page "/settings/glasses"
|
@page "/settings/glasses"
|
||||||
|
@using CocktailWeb.Data
|
||||||
@using Microsoft.AspNetCore.Components.Sections
|
@using Microsoft.AspNetCore.Components.Sections
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@inject IDbContextFactory<DbDataContext> DataContextFactory
|
||||||
|
|
||||||
<SectionContent SectionId="TopRow.Title">
|
<SectionContent SectionId="TopRow.Title">
|
||||||
<label>Einstellungen - Gläser</label>
|
<label>Einstellungen - Gläser</label>
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="btn btn-primary mb-3" href="/settings/glasses/edit">Glas hinzufügen</a>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-hover table-bordered table-dark border-dark">
|
||||||
|
<tbody>
|
||||||
|
@foreach (Glas g in GlassList)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td class="p-0" style="width:64px"><img src="@g.ImageURL" style="max-width:100%; max-height:auto;" /></td>
|
||||||
|
<td style="vertical-align:middle;">@g.DisplayName</td>
|
||||||
|
<td style="text-align:right; vertical-align:middle;">
|
||||||
|
<a class="btn btn-primary" href="/settings/glasses/edit/@g.Id">Bearbeiten</a>
|
||||||
|
<button name="submit" type="submit" class="btn btn-outline-danger" @onclick="() => ConfirmDeleteAsync(g)">Löschen</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ModalComponent @ref="modal">
|
||||||
|
<Title>Löschen bestätigen</Title>
|
||||||
|
<Body>
|
||||||
|
Willst du das Glas wirklich löschen?
|
||||||
|
</Body>
|
||||||
|
<Footer>
|
||||||
|
<button class="btn btn-danger" @onclick="DeleteGlassAsync">Jo</button>
|
||||||
|
<button class="btn btn-primary" @onclick="CloseDialogAsync">Nee</button>
|
||||||
|
</Footer>
|
||||||
|
</ModalComponent>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private List<Glas> GlassList = new();
|
||||||
|
private DbDataContext? _DataContext;
|
||||||
|
|
||||||
|
private ModalComponent modal = null!;
|
||||||
|
private Glas? SelectedGlas;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await ShowGlassesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ShowGlassesAsync()
|
||||||
|
{
|
||||||
|
_DataContext ??= await DataContextFactory.CreateDbContextAsync();
|
||||||
|
if (_DataContext != null)
|
||||||
|
{
|
||||||
|
GlassList = _DataContext.Glasses.OrderBy(g => g.Fuellmenge).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ConfirmDeleteAsync(Glas g)
|
||||||
|
{
|
||||||
|
SelectedGlas = g;
|
||||||
|
await modal.ShowAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteGlassAsync()
|
||||||
|
{
|
||||||
|
if (SelectedGlas == null) return;
|
||||||
|
_DataContext ??= await DataContextFactory.CreateDbContextAsync();
|
||||||
|
if (_DataContext != null)
|
||||||
|
{
|
||||||
|
_DataContext.Glasses.Remove(SelectedGlas);
|
||||||
|
await _DataContext.SaveChangesAsync();
|
||||||
|
await ShowGlassesAsync();
|
||||||
|
}
|
||||||
|
await CloseDialogAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CloseDialogAsync()
|
||||||
|
{
|
||||||
|
SelectedGlas = null;
|
||||||
|
await modal.CloseAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -105,12 +105,12 @@
|
|||||||
if (CocktailsWithIngredient.Count > 0)
|
if (CocktailsWithIngredient.Count > 0)
|
||||||
{
|
{
|
||||||
InfoText = String.Join(", ", CocktailsWithIngredient.Select(c => c.Name).ToArray());
|
InfoText = String.Join(", ", CocktailsWithIngredient.Select(c => c.Name).ToArray());
|
||||||
await dlgInfo.OpenModal();
|
await dlgInfo.ShowAsync();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SelectedIngredient = fl;
|
SelectedIngredient = fl;
|
||||||
await dlgDelete.OpenModal();
|
await dlgDelete.ShowAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +133,6 @@
|
|||||||
private async Task CloseDialog(ModalComponent dlg)
|
private async Task CloseDialog(ModalComponent dlg)
|
||||||
{
|
{
|
||||||
SelectedIngredient = null;
|
SelectedIngredient = null;
|
||||||
await dlg.Close();
|
await dlg.CloseAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ namespace CocktailWeb.Pages.Settings
|
|||||||
{
|
{
|
||||||
SelectedFiller = f;
|
SelectedFiller = f;
|
||||||
SelectedFlasche = f.Flasche;
|
SelectedFlasche = f.Flasche;
|
||||||
await modal.OpenModal();
|
await modal.ShowAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ namespace CocktailWeb.Pages.Settings
|
|||||||
{
|
{
|
||||||
SelectedFiller = null;
|
SelectedFiller = null;
|
||||||
SelectedFlasche = null;
|
SelectedFlasche = null;
|
||||||
await modal.Close();
|
await modal.CloseAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,14 +104,14 @@
|
|||||||
|
|
||||||
private async Task OpenDialog()
|
private async Task OpenDialog()
|
||||||
{
|
{
|
||||||
await Pwd_Dialog.OpenModal();
|
await Pwd_Dialog.ShowAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CloseDialog()
|
private async Task CloseDialog()
|
||||||
{
|
{
|
||||||
Pwd_ErrorText = null;
|
Pwd_ErrorText = null;
|
||||||
Pwd_inputPassword = null;
|
Pwd_inputPassword = null;
|
||||||
await Pwd_Dialog.Close();
|
await Pwd_Dialog.CloseAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File renamed without changes.
Binary file not shown.
Reference in new issue
Block a user