Aggiunta dialog quando salvo dati in create e edit dati azienda

This commit is contained in:
michele 2025-10-06 16:58:03 +02:00
parent c1eef15b99
commit e84103edbc
4 changed files with 218 additions and 42 deletions

View File

@ -40,6 +40,9 @@ namespace VirtualTask.Controllers
_urlLoghi = _configuration["ApplicationInsights:rootUrlApi2"];
}
#region INDEX
public IActionResult Index()
{
SessionHelper helper = new SessionHelper(this);
@ -78,6 +81,7 @@ namespace VirtualTask.Controllers
return RedirectToAction("Error");
}
}
#endregion
#region CREATE
@ -96,28 +100,29 @@ namespace VirtualTask.Controllers
SessionHelper helper = new SessionHelper(this);
string token = helper.GetStringValue("tok");
string tenant2 = helper.GetStringValue("tenant2"); // tenant = azienda
string apiUrl = helper.GetStringValue("apiUrl");
string admin = helper.GetStringValue("admin");
ViewBag.Admin = admin;
ViewBag.AllTecnici = getTecnici();
// ❌ Validazione fallita → restituisco errori in JSON
if (!ModelState.IsValid)
return View(model);
{
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
return BadRequest(string.Join("\n", errors));
}
string logoUrl = null;
// 1⃣ Upload del logo tramite API UploadLogo
// 1⃣ Upload del logo tramite API UploadLogo
if (model.logo != null && model.logo.Length > 0)
{
// ✅ Token nella query string
string uploadUrl = $"{apiUrl}datiazienda/upload_logo?token={token}";
using (var httpClient = new HttpClient())
using (var form = new MultipartFormDataContent())
{
// ⚡ Solo il file nel multipart
var fileContent = new StreamContent(model.logo.OpenReadStream());
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(
string.IsNullOrWhiteSpace(model.logo.ContentType) ? "application/octet-stream" : model.logo.ContentType
@ -129,17 +134,15 @@ namespace VirtualTask.Controllers
if (!response.IsSuccessStatusCode)
{
string err = await response.Content.ReadAsStringAsync();
ModelState.AddModelError("", "Errore upload logo: " + err);
return View(model);
return BadRequest("Errore upload logo: " + err);
}
dynamic result = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
logoUrl = result.url;
}
}
// 2⃣ Creazione oggetto da inviare all'API datiazienda/add
// 2⃣ Creo l'oggetto da inviare all'API
var dat = new DatiAziendaTable
{
azienda = tenant2,
@ -161,12 +164,20 @@ namespace VirtualTask.Controllers
if (!saveResponse.IsSuccessStatusCode)
{
string err = await saveResponse.Content.ReadAsStringAsync();
ModelState.AddModelError("", "Errore salvataggio dati: " + err);
return View(model);
return BadRequest("Errore salvataggio dati: " + err);
}
}
return RedirectToAction("Index");
// ✅ Risposta JSON usata dalla view per aprire la finestra popup
return Json(new { success = true });
}
/// <summary>
/// Pagina popup mostrata dopo il salvataggio
/// </summary>
public IActionResult Dialog()
{
return View();
}
#endregion CREATE
@ -274,7 +285,10 @@ namespace VirtualTask.Controllers
}
}
return RedirectToAction("Index");
//return RedirectToAction("Index");
// ✅ Risposta OK per far apparire la dialog nella view
return Ok();
}
#endregion

View File

