Fix gestione allegati e creato metodo di esportazione log
This commit is contained in:
@@ -182,6 +182,17 @@ public class IspezioniService(AppDbContext db) : IIspezioniService
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateFileListSchedaAsync(int schedaId, List<string>? imageNames)
|
||||
{
|
||||
var scheda = await db.Schede.FirstOrDefaultAsync(x => x.Id == schedaId);
|
||||
if (scheda is null) return false;
|
||||
|
||||
scheda.ImageNames = imageNames;
|
||||
db.Schede.Update(scheda);
|
||||
await db.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteSchedaAsync(int schedaId)
|
||||
{
|
||||
var scheda = await db.Schede.FirstOrDefaultAsync(x => x.Id == schedaId);
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SteUp.Maui.Core.UtilityException;
|
||||
|
||||
namespace SteUp.Maui
|
||||
{
|
||||
public partial class App
|
||||
{
|
||||
public App()
|
||||
public App(ILogger<App> logger)
|
||||
{
|
||||
InitializeComponent();
|
||||
GlobalExceptionHandler.Register(logger);
|
||||
}
|
||||
|
||||
protected override Window CreateWindow(IActivationState? activationState)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SteUp.Data.LocalDb;
|
||||
using SteUp.Data.LocalDb.EntityServices;
|
||||
using SteUp.Maui.Core.Logger;
|
||||
using SteUp.Maui.Core.Services;
|
||||
using SteUp.Maui.Core.System;
|
||||
using SteUp.Maui.Core.System.Network;
|
||||
@@ -45,6 +47,7 @@ public static class CoreModule
|
||||
{
|
||||
builder.Services.AddSingleton<INetworkService, NetworkService>();
|
||||
builder.Services.AddSingleton<IAttachedService, AttachedService>();
|
||||
builder.Services.AddSingleton<IFileManager, FileManager>();
|
||||
builder.Services.AddSingleton<IBarcodeReaderService, HoneywellScannerService>();
|
||||
}
|
||||
|
||||
@@ -75,5 +78,17 @@ public static class CoreModule
|
||||
builder.Services.AddSingleton<IDbInitializer, DbInitializer>();
|
||||
builder.Services.AddSingleton<IIspezioniService, IspezioniService>();
|
||||
}
|
||||
|
||||
public void RegisterLoggerServices()
|
||||
{
|
||||
var logPath = Path.Combine(FileSystem.AppDataDirectory, "logs");
|
||||
const string logFilePrefix = "SteUp-log";
|
||||
|
||||
builder.Services.AddLogging(loggingBuilder =>
|
||||
{
|
||||
loggingBuilder.AddProvider(new FileLoggerProvider(logPath, logFilePrefix));
|
||||
loggingBuilder.SetMinimumLevel(LogLevel.Information);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
185
SteUp.Maui/Core/Logger/FileLogger.cs
Normal file
185
SteUp.Maui/Core/Logger/FileLogger.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace SteUp.Maui.Core.Logger;
|
||||
|
||||
public class FileLogger : ILogger
|
||||
{
|
||||
private readonly string _path;
|
||||
private readonly string _fileNamePrefix;
|
||||
private readonly string _categoryName;
|
||||
private readonly Lock _lock = new();
|
||||
private readonly int _retentionDays;
|
||||
private string? _currentFileName;
|
||||
private DateTime _currentFileDate;
|
||||
private DateTime _lastCleanupDate;
|
||||
|
||||
public FileLogger(string path, string fileNamePrefix, string categoryName, int retentionDays = 60)
|
||||
{
|
||||
_path = path;
|
||||
_fileNamePrefix = fileNamePrefix;
|
||||
_retentionDays = retentionDays;
|
||||
_lastCleanupDate = DateTime.MinValue;
|
||||
_categoryName = categoryName;
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
UpdateCurrentFileName();
|
||||
TryCleanOldLogs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elimina i log più vecchi di <see cref="_retentionDays"/> giorni.
|
||||
/// Viene eseguita al massimo una volta al giorno.
|
||||
/// </summary>
|
||||
private void ClearOldLogs()
|
||||
{
|
||||
try
|
||||
{
|
||||
var cutoff = DateTime.Now.Date.AddDays(-_retentionDays);
|
||||
var logFiles = Directory.GetFiles(_path, $"{_fileNamePrefix}-*.log");
|
||||
|
||||
foreach (var file in logFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileNameWithoutExtension(file);
|
||||
|
||||
var datePart = fileName[(_fileNamePrefix.Length + 1)..];
|
||||
|
||||
if (!DateTime.TryParseExact(datePart, "yyyy-MM-dd",
|
||||
CultureInfo.InvariantCulture,
|
||||
DateTimeStyles.None,
|
||||
out var fileDate) || fileDate >= cutoff) continue;
|
||||
File.Delete(file);
|
||||
Debug.WriteLine($"[FileLogger] Log eliminato: {file}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[FileLogger] Errore durante l'eliminazione del file {file}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[FileLogger] Errore durante la pulizia dei log: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue la pulizia dei log solo se non è già stata eseguita oggi.
|
||||
/// </summary>
|
||||
private void TryCleanOldLogs()
|
||||
{
|
||||
var today = DateTime.Now.Date;
|
||||
if (_lastCleanupDate == today) return;
|
||||
_lastCleanupDate = today;
|
||||
ClearOldLogs();
|
||||
}
|
||||
|
||||
private void UpdateCurrentFileName()
|
||||
{
|
||||
var today = DateTime.Now.Date;
|
||||
if (_currentFileName != null && _currentFileDate == today) return;
|
||||
_currentFileDate = today;
|
||||
_currentFileName = $"{_fileNamePrefix}-{today:yyyy-MM-dd}.log";
|
||||
}
|
||||
|
||||
public IDisposable? BeginScope<TState>(TState state) => null;
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
|
||||
|
||||
public void Log<TState>(
|
||||
LogLevel logLevel,
|
||||
EventId eventId,
|
||||
TState state,
|
||||
Exception? exception,
|
||||
Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
if (!IsEnabled(logLevel))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
UpdateCurrentFileName();
|
||||
TryCleanOldLogs();
|
||||
|
||||
if (_currentFileName == null) return;
|
||||
|
||||
var fullPath = Path.Combine(_path, _currentFileName);
|
||||
var logEntry = BuildLogEntry(logLevel, eventId, state, exception, formatter);
|
||||
|
||||
File.AppendAllText(fullPath, logEntry + Environment.NewLine + Environment.NewLine);
|
||||
Debug.WriteLine($"[FileLogger] {logEntry}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[FileLogger] Errore durante la scrittura del log: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
private string BuildLogEntry<TState>(
|
||||
LogLevel logLevel,
|
||||
EventId eventId,
|
||||
TState state,
|
||||
Exception? exception,
|
||||
Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}]");
|
||||
sb.Append($" [{GetLogLevelShort(logLevel)}]");
|
||||
sb.Append($" [{_categoryName}]");
|
||||
|
||||
if (eventId.Id != 0 || !string.IsNullOrEmpty(eventId.Name))
|
||||
sb.Append($" [{eventId}]");
|
||||
|
||||
sb.Append($" {formatter(state, exception)}");
|
||||
|
||||
if (exception != null)
|
||||
AppendException(sb, exception);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static void AppendException(StringBuilder sb, Exception exception, int depth = 0)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var indent = depth == 0 ? "" : " Inner ";
|
||||
sb.AppendLine();
|
||||
sb.Append($"{indent}Exception: {exception.GetType().FullName}: {exception.Message}");
|
||||
if (!string.IsNullOrWhiteSpace(exception.StackTrace))
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.Append($"{indent}StackTrace: {exception.StackTrace.Trim()}");
|
||||
}
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
exception = exception.InnerException;
|
||||
depth += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetLogLevelShort(LogLevel level) => level switch
|
||||
{
|
||||
LogLevel.Trace => "TRC",
|
||||
LogLevel.Debug => "DBG",
|
||||
LogLevel.Information => "INF",
|
||||
LogLevel.Warning => "WRN",
|
||||
LogLevel.Error => "ERR",
|
||||
LogLevel.Critical => "CRT",
|
||||
_ => "???"
|
||||
};
|
||||
}
|
||||
14
SteUp.Maui/Core/Logger/FileLoggerProvider.cs
Normal file
14
SteUp.Maui/Core/Logger/FileLoggerProvider.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SteUp.Maui.Core.Logger;
|
||||
|
||||
public class FileLoggerProvider(string path, string logFilePrefix, int retentionDays = 60)
|
||||
: ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
return new FileLogger(path, logFilePrefix, categoryName, retentionDays);
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
using SteUp.Shared.Core.Dto;
|
||||
using SteUp.Shared.Core.Entities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SteUp.Maui.Core.Utility;
|
||||
using SteUp.Shared.Core.Dto;
|
||||
using SteUp.Shared.Core.Helpers;
|
||||
using SteUp.Shared.Core.Interface.System;
|
||||
|
||||
namespace SteUp.Maui.Core.Services;
|
||||
|
||||
public class AttachedService : IAttachedService
|
||||
public class AttachedService(ILogger<FileManager> logger) : IAttachedService
|
||||
{
|
||||
private static string AttachedRoot =>
|
||||
Path.Combine(FileSystem.CacheDirectory, "attached");
|
||||
|
||||
public async Task<AttachedDto?> SelectImageFromCamera()
|
||||
{
|
||||
var cameraPerm = await Permissions.RequestAsync<Permissions.Camera>();
|
||||
@@ -27,12 +25,13 @@ public class AttachedService : IAttachedService
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, ex.Message);
|
||||
Console.WriteLine($"Errore cattura foto: {ex.Message}");
|
||||
SentrySdk.CaptureException(ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
return result is null ? null : await ConvertToDto(result, AttachedDto.TypeAttached.Image);
|
||||
return result is null ? null : await UtilityFile.ConvertToDto(result, AttachedDto.TypeAttached.Image);
|
||||
}
|
||||
|
||||
public async Task<List<AttachedDto>?> SelectImageFromGallery()
|
||||
@@ -48,6 +47,7 @@ public class AttachedService : IAttachedService
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, ex.Message);
|
||||
Console.WriteLine($"Errore selezione galleria: {ex.Message}");
|
||||
SentrySdk.CaptureException(ex);
|
||||
return null;
|
||||
@@ -58,308 +58,9 @@ public class AttachedService : IAttachedService
|
||||
List<AttachedDto> returnList = [];
|
||||
foreach (var fileResult in resultList)
|
||||
{
|
||||
returnList.Add(await ConvertToDto(fileResult, AttachedDto.TypeAttached.Image));
|
||||
returnList.Add(await UtilityFile.ConvertToDto(fileResult, AttachedDto.TypeAttached.Image));
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private static async Task<AttachedDto> ConvertToDto(FileResult file, AttachedDto.TypeAttached type)
|
||||
{
|
||||
var stream = await file.OpenReadAsync();
|
||||
using var ms = new MemoryStream();
|
||||
await stream.CopyToAsync(ms);
|
||||
|
||||
return new AttachedDto
|
||||
{
|
||||
Name = file.FileName,
|
||||
Path = file.FullPath,
|
||||
MimeType = file.ContentType,
|
||||
DimensionBytes = ms.Length,
|
||||
FileBytes = ms.ToArray(),
|
||||
Type = type
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<AttachedDto> ConvertToDto(FileInfo file, AttachedDto.TypeAttached type, bool isFromToUpload)
|
||||
{
|
||||
var (origUrl, thumbUrl) = await SaveAndCreateThumbAsync(
|
||||
await File.ReadAllBytesAsync(file.FullName),
|
||||
file.Name
|
||||
);
|
||||
|
||||
return new AttachedDto
|
||||
{
|
||||
Name = file.Name,
|
||||
Path = file.FullName,
|
||||
TempPath = origUrl,
|
||||
ThumbPath = thumbUrl,
|
||||
Type = type,
|
||||
SavedOnAppData = true,
|
||||
ToUpload = isFromToUpload
|
||||
};
|
||||
}
|
||||
|
||||
private const string ToUploadFolderName = "toUpload";
|
||||
|
||||
private string GetInspectionBaseDir(Ispezione ispezione)
|
||||
{
|
||||
var baseDir = FileSystem.AppDataDirectory;
|
||||
return Path.Combine(baseDir, $"attached_{GetInspectionKey(ispezione)}");
|
||||
}
|
||||
|
||||
private string GetInspectionToUploadDir(Ispezione ispezione)
|
||||
=> Path.Combine(GetInspectionBaseDir(ispezione), ToUploadFolderName);
|
||||
|
||||
private string GetInspectionFinalDir(Ispezione ispezione)
|
||||
=> GetInspectionBaseDir(ispezione);
|
||||
|
||||
/// <summary>
|
||||
/// Ritorna i file dell'ispezione filtrati per nome.
|
||||
/// Per default include sia "final" sia "toUpload" (utile per UI).
|
||||
/// </summary>
|
||||
public async Task<List<AttachedDto>?> GetInspectionFiles(
|
||||
Ispezione ispezione,
|
||||
List<string> fileNameFilter,
|
||||
bool includeToUpload,
|
||||
CancellationToken ct)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ispezione);
|
||||
ArgumentNullException.ThrowIfNull(fileNameFilter);
|
||||
|
||||
var baseDir = GetInspectionBaseDir(ispezione);
|
||||
if (!Directory.Exists(baseDir)) return null;
|
||||
|
||||
var result = new List<AttachedDto>();
|
||||
|
||||
var finalDir = GetInspectionFinalDir(ispezione);
|
||||
if (Directory.Exists(finalDir))
|
||||
{
|
||||
var finalFiles = new DirectoryInfo(finalDir)
|
||||
.GetFiles("*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (var file in finalFiles)
|
||||
{
|
||||
if (file.Directory?.Name == ToUploadFolderName)
|
||||
continue;
|
||||
|
||||
if (!fileNameFilter.Contains(file.Name))
|
||||
continue;
|
||||
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
result.Add(await ConvertToDto(
|
||||
file,
|
||||
AttachedDto.TypeAttached.Image,
|
||||
isFromToUpload: false));
|
||||
}
|
||||
}
|
||||
|
||||
if (!includeToUpload) return result;
|
||||
|
||||
var toUploadDir = GetInspectionToUploadDir(ispezione);
|
||||
if (!Directory.Exists(toUploadDir)) return result;
|
||||
|
||||
var toUploadFiles = new DirectoryInfo(toUploadDir)
|
||||
.GetFiles("*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (var file in toUploadFiles)
|
||||
{
|
||||
if (!fileNameFilter.Contains(file.Name))
|
||||
continue;
|
||||
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
result.Add(await ConvertToDto(
|
||||
file,
|
||||
AttachedDto.TypeAttached.Image,
|
||||
isFromToUpload: true));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salva SEMPRE in /toUpload.
|
||||
/// </summary>
|
||||
public async Task<string?> SaveInspectionFile(
|
||||
Ispezione ispezione,
|
||||
byte[] file,
|
||||
string fileName,
|
||||
CancellationToken ct)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ispezione);
|
||||
ArgumentNullException.ThrowIfNull(file);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(fileName);
|
||||
|
||||
var toUploadDir = GetInspectionToUploadDir(ispezione);
|
||||
Directory.CreateDirectory(toUploadDir);
|
||||
|
||||
var filePath = Path.Combine(toUploadDir, fileName);
|
||||
await File.WriteAllBytesAsync(filePath, file, ct);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public Task<bool> MoveInspectionFileFromToUploadToFinal(
|
||||
Ispezione ispezione,
|
||||
string fileName,
|
||||
bool overwrite,
|
||||
CancellationToken ct)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ispezione);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(fileName);
|
||||
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
var toUploadDir = GetInspectionToUploadDir(ispezione);
|
||||
var finalDir = GetInspectionFinalDir(ispezione);
|
||||
|
||||
if (!Directory.Exists(toUploadDir)) return Task.FromResult(false);
|
||||
|
||||
var sourcePath = Path.Combine(toUploadDir, fileName);
|
||||
if (!File.Exists(sourcePath)) return Task.FromResult(false);
|
||||
|
||||
Directory.CreateDirectory(finalDir);
|
||||
|
||||
var destPath = Path.Combine(finalDir, fileName);
|
||||
|
||||
if (File.Exists(destPath))
|
||||
{
|
||||
if (!overwrite) return Task.FromResult(false);
|
||||
File.Delete(destPath);
|
||||
}
|
||||
|
||||
File.Move(sourcePath, destPath);
|
||||
|
||||
// Pulizia: se /toUpload resta vuota la elimino
|
||||
CleanupDirectoriesIfEmpty(ispezione);
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rimuove un file cercandolo prima in /toUpload e poi in final (o viceversa).
|
||||
/// Default: prova a cancellare ovunque.
|
||||
/// </summary>
|
||||
public bool RemoveInspectionFile(
|
||||
Ispezione ispezione,
|
||||
string fileName,
|
||||
bool removeAlsoFromFinal,
|
||||
bool removeAlsoFromToUpload)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ispezione);
|
||||
if (string.IsNullOrWhiteSpace(fileName)) return false;
|
||||
|
||||
var removed = false;
|
||||
|
||||
if (removeAlsoFromToUpload)
|
||||
{
|
||||
var toUploadPath = Path.Combine(GetInspectionToUploadDir(ispezione), fileName);
|
||||
if (File.Exists(toUploadPath))
|
||||
{
|
||||
File.Delete(toUploadPath);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeAlsoFromFinal)
|
||||
{
|
||||
var finalPath = Path.Combine(GetInspectionFinalDir(ispezione), fileName);
|
||||
if (File.Exists(finalPath))
|
||||
{
|
||||
File.Delete(finalPath);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed)
|
||||
CleanupDirectoriesIfEmpty(ispezione);
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
private void CleanupDirectoriesIfEmpty(Ispezione ispezione)
|
||||
{
|
||||
var baseDir = GetInspectionBaseDir(ispezione);
|
||||
var toUploadDir = GetInspectionToUploadDir(ispezione);
|
||||
|
||||
// 1) se /toUpload esiste e vuota => delete
|
||||
if (Directory.Exists(toUploadDir) && !Directory.EnumerateFileSystemEntries(toUploadDir).Any())
|
||||
Directory.Delete(toUploadDir);
|
||||
|
||||
// 2) se base dir vuota (attenzione: dopo delete toUpload) => delete
|
||||
if (Directory.Exists(baseDir) && !Directory.EnumerateFileSystemEntries(baseDir).Any())
|
||||
Directory.Delete(baseDir);
|
||||
}
|
||||
|
||||
public async Task<string> SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(file);
|
||||
|
||||
if (file.CanSeek)
|
||||
file.Position = 0;
|
||||
|
||||
fileName = Path.GetFileName(fileName);
|
||||
|
||||
var dir = FileSystem.CacheDirectory;
|
||||
var filePath = Path.Combine(dir, fileName);
|
||||
|
||||
await using var fileStream = File.Create(filePath);
|
||||
await file.CopyToAsync(fileStream, ct);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public Task CleanTempStorageAsync(CancellationToken ct = default)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
if (Directory.Exists(AttachedRoot))
|
||||
Directory.Delete(AttachedRoot, true);
|
||||
}, ct);
|
||||
}
|
||||
|
||||
public Task OpenFile(string fileName, string filePath)
|
||||
{
|
||||
#if IOS
|
||||
throw new NotImplementedException();
|
||||
#else
|
||||
return Launcher.OpenAsync(new OpenFileRequest
|
||||
{
|
||||
Title = "Apri file",
|
||||
File = new ReadOnlyFile(filePath)
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
public async Task<(string originalUrl, string thumbUrl)> SaveAndCreateThumbAsync(
|
||||
byte[] bytes, string fileName, CancellationToken ct = default)
|
||||
{
|
||||
Directory.CreateDirectory(AttachedRoot);
|
||||
|
||||
var id = Guid.NewGuid().ToString("N");
|
||||
var safeName = SanitizeFileName(fileName);
|
||||
|
||||
var originalFile = $"{id}_{safeName}";
|
||||
var thumbFile = $"{id}_thumb.jpg";
|
||||
|
||||
var originalPath = Path.Combine(AttachedRoot, originalFile);
|
||||
await File.WriteAllBytesAsync(originalPath, bytes, ct);
|
||||
|
||||
var thumbPath = Path.Combine(AttachedRoot, thumbFile);
|
||||
await ImageThumb.CreateThumbnailAsync(originalPath, thumbPath, maxSide: 320, quality: 70, ct);
|
||||
|
||||
return ($"https://localfiles/attached/{originalFile}",
|
||||
$"https://localfiles/attached/{thumbFile}");
|
||||
}
|
||||
|
||||
private static string SanitizeFileName(string fileName)
|
||||
{
|
||||
var name = Path.GetFileName(fileName);
|
||||
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, '_'));
|
||||
}
|
||||
|
||||
private static string GetInspectionKey(Ispezione ispezione) =>
|
||||
$"{ispezione.CodMdep}_{ispezione.Data:ddMMyyyy}_{ispezione.Rilevatore.ToLower()}";
|
||||
}
|
||||
442
SteUp.Maui/Core/Services/FileManager.cs
Normal file
442
SteUp.Maui/Core/Services/FileManager.cs
Normal file
@@ -0,0 +1,442 @@
|
||||
using System.IO.Compression;
|
||||
using SteUp.Data.LocalDb;
|
||||
using SteUp.Shared.Core.Dto;
|
||||
using SteUp.Shared.Core.Entities;
|
||||
using SteUp.Shared.Core.Helpers;
|
||||
using SteUp.Shared.Core.Interface.System;
|
||||
|
||||
namespace SteUp.Maui.Core.Services;
|
||||
|
||||
public class FileManager(IDbPathProvider dbPathProvider) : IFileManager
|
||||
{
|
||||
private static string AttachedRoot =>
|
||||
Path.Combine(FileSystem.CacheDirectory, "attached");
|
||||
|
||||
private async Task<AttachedDto> ConvertToDto(FileInfo file, AttachedDto.TypeAttached type, bool isFromToUpload)
|
||||
{
|
||||
var (origUrl, thumbUrl) = await SaveAndCreateThumbAsync(
|
||||
await File.ReadAllBytesAsync(file.FullName),
|
||||
file.Name
|
||||
);
|
||||
|
||||
return new AttachedDto
|
||||
{
|
||||
Name = file.Name,
|
||||
Path = file.FullName,
|
||||
TempPath = origUrl,
|
||||
ThumbPath = thumbUrl,
|
||||
Type = type,
|
||||
SavedOnAppData = true,
|
||||
ToUpload = isFromToUpload
|
||||
};
|
||||
}
|
||||
|
||||
private const string ToUploadFolderName = "toUpload";
|
||||
|
||||
private string GetInspectionBaseDir(Ispezione ispezione)
|
||||
{
|
||||
var baseDir = FileSystem.AppDataDirectory;
|
||||
return Path.Combine(baseDir, "attached", $"inspection_{GetInspectionKey(ispezione)}");
|
||||
}
|
||||
|
||||
private string GetInspectionToUploadDir(Ispezione ispezione)
|
||||
=> Path.Combine(GetInspectionBaseDir(ispezione), ToUploadFolderName);
|
||||
|
||||
public string GetFileToUploadDir(Ispezione ispezione, string fileName) =>
|
||||
Path.Combine(GetInspectionToUploadDir(ispezione), fileName);
|
||||
|
||||
private string GetInspectionFinalDir(Ispezione ispezione)
|
||||
=> GetInspectionBaseDir(ispezione);
|
||||
|
||||
/// <summary>
|
||||
/// Ritorna i file dell'ispezione filtrati per nome.
|
||||
/// Per default include sia "final" sia "toUpload" (utile per UI).
|
||||
/// </summary>
|
||||
public async Task<List<AttachedDto>?> GetInspectionFiles(
|
||||
Ispezione ispezione,
|
||||
List<string> fileNameFilter,
|
||||
bool includeToUpload,
|
||||
CancellationToken ct)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ispezione);
|
||||
ArgumentNullException.ThrowIfNull(fileNameFilter);
|
||||
|
||||
var baseDir = GetInspectionBaseDir(ispezione);
|
||||
if (!Directory.Exists(baseDir)) return null;
|
||||
|
||||
var result = new List<AttachedDto>();
|
||||
|
||||
var finalDir = GetInspectionFinalDir(ispezione);
|
||||
if (Directory.Exists(finalDir))
|
||||
{
|
||||
var finalFiles = new DirectoryInfo(finalDir)
|
||||
.GetFiles("*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (var file in finalFiles)
|
||||
{
|
||||
if (file.Directory?.Name == ToUploadFolderName)
|
||||
continue;
|
||||
|
||||
if (!fileNameFilter.Contains(file.FullName))
|
||||
continue;
|
||||
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
result.Add(await ConvertToDto(
|
||||
file,
|
||||
AttachedDto.TypeAttached.Image,
|
||||
isFromToUpload: false));
|
||||
}
|
||||
}
|
||||
|
||||
if (!includeToUpload) return result;
|
||||
|
||||
var toUploadDir = GetInspectionToUploadDir(ispezione);
|
||||
if (!Directory.Exists(toUploadDir)) return result;
|
||||
|
||||
var toUploadFiles = new DirectoryInfo(toUploadDir)
|
||||
.GetFiles("*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (var file in toUploadFiles)
|
||||
{
|
||||
if (!fileNameFilter.Contains(file.Name))
|
||||
continue;
|
||||
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
result.Add(await ConvertToDto(
|
||||
file,
|
||||
AttachedDto.TypeAttached.Image,
|
||||
isFromToUpload: true));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salva SEMPRE in /toUpload.
|
||||
/// </summary>
|
||||
public async Task<string?> SaveInspectionFile(
|
||||
Ispezione ispezione,
|
||||
byte[] file,
|
||||
string fileName,
|
||||
CancellationToken ct)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ispezione);
|
||||
ArgumentNullException.ThrowIfNull(file);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(fileName);
|
||||
|
||||
var toUploadDir = GetInspectionToUploadDir(ispezione);
|
||||
Directory.CreateDirectory(toUploadDir);
|
||||
|
||||
var filePath = Path.Combine(toUploadDir, fileName);
|
||||
await File.WriteAllBytesAsync(filePath, file, ct);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public Task<string?> MoveInspectionFileFromToUploadToFinal(
|
||||
Ispezione ispezione,
|
||||
string fileName,
|
||||
bool overwrite,
|
||||
CancellationToken ct)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ispezione);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(fileName);
|
||||
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
var toUploadDir = GetInspectionToUploadDir(ispezione);
|
||||
var finalDir = GetInspectionFinalDir(ispezione);
|
||||
|
||||
if (!Directory.Exists(toUploadDir)) return Task.FromResult<string?>(null);
|
||||
|
||||
var sourcePath = Path.Combine(toUploadDir, fileName);
|
||||
if (!File.Exists(sourcePath)) return Task.FromResult<string?>(null);
|
||||
|
||||
Directory.CreateDirectory(finalDir);
|
||||
|
||||
var destPath = Path.Combine(finalDir, fileName);
|
||||
|
||||
if (File.Exists(destPath))
|
||||
{
|
||||
if (!overwrite) return Task.FromResult<string?>(null);
|
||||
File.Delete(destPath);
|
||||
}
|
||||
|
||||
File.Move(sourcePath, destPath);
|
||||
|
||||
// Pulizia: se /toUpload resta vuota la elimino
|
||||
CleanupDirectoriesIfEmpty(ispezione);
|
||||
|
||||
return Task.FromResult<string?>(destPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rimuove un file cercandolo prima in /toUpload e poi in final (o viceversa).
|
||||
/// Default: prova a cancellare ovunque.
|
||||
/// </summary>
|
||||
public bool RemoveInspectionFile(
|
||||
Ispezione ispezione,
|
||||
string fileName,
|
||||
bool removeAlsoFromFinal,
|
||||
bool removeAlsoFromToUpload)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ispezione);
|
||||
if (string.IsNullOrWhiteSpace(fileName)) return false;
|
||||
|
||||
var removed = false;
|
||||
|
||||
if (removeAlsoFromToUpload)
|
||||
{
|
||||
var toUploadPath = Path.Combine(GetInspectionToUploadDir(ispezione), fileName);
|
||||
if (File.Exists(toUploadPath))
|
||||
{
|
||||
File.Delete(toUploadPath);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeAlsoFromFinal)
|
||||
{
|
||||
var finalPath = Path.Combine(GetInspectionFinalDir(ispezione), fileName);
|
||||
if (File.Exists(finalPath))
|
||||
{
|
||||
File.Delete(finalPath);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed)
|
||||
CleanupDirectoriesIfEmpty(ispezione);
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
private void CleanupDirectoriesIfEmpty(Ispezione ispezione)
|
||||
{
|
||||
var baseDir = GetInspectionBaseDir(ispezione);
|
||||
var toUploadDir = GetInspectionToUploadDir(ispezione);
|
||||
|
||||
// 1) se /toUpload esiste e vuota => delete
|
||||
if (Directory.Exists(toUploadDir) && !Directory.EnumerateFileSystemEntries(toUploadDir).Any())
|
||||
Directory.Delete(toUploadDir);
|
||||
|
||||
// 2) se base dir vuota (attenzione: dopo delete toUpload) => delete
|
||||
if (Directory.Exists(baseDir) && !Directory.EnumerateFileSystemEntries(baseDir).Any())
|
||||
Directory.Delete(baseDir);
|
||||
}
|
||||
|
||||
public async Task<string> SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(file);
|
||||
|
||||
if (file.CanSeek)
|
||||
file.Position = 0;
|
||||
|
||||
fileName = Path.GetFileName(fileName);
|
||||
|
||||
var dir = FileSystem.CacheDirectory;
|
||||
var filePath = Path.Combine(dir, fileName);
|
||||
|
||||
await using var fileStream = File.Create(filePath);
|
||||
await file.CopyToAsync(fileStream, ct);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public Task CleanTempStorageAsync(CancellationToken ct = default)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
if (Directory.Exists(AttachedRoot))
|
||||
Directory.Delete(AttachedRoot, true);
|
||||
}, ct);
|
||||
}
|
||||
|
||||
public Task OpenFile(string fileName, string filePath)
|
||||
{
|
||||
#if IOS
|
||||
throw new NotImplementedException();
|
||||
#else
|
||||
return Launcher.OpenAsync(new OpenFileRequest
|
||||
{
|
||||
Title = "Apri file",
|
||||
File = new ReadOnlyFile(filePath)
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
public async Task<(string originalUrl, string thumbUrl)> SaveAndCreateThumbAsync(
|
||||
byte[] bytes, string fileName, CancellationToken ct = default)
|
||||
{
|
||||
Directory.CreateDirectory(AttachedRoot);
|
||||
|
||||
var id = Guid.NewGuid().ToString("N");
|
||||
var safeName = SanitizeFileName(fileName);
|
||||
|
||||
var originalFile = $"{id}_{safeName}";
|
||||
var thumbFile = $"{id}_thumb.jpg";
|
||||
|
||||
var originalPath = Path.Combine(AttachedRoot, originalFile);
|
||||
await File.WriteAllBytesAsync(originalPath, bytes, ct);
|
||||
|
||||
var thumbPath = Path.Combine(AttachedRoot, thumbFile);
|
||||
await ImageThumb.CreateThumbnailAsync(originalPath, thumbPath, maxSide: 320, quality: 70, ct);
|
||||
|
||||
return ($"https://localfiles/attached/{originalFile}",
|
||||
$"https://localfiles/attached/{thumbFile}");
|
||||
}
|
||||
|
||||
private static string SanitizeFileName(string fileName)
|
||||
{
|
||||
var name = Path.GetFileName(fileName);
|
||||
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, '_'));
|
||||
}
|
||||
|
||||
private static string GetInspectionKey(Ispezione ispezione) =>
|
||||
$"{ispezione.CodMdep}_{ispezione.Data:ddMMyyyy}_{ispezione.Rilevatore.ToLower()}";
|
||||
|
||||
public List<SendEmailDto.AttachmentsDto> GetFileForExport()
|
||||
{
|
||||
var attachments = new List<SendEmailDto.AttachmentsDto>();
|
||||
|
||||
// 1) log file singolo (se ti serve ancora)
|
||||
var logFile = RetrieveLogFile();
|
||||
if (!logFile.IsNullOrEmpty())
|
||||
{
|
||||
attachments.Add(new SendEmailDto.AttachmentsDto
|
||||
{
|
||||
FileName = $"logs_{DateTime.Today:yyyyMMdd}.zip",
|
||||
FileContent = CreateZipBytes(logFile!)
|
||||
});
|
||||
}
|
||||
|
||||
// 2) database zip
|
||||
var dbZip = CreateDatabaseZipAttachment();
|
||||
if (dbZip != null) attachments.Add(dbZip);
|
||||
|
||||
// 3) Img zip
|
||||
var attachedInfo = new DirectoryInfo(Path.Combine(FileSystem.AppDataDirectory, "attached"));
|
||||
if (!attachedInfo.Exists) return attachments;
|
||||
|
||||
var attachedFiles = attachedInfo
|
||||
.EnumerateFiles("*", SearchOption.AllDirectories)
|
||||
.ToList();
|
||||
|
||||
if (attachedFiles.Count > 0)
|
||||
{
|
||||
attachments.Add(new SendEmailDto.AttachmentsDto
|
||||
{
|
||||
FileName = $"immagini_allegate_{DateTime.Today:yyyyMMdd}.zip",
|
||||
FileContent = CreateZipBytes(attachedInfo.FullName, attachedFiles)
|
||||
});
|
||||
}
|
||||
|
||||
return attachments;
|
||||
}
|
||||
|
||||
private static List<FileInfo>? RetrieveLogFile()
|
||||
{
|
||||
var appDataPath = FileSystem.AppDataDirectory;
|
||||
var targetDirectory = Path.Combine(appDataPath, "logs");
|
||||
|
||||
var directory = new DirectoryInfo(targetDirectory);
|
||||
|
||||
List<FileInfo>? files = null;
|
||||
|
||||
if (directory.Exists)
|
||||
files = directory.GetFiles().ToList();
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
private SendEmailDto.AttachmentsDto? CreateDatabaseZipAttachment()
|
||||
{
|
||||
var files = new[]
|
||||
{
|
||||
new FileInfo(dbPathProvider.GetDbPath())
|
||||
};
|
||||
|
||||
// Filtra solo quelli esistenti
|
||||
var existingFiles = files.Where(f => f.Exists).ToList();
|
||||
|
||||
if (existingFiles.Count == 0)
|
||||
return null;
|
||||
|
||||
using var memoryStream = new MemoryStream();
|
||||
|
||||
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
|
||||
{
|
||||
foreach (var file in existingFiles)
|
||||
{
|
||||
var entry = archive.CreateEntry(file.Name, CompressionLevel.Optimal);
|
||||
|
||||
using var entryStream = entry.Open();
|
||||
using var fileStream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
fileStream.CopyTo(entryStream);
|
||||
}
|
||||
}
|
||||
|
||||
return new SendEmailDto.AttachmentsDto
|
||||
{
|
||||
FileName = $"database_{DateTime.Now:yyyyMMdd_HHmm}.zip",
|
||||
FileContent = memoryStream.ToArray()
|
||||
};
|
||||
}
|
||||
|
||||
private static byte[] CreateZipBytes(IEnumerable<FileInfo> files)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, leaveOpen: true))
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (!file.Exists)
|
||||
continue;
|
||||
|
||||
// Nome dentro lo zip (evita path e collisioni minime)
|
||||
var entryName = file.Name;
|
||||
|
||||
var entry = archive.CreateEntry(entryName, CompressionLevel.Optimal);
|
||||
|
||||
using var entryStream = entry.Open();
|
||||
using var fileStream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
fileStream.CopyTo(entryStream);
|
||||
}
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private static byte[] CreateZipBytes(string rootDir, IEnumerable<FileInfo> files)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
|
||||
using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, leaveOpen: true))
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (!file.Exists)
|
||||
continue;
|
||||
|
||||
// Path relativo rispetto a rootDir -> mantiene le directory nello zip
|
||||
var relativePath = Path.GetRelativePath(rootDir, file.FullName);
|
||||
|
||||
// Zip usa "/" come separatore: normalizziamo per compatibilità
|
||||
var entryName = relativePath.Replace('\\', '/');
|
||||
|
||||
var entry = archive.CreateEntry(entryName, CompressionLevel.Optimal);
|
||||
|
||||
using var entryStream = entry.Open();
|
||||
using var fileStream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
fileStream.CopyTo(entryStream);
|
||||
}
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
23
SteUp.Maui/Core/Utility/UtilityFile.cs
Normal file
23
SteUp.Maui/Core/Utility/UtilityFile.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using SteUp.Shared.Core.Dto;
|
||||
|
||||
namespace SteUp.Maui.Core.Utility;
|
||||
|
||||
public static class UtilityFile
|
||||
{
|
||||
public static async Task<AttachedDto> ConvertToDto(FileResult file, AttachedDto.TypeAttached type)
|
||||
{
|
||||
var stream = await file.OpenReadAsync();
|
||||
using var ms = new MemoryStream();
|
||||
await stream.CopyToAsync(ms);
|
||||
|
||||
return new AttachedDto
|
||||
{
|
||||
Name = file.FileName,
|
||||
Path = file.FullPath,
|
||||
MimeType = file.ContentType,
|
||||
DimensionBytes = ms.Length,
|
||||
FileBytes = ms.ToArray(),
|
||||
Type = type
|
||||
};
|
||||
}
|
||||
}
|
||||
37
SteUp.Maui/Core/UtilityException/GlobalExceptionHandler.cs
Normal file
37
SteUp.Maui/Core/UtilityException/GlobalExceptionHandler.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SteUp.Maui.Core.UtilityException;
|
||||
|
||||
public static class GlobalExceptionHandler
|
||||
{
|
||||
public static void Register(ILogger logger)
|
||||
{
|
||||
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
|
||||
{
|
||||
var ex = args.ExceptionObject as Exception;
|
||||
logger.LogCritical(ex, "UnhandledException (AppDomain) — IsTerminating: {t}", args.IsTerminating);
|
||||
};
|
||||
|
||||
TaskScheduler.UnobservedTaskException += (_, args) =>
|
||||
{
|
||||
logger.LogCritical(args.Exception, "UnobservedTaskException");
|
||||
args.SetObserved();
|
||||
};
|
||||
|
||||
#if ANDROID
|
||||
Android.Runtime.AndroidEnvironment.UnhandledExceptionRaiser += (_, args) =>
|
||||
{
|
||||
logger.LogCritical(args.Exception, "Android UnhandledException");
|
||||
args.Handled = true;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IOS || MACCATALYST
|
||||
ObjCRuntime.Runtime.MarshalManagedException += (_, args) =>
|
||||
{
|
||||
logger.LogCritical(args.Exception, "iOS MarshalManagedException");
|
||||
args.ExceptionMode = ObjCRuntime.MarshalManagedExceptionMode.UnwindNativeCode;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ namespace SteUp.Maui
|
||||
builder.RegisterSystemService();
|
||||
builder.RegisterDbServices();
|
||||
builder.RegisterMessageServices();
|
||||
builder.RegisterLoggerServices();
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@page "/ispezione"
|
||||
@using Microsoft.Extensions.Logging
|
||||
@using SteUp.Shared.Components.Layout
|
||||
@using SteUp.Shared.Components.Layout.Overlay
|
||||
@using SteUp.Shared.Components.SingleElements.Card
|
||||
@@ -15,7 +16,8 @@
|
||||
@inject IIspezioniService IspezioniService
|
||||
@inject IDialogService Dialog
|
||||
@inject IIntegrySteupService IntegrySteupService
|
||||
@inject IAttachedService AttachedService
|
||||
@inject IFileManager FileManager
|
||||
@inject ILogger<IspezionePage> Logger
|
||||
@implements IDisposable
|
||||
|
||||
<HeaderLayout Title="Ispezione" BackTo="Indietro" Back="true"/>
|
||||
@@ -150,7 +152,7 @@
|
||||
|
||||
if (scheda.ImageNames == null) continue;
|
||||
|
||||
var fileList = (await AttachedService.GetInspectionFiles(ispezione, scheda.ImageNames))?
|
||||
var fileList = (await FileManager.GetInspectionFiles(ispezione, scheda.ImageNames))?
|
||||
.Where(x => x.ToUpload).ToList();
|
||||
|
||||
if (fileList == null) continue;
|
||||
@@ -187,7 +189,7 @@
|
||||
StateHasChanged();
|
||||
});
|
||||
|
||||
OnError(e.Message);
|
||||
OnError(e, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,8 +288,9 @@
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void OnError(string? errorMessage)
|
||||
private void OnError(Exception? e, string? errorMessage)
|
||||
{
|
||||
if (e != null) Logger.LogError(e, errorMessage);
|
||||
if (errorMessage == null) return;
|
||||
|
||||
_ = Dialog.ShowError(errorMessage);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@page "/login"
|
||||
@using Microsoft.Extensions.Logging
|
||||
@using SteUp.Shared.Components.Layout.Spinner
|
||||
@using SteUp.Shared.Core.BarcodeReader.Contracts
|
||||
@using SteUp.Shared.Core.Interface.System
|
||||
@@ -7,6 +8,7 @@
|
||||
@inject AppAuthenticationStateProvider AuthenticationStateProvider
|
||||
@inject IGenericSystemService GenericSystemService
|
||||
@inject IBarcodeManager BarcodeManager
|
||||
@inject ILogger<LoginPage> Logger
|
||||
|
||||
@if (Spinner)
|
||||
{
|
||||
@@ -100,12 +102,13 @@ else
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ErrorMessage = e.Message;
|
||||
Logger.LogError(e, ErrorMessage);
|
||||
Console.WriteLine(e.Message);
|
||||
|
||||
Spinner = false;
|
||||
StateHasChanged();
|
||||
|
||||
ErrorMessage = e.Message;
|
||||
_attemptFailed = true;
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
@page "/user"
|
||||
@attribute [Authorize]
|
||||
@using SteUp.Shared.Components.Layout
|
||||
@using SteUp.Shared.Components.Layout.Overlay
|
||||
@using SteUp.Shared.Components.SingleElements
|
||||
@using SteUp.Shared.Core.Authorization.Enum
|
||||
@using SteUp.Shared.Core.Interface.System.Network
|
||||
@using SteUp.Shared.Core.Dto
|
||||
@using SteUp.Shared.Core.Interface.IntegryApi
|
||||
@using SteUp.Shared.Core.Interface.System
|
||||
@using SteUp.Shared.Core.Services
|
||||
@using SteUp.Shared.Core.Utility
|
||||
@inject AppAuthenticationStateProvider AuthenticationStateProvider
|
||||
@inject INetworkService NetworkService
|
||||
@inject IGenericSystemService GenericSystemService
|
||||
@inject IFileManager FileManager
|
||||
@inject IIntegryApiService IntegryApiService
|
||||
|
||||
<HeaderLayout Title="Profilo"/>
|
||||
|
||||
@@ -63,18 +69,29 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-button mud-elevation-1">
|
||||
<div class="container-button ripple-container mud-elevation-1">
|
||||
<MudButton Class="button-settings red-icon"
|
||||
FullWidth="true"
|
||||
StartIcon="@Icons.Material.Rounded.UploadFile"
|
||||
Size="Size.Medium"
|
||||
OnClick="@ExportLog"
|
||||
Variant="Variant.Outlined">
|
||||
Esporta log
|
||||
</MudButton>
|
||||
</div>
|
||||
|
||||
<div class="container-button ripple-container mud-elevation-1">
|
||||
<MudButton Class="button-settings green-icon"
|
||||
FullWidth="true"
|
||||
StartIcon="@Icons.Material.Outlined.Sync"
|
||||
Size="Size.Medium"
|
||||
OnClick="@UpdateDb"
|
||||
Variant="Variant.Outlined">
|
||||
Sincronizza ispezioni
|
||||
Sincronizza ispezioni esportate
|
||||
</MudButton>
|
||||
</div>
|
||||
|
||||
<div class="container-button mud-elevation-1">
|
||||
<div class="container-button ripple-container mud-elevation-1">
|
||||
<MudButton Class="button-settings exit"
|
||||
FullWidth="true"
|
||||
Color="Color.Error"
|
||||
@@ -89,8 +106,11 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<SpinnerOverlay VisibleOverlay="VisibleOverlay"/>
|
||||
|
||||
@code {
|
||||
private bool IsLoggedIn { get; set; }
|
||||
private bool VisibleOverlay { get; set; }
|
||||
private string? CodHash { get; set; } = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
@@ -100,8 +120,41 @@
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void UpdateDb()
|
||||
private async Task ExportLog()
|
||||
{
|
||||
VisibleOverlay = true;
|
||||
StateHasChanged();
|
||||
|
||||
var profiloAzienda = LocalStorage.GetString("codHash");
|
||||
|
||||
var email = new SendEmailDto
|
||||
{
|
||||
FromName = "Integry Log",
|
||||
To = "developer@integry.it",
|
||||
Subject = $"SteUP - Log del {DateTime.Today:d} di {UserSession.User.Username}",
|
||||
IsHtml = true,
|
||||
MsgText = $"Username: <b>{UserSession.User.Username}</b><br/>" +
|
||||
$"Profilo azienda: <b>{profiloAzienda}</b><br/>" +
|
||||
$"ProfileDb: <b>{UserSession.ProfileDb}</b><br/>" +
|
||||
$"Versione app: <b>{GenericSystemService.GetCurrentAppVersion()}</b>",
|
||||
Attachments = FileManager.GetFileForExport()
|
||||
};
|
||||
|
||||
await IntegryApiService.SendEmail(email);
|
||||
|
||||
VisibleOverlay = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task UpdateDb()
|
||||
{
|
||||
VisibleOverlay = true;
|
||||
StateHasChanged();
|
||||
|
||||
await SteupDataService.CheckAndUpdateStatus();
|
||||
|
||||
VisibleOverlay = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task Logout()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@inject IIspezioniService IspezioniService
|
||||
@inject IIntegrySteupService IntegrySteupService
|
||||
@inject IDialogService Dialog
|
||||
@inject IAttachedService AttachedService
|
||||
@inject IFileManager FileManager
|
||||
|
||||
<div class="scheda-card">
|
||||
<div class="scheda-body-section">
|
||||
@@ -104,7 +104,7 @@
|
||||
{
|
||||
foreach (var fileName in Scheda.ImageNames)
|
||||
{
|
||||
AttachedService.RemoveInspectionFile(Ispezione, fileName);
|
||||
FileManager.RemoveInspectionFile(Ispezione, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
{
|
||||
if (Scheda.ImageNames == null) return;
|
||||
|
||||
var fileList = (await AttachedService.GetInspectionFiles(Ispezione, Scheda.ImageNames))?
|
||||
var fileList = (await FileManager.GetInspectionFiles(Ispezione, Scheda.ImageNames))?
|
||||
.Where(x => x.ToUpload).ToList();
|
||||
|
||||
if (fileList == null) return;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<div class="container container-modal">
|
||||
@using Microsoft.Extensions.Logging
|
||||
@inject ILogger<ExceptionModal> Logger
|
||||
|
||||
<div class="container container-modal">
|
||||
<div class="c-modal">
|
||||
<div class="exception-header mb-2">
|
||||
<i class="ri-emotion-unhappy-line"></i>
|
||||
@@ -43,6 +46,8 @@
|
||||
{
|
||||
Message = Exception.Message;
|
||||
}
|
||||
|
||||
Logger.LogError(Exception, "Errore nel componente Blazor: {Message}", Message);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
@using SteUp.Shared.Components.Layout
|
||||
@using System.Data.Common
|
||||
@using Microsoft.Extensions.Logging
|
||||
@using SteUp.Shared.Components.Layout
|
||||
@using SteUp.Shared.Components.Layout.Overlay
|
||||
@using SteUp.Shared.Components.Layout.Spinner
|
||||
@using SteUp.Shared.Components.SingleElements.Card.ModalForm
|
||||
@@ -13,10 +15,11 @@
|
||||
@inject INetworkService NetworkService
|
||||
@inject IDialogService Dialog
|
||||
@inject IIntegryApiService IntegryApiService
|
||||
@inject IAttachedService AttachedService
|
||||
@inject IFileManager FileManager
|
||||
@inject IIspezioniService IspezioniService
|
||||
@inject IIntegrySteupService IntegrySteupService
|
||||
@inject OnScannerService OnScannerService
|
||||
@inject ILogger<ModalFormScheda> Logger
|
||||
|
||||
<MudDialog Class="customDialog-form">
|
||||
<DialogContent>
|
||||
@@ -75,7 +78,7 @@
|
||||
}
|
||||
<MudCardContent Class="image_card">
|
||||
<MudText Typo="Typo.subtitle1"><b>@item.p.Name</b></MudText>
|
||||
@if (IsNew)
|
||||
@if (item.p.ToUpload)
|
||||
{
|
||||
<MudIconButton Variant="Variant.Outlined"
|
||||
Icon="@Icons.Material.Rounded.Close"
|
||||
@@ -236,7 +239,7 @@
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var fileList = await AttachedService.GetInspectionFiles(
|
||||
var fileList = await FileManager.GetInspectionFiles(
|
||||
new Ispezione
|
||||
{
|
||||
CodMdep = CodMdep,
|
||||
@@ -285,17 +288,19 @@
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
var message = e.Message;
|
||||
|
||||
await Dialog.ShowError(e.Message);
|
||||
Logger.LogError(e, message);
|
||||
Console.WriteLine(message);
|
||||
await Dialog.ShowError(message);
|
||||
}
|
||||
|
||||
if (IsNew) await NewSave(apiResponse);
|
||||
else await Update(apiResponse);
|
||||
|
||||
if (Scheda.ActivityId.IsValorized()) await UploadFile(Scheda.ActivityId!);
|
||||
if (Scheda.ActivityId.IsValorized()) await UploadFile(Scheda);
|
||||
|
||||
await AttachedService.CleanTempStorageAsync();
|
||||
await FileManager.CleanTempStorageAsync();
|
||||
|
||||
SuccessAnimation = true;
|
||||
StateHasChanged();
|
||||
@@ -311,7 +316,7 @@
|
||||
{
|
||||
foreach (var attached in AttachedList!)
|
||||
{
|
||||
var fileNameAdded = await AttachedService.SaveInspectionFile(
|
||||
var fileNameAdded = await FileManager.SaveInspectionFile(
|
||||
new Ispezione
|
||||
{
|
||||
CodMdep = CodMdep,
|
||||
@@ -354,7 +359,7 @@
|
||||
|
||||
if (!attached.ToRemove)
|
||||
{
|
||||
var fileNameAdded = await AttachedService.SaveInspectionFile(
|
||||
var fileNameAdded = await FileManager.SaveInspectionFile(
|
||||
ispezione,
|
||||
attached.FileBytes!,
|
||||
attached.Name!
|
||||
@@ -365,7 +370,7 @@
|
||||
Scheda.ImageNames.Add(fileNameAdded);
|
||||
}
|
||||
else
|
||||
_ = AttachedService.RemoveInspectionFile(ispezione, attached.Name!);
|
||||
_ = FileManager.RemoveInspectionFile(ispezione, attached.Name!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,7 +383,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
private async Task UploadFile(string activityId)
|
||||
private async Task UploadFile(Scheda scheda)
|
||||
{
|
||||
if (AttachedList.IsNullOrEmpty()) return;
|
||||
|
||||
@@ -393,16 +398,23 @@
|
||||
{
|
||||
if (file.FileBytes == null || file.Name == null) continue;
|
||||
|
||||
await IntegrySteupService.UploadFile(activityId, file.FileBytes, file.Name);
|
||||
await AttachedService.MoveInspectionFileFromToUploadToFinal(ispezione, file.Name);
|
||||
await IntegrySteupService.UploadFile(scheda.ActivityId!, file.FileBytes, file.Name);
|
||||
var newPath = await FileManager.MoveInspectionFileFromToUploadToFinal(ispezione, file.Name);
|
||||
if (newPath == null) continue;
|
||||
|
||||
var filePathToRemove = FileManager.GetFileToUploadDir(ispezione, file.Name);
|
||||
scheda.ImageNames!.Remove(filePathToRemove);
|
||||
scheda.ImageNames.Add(newPath);
|
||||
}
|
||||
|
||||
await IspezioniService.UpdateFileListSchedaAsync(scheda.Id, scheda.ImageNames);
|
||||
}
|
||||
|
||||
private async Task Cancel()
|
||||
{
|
||||
if (await CheckSavePreAction())
|
||||
{
|
||||
await AttachedService.CleanTempStorageAsync();
|
||||
await FileManager.CleanTempStorageAsync();
|
||||
DisposeMessage();
|
||||
MudDialog.Cancel();
|
||||
}
|
||||
@@ -500,7 +512,7 @@
|
||||
var a = attachedList[i];
|
||||
if (a.FileBytes is null || a.Name is null) continue;
|
||||
|
||||
var (origUrl, thumbUrl) = await AttachedService.SaveAndCreateThumbAsync(a.FileBytes, a.Name);
|
||||
var (origUrl, thumbUrl) = await FileManager.SaveAndCreateThumbAsync(a.FileBytes, a.Name);
|
||||
|
||||
await InvokeAsync(() =>
|
||||
{
|
||||
@@ -557,7 +569,7 @@
|
||||
TextLoading = null;
|
||||
StateHasChanged();
|
||||
|
||||
OnError(e.Message);
|
||||
OnError(e, e.Message);
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -670,7 +682,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError("Nessun articolo trovato");
|
||||
OnError(null, "Nessun articolo trovato");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -684,16 +696,17 @@
|
||||
StateHasChanged();
|
||||
});
|
||||
|
||||
OnError(e.Message);
|
||||
OnError(e, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnErrorScan(string? value) => OnError(value);
|
||||
private void OnErrorScan(string? value) => OnError(new Exception(value), value);
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnError(string? errorMessage)
|
||||
private void OnError(Exception? e, string? errorMessage)
|
||||
{
|
||||
if (e != null) Logger.LogError(e, errorMessage);
|
||||
if (errorMessage == null) return;
|
||||
|
||||
_ = Dialog.ShowError(errorMessage);
|
||||
|
||||
@@ -67,19 +67,20 @@
|
||||
if (FilterText.IsNullOrEmpty())
|
||||
{
|
||||
FilteredList = SteupDataService.PuntiVenditaList;
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
FilteredList = SteupDataService.PuntiVenditaList.FindAll(x =>
|
||||
(x.Indirizzo != null && x.Indirizzo.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.Descrizione != null && x.Descrizione.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.CodMdep != null && x.CodMdep.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.Citta != null && x.Citta.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.Cap != null && x.Cap.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.Provincia != null && x.Provincia.ContainsIgnoreCase(FilterText!))
|
||||
);
|
||||
}
|
||||
|
||||
FilteredList = SteupDataService.PuntiVenditaList.FindAll(x =>
|
||||
(x.Indirizzo != null && x.Indirizzo.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.Descrizione != null && x.Descrizione.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.CodMdep != null && x.CodMdep.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.Citta != null && x.Citta.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.Cap != null && x.Cap.ContainsIgnoreCase(FilterText!)) ||
|
||||
(x.Provincia != null && x.Provincia.ContainsIgnoreCase(FilterText!))
|
||||
);
|
||||
|
||||
FilteredList = FilteredList.OrderBy(x => x.CodMdep).ToList();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ public interface ISteupDataService
|
||||
Task Init();
|
||||
Task<bool> CanOpenNewInspection();
|
||||
void RegisterAppVersion();
|
||||
Task CheckAndUpdateStatus();
|
||||
|
||||
List<PuntoVenditaDto> PuntiVenditaList { get; }
|
||||
InspectionPageState InspectionPageState { get; set; }
|
||||
|
||||
@@ -34,7 +34,7 @@ public class SteupDataService(
|
||||
);
|
||||
}
|
||||
|
||||
private async Task CheckAndUpdateStatus()
|
||||
public async Task CheckAndUpdateStatus()
|
||||
{
|
||||
var ispezioni = await ispezioniService.GetAllIspezioniWithSchedeAsync();
|
||||
var listActivityId = ispezioni
|
||||
|
||||
33
SteUp.Shared/Core/Dto/SendEmailDto.cs
Normal file
33
SteUp.Shared/Core/Dto/SendEmailDto.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SteUp.Shared.Core.Dto;
|
||||
|
||||
public class SendEmailDto
|
||||
{
|
||||
[JsonPropertyName("from")]
|
||||
public string? From { get; set; }
|
||||
|
||||
[JsonPropertyName("fromName")]
|
||||
public string? FromName { get; set; }
|
||||
|
||||
[JsonPropertyName("to")]
|
||||
public string? To { get; set; }
|
||||
|
||||
[JsonPropertyName("subject")]
|
||||
public string? Subject { get; set; }
|
||||
|
||||
[JsonPropertyName("msgText")]
|
||||
public string? MsgText { get; set; }
|
||||
|
||||
[JsonPropertyName("html")]
|
||||
public bool IsHtml { get; set; }
|
||||
|
||||
[JsonPropertyName("attachments")]
|
||||
public List<AttachmentsDto>? Attachments { get; set; }
|
||||
|
||||
public class AttachmentsDto
|
||||
{
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public byte[] FileContent { get; set; } = [];
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,6 @@ public interface IIntegryApiService
|
||||
Task<bool> SystemOk();
|
||||
|
||||
Task<List<StbActivityTyperDto>?> SuggestActivityDescription(string activityTypeId);
|
||||
|
||||
Task SendEmail(SendEmailDto sendEmail);
|
||||
}
|
||||
@@ -24,6 +24,7 @@ public interface IIspezioniService
|
||||
Task<Scheda?> GetSchedaWithIspezioneAsync(int schedaId);
|
||||
Task<bool> UpdateSchedaAsync(Scheda scheda);
|
||||
Task<bool> UpdateActivityIdSchedaAsync(int schedaId, string? activityId);
|
||||
Task<bool> UpdateFileListSchedaAsync(int schedaId, List<string>? imageNames);
|
||||
Task<bool> DeleteSchedaAsync(int schedaId);
|
||||
Task<int> DeleteAllSchedeOfIspezioneAsync(string codMdep, DateTime data, string rilevatore);
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using SteUp.Shared.Core.Dto;
|
||||
using SteUp.Shared.Core.Entities;
|
||||
using SteUp.Shared.Core.Dto;
|
||||
|
||||
namespace SteUp.Shared.Core.Interface.System;
|
||||
|
||||
@@ -7,22 +6,4 @@ public interface IAttachedService
|
||||
{
|
||||
Task<AttachedDto?> SelectImageFromCamera();
|
||||
Task<List<AttachedDto>?> SelectImageFromGallery();
|
||||
|
||||
Task<List<AttachedDto>?> GetInspectionFiles(Ispezione ispezione, List<string> fileNameFilter,
|
||||
bool includeToUpload = true, CancellationToken ct = default);
|
||||
|
||||
Task<string?> SaveInspectionFile(Ispezione ispezione, byte[] file, string fileName, CancellationToken ct = default);
|
||||
|
||||
bool RemoveInspectionFile(Ispezione ispezione, string fileName, bool removeAlsoFromFinal = true,
|
||||
bool removeAlsoFromToUpload = true);
|
||||
|
||||
Task<bool> MoveInspectionFileFromToUploadToFinal(Ispezione ispezione, string fileName, bool overwrite = true,
|
||||
CancellationToken ct = default);
|
||||
|
||||
Task<string> SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default);
|
||||
Task CleanTempStorageAsync(CancellationToken ct = default);
|
||||
Task OpenFile(string fileName, string filePath);
|
||||
|
||||
Task<(string originalUrl, string thumbUrl)> SaveAndCreateThumbAsync(byte[] bytes, string fileName,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
29
SteUp.Shared/Core/Interface/System/IFileManager.cs
Normal file
29
SteUp.Shared/Core/Interface/System/IFileManager.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using SteUp.Shared.Core.Dto;
|
||||
using SteUp.Shared.Core.Entities;
|
||||
|
||||
namespace SteUp.Shared.Core.Interface.System;
|
||||
|
||||
public interface IFileManager
|
||||
{
|
||||
Task<List<AttachedDto>?> GetInspectionFiles(Ispezione ispezione, List<string> fileNameFilter,
|
||||
bool includeToUpload = true, CancellationToken ct = default);
|
||||
|
||||
Task<string?> SaveInspectionFile(Ispezione ispezione, byte[] file, string fileName, CancellationToken ct = default);
|
||||
|
||||
string GetFileToUploadDir(Ispezione ispezione, string fileName);
|
||||
|
||||
bool RemoveInspectionFile(Ispezione ispezione, string fileName, bool removeAlsoFromFinal = true,
|
||||
bool removeAlsoFromToUpload = true);
|
||||
|
||||
Task<string?> MoveInspectionFileFromToUploadToFinal(Ispezione ispezione, string fileName, bool overwrite = true,
|
||||
CancellationToken ct = default);
|
||||
|
||||
Task<string> SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default);
|
||||
Task CleanTempStorageAsync(CancellationToken ct = default);
|
||||
Task OpenFile(string fileName, string filePath);
|
||||
|
||||
Task<(string originalUrl, string thumbUrl)> SaveAndCreateThumbAsync(byte[] bytes, string fileName,
|
||||
CancellationToken ct = default);
|
||||
|
||||
List<SendEmailDto.AttachmentsDto> GetFileForExport();
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using IntegryApiClient.Core.Domain.Abstraction.Contracts.Account;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using IntegryApiClient.Core.Domain.RestClient.Contacts;
|
||||
using MudBlazor;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SteUp.Shared.Core.Dto;
|
||||
using SteUp.Shared.Core.Interface.IntegryApi;
|
||||
|
||||
@@ -8,7 +10,7 @@ namespace SteUp.Shared.Core.Services;
|
||||
|
||||
public class IntegryApiService(
|
||||
IIntegryApiRestClient integryApiRestClient,
|
||||
IUserSession userSession) : IIntegryApiService
|
||||
ILogger<IntegryApiService> logger) : IIntegryApiService
|
||||
{
|
||||
public async Task<bool> SystemOk()
|
||||
{
|
||||
@@ -19,6 +21,7 @@ public class IntegryApiService(
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, e.Message);
|
||||
Console.WriteLine(e.Message);
|
||||
return false;
|
||||
}
|
||||
@@ -31,4 +34,44 @@ public class IntegryApiService(
|
||||
{ "activityType", activityTypeId }
|
||||
}
|
||||
);
|
||||
|
||||
public async Task SendEmail(SendEmailDto sendEmail)
|
||||
{
|
||||
var content = new MultipartFormDataContent();
|
||||
|
||||
try
|
||||
{
|
||||
if (sendEmail.Attachments != null)
|
||||
{
|
||||
foreach (var a in sendEmail.Attachments)
|
||||
{
|
||||
var fileContent = new ByteArrayContent(a.FileContent);
|
||||
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
|
||||
content.Add(fileContent, "allegati", a.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
sendEmail.Attachments = null;
|
||||
content.Add(
|
||||
new StringContent(
|
||||
JsonSerializer.Serialize(sendEmail),
|
||||
Encoding.UTF8,
|
||||
"application/json"
|
||||
),
|
||||
"request"
|
||||
);
|
||||
|
||||
await integryApiRestClient.AuthorizedPost<object>("sendEmailNew", content);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
logger.LogError(e, e.Message);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
content.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,16 +56,17 @@ public class IntegrySteupService(IIntegryApiRestClient integryApiRestClient) : I
|
||||
|
||||
#endregion
|
||||
|
||||
public Task UploadFile(string activityId, byte[] file, string fileName)
|
||||
public async Task UploadFile(string activityId, byte[] file, string fileName)
|
||||
{
|
||||
var queryParams = new Dictionary<string, object> { { "activityId", activityId } };
|
||||
|
||||
using var content = new MultipartFormDataContent();
|
||||
var content = new MultipartFormDataContent();
|
||||
var fileContent = new ByteArrayContent(file);
|
||||
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
|
||||
content.Add(fileContent, "file", fileName);
|
||||
|
||||
return integryApiRestClient.Post<object>($"{BaseRequest}/uploadAttachment", content, queryParams!);
|
||||
await integryApiRestClient.Post<object>($"{BaseRequest}/uploadAttachment", content, queryParams!);
|
||||
content.Dispose();
|
||||
}
|
||||
|
||||
public Task DeleteScheda(string activityId) =>
|
||||
|
||||
Reference in New Issue
Block a user