Compare commits
3 Commits
c61c1b7039
...
3b66fedd2d
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b66fedd2d | |||
| 8505dbf1db | |||
| 1dee3880c3 |
@ -245,11 +245,6 @@ namespace VirtualTask.Controllers
|
|||||||
//model.chdtapp = model.chdata;
|
//model.chdtapp = model.chdata;
|
||||||
model.chdtass = model.chdata;
|
model.chdtass = model.chdata;
|
||||||
model.chtipo = "A";//X=creato da app, A creato da adhoc. DEVO METTERE A perche altrimenti l'app lo tratta come una chiamata da commessa
|
model.chtipo = "A";//X=creato da app, A creato da adhoc. DEVO METTERE A perche altrimenti l'app lo tratta come una chiamata da commessa
|
||||||
|
|
||||||
if (model.chtchiam != null)
|
|
||||||
{
|
|
||||||
model.chstato = "C";
|
|
||||||
}
|
|
||||||
model.chmodrac = "EMAIL";
|
model.chmodrac = "EMAIL";
|
||||||
//int year=adesso.Year;
|
//int year=adesso.Year;
|
||||||
//int ora = adesso.Hour;
|
//int ora = adesso.Hour;
|
||||||
|
|||||||
@ -40,9 +40,6 @@ namespace VirtualTask.Controllers
|
|||||||
_urlLoghi = _configuration["ApplicationInsights:rootUrlApi2"];
|
_urlLoghi = _configuration["ApplicationInsights:rootUrlApi2"];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region INDEX
|
|
||||||
|
|
||||||
public IActionResult Index()
|
public IActionResult Index()
|
||||||
{
|
{
|
||||||
SessionHelper helper = new SessionHelper(this);
|
SessionHelper helper = new SessionHelper(this);
|
||||||
@ -81,7 +78,6 @@ namespace VirtualTask.Controllers
|
|||||||
return RedirectToAction("Error");
|
return RedirectToAction("Error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region CREATE
|
#region CREATE
|
||||||
|
|
||||||
@ -95,89 +91,99 @@ namespace VirtualTask.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Create(DatiAzienda model)
|
public IActionResult Create(DatiAzienda model)
|
||||||
{
|
{
|
||||||
|
DatiAziendaTable dat=new DatiAziendaTable();
|
||||||
|
|
||||||
SessionHelper helper = new SessionHelper(this);
|
SessionHelper helper = new SessionHelper(this);
|
||||||
string token = helper.GetStringValue("tok");
|
admin = helper.GetStringValue("admin");
|
||||||
string tenant2 = helper.GetStringValue("tenant2"); // tenant = azienda
|
token = helper.GetStringValue("tok");
|
||||||
string apiUrl = helper.GetStringValue("apiUrl");
|
tenant = helper.GetStringValue("tenant");
|
||||||
string admin = helper.GetStringValue("admin");
|
tenant2 = helper.GetStringValue("tenant2");
|
||||||
|
|
||||||
ViewBag.Admin = admin;
|
ViewBag.Admin = admin;
|
||||||
ViewBag.AllTecnici = getTecnici();
|
if (model.logo != null)
|
||||||
|
|
||||||
// ❌ Validazione fallita → restituisco errori in JSON
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
{
|
||||||
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
string pic = System.IO.Path.GetFileName(model.logo.FileName);
|
||||||
return BadRequest(string.Join("\n", errors));
|
//2025-05-05: gestione directory iommagine nel caso che l'azienda sia più corta di 5 caratteri
|
||||||
}
|
string dir = tenant2;
|
||||||
|
if (!string.IsNullOrEmpty(tenant2) && tenant2.Trim().Length < 5)
|
||||||
string logoUrl = null;
|
|
||||||
|
|
||||||
// 1️⃣ Upload del logo tramite API UploadLogo
|
|
||||||
if (model.logo != null && model.logo.Length > 0)
|
|
||||||
{
|
|
||||||
string uploadUrl = $"{apiUrl}datiazienda/upload_logo?token={token}";
|
|
||||||
|
|
||||||
using (var httpClient = new HttpClient())
|
|
||||||
using (var form = new MultipartFormDataContent())
|
|
||||||
{
|
{
|
||||||
var fileContent = new StreamContent(model.logo.OpenReadStream());
|
dir = tenant2.Trim();
|
||||||
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(
|
}
|
||||||
string.IsNullOrWhiteSpace(model.logo.ContentType) ? "application/octet-stream" : model.logo.ContentType
|
string path = string.Format("{0}{1}\\{2}",_pathLoghi, dir, pic);
|
||||||
);
|
//string projectRootPath = _hostingEnvironment.ContentRootPath;
|
||||||
form.Add(fileContent, "file", model.logo.FileName);
|
|
||||||
|
|
||||||
HttpResponseMessage response = await httpClient.PostAsync(uploadUrl, form);
|
//// file is uploaded
|
||||||
|
using (Stream fileStream = new FileStream(path, FileMode.Create))
|
||||||
|
{
|
||||||
|
model.logo.CopyToAsync(fileStream);
|
||||||
|
}
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
//// save the image path path to the database or you can send image
|
||||||
{
|
//// directly to database
|
||||||
string err = await response.Content.ReadAsStringAsync();
|
//// in-case if you want to store byte[] ie. for DB
|
||||||
return BadRequest("Errore upload logo: " + err);
|
using (MemoryStream ms = new MemoryStream())
|
||||||
}
|
{
|
||||||
|
model.logo.CopyTo(ms);
|
||||||
|
byte[] array = ms.GetBuffer();
|
||||||
|
dat.logo = array;
|
||||||
|
}
|
||||||
|
dat.azienda = tenant2;
|
||||||
|
dat.testo_buono = model.testo_buono;
|
||||||
|
dat.url_logo = string.Format("{0}{1}/{2}", _urlLoghi, dir, pic);
|
||||||
|
dat.ragsoc = model.ragsoc;
|
||||||
|
dat.tecnico = model.tecnico;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dynamic result = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
|
apiUrl = helper.GetStringValue("apiUrl");
|
||||||
logoUrl = result.url;
|
admin = helper.GetStringValue("admin");
|
||||||
|
ViewBag.Admin = admin;
|
||||||
|
urlBase = apiUrl + "datiazienda/add";
|
||||||
|
urlBase = urlBase + "?token=" + token;
|
||||||
|
Uri baseAddress = new Uri(urlBase);
|
||||||
|
client = new HttpClient();
|
||||||
|
client.BaseAddress = baseAddress;
|
||||||
|
|
||||||
|
string data = JsonConvert.SerializeObject(dat);
|
||||||
|
StringContent content = new StringContent(data, Encoding.UTF8, "application/json");
|
||||||
|
HttpResponseMessage response = client.PostAsync(baseAddress, content).Result;
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
//prima di andare alla pagina devo chiamare il metodo per
|
||||||
|
//salvare il file in locale in modo che sia visibile sul web dall'app
|
||||||
|
//C:\ZAPIPOLO\loghi
|
||||||
|
//https://api.poloinformatico.it:9000/api/Polo/datiazienda/saveFile?azienda=AZI02&tecnico=aaaaa%20%20%20%20%20%20%20%20%20%20&pathSrv=C%3A%5CZAPIPOLO%5Cloghi'
|
||||||
|
apiUrl = helper.GetStringValue("apiUrl");
|
||||||
|
urlBase = apiUrl + "datiazienda/savefile";
|
||||||
|
urlBase = urlBase + "?azienda=" + model.azienda;
|
||||||
|
urlBase = urlBase + "&tecnico=" + model.tecnico;
|
||||||
|
//urlBase = urlBase + "&pathSrv=" + "C:\\ZAPIPOLO\\loghi";
|
||||||
|
urlBase = urlBase + "&pathSrv=" + _pathLoghi;
|
||||||
|
|
||||||
|
baseAddress = new Uri(urlBase);
|
||||||
|
client = new HttpClient();
|
||||||
|
client.BaseAddress = baseAddress;
|
||||||
|
HttpResponseMessage response2 = client.GetAsync(baseAddress).Result;
|
||||||
|
if (response2.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return RedirectToAction("Index");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errMes = response.Content.ReadAsStringAsync().Result;
|
||||||
|
helper.SetStringValue("errMsg", errMes);
|
||||||
|
return RedirectToAction("Error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// 2️⃣ Creo l'oggetto da inviare all'API
|
|
||||||
var dat = new DatiAziendaTable
|
|
||||||
{
|
{
|
||||||
azienda = tenant2,
|
errMes = response.Content.ReadAsStringAsync().Result;
|
||||||
tecnico = model.tecnico,
|
helper.SetStringValue("errMsg", errMes);
|
||||||
ragsoc = model.ragsoc,
|
return RedirectToAction("Error");
|
||||||
testo_buono = model.testo_buono,
|
|
||||||
url_logo = logoUrl,
|
|
||||||
logo = model.logo != null ? await ConvertToByteArrayAsync(model.logo) : null
|
|
||||||
};
|
|
||||||
|
|
||||||
// 3️⃣ Invio dati all'API datiazienda/add
|
|
||||||
string apiAddUrl = apiUrl + "datiazienda/add?token=" + token;
|
|
||||||
using (var httpClient = new HttpClient())
|
|
||||||
{
|
|
||||||
string data = JsonConvert.SerializeObject(dat);
|
|
||||||
StringContent content = new StringContent(data, Encoding.UTF8, "application/json");
|
|
||||||
HttpResponseMessage saveResponse = await httpClient.PostAsync(apiAddUrl, content);
|
|
||||||
|
|
||||||
if (!saveResponse.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
string err = await saveResponse.Content.ReadAsStringAsync();
|
|
||||||
return BadRequest("Errore salvataggio dati: " + err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ 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
|
#endregion CREATE
|
||||||
@ -222,75 +228,103 @@ namespace VirtualTask.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Edit(DatiAziendaTable model)
|
public IActionResult Edit(DatiAziendaTable model)
|
||||||
{
|
{
|
||||||
SessionHelper helper = new SessionHelper(this);
|
SessionHelper helper = new SessionHelper(this);
|
||||||
|
|
||||||
string token = helper.GetStringValue("tok");
|
token = helper.GetStringValue("tok");
|
||||||
string tenant2 = helper.GetStringValue("tenant2");
|
tenant = helper.GetStringValue("tenant");
|
||||||
|
tenant2 = helper.GetStringValue("tenant2");
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(token))
|
if (string.IsNullOrEmpty(token))
|
||||||
return RedirectToAction("Login2", "Login");
|
|
||||||
|
|
||||||
string apiUrl = helper.GetStringValue("apiUrl");
|
|
||||||
|
|
||||||
// 1️⃣ Upload del logo tramite API UploadLogo
|
|
||||||
if (model.logo2 != null && model.logo2.Length > 0)
|
|
||||||
{
|
{
|
||||||
string uploadUrl = $"{apiUrl}datiazienda/upload_logo?token={token}";
|
return RedirectToAction("Login2", "Login");
|
||||||
|
}
|
||||||
|
//model.azienda = tenant;
|
||||||
|
if(model.logo2!=null)
|
||||||
|
{
|
||||||
|
string pic = System.IO.Path.GetFileName(model.logo2.FileName);
|
||||||
|
|
||||||
using (var httpClient = new HttpClient())
|
//2025-05-05: gestione directory iommagine nel caso che l'azienda sia più corta di 5 caratteri
|
||||||
using (var form = new MultipartFormDataContent())
|
string dir = tenant2;
|
||||||
|
if (!string.IsNullOrEmpty(tenant2) && tenant2.Trim().Length < 5)
|
||||||
{
|
{
|
||||||
var fileContent = new StreamContent(model.logo2.OpenReadStream());
|
dir = tenant2.Trim();
|
||||||
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(
|
}
|
||||||
string.IsNullOrWhiteSpace(model.logo2.ContentType) ? "application/octet-stream" : model.logo2.ContentType
|
string path = string.Format("{0}{1}\\{2}", _pathLoghi, dir, pic);
|
||||||
);
|
//string projectRootPath = _hostingEnvironment.ContentRootPath;
|
||||||
form.Add(fileContent, "file", model.logo2.FileName);
|
|
||||||
|
//// file is uploaded
|
||||||
HttpResponseMessage response = await httpClient.PostAsync(uploadUrl, form);
|
using (Stream fileStream = new FileStream(path, FileMode.Create))
|
||||||
if (!response.IsSuccessStatusCode)
|
{
|
||||||
{
|
model.logo2.CopyToAsync(fileStream);
|
||||||
string err = await response.Content.ReadAsStringAsync();
|
|
||||||
ModelState.AddModelError("", "Errore upload logo: " + err);
|
|
||||||
return View(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
dynamic result = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
|
|
||||||
model.url_logo = result.url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Salvo i byte del file nel modello se serve per il DB
|
//// save the image path path to the database or you can send image
|
||||||
|
//// directly to database
|
||||||
|
//// in-case if you want to store byte[] ie. for DB
|
||||||
using (MemoryStream ms = new MemoryStream())
|
using (MemoryStream ms = new MemoryStream())
|
||||||
{
|
{
|
||||||
await model.logo2.CopyToAsync(ms);
|
model.logo2.CopyTo(ms);
|
||||||
model.logo = ms.ToArray();
|
byte[] array = ms.GetBuffer();
|
||||||
|
model.logo = array;
|
||||||
}
|
}
|
||||||
model.logo2 = null;
|
model.logo2 = null;
|
||||||
|
model.url_logo = string.Format("{0}{1}/{2}", _urlLoghi, dir, pic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 2️⃣ Invio dati all'API datiazienda/mod
|
apiUrl = helper.GetStringValue("apiUrl");
|
||||||
string modUrl = $"{apiUrl}datiazienda/mod?token={token}";
|
urlBase = apiUrl + "datiazienda/mod";
|
||||||
using (var client = new HttpClient())
|
urlBase = urlBase + "?token=" + token;
|
||||||
|
Uri baseAddress = new Uri(urlBase);
|
||||||
|
client = new HttpClient();
|
||||||
|
client.BaseAddress = baseAddress;
|
||||||
|
|
||||||
|
string data = JsonConvert.SerializeObject(model);
|
||||||
|
StringContent content = new StringContent(data, Encoding.UTF8, "application/json");
|
||||||
|
HttpResponseMessage response = client.PostAsync(baseAddress, content).Result;
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
string data = JsonConvert.SerializeObject(model);
|
//prima di andare alla pagina devo chiamare il metodo per
|
||||||
StringContent content = new StringContent(data, Encoding.UTF8, "application/json");
|
//salvare il file in locale in modo che sia visibile sul web dall'app
|
||||||
HttpResponseMessage response = await client.PostAsync(modUrl, content);
|
//C:\ZAPIPOLO\loghi
|
||||||
|
//https://api.poloinformatico.it:9000/api/Polo/datiazienda/saveFile?azienda=AZI02&tecnico=aaaaa%20%20%20%20%20%20%20%20%20%20&pathSrv=C%3A%5CZAPIPOLO%5Cloghi'
|
||||||
if (!response.IsSuccessStatusCode)
|
apiUrl = helper.GetStringValue("apiUrl");
|
||||||
|
urlBase = apiUrl + "datiazienda/savefile";
|
||||||
|
if(!string.IsNullOrEmpty(model.azienda) && model.azienda.Length<5)
|
||||||
{
|
{
|
||||||
string errMes = await response.Content.ReadAsStringAsync();
|
model.azienda= model.azienda.Trim();
|
||||||
|
}
|
||||||
|
urlBase = urlBase + "?azienda=" + model.azienda;
|
||||||
|
urlBase = urlBase + "&tecnico=" + model.tecnico.Trim();
|
||||||
|
urlBase = urlBase + "&pathSrv=" + _pathLoghi;
|
||||||
|
baseAddress = new Uri(urlBase);
|
||||||
|
client = new HttpClient();
|
||||||
|
client.BaseAddress = baseAddress;
|
||||||
|
|
||||||
|
data = JsonConvert.SerializeObject(model);
|
||||||
|
content = new StringContent(data, Encoding.UTF8, "application/json");
|
||||||
|
HttpResponseMessage response2 = client.PostAsync(baseAddress, content).Result;
|
||||||
|
if (response2.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return RedirectToAction("Index");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errMes = response2.Content.ReadAsStringAsync().Result;
|
||||||
helper.SetStringValue("errMsg", errMes);
|
helper.SetStringValue("errMsg", errMes);
|
||||||
return RedirectToAction("Error");
|
return RedirectToAction("Error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
//return RedirectToAction("Index");
|
{
|
||||||
// ✅ Risposta OK per far apparire la dialog nella view
|
errMes = response.Content.ReadAsStringAsync().Result;
|
||||||
return Ok();
|
helper.SetStringValue("errMsg", errMes);
|
||||||
|
return RedirectToAction("Error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region DETAIL
|
#region DETAIL
|
||||||
@ -401,7 +435,7 @@ namespace VirtualTask.Controllers
|
|||||||
}
|
}
|
||||||
#endregion DELETE
|
#endregion DELETE
|
||||||
|
|
||||||
#region ALTRI METODI
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
public IActionResult Error()
|
public IActionResult Error()
|
||||||
{
|
{
|
||||||
@ -409,7 +443,6 @@ namespace VirtualTask.Controllers
|
|||||||
string e = helper.GetStringValue("errMsg");
|
string e = helper.GetStringValue("errMsg");
|
||||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier, ErrMsg = e });
|
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier, ErrMsg = e });
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SelectListItem> getTecnici()
|
private List<SelectListItem> getTecnici()
|
||||||
{
|
{
|
||||||
SessionHelper helper = new SessionHelper(this);
|
SessionHelper helper = new SessionHelper(this);
|
||||||
@ -447,27 +480,5 @@ namespace VirtualTask.Controllers
|
|||||||
}
|
}
|
||||||
return selectItems;
|
return selectItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Metodo helper per convertire IFormFile in byte[]
|
|
||||||
private async Task<byte[]> ConvertToByteArrayAsync(IFormFile file)
|
|
||||||
{
|
|
||||||
using (var ms = new MemoryStream())
|
|
||||||
{
|
|
||||||
await file.CopyToAsync(ms);
|
|
||||||
return ms.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion ALTRI METODI
|
|
||||||
|
|
||||||
// Classe per deserializzare la risposta JSON dell'API
|
|
||||||
private class UploadResponse
|
|
||||||
{
|
|
||||||
public string? message { get; set; }
|
|
||||||
public string? url { get; set; }
|
|
||||||
public string? fileName { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,7 +68,7 @@ namespace VirtualTask.Controllers
|
|||||||
string app = "";
|
string app = "";
|
||||||
byte[] fileBytes = System.IO.File.ReadAllBytes(file);
|
byte[] fileBytes = System.IO.File.ReadAllBytes(file);
|
||||||
var response = new FileContentResult(fileBytes, "application/octet-stream");
|
var response = new FileContentResult(fileBytes, "application/octet-stream");
|
||||||
response.FileDownloadName = "app_Virtual_Task_1_34.apk";
|
response.FileDownloadName = "appTest.apk";
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace VirtualTask.Models
|
|||||||
[Display(Name = "Tecnico")]
|
[Display(Name = "Tecnico")]
|
||||||
public string? chtchiam { get; set; }
|
public string? chtchiam { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Stato")/*, Required(ErrorMessage = "Selezionare uno stato di assegnazione")*/]
|
[Display(Name = "Stato")]
|
||||||
public string? chstato { get; set; }
|
public string? chstato { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Rifiutata")]
|
[Display(Name = "Rifiutata")]
|
||||||
|
|||||||
@ -25,12 +25,12 @@
|
|||||||
@Html.DropDownListFor(x => x.chtchiam, (IEnumerable<SelectListItem>)ViewBag.Tecnici, new { @class = "agy-form-field require" })
|
@Html.DropDownListFor(x => x.chtchiam, (IEnumerable<SelectListItem>)ViewBag.Tecnici, new { @class = "agy-form-field require" })
|
||||||
<span asp-validation-for="chtchiam" class="text-danger"></span>
|
<span asp-validation-for="chtchiam" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
@* <div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
<div class="form-group" style="width: 40%;">
|
<div class="form-group" style="width: 40%;">
|
||||||
<h5><label asp-for="chstato" class="agy-client-quote"></label></h5>
|
<h5><label asp-for="chstato" class="agy-client-quote"></label></h5>
|
||||||
@Html.DropDownListFor(x => x.chstato, (IEnumerable<SelectListItem>)ViewBag.StatiChiamata, new { @class = "agy-form-field require" })
|
@Html.DropDownListFor(x => x.chstato, (IEnumerable<SelectListItem>)ViewBag.StatiChiamata, new { @class = "agy-form-field require" })
|
||||||
<span asp-validation-for="chstato" class="text-danger"></span>
|
<span asp-validation-for="chstato" class="text-danger"></span>
|
||||||
</div> *@
|
</div>
|
||||||
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
<div class="form-group" style="width: 40%;">
|
<div class="form-group" style="width: 40%;">
|
||||||
<h5><label asp-for="chdtapp" class="agy-client-quote"></label></h5>
|
<h5><label asp-for="chdtapp" class="agy-client-quote"></label></h5>
|
||||||
|
|||||||
@ -216,14 +216,14 @@
|
|||||||
@Html.PagedListPager(Model, page => Url.Action("index", new
|
@Html.PagedListPager(Model, page => Url.Action("index", new
|
||||||
{
|
{
|
||||||
page = page,
|
page = page,
|
||||||
cliente = ViewData["ClienteFilter"],
|
cliente = ViewData["ClienteFilter"],
|
||||||
impianto = ViewData["CurrentFilter"],
|
impianto = ViewData["CurrentFilter"],
|
||||||
tecnico = ViewData["CurrentFilterTec"],
|
tecnico = ViewData["CurrentFilterTec"],
|
||||||
indirizzo = ViewData["CurrentFilterIndiri"],
|
indirizzo = ViewData["CurrentFilterIndiri"],
|
||||||
stato = ViewData["CurrentFilterStato"],
|
stato = ViewData["CurrentFilterStato"],
|
||||||
dataIni = ViewData["CurrentFilterDataDa"],
|
dataIni = ViewData["CurrentFilterDataDa"],
|
||||||
dataFin = ViewData["CurrentFilterDataA"]
|
dataFin = ViewData["CurrentFilterDataA"]
|
||||||
}), new PagedListRenderOptions()
|
}), new PagedListRenderOptions()
|
||||||
{
|
{
|
||||||
ActiveLiElementClass = "active",
|
ActiveLiElementClass = "active",
|
||||||
PageClasses = new[] { "page-link" },
|
PageClasses = new[] { "page-link" },
|
||||||
|
|||||||
@ -4,133 +4,61 @@
|
|||||||
ViewData["Title"] = "Nuova Intestazione Buoni Intervento";
|
ViewData["Title"] = "Nuova Intestazione Buoni Intervento";
|
||||||
Layout = "~/Views/Shared/_LayoutAreaRiservata.cshtml";
|
Layout = "~/Views/Shared/_LayoutAreaRiservata.cshtml";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="agy-project-wrapper agy-project-page-wrapper">
|
<div class="agy-project-wrapper agy-project-page-wrapper">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<form id="createForm" asp-action="Create" enctype="multipart/form-data">
|
<form asp-action="Create" enctype="multipart/form-data">
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||||
|
|
||||||
@Html.HiddenFor(x => x.azienda)
|
@Html.HiddenFor(x => x.azienda)
|
||||||
@Html.HiddenFor(x => x.url_logo)
|
@Html.HiddenFor(x => x.url_logo)
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5><label asp-for="tecnico" class="control-label"></label></h5>
|
<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>
|
<span asp-validation-for="tecnico" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5><label asp-for="ragsoc" class="control-label"></label></h5>
|
<h5><label asp-for="ragsoc" class="control-label"></label></h5>
|
||||||
<input asp-for="ragsoc" class="form-control" />
|
<input asp-for="ragsoc" class="form-control" />
|
||||||
<span asp-validation-for="ragsoc" class="text-danger"></span>
|
<span asp-validation-for="ragsoc" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5><label asp-for="logo" class="control-label"></label></h5>
|
<h5><label asp-for="logo" class="control-label"></label></h5>
|
||||||
<input type="file" asp-for="logo" />
|
<input type="file" asp-for="logo" />
|
||||||
<span asp-validation-for="logo" class="text-danger"></span>
|
<span asp-validation-for="logo" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5><label asp-for="testo_buono" class="control-label"></label></h5>
|
<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>
|
<textarea asp-for="testo_buono" class="form-control"></textarea>
|
||||||
<span asp-validation-for="testo_buono" class="text-danger"></span>
|
<span asp-validation-for="testo_buono" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="submit" value="Salva" class="agy-btn submitForm" />
|
<input type="submit" value="Salva" class="agy-btn submitForm" />
|
||||||
<a asp-action="Index" class="agy-btn submitForm">Torna alla lista</a>
|
<a asp-action="Index" value="Torna alla lista" class="agy-btn submitForm">Torna alla lista</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
</div>
|
@* <a asp-action="Index">Torna alla lista</a> *@
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ✅ Modale di conferma identica a quella della Edit -->
|
|
||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="~/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
|
<script src="~/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
|
||||||
|
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
@{
|
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||||
await Html.RenderPartialAsync("_ValidationScriptsPartial");
|
|
||||||
}
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// inizializza TinyMCE
|
|
||||||
tinymce.init({
|
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'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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(form.action, {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.ok) {
|
|
||||||
// ✅ Mostra la modale di conferma
|
|
||||||
$('#saveModal').modal('show');
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// quando l'utente clicca OK sulla modale, vai alla Index
|
|
||||||
document.getElementById('modalOkBtn').addEventListener('click', function () {
|
|
||||||
window.location.href = '@Url.Action("Index")';
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,7 +60,9 @@
|
|||||||
<input type="submit" value="Elimina" class="agy-btn submitForm" />
|
<input type="submit" value="Elimina" class="agy-btn submitForm" />
|
||||||
<input type="hidden" id="azienda" value=@Html.DisplayFor(model => model.azienda) name="azienda" />
|
<input type="hidden" id="azienda" value=@Html.DisplayFor(model => model.azienda) name="azienda" />
|
||||||
<input type="hidden" id="tecnico" value=@Html.DisplayFor(model => model.tecnico) name="tecnico" />
|
<input type="hidden" id="tecnico" value=@Html.DisplayFor(model => model.tecnico) name="tecnico" />
|
||||||
<a asp-action="Index" value="Torna alla lista" class="agy-btn submitForm">Torna alla lista</a>
|
<div>
|
||||||
|
<a asp-action="Index">Torna alla lista</a>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -10,113 +10,61 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<form id="editForm" asp-action="Edit" enctype="multipart/form-data">
|
<form asp-action="Edit" enctype="multipart/form-data">
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||||
@Html.HiddenFor(x => x.azienda)
|
@Html.HiddenFor(x => x.azienda)
|
||||||
@Html.HiddenFor(x => x.url_logo)
|
@Html.HiddenFor(x => x.url_logo)
|
||||||
@Html.HiddenFor(x => x.logo)
|
@Html.HiddenFor(x => x.logo)
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5><label asp-for="tecnico"></label></h5>
|
<h5><label asp-for="tecnico" class="agy-client-quote"></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>
|
<span asp-validation-for="tecnico" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5><label asp-for="ragsoc"></label></h5>
|
<h5><label asp-for="ragsoc" class="agy-client-quote"></label></h5>
|
||||||
<input asp-for="ragsoc" class="form-control" />
|
<input asp-for="ragsoc" class="form-control" />
|
||||||
<span asp-validation-for="ragsoc" class="text-danger"></span>
|
<span asp-validation-for="ragsoc" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5><label asp-for="logo"></label></h5>
|
<h5><label asp-for="logo" class="agy-client-quote"></label></h5>
|
||||||
@{
|
@{
|
||||||
if (Model.logo != null && Model.logo.Length > 0)
|
byte[] appo = Model.logo;
|
||||||
{
|
var base64 = Convert.ToBase64String(appo);
|
||||||
var base64 = Convert.ToBase64String(Model.logo);
|
var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
|
||||||
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" />
|
<input type="file" asp-for="logo2" />
|
||||||
<span asp-validation-for="logo" class="text-danger"></span>
|
<span asp-validation-for="logo" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12"> </div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5><label asp-for="testo_buono"></label></h5>
|
<h5><label asp-for="testo_buono" class="agy-client-quote"></label></h5>
|
||||||
<textarea asp-for="testo_buono" id="testo_buono" class="form-control"></textarea>
|
<textarea asp-for="testo_buono" class="form-control"></textarea>
|
||||||
<span asp-validation-for="testo_buono" class="text-danger"></span>
|
<span asp-validation-for="testo_buono" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
<div class="form-group mt-3">
|
|
||||||
<input type="submit" value="Salva" class="agy-btn submitForm" />
|
<input type="submit" value="Salva" class="agy-btn submitForm" />
|
||||||
<a asp-action="Index" class="agy-btn submitForm">Torna alla lista</a>
|
<a asp-action="Index" value="Torna alla lista" class="agy-btn submitForm">Torna alla lista</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
</div>
|
@* <a asp-action="Index">Back to List</a> *@
|
||||||
|
|
||||||
<!-- 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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="~/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
@{
|
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||||
await Html.RenderPartialAsync("_ValidationScriptsPartial");
|
|
||||||
}
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
tinymce.init({
|
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>
|
</script>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,6 @@
|
|||||||
}
|
}
|
||||||
<h1>@ViewData["Title"]</h1>
|
<h1>@ViewData["Title"]</h1>
|
||||||
|
|
||||||
<p> <a href="Download?file=wwwroot/APP/app-env_vt_1_34.apk" target="_blank">Download Android App (ver. 1.34)</a> </p>
|
<p> <a href="Download?file=wwwroot/APP/app-env_vt_1_25.apk" target="_blank">Download Android App (ver. 1.25)</a> </p>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,68 +4,6 @@
|
|||||||
ViewData["Title"] = "Virtual Task Pro";
|
ViewData["Title"] = "Virtual Task Pro";
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- CSS lightbox -->
|
|
||||||
<style>
|
|
||||||
.lightbox {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 9999;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(0,0,0,0.8);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .lightbox img {
|
|
||||||
max-width: 90%;
|
|
||||||
max-height: 80%;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 0 20px rgba(255,255,255,0.3);
|
|
||||||
animation: fadeIn 0.3s ease;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.lightbox img {
|
|
||||||
width: 400px;
|
|
||||||
height: auto; /* mantiene proporzioni */
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 0 20px rgba(255,255,255,0.3);
|
|
||||||
animation: fadeIn 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lightbox .close {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
right: 40px;
|
|
||||||
font-size: 40px;
|
|
||||||
color: #fff;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.lightbox-img {
|
|
||||||
cursor: pointer;
|
|
||||||
transition: transform 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lightbox-img:hover {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="agy-project-wrapper agy-project-page-wrapper">
|
<div class="agy-project-wrapper agy-project-page-wrapper">
|
||||||
<div class="container" style="width:100%; text-align:justify">
|
<div class="container" style="width:100%; text-align:justify">
|
||||||
<div>
|
<div>
|
||||||
@ -92,8 +30,8 @@
|
|||||||
<div class="col-lg-6 col-md-6 col-sm-12 col-12">
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12">
|
||||||
<div class="agy-about-img relative">
|
<div class="agy-about-img relative">
|
||||||
<div class="">
|
<div class="">
|
||||||
<img src="~/assets/images/app1.png" alt="Virtual Task App" style="width:30%;height:30%;" class="lightbox-img" />
|
<img src="~/assets/images/app1.png" alt="Virtual Task App" style="width:30%;height:30%;" />
|
||||||
<img src="~/assets/images/app2.png" alt="Virtual Task App" style="width:30%;height:30%;" class="lightbox-img" />
|
<img src="~/assets/images/app2.png" alt="Virtual Task App" style="width:30%;height:30%;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -122,7 +60,7 @@
|
|||||||
<table style="width:100%">
|
<table style="width:100%">
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:20%">
|
<th style="width:20%">
|
||||||
<img src="~/assets/images/app3.png" alt="Virtual Task App" style="width:70%;height:70%;" class="lightbox-img" />
|
<img src="~/assets/images/app3.png" alt="Virtual Task App" style="width:70%;height:70%;" />
|
||||||
</th>
|
</th>
|
||||||
<th style="width:70%">
|
<th style="width:70%">
|
||||||
<ol>
|
<ol>
|
||||||
@ -186,8 +124,8 @@
|
|||||||
<div class="col-lg-6 col-md-6 col-sm-12 col-12">
|
<div class="col-lg-6 col-md-6 col-sm-12 col-12">
|
||||||
<div class="agy-about-img relative">
|
<div class="agy-about-img relative">
|
||||||
<div class="">
|
<div class="">
|
||||||
<img src="~/assets/images/app5.png" alt="Virtual Task App" style="width:30%;height:30%;" class="lightbox-img" />
|
<img src="~/assets/images/app5.png" alt="Virtual Task App" style="width:30%;height:30%;" />
|
||||||
<img src="~/assets/images/app6.png" alt="Virtual Task App" style="width:30%;height:30%;" class="lightbox-img" />
|
<img src="~/assets/images/app6.png" alt="Virtual Task App" style="width:30%;height:30%;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -226,37 +164,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Lightbox HTML -->
|
|
||||||
<div class="lightbox" id="lightbox">
|
|
||||||
<span class="close" id="lightbox-close">×</span>
|
|
||||||
<img id="lightbox-img" src="" alt="Anteprima immagine">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<script>
|
|
||||||
const lightbox = document.getElementById('lightbox');
|
|
||||||
const lightboxImg = document.getElementById('lightbox-img');
|
|
||||||
const closeBtn = document.getElementById('lightbox-close');
|
|
||||||
|
|
||||||
document.querySelectorAll('.lightbox-img').forEach(img => {
|
|
||||||
img.addEventListener('click', () => {
|
|
||||||
lightboxImg.src = img.src;
|
|
||||||
lightbox.style.display = 'flex';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
closeBtn.addEventListener('click', () => {
|
|
||||||
lightbox.style.display = 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
lightbox.addEventListener('click', (e) => {
|
|
||||||
if (e.target === lightbox) {
|
|
||||||
lightbox.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
}
|
|
||||||
|
|
||||||
@* <script>
|
@* <script>
|
||||||
$('.zoom').click(function () {
|
$('.zoom').click(function () {
|
||||||
var imageUrl = $(this).attr('src');
|
var imageUrl = $(this).attr('src');
|
||||||
|
|||||||
@ -1,63 +1,8 @@
|
|||||||
@{
|
@{
|
||||||
Layout = "~/Views/Shared/_LayoutAreaRiservata.cshtml";
|
Layout = "~/Views/Shared/_LayoutAreaRiservata.cshtml";
|
||||||
ViewData["Title"] = "Task Manager";
|
ViewData["Title"] = "Task Manager";
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- CSS lightbox -->
|
|
||||||
<style>
|
|
||||||
.lightbox {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 9999;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(0,0,0,0.8);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .lightbox img {
|
|
||||||
max-width: 90%;
|
|
||||||
max-height: 80%;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 0 20px rgba(255,255,255,0.3);
|
|
||||||
animation: fadeIn 0.3s ease;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.lightbox img {
|
|
||||||
width:1200px;
|
|
||||||
height: auto; /* mantiene proporzioni */
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 0 20px rgba(255,255,255,0.3);
|
|
||||||
animation: fadeIn 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lightbox .close {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
right: 40px;
|
|
||||||
font-size: 40px;
|
|
||||||
color: #fff;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@keyframes fadeIn {
|
|
||||||
from { opacity: 0; transform: scale(0.9); }
|
|
||||||
to { opacity: 1; transform: scale(1); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.lightbox-img {
|
|
||||||
cursor: pointer;
|
|
||||||
transition: transform 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lightbox-img:hover {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="agy-project-wrapper agy-project-page-wrapper">
|
<div class="agy-project-wrapper agy-project-page-wrapper">
|
||||||
<div class="container" style="width:100%; text-align:justify">
|
<div class="container" style="width:100%; text-align:justify">
|
||||||
<div>
|
<div>
|
||||||
@ -65,7 +10,7 @@
|
|||||||
<br />
|
<br />
|
||||||
<div class="agy-about-img relative">
|
<div class="agy-about-img relative">
|
||||||
<div class="">
|
<div class="">
|
||||||
<img src="~/assets/images/pro1.png" alt="Virtual Task App" style="width:50%;height:50%;" class="lightbox-img" />
|
<img src="~/assets/images/pro1.png" alt="Virtual Task App" style="width:55%;height:55%;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -80,15 +25,33 @@
|
|||||||
<br />
|
<br />
|
||||||
<p>
|
<p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>A. Gestione anagrafica IMPIANTO con dati tecnici ed eventuale composizione specifica componenti.</li>
|
<li>
|
||||||
<li>B. Gestione Manutenzioni programmate previste per l'IMPIANTO.</li>
|
A. Gestione anagrafica IMPIANTO con dati tecnici ed eventuale composizione specifica componenti.
|
||||||
<li>C. Gestione Contratti con specifica degli impianti, calcolo delle rate e relativa fatturazione.</li>
|
</li>
|
||||||
<li>D. Gestione Commesse di lavoro con aggancio all'analitica standard.</li>
|
<li>
|
||||||
<li>E. Completa gestione delle chiamate di intervento, dall'inserimento alla sua assegnazione a tecnico e consuntivazione.</li>
|
B. Gestione Manutenzioni programmate previste per l'IMPIANTO.
|
||||||
<li>F. Gestione RAPPORTINI DI INTERVENTO come consuntivi tecnici siano essi legati a manutenzioni, commesse o chiamate.</li>
|
</li>
|
||||||
<li>G. Fatturazione canoni dei contratti.</li>
|
<li>
|
||||||
<li>H. Fatturazione rapportini di intervento.</li>
|
C. Gestione Contratti con specifica degli impianti, calcolo delle rate e relativa fatturazione.
|
||||||
<li>I. Fatturazione commesse ad avanzamento lavoro.</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
D. Gestione Commesse di lavoro con aggancio all'analitica standard.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
E. Completa gestione delle chiamate di intervento, dall'inserimento alla sua assegnazione a tecnico e consuntivazione.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
F. Gestione RAPPORTINI DI INTERVENTO come consuntivi tecnici siano essi legati a manutenzioni, commesse o chiamate.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
G. Fatturazione canoni dei contratti.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
H. Fatturazione rapportini di intervento.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
I. Fatturazione commesse ad avanzamento lavoro.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -99,38 +62,46 @@
|
|||||||
<br />
|
<br />
|
||||||
<div class="agy-about-img relative">
|
<div class="agy-about-img relative">
|
||||||
<div class="">
|
<div class="">
|
||||||
<img src="~/assets/images/pro2.png" alt="Virtual Task App" style="width:55%;height:55%;" class="lightbox-img" />
|
<img src="~/assets/images/pro2.png" alt="Virtual Task App" style="width:55%;height:55%;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div class="container" style="width:100%; text-align:justify">
|
<div class="container" style="width:100%; text-align:justify">
|
||||||
<p><h4>Cruscotto Operativo Chiamate</h4></p>
|
<p>
|
||||||
|
<h4>
|
||||||
|
Cruscotto Operativo Chiamate
|
||||||
|
</h4>
|
||||||
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<div class="agy-about-img relative">
|
<div class="agy-about-img relative">
|
||||||
<div class="">
|
<div class="">
|
||||||
<img src="~/assets/images/pro3.png" alt="Virtual Task App" style="width:55%;height:55%;" class="lightbox-img" />
|
<img src="~/assets/images/pro3.png" alt="Virtual Task App" style="width:55%;height:55%;" />
|
||||||
<img src="~/assets/images/pro4.png" alt="Virtual Task App" style="width:55%;height:55%;" class="lightbox-img" />
|
<img src="~/assets/images/pro4.png" alt="Virtual Task App" style="width:55%;height:55%;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div class="container" style="width:100%; text-align:justify">
|
<div class="container" style="width:100%; text-align:justify">
|
||||||
<p><h4>Gestione Rapportini</h4></p>
|
<p>
|
||||||
|
<h4>
|
||||||
|
Gestione Rapportini
|
||||||
|
</h4>
|
||||||
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<p>Dettaglio rapportini</p>
|
<p>Dettaglio rapportini</p>
|
||||||
<br />
|
<br />
|
||||||
<div class="agy-about-img relative">
|
<div class="agy-about-img relative">
|
||||||
<div class="">
|
<div class="">
|
||||||
<img src="~/assets/images/pro5.png" alt="Virtual Task App" style="width:55%;height:55%;" class="lightbox-img" />
|
<img src="~/assets/images/pro5.png" alt="Virtual Task App" style="width:55%;height:55%;" />
|
||||||
<img src="~/assets/images/pro6.png" alt="Virtual Task App" style="width:55%;height:55%;" class="lightbox-img" />
|
<img src="~/assets/images/pro6.png" alt="Virtual Task App" style="width:55%;height:55%;" />
|
||||||
<img src="~/assets/images/pro7.png" alt="Virtual Task App" style="width:55%;height:55%;" class="lightbox-img" />
|
<img src="~/assets/images/pro7.png" alt="Virtual Task App" style="width:55%;height:55%;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container" style="width:100%; text-align:justify">
|
<div class="container" style="width:100%; text-align:justify">
|
||||||
<p>
|
<p>
|
||||||
Il Polo Informatico garantisce comunque la possibilità di potere customizzare tale App secondo le esigenze del cliente, modificando loghi, layout e colori ma anche delineando
|
Il Polo Informatico garantisce comunque la possibilità di potere customizzare tale App secondo le esigenze del cliente, modificando loghi, layout e colori ma anche delineando
|
||||||
nuovi possibili flussi e/o implementando nuove funzionalità.
|
nuovi possibili flussi e/o implementando nuove funzionalità.
|
||||||
Infine Vuoi aggiungere delle funzionalità? Le nostre app per la gestione dei clienti sono <b>totalmente personalizzabili</b> per offrire un’esperienza di utilizzo unica.
|
Infine Vuoi aggiungere delle funzionalità? Le nostre app per la gestione dei clienti sono <b>totalmente personalizzabili</b> per offrire un’esperienza di utilizzo unica.
|
||||||
</p>
|
</p>
|
||||||
@ -138,33 +109,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Lightbox HTML -->
|
|
||||||
<div class="lightbox" id="lightbox">
|
|
||||||
<span class="close" id="lightbox-close">×</span>
|
|
||||||
<img id="lightbox-img" src="" alt="Anteprima immagine">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<script>
|
|
||||||
const lightbox = document.getElementById('lightbox');
|
|
||||||
const lightboxImg = document.getElementById('lightbox-img');
|
|
||||||
const closeBtn = document.getElementById('lightbox-close');
|
|
||||||
|
|
||||||
document.querySelectorAll('.lightbox-img').forEach(img => {
|
|
||||||
img.addEventListener('click', () => {
|
|
||||||
lightboxImg.src = img.src;
|
|
||||||
lightbox.style.display = 'flex';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
closeBtn.addEventListener('click', () => {
|
|
||||||
lightbox.style.display = 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
lightbox.addEventListener('click', (e) => {
|
|
||||||
if (e.target === lightbox) {
|
|
||||||
lightbox.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,30 +1,19 @@
|
|||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Visualizza immagine";
|
ViewData["Title"] = "Visualizza immagine";
|
||||||
Layout = "~/Views/Shared/_LayoutAreaRiservata.cshtml";
|
|
||||||
var fileName = ViewBag.FileName as string;
|
var fileName = ViewBag.FileName as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
<h2>@ViewData["Title"]</h2>
|
<h2>@ViewData["Title"]</h2>
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(fileName))
|
||||||
<div class="agy-project-wrapper agy-project-page-wrapper">
|
{
|
||||||
<div class="container">
|
<div>
|
||||||
<div class="row">
|
<img src="@Url.Action("GetImage", "Rapp_New", new { filePath = fileName })"
|
||||||
<div class="col-md-4">
|
alt="Immagine: @fileName"
|
||||||
@if (!string.IsNullOrEmpty(fileName))
|
style="max-width:600px; height:auto; border:1px solid #ccc;" />
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<img src="@Url.Action("GetImage", "Rapp_New", new { filePath = fileName })"
|
|
||||||
alt="Immagine: @fileName"
|
|
||||||
style="max-width:600px; height:auto; border:1px solid #ccc;" />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<p>Nessuna immagine specificata.</p>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>Nessuna immagine specificata.</p>
|
||||||
|
}
|
||||||
|
|||||||
@ -7,12 +7,11 @@
|
|||||||
},
|
},
|
||||||
"ApplicationInsights": {
|
"ApplicationInsights": {
|
||||||
|
|
||||||
//PRODUZIONE
|
////PRODUZIONE
|
||||||
"rootUrlApi": "https://api-vt.poloinformatico.it/api/Polo/",
|
"rootUrlApi": "https://api-vt.poloinformatico.it/api/Polo/",
|
||||||
"rootUrlApi2": "https://api-vt.poloinformatico.it/VIRTU/",
|
"rootUrlApi2": "https://api-vt.poloinformatico.it/VIRTU/",
|
||||||
//"rootWebLoghi": "C:\\ZAPIPOLO\\api_polo\\wwwroot\\VIRTU\\",
|
//"rootWebLoghi": "C:\\ZAPIPOLO\\api_polo\\wwwroot\\VIRTU\\",
|
||||||
//"rootWebLoghi": "/zucchetti/api/api-vt.poloinformatico.it/app/wwwroot/VIRTU/",
|
"rootWebLoghi": "/zucchetti/api/api-vt.poloinformatico.it/app/wwwroot/VIRTU/",
|
||||||
"rootWebLoghi": "./wwwroot/VIRTU",
|
|
||||||
"rootUrl": "https://virtualtask.it/",
|
"rootUrl": "https://virtualtask.it/",
|
||||||
"rootPath": "/mnt/storagebox",
|
"rootPath": "/mnt/storagebox",
|
||||||
|
|
||||||
@ -22,11 +21,10 @@
|
|||||||
//"rootWebLoghi": "C:\\Users\\audif\\source\\repos\\VirtualTask\\wwwroot\\VIRTU\\",
|
//"rootWebLoghi": "C:\\Users\\audif\\source\\repos\\VirtualTask\\wwwroot\\VIRTU\\",
|
||||||
//"rootUrl": "https://localhost:7140/",
|
//"rootUrl": "https://localhost:7140/",
|
||||||
|
|
||||||
////MICHELE: PUNTAMENTO A MIO PC PER FARE I TEST
|
//MICHELE: PUNTAMENTO A MIO PC PER FARE I TEST
|
||||||
//"rootUrlApi": "https://localhost:7068/api/Polo/",
|
//"rootUrlApi": "https://localhost:7068/api/Polo/",
|
||||||
//"rootUrlApi2": "https://localhost:7068//VIRTU/",
|
//"rootUrlApi2": "https://localhost:7068//VIRTU/",
|
||||||
////"rootWebLoghi": "C:\\Users\\audif\\source\\repos\\VirtualTask\\wwwroot\\VIRTU\\",
|
//"rootWebLoghi": "C:\\Users\\audif\\source\\repos\\VirtualTask\\wwwroot\\VIRTU\\",
|
||||||
//"rootWebLoghi": "/zucchetti/api/api-vt.poloinformatico.it/app/wwwroot/VIRTU/",
|
|
||||||
//"rootUrl": "https://localhost:7068/",
|
//"rootUrl": "https://localhost:7068/",
|
||||||
|
|
||||||
"mittenteMail": "info@virtualtask.it",
|
"mittenteMail": "info@virtualtask.it",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user