@ -4,61 +4,110 @@
ViewData["Title"] = "Nuova Intestazione Buoni Intervento";
Layout = "~/Views/Shared/_LayoutAreaRiservata.cshtml";
}
<div class="agy-project-wrapper agy-project-page-wrapper">
<div class="container">
<div class="row">
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
<form id="createForm" asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@Html.HiddenFor(x => x.azienda)
@Html.HiddenFor(x => x.url_logo)
<div class="form-group">
<h5><label asp-for="tecnico" class="control-label"></label></h5>
@Html.DropDownListFor(x =>x.tecnico,(IEnumerable<SelectListItem>)ViewBag.AllTecnici,new {@class = "form-control"})
@Html.DropDownListFor(x => x.tecnico, (IEnumerable<SelectListItem>)ViewBag.AllTecnici, new { @class = "form-control" })
<span asp-validation-for="tecnico" class="text-danger"></span>
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-12">&nbsp;</div>
<div class="form-group">
<h5><label asp-for="ragsoc" class="control-label"></label></h5>
<input asp-for="ragsoc" class="form-control" />
<span asp-validation-for="ragsoc" class="text-danger"></span>
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-12">&nbsp;</div>
<div class="form-group">
<h5><label asp-for="logo" class="control-label"></label></h5>
<input type="file" asp-for="logo" />
<span asp-validation-for="logo" class="text-danger"></span>
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-12">&nbsp;</div>
<div class="form-group">
<h5><label asp-for="testo_buono" class="control-label"></label></h5>
@*<input asp-for="testo_buono" class="form-control" />*@
<textarea asp-for="testo_buono" class="form-control"></textarea>
<span asp-validation-for="testo_buono" class="text-danger"></span>
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-12">&nbsp;</div>
<div class="form-group">
<input type="submit" value="Salva" class="agy-btn submitForm" />
<a asp-action="Index" value="Torna alla lista" class="agy-btn submitForm">Torna alla lista</a>
<a asp-action="Index" class="agy-btn submitForm">Torna alla lista</a>
</div>
</form>
</div>
</div>
<div>
@* <a asp-action="Index">Torna alla lista</a> *@
</div>
</div>
</div>
</div>
<script src="~/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
@{
await Html.RenderPartialAsync("_ValidationScriptsPartial");
}
<script>
// inizializza TinyMCE
tinymce.init({
selector: 'textarea#testo_buono'
});
// intercetta il submit per gestire la chiamata AJAX + popup
document.getElementById('createForm').addEventListener('submit', function (e) {
e.preventDefault();
tinymce.triggerSave();
const form = e.target;
const formData = new FormData(form);
fetch('@Url.Action("Create", "DatiAzienda")', {
method: 'POST',
body: formData
})
.then(response => {
if (response.ok) {
// ✅ apre la finestra popup con il messaggio
window.open(
'@Url.Action("Dialog", "DatiAzienda")',
'dialogWindow',
'width=500,height=300,top=200,left=400,resizable=no'
);
// reset del form
form.reset();
if (tinymce.get('testo_buono')) {
tinymce.get('testo_buono').setContent('');
}
} else {
response.text().then(text => {
alert("Errore nel salvataggio: " + text);
});
}
})
.catch(err => {
alert("Errore di rete: " + err);
});
});
</script>
}

View File

@ -0,0 +1,61 @@
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Dati salvati</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding-top: 50px;
background-color: #f9f9f9;
}
h2 {
color: #28a745;
}
p {
margin-top: 15px;
color: #333;
}
.btn {
margin-top: 25px;
background-color: #007bff;
color: white;
padding: 10px 18px;
text-decoration: none;
border-radius: 4px;
display: inline-block;
font-size: 15px;
cursor: pointer;
}
.btn:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<h2>Dati salvati correttamente ✅</h2>
<p>I dati non saranno visibili nell'app finché non effettuerai il logout e login.</p>
<button class="btn" id="okButton">OK</button>
<script>
document.getElementById('okButton').addEventListener('click', function () {
// 🔸 Reindirizza la finestra principale alla Index
if (window.opener && !window.opener.closed) {
window.opener.location.href = '@Url.Action("Index", "DatiAzienda")';
}
// 🔸 Chiude la finestra popup
window.close();
});
</script>
</body>
</html>

View File

