Initial commit
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY ["Francesco.Recipes.World/Francesco.Recipes.World.csproj", "Francesco.Recipes.World/"]
|
||||||
|
RUN dotnet restore "Francesco.Recipes.World/Francesco.Recipes.World.csproj"
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/Francesco.Recipes.World"
|
||||||
|
RUN dotnet publish "Francesco.Recipes.World.csproj" -c Release -o /app/publish
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "Francesco.Recipes.World.dll"]
|
||||||
@@ -32,14 +32,52 @@
|
|||||||
return BadRequest("No ingredients provided.");
|
return BadRequest("No ingredients provided.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var shoppingList = await _shoppingListRepository.AddIngredientsToShoppingListAsync(request.RecipeId, request.IngredientIds);
|
// Compute duplicates for this recipe in the current shopping list
|
||||||
|
var existingShoppingList = await _context.ShoppingLists
|
||||||
|
.Include(sl => sl.RecipeShoppingList)
|
||||||
|
.ThenInclude(rsl => rsl.SelectedIngredients)
|
||||||
|
.ThenInclude(si => si.RecipeIngredient)
|
||||||
|
.Include(sl => sl.RecipeShoppingList)
|
||||||
|
.ThenInclude(rsl => rsl.Recipe)
|
||||||
|
.FirstOrDefaultAsync(sl => sl.RecipeShoppingList.Any(rsl => rsl.Recipe.Id == request.RecipeId));
|
||||||
|
|
||||||
|
var existingForRecipe = existingShoppingList?
|
||||||
|
.RecipeShoppingList.FirstOrDefault(rsl => rsl.Recipe.Id == request.RecipeId);
|
||||||
|
|
||||||
|
var existingIds = existingForRecipe?.SelectedIngredients
|
||||||
|
.Where(si => si.RecipeIngredient != null)
|
||||||
|
.Select(si => si.RecipeIngredient.Id)
|
||||||
|
.ToHashSet() ?? new HashSet<Guid>();
|
||||||
|
|
||||||
|
var skippedExisting = request.IngredientIds.Where(id => existingIds.Contains(id)).Distinct().ToList();
|
||||||
|
var ingredientIdsToAdd = request.IngredientIds.Except(skippedExisting).Distinct().ToList();
|
||||||
|
|
||||||
|
if (ingredientIdsToAdd.Count == 0)
|
||||||
|
{
|
||||||
|
return Json(new
|
||||||
|
{
|
||||||
|
shoppingListId = existingShoppingList?.Id,
|
||||||
|
skippedExisting,
|
||||||
|
addedCount = 0,
|
||||||
|
skippedCount = skippedExisting.Count,
|
||||||
|
noAdditions = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var shoppingList = await _shoppingListRepository.AddIngredientsToShoppingListAsync(request.RecipeId, ingredientIdsToAdd);
|
||||||
|
|
||||||
if (shoppingList == null)
|
if (shoppingList == null)
|
||||||
{
|
{
|
||||||
return BadRequest("Error creating shopping list.");
|
return BadRequest("Error creating shopping list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Json(new { shoppingListId = shoppingList.Id });
|
return Json(new
|
||||||
|
{
|
||||||
|
shoppingListId = shoppingList.Id,
|
||||||
|
skippedExisting,
|
||||||
|
addedCount = ingredientIdsToAdd.Count,
|
||||||
|
skippedCount = skippedExisting.Count,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("RecipeCount")]
|
[HttpGet("RecipeCount")]
|
||||||
|
|||||||
@@ -196,10 +196,28 @@
|
|||||||
})
|
})
|
||||||
.then(result => {
|
.then(result => {
|
||||||
localStorage.setItem('shoppingListId', result.shoppingListId);
|
localStorage.setItem('shoppingListId', result.shoppingListId);
|
||||||
alert('Einkaufsliste aktualisiert.');
|
const showInfo = (msg) => {
|
||||||
|
if (window.Swal) {
|
||||||
|
Swal.fire({ icon: 'info', title: 'Hinweis', text: msg, timer: 1800, showConfirmButton: false });
|
||||||
|
} else { alert(msg); }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (result.skippedCount && result.skippedCount > 0) {
|
||||||
|
if (result.addedCount && result.addedCount > 0) {
|
||||||
|
showInfo(`Einkaufsliste aktualisiert. ${result.skippedCount} Zutaten waren bereits vorhanden und wurden übersprungen.`);
|
||||||
|
} else {
|
||||||
|
showInfo('Diese Zutaten sind bereits in der Einkaufsliste vorhanden.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showInfo('Einkaufsliste aktualisiert.');
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
alert('Fehler beim Aktualisieren der Einkaufsliste.');
|
if (window.Swal) {
|
||||||
|
Swal.fire({ icon: 'error', title: 'Fehler', text: 'Fehler beim Aktualisieren der Einkaufsliste.' });
|
||||||
|
} else {
|
||||||
|
alert('Fehler beim Aktualisieren der Einkaufsliste.');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
id = ri.Id,
|
id = ri.Id,
|
||||||
name = ri.Ingredient.Name,
|
name = ri.Ingredient.Name,
|
||||||
amount = ri.Quantity,
|
amount = ri.Quantity,
|
||||||
unit = ri.Unit.Name,
|
unit = ri.Unit.Symbol,
|
||||||
shoppingListId = Model.RecipeIngredientToShoppingListMap.ContainsKey(ri.Id)
|
shoppingListId = Model.RecipeIngredientToShoppingListMap.ContainsKey(ri.Id)
|
||||||
? Model.RecipeIngredientToShoppingListMap[ri.Id]
|
? Model.RecipeIngredientToShoppingListMap[ri.Id]
|
||||||
: Guid.Empty
|
: Guid.Empty
|
||||||
@@ -104,3 +104,4 @@
|
|||||||
</script>
|
</script>
|
||||||
<script src="~/js/site.js"></script>
|
<script src="~/js/site.js"></script>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"FrancescosRecipesWorldDbContextConnection": "Server=sqlserver-recipes,1433;Database=Francesco.Recipes.World;User Id=sa;Password=YourRecipesPassword123!;TrustServerCertificate=True;MultipleActiveResultSets=true"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
networks:
|
||||||
|
recipesnet-dev:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
francescos-recipes-world:
|
||||||
|
container_name: francescos-recipes-world-dev
|
||||||
|
depends_on:
|
||||||
|
sqlserver-recipes:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- TZ=Europe/Zurich
|
||||||
|
- ConnectionStrings__FrancescosRecipesWorldDbContextConnection=Server=sqlserver-recipes,1433;Database=Francesco.Recipes.World;User Id=sa;Password=YourRecipesPassword123!;TrustServerCertificate=True;MultipleActiveResultSets=true
|
||||||
|
image: francesco448/francescos.recipes.world:latest
|
||||||
|
networks:
|
||||||
|
- recipesnet-dev
|
||||||
|
ports:
|
||||||
|
- '9003:8080'
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /mnt/PoolHDD/AppData/Francescos--Recipes-World/app:/app
|
||||||
|
working_dir: /app
|
||||||
|
|
||||||
|
sqlserver-recipes:
|
||||||
|
container_name: sqlserver-recipes-dev
|
||||||
|
environment:
|
||||||
|
- ACCEPT_EULA=Y
|
||||||
|
- SA_PASSWORD=YourRecipesPassword123!
|
||||||
|
healthcheck:
|
||||||
|
interval: 10s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
test:
|
||||||
|
- CMD-SHELL
|
||||||
|
- >-
|
||||||
|
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P YourRecipesPassword123!
|
||||||
|
-Q 'SELECT 1' -No
|
||||||
|
timeout: 5s
|
||||||
|
image: mcr.microsoft.com/mssql/server:2022-latest
|
||||||
|
networks:
|
||||||
|
- recipesnet-dev
|
||||||
|
ports:
|
||||||
|
- '1702:1433'
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /mnt/PoolHDD/AppData/Francescos--Recipes-World/sqlserver:/var/opt/mssql
|
||||||
Reference in New Issue
Block a user