Add project files.
This commit is contained in:
4
DXApp.TemplateKitProject/Pages/About.cshtml
Normal file
4
DXApp.TemplateKitProject/Pages/About.cshtml
Normal file
@@ -0,0 +1,4 @@
|
||||
@page
|
||||
<h2 class="content-block">About</h2>
|
||||
|
||||
<p class="content-block dx-card responsive-paddings">Use this area to provide additional information.</p>
|
||||
17
DXApp.TemplateKitProject/Pages/About.cshtml.cs
Normal file
17
DXApp.TemplateKitProject/Pages/About.cshtml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace DXApp.TemplateKitProject.Pages
|
||||
{
|
||||
public class AboutModel : PageModel
|
||||
{
|
||||
public void OnGet()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
9
DXApp.TemplateKitProject/Pages/Error.cshtml
Normal file
9
DXApp.TemplateKitProject/Pages/Error.cshtml
Normal file
@@ -0,0 +1,9 @@
|
||||
@page
|
||||
|
||||
<h2 class="content-block">An error occurred while the server was processing your request.</h2>
|
||||
|
||||
<div class="content-block dx-card responsive-paddings">
|
||||
To display detailed information about the error, set the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong> and restart the app.
|
||||
<br /><br />
|
||||
<strong>The Development environment should not be enabled for deployed applications</strong> because it provides users access to exceptions that can contain sensitive information.
|
||||
</div>
|
||||
19
DXApp.TemplateKitProject/Pages/Error.cshtml.cs
Normal file
19
DXApp.TemplateKitProject/Pages/Error.cshtml.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace DXApp.TemplateKitProject.Pages
|
||||
{
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public class ErrorModel : PageModel
|
||||
{
|
||||
public void OnGet()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
28
DXApp.TemplateKitProject/Pages/Index.cshtml
Normal file
28
DXApp.TemplateKitProject/Pages/Index.cshtml
Normal file
@@ -0,0 +1,28 @@
|
||||
@page
|
||||
@using DXApp.TemplateKitProject.Models
|
||||
|
||||
<h2 class="content-block">Home</h2>
|
||||
|
||||
@(Html.DevExtreme().DataGrid<SampleOrder>()
|
||||
.ElementAttr(new { @class = "dx-card wide-card" })
|
||||
.DataSource(d => d.Mvc().Controller("SampleData").LoadAction("Get").Key("OrderID"))
|
||||
.ShowBorders(false)
|
||||
.FilterRow(f => f.Visible(true))
|
||||
.FocusedRowEnabled(true)
|
||||
.FocusedRowIndex(0)
|
||||
.ColumnAutoWidth(true)
|
||||
.ColumnHidingEnabled(true)
|
||||
.Columns(columns => {
|
||||
columns.AddFor(m => m.OrderID);
|
||||
columns.AddFor(m => m.OrderDate);
|
||||
columns.AddFor(m => m.CustomerName);
|
||||
columns.AddFor(m => m.ShipCountry);
|
||||
columns.AddFor(m => m.ShipCity);
|
||||
})
|
||||
.Paging(p => p.PageSize(10))
|
||||
.Pager(p => p
|
||||
.ShowPageSizeSelector(true)
|
||||
.AllowedPageSizes(new[] { 5, 10, 20 })
|
||||
.ShowInfo(true)
|
||||
)
|
||||
)
|
||||
17
DXApp.TemplateKitProject/Pages/Index.cshtml.cs
Normal file
17
DXApp.TemplateKitProject/Pages/Index.cshtml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace DXApp.TemplateKitProject.Pages
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
public void OnGet()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
67
DXApp.TemplateKitProject/Pages/Invoices/Upload.cshtml
Normal file
67
DXApp.TemplateKitProject/Pages/Invoices/Upload.cshtml
Normal file
@@ -0,0 +1,67 @@
|
||||
@page
|
||||
@model DXApp.TemplateKitProject.Pages.Invoices.UploadModel
|
||||
@{
|
||||
ViewData["Title"] = "PDF/A Upload";
|
||||
}
|
||||
|
||||
<h2>PDF/A Rechnung hochladen</h2>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<div class="mb-3">
|
||||
<label asp-for="PdfFile" class="form-label">PDF/A-Datei auswählen</label>
|
||||
<input asp-for="PdfFile" type="file" class="form-control" accept=".pdf" />
|
||||
<span asp-validation-for="PdfFile" class="text-danger"></span>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Hochladen & Analysieren</button>
|
||||
</form>
|
||||
|
||||
@if (Model.ExtractionDone)
|
||||
{
|
||||
<hr />
|
||||
<h4>Ergebnis</h4>
|
||||
|
||||
@if (!string.IsNullOrEmpty(Model.ErrorMessage))
|
||||
{
|
||||
<div class="alert alert-danger">@Model.ErrorMessage</div>
|
||||
}
|
||||
else if (Model.Result == null || !Model.Result.HasAttachments)
|
||||
{
|
||||
<div class="alert alert-warning">Keine Anhänge in der PDF gefunden.</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert @(Model.Result.HasZugferdXml ? "alert-success" : "alert-warning")">
|
||||
@if (Model.Result.HasZugferdXml)
|
||||
{
|
||||
<strong>✔ ZUGFeRD/Factur-X XML gefunden:</strong>
|
||||
<span>@Model.Result.ZugferdXmlAttachment!.OriginalFileName</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<strong>⚠ Kein ZUGFeRD-XML gefunden.</strong>
|
||||
}
|
||||
</div>
|
||||
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Dateiname</th>
|
||||
<th>Größe</th>
|
||||
<th>ZUGFeRD?</th>
|
||||
<th>Gespeichert unter</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var a in Model.Result.Attachments)
|
||||
{
|
||||
<tr class="@(a.IsZugferdXml ? "table-success" : "")">
|
||||
<td>@a.OriginalFileName</td>
|
||||
<td>@($"{a.FileSizeBytes:N0}") Bytes</td>
|
||||
<td>@(a.IsZugferdXml ? "✔ Ja" : "Nein")</td>
|
||||
<td><small class="text-muted">@a.SavedFilePath</small></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
}
|
||||
51
DXApp.TemplateKitProject/Pages/Invoices/Upload.cshtml.cs
Normal file
51
DXApp.TemplateKitProject/Pages/Invoices/Upload.cshtml.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using DXApp.TemplateKitProject.Models;
|
||||
using DXApp.TemplateKitProject.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace DXApp.TemplateKitProject.Pages.Invoices;
|
||||
|
||||
public class UploadModel(
|
||||
PdfAttachmentExtractorService extractor,
|
||||
ILogger<UploadModel> logger) : PageModel
|
||||
{
|
||||
[BindProperty]
|
||||
public IFormFile? PdfFile { get; set; }
|
||||
|
||||
public PdfExtractionResult? Result { get; private set; }
|
||||
public bool ExtractionDone { get; private set; }
|
||||
public string? ErrorMessage { get; private set; }
|
||||
|
||||
public void OnGet()
|
||||
{ }
|
||||
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (PdfFile is null || PdfFile.Length == 0)
|
||||
{
|
||||
ModelState.AddModelError(nameof(PdfFile), "Bitte eine PDF-Datei auswählen.");
|
||||
return Page();
|
||||
}
|
||||
|
||||
if (!PdfFile.FileName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ModelState.AddModelError(nameof(PdfFile), "Nur PDF-Dateien sind erlaubt.");
|
||||
return Page();
|
||||
}
|
||||
|
||||
ExtractionDone = true;
|
||||
|
||||
try
|
||||
{
|
||||
await using var stream = PdfFile.OpenReadStream();
|
||||
Result = extractor.ExtractAttachments(stream, PdfFile.FileName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Fehler beim Verarbeiten der Datei '{FileName}'.", PdfFile.FileName);
|
||||
ErrorMessage = $"Fehler beim Verarbeiten der Datei: {ex.Message}";
|
||||
}
|
||||
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
203
DXApp.TemplateKitProject/Pages/Shared/_Layout.cshtml
Normal file
203
DXApp.TemplateKitProject/Pages/Shared/_Layout.cshtml
Normal file
@@ -0,0 +1,203 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>DXApp.TemplateKitProject</title>
|
||||
@* Custom theme with a color swatch *@
|
||||
@* Docs: https://js.devexpress.com/DevExtreme/Guide/Themes_and_Styles/Predefined_Themes/#Color_Swatches *@
|
||||
<link href="~/css/devextreme/dx.fluent.blue.light.css" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="~/css/Site.css" />
|
||||
<script src="~/js/devextreme/jquery.js"></script>
|
||||
<script src="~/js/devextreme/dx.all.js"></script>
|
||||
<script src="~/js/devextreme/aspnet/dx.aspnet.mvc.js"></script>
|
||||
<script src="~/js/devextreme/aspnet/dx.aspnet.data.js"></script>
|
||||
</head>
|
||||
|
||||
<body class="dx-viewport">
|
||||
<div id="app-side-nav-outer-toolbar">
|
||||
<div class="layout-header">
|
||||
@(Html.DevExtreme().Toolbar()
|
||||
.Items(items => {
|
||||
items.Add()
|
||||
.Widget(w => w
|
||||
.Button()
|
||||
.Icon("menu")
|
||||
.OnClick("DevExtremeAspNetCoreAppMatRazorPages.onMenuButtonClick")
|
||||
)
|
||||
.Location(ToolbarItemLocation.Before)
|
||||
.CssClass("menu-button");
|
||||
items.Add()
|
||||
.Html("<div>DXApp.TemplateKitProject</div>")
|
||||
.Location(ToolbarItemLocation.Before)
|
||||
.CssClass("header-title");
|
||||
})
|
||||
)
|
||||
</div>
|
||||
<div class="layout-body layout-body-hidden">
|
||||
@(Html.DevExtreme().Drawer()
|
||||
.ID("layout-drawer")
|
||||
.Position(DrawerPosition.Left)
|
||||
.Opened(new JS("DevExtremeAspNetCoreAppMatRazorPages.restoreDrawerOpened()"))
|
||||
.Content(@<text>
|
||||
<div id="layout-drawer-scrollview" class="with-footer">
|
||||
<div class="content">
|
||||
@RenderBody()
|
||||
</div>
|
||||
<div>
|
||||
<div class="content-footer">
|
||||
<div id="footer">
|
||||
Copyright (c) 2000-@DateTime.Now.Year Developer Express Inc.
|
||||
<br />
|
||||
All trademarks or registered trademarks are property of their respective owners.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</text>)
|
||||
.Template(new TemplateName("navigation-menu"))
|
||||
)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@using(Html.DevExtreme().NamedTemplate("navigation-menu")) {
|
||||
<div class="menu-container dx-swatch-additional">
|
||||
|
||||
@functions{
|
||||
string GetUrl(string pageName) => Url.Page(pageName);
|
||||
string GetCurrentUrl() => Url.Page(ViewContext.RouteData.Values["page"].ToString());
|
||||
bool IsCurrentUrl(string pageName) => GetUrl(pageName) == GetCurrentUrl();
|
||||
}
|
||||
|
||||
@(Html.DevExtreme().TreeView()
|
||||
.Items(items =>
|
||||
{
|
||||
items.Add()
|
||||
.Text("Home")
|
||||
.Icon("home")
|
||||
.Option("path", GetUrl("/Index"))
|
||||
.Selected(IsCurrentUrl("/Index"));
|
||||
|
||||
items.Add()
|
||||
.Text("About")
|
||||
.Icon("info")
|
||||
.Option("path", GetUrl("/About"))
|
||||
.Selected(IsCurrentUrl("/About"));
|
||||
})
|
||||
.ExpandEvent(TreeViewExpandEvent.Click)
|
||||
.SelectionMode(NavSelectionMode.Single)
|
||||
.SelectedExpr("selected")
|
||||
.FocusStateEnabled(false)
|
||||
.Width(250)
|
||||
.OnItemClick("DevExtremeAspNetCoreAppMatRazorPages.onTreeViewItemClick")
|
||||
)
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
<script>
|
||||
|
||||
var DevExtremeAspNetCoreAppMatRazorPages = (function() {
|
||||
|
||||
var DRAWER_OPENED_KEY = "DevExtremeAspNetCoreAppMatRazorPages-drawer-opened";
|
||||
|
||||
var breakpoints = {
|
||||
xSmallMedia: window.matchMedia("(max-width: 599.99px)"),
|
||||
smallMedia: window.matchMedia("(min-width: 600px) and (max-width: 959.99px)"),
|
||||
mediumMedia: window.matchMedia("(min-width: 960px) and (max-width: 1279.99px)"),
|
||||
largeMedia: window.matchMedia("(min-width: 1280px)")
|
||||
};
|
||||
|
||||
function getDrawer() {
|
||||
return $("#layout-drawer").dxDrawer("instance");
|
||||
}
|
||||
|
||||
function restoreDrawerOpened() {
|
||||
var isLarge = breakpoints.largeMedia.matches;
|
||||
if(!isLarge)
|
||||
return false;
|
||||
|
||||
var state = sessionStorage.getItem(DRAWER_OPENED_KEY);
|
||||
if(state === null)
|
||||
return isLarge;
|
||||
|
||||
return state === "true";
|
||||
}
|
||||
|
||||
function saveDrawerOpened() {
|
||||
sessionStorage.setItem(DRAWER_OPENED_KEY, getDrawer().option("opened"));
|
||||
}
|
||||
|
||||
function updateDrawer() {
|
||||
var isXSmall = breakpoints.xSmallMedia.matches,
|
||||
isLarge = breakpoints.largeMedia.matches;
|
||||
|
||||
getDrawer().option({
|
||||
openedStateMode: isLarge ? "shrink" : "overlap",
|
||||
revealMode: isXSmall ? "slide" : "expand",
|
||||
minSize: isXSmall ? 0 : 60,
|
||||
shading: !isLarge,
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
$("#layout-drawer-scrollview").dxScrollView({ direction: "vertical" });
|
||||
|
||||
$.each(breakpoints, function(_, size) {
|
||||
size.addListener(function(e) {
|
||||
if(e.matches)
|
||||
updateDrawer();
|
||||
});
|
||||
});
|
||||
|
||||
updateDrawer();
|
||||
|
||||
$('.layout-body').removeClass('layout-body-hidden');
|
||||
}
|
||||
|
||||
function navigate(url, delay) {
|
||||
if(url)
|
||||
setTimeout(function() { location.href = url }, delay);
|
||||
}
|
||||
|
||||
function onMenuButtonClick() {
|
||||
getDrawer().toggle();
|
||||
saveDrawerOpened();
|
||||
}
|
||||
|
||||
function onTreeViewItemClick(e) {
|
||||
var drawer = getDrawer();
|
||||
var savedOpened = restoreDrawerOpened();
|
||||
var actualOpened = drawer.option("opened");
|
||||
|
||||
if(!actualOpened) {
|
||||
drawer.show();
|
||||
} else {
|
||||
var willHide = !savedOpened || !breakpoints.largeMedia.matches;
|
||||
var willNavigate = !e.itemData.selected;
|
||||
|
||||
if(willHide)
|
||||
drawer.hide();
|
||||
|
||||
if(willNavigate)
|
||||
navigate(e.itemData.path, willHide ? 400 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
restoreDrawerOpened: restoreDrawerOpened,
|
||||
onMenuButtonClick: onMenuButtonClick,
|
||||
onTreeViewItemClick: onTreeViewItemClick
|
||||
};
|
||||
})();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function documentReady() {
|
||||
this.removeEventListener("DOMContentLoaded", documentReady);
|
||||
DevExtremeAspNetCoreAppMatRazorPages.init();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
4
DXApp.TemplateKitProject/Pages/_ViewImports.cshtml
Normal file
4
DXApp.TemplateKitProject/Pages/_ViewImports.cshtml
Normal file
@@ -0,0 +1,4 @@
|
||||
@using DXApp.TemplateKitProject
|
||||
@namespace DXApp.TemplateKitProject.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using DevExtreme.AspNet.Mvc
|
||||
3
DXApp.TemplateKitProject/Pages/_ViewStart.cshtml
Normal file
3
DXApp.TemplateKitProject/Pages/_ViewStart.cshtml
Normal file
@@ -0,0 +1,3 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
Reference in New Issue
Block a user