@ -10,61 +10,113 @@
<div class="row">
<div class="row">
<div class="col-md-4">
<form asp-action="Edit" enctype="multipart/form-data">
<form id="editForm" asp-action="Edit" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@Html.HiddenFor(x => x.azienda)
@Html.HiddenFor(x => x.url_logo)
@Html.HiddenFor(x => x.logo)
<div class="form-group">
<h5><label asp-for="tecnico" class="agy-client-quote"></label></h5>
@Html.DropDownListFor(x => x.tecnico,(IEnumerable<SelectListItem>)ViewBag.AllTecnici, new {@class = "form-control"})
<h5><label asp-for="tecnico"></label></h5>
@Html.DropDownListFor(x => x.tecnico, (IEnumerable<SelectListItem>)ViewBag.AllTecnici, new { @class = "form-control" })
<span asp-validation-for="tecnico" class="text-danger"></span>
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-12">&nbsp;</div>
<div class="form-group">
<h5><label asp-for="ragsoc" class="agy-client-quote"></label></h5>
<h5><label asp-for="ragsoc"></label></h5>
<input asp-for="ragsoc" class="form-control" />
<span asp-validation-for="ragsoc" class="text-danger"></span>
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-12">&nbsp;</div>
<div class="form-group">
<h5><label asp-for="logo" class="agy-client-quote"></label></h5>
<h5><label asp-for="logo"></label></h5>
@{
byte[] appo = Model.logo;
var base64 = Convert.ToBase64String(appo);
var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
if (Model.logo != null && Model.logo.Length > 0)
{
var base64 = Convert.ToBase64String(Model.logo);
var imgSrc = $"data:image/png;base64,{base64}";
<img src="@imgSrc" height="80" class="mb-2" />
}
}
<img src="@imgSrc" height="80" />
<input type="file" asp-for="logo2" />
<span asp-validation-for="logo" class="text-danger"></span>
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-12">&nbsp;</div>
<div class="form-group">
<h5><label asp-for="testo_buono" class="agy-client-quote"></label></h5>
<textarea asp-for="testo_buono" class="form-control"></textarea>
<h5><label asp-for="testo_buono"></label></h5>
<textarea asp-for="testo_buono" id="testo_buono" class="form-control"></textarea>
<span asp-validation-for="testo_buono" class="text-danger"></span>
</div>
<div class="form-group">
<div class="form-group mt-3">
<input type="submit" value="Salva" class="agy-btn submitForm" />
<a asp-action="Index" value="Torna alla lista" class="agy-btn submitForm">Torna alla lista</a>
<a asp-action="Index" class="agy-btn submitForm">Torna alla lista</a>
</div>
</form>
</div>
</div>
</div>
<div>
@* <a asp-action="Index">Back to List</a> *@
</div>
</div>
<!-- TinyMCE -->
<script src="~/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
<!-- ✅ Dialog identica a quella della Create -->
<div class="modal fade" id="saveModal" tabindex="-1" role="dialog" aria-labelledby="saveModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="saveModalLabel">Dati salvati</h5>
</div>
<div class="modal-body">
I dati salvati non saranno visibili nell'app finché non effettuerai il logout.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="modalOkBtn">OK</button>
</div>
</div>
</div>
</div>
<script src="~/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
@{
await Html.RenderPartialAsync("_ValidationScriptsPartial");
}
<script>
tinymce.init({
selector: 'textarea#testo_buono'
selector: 'textarea#testo_buono',
height: 300,
menubar: false,
plugins: 'lists link table code',
toolbar: 'undo redo | bold italic | bullist numlist | link table | code'
});
document.getElementById('editForm').addEventListener('submit', function (e) {
e.preventDefault();
tinymce.triggerSave();
const form = e.target;
const formData = new FormData(form);
fetch(form.action, {
method: 'POST',
body: formData
})
.then(response => {
if (response.ok) {
// ✅ Mostra la stessa dialog della Create
$('#saveModal').modal('show');
} else {
alert("Errore durante il salvataggio.");
}
})
.catch(err => console.error(err));
});
document.getElementById('modalOkBtn').addEventListener('click', function () {
window.location.href = '@Url.Action("Index")';
});
</script>
}