Add project files.
This commit is contained in:
61
ConfigurationPannel/Services/ConfigurationManager.cs
Normal file
61
ConfigurationPannel/Services/ConfigurationManager.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.Text.Json;
|
||||
using Inspectron.Epson.PrintServer.ConfigurationSources;
|
||||
using Inspectron.Epson.PrintServer.PrintServices;
|
||||
|
||||
namespace ConfigurationPannel.Services;
|
||||
|
||||
public class ConfigurationManager
|
||||
{
|
||||
private readonly string _configPath;
|
||||
private readonly SemaphoreSlim _configLock = new SemaphoreSlim(1, 1);
|
||||
private EpsonPrintServiceConfiguration? _currentConfig;
|
||||
|
||||
public ConfigurationManager(IWebHostEnvironment env)
|
||||
{
|
||||
_configPath = Path.Combine(env.ContentRootPath, "config.json");
|
||||
}
|
||||
|
||||
public async Task<EpsonPrintServiceConfiguration> LoadConfigurationAsync()
|
||||
{
|
||||
await _configLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (File.Exists(_configPath))
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(_configPath);
|
||||
_currentConfig = JsonSerializer.Deserialize<EpsonPrintServiceConfiguration>(json);
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentConfig = new EpsonPrintServiceConfiguration
|
||||
{
|
||||
GroupId = "default-group",
|
||||
RestaurantId = "default-restaurant",
|
||||
PrinterConfigurations = new Dictionary<string, PrinterConfiguration>()
|
||||
};
|
||||
}
|
||||
return _currentConfig!;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_configLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveConfigurationAsync(EpsonPrintServiceConfiguration config)
|
||||
{
|
||||
await _configLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
var json = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
|
||||
await File.WriteAllTextAsync(_configPath, json);
|
||||
_currentConfig = config;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_configLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public EpsonPrintServiceConfiguration? GetCurrentConfiguration() => _currentConfig;
|
||||
}
|
||||
119
ConfigurationPannel/Services/LogoService.cs
Normal file
119
ConfigurationPannel/Services/LogoService.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
namespace ConfigurationPannel.Services;
|
||||
|
||||
public class LogoService
|
||||
{
|
||||
private readonly IWebHostEnvironment _env;
|
||||
private readonly string _logosPath;
|
||||
private readonly ILogger<LogoService> _logger;
|
||||
|
||||
public LogoService(IWebHostEnvironment env, ILogger<LogoService> logger)
|
||||
{
|
||||
_env = env;
|
||||
_logger = logger;
|
||||
_logosPath = Path.Combine(_env.WebRootPath, "logos");
|
||||
|
||||
// Ensure logos directory exists
|
||||
if (!Directory.Exists(_logosPath))
|
||||
{
|
||||
Directory.CreateDirectory(_logosPath);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> SaveLogoAsync(IFormFile file)
|
||||
{
|
||||
if (file == null || file.Length == 0)
|
||||
throw new ArgumentException("No file provided");
|
||||
|
||||
// Validate file type
|
||||
var allowedExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
|
||||
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||
|
||||
if (!allowedExtensions.Contains(extension))
|
||||
throw new ArgumentException($"Invalid file type. Allowed: {string.Join(", ", allowedExtensions)}");
|
||||
|
||||
// Generate unique filename to avoid collisions
|
||||
var fileName = $"{Path.GetFileNameWithoutExtension(file.FileName)}_{Guid.NewGuid().ToString("N").Substring(0, 8)}{extension}";
|
||||
var filePath = Path.Combine(_logosPath, fileName);
|
||||
|
||||
using (var stream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
await file.CopyToAsync(stream);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Logo uploaded: {FileName}", fileName);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public List<string> GetAllLogos()
|
||||
{
|
||||
if (!Directory.Exists(_logosPath))
|
||||
return new List<string>();
|
||||
|
||||
return Directory.GetFiles(_logosPath)
|
||||
.Select(Path.GetFileName)
|
||||
.Where(f => f != null)
|
||||
.Select(f => f!)
|
||||
.OrderBy(f => f)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public string GetLogoUrl(string? filename)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
return string.Empty;
|
||||
|
||||
return $"/logos/{filename}";
|
||||
}
|
||||
|
||||
public bool LogoExists(string filename)
|
||||
{
|
||||
return File.Exists(Path.Combine(_logosPath, filename));
|
||||
}
|
||||
|
||||
public void DeleteLogo(string filename)
|
||||
{
|
||||
var filePath = Path.Combine(_logosPath, filename);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
_logger.LogInformation("Logo deleted: {FileName}", filename);
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> CleanUnusedLogos(IEnumerable<string> usedLogoFilenames)
|
||||
{
|
||||
var allLogos = GetAllLogos();
|
||||
var usedSet = new HashSet<string>(usedLogoFilenames.Where(f => !string.IsNullOrEmpty(f))!);
|
||||
var unusedLogos = allLogos.Where(logo => !usedSet.Contains(logo)).ToList();
|
||||
|
||||
foreach (var logo in unusedLogos)
|
||||
{
|
||||
DeleteLogo(logo);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Cleaned {Count} unused logos", unusedLogos.Count);
|
||||
return unusedLogos;
|
||||
}
|
||||
|
||||
public void CopyLogoToDirectory(string filename, string targetDirectory)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
return;
|
||||
|
||||
var sourcePath = Path.Combine(_logosPath, filename);
|
||||
if (!File.Exists(sourcePath))
|
||||
{
|
||||
_logger.LogWarning("Logo file not found for copy: {FileName}", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(targetDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(targetDirectory);
|
||||
}
|
||||
|
||||
var targetPath = Path.Combine(targetDirectory, filename);
|
||||
File.Copy(sourcePath, targetPath, overwrite: true);
|
||||
_logger.LogInformation("Logo copied to: {TargetPath}", targetPath);
|
||||
}
|
||||
}
|
||||
16
ConfigurationPannel/Services/NoOpPrintJobSource.cs
Normal file
16
ConfigurationPannel/Services/NoOpPrintJobSource.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Threading.Channels;
|
||||
using Inspectron.Epson.PrintServer;
|
||||
|
||||
namespace ConfigurationPannel.Services;
|
||||
|
||||
public class NoOpPrintJobSource : IPrintJobSource
|
||||
{
|
||||
private readonly Channel<PrintJob> _channel = Channel.CreateUnbounded<PrintJob>();
|
||||
|
||||
public Task<PrintJob> GetNextJobAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
// Blocks indefinitely, keeping PrintLoop alive without processing jobs
|
||||
// This stub implementation keeps the loop running but never provides actual jobs
|
||||
return _channel.Reader.ReadAsync(cancellationToken).AsTask();
|
||||
}
|
||||
}
|
||||
130
ConfigurationPannel/Services/PrintServerHostedService.cs
Normal file
130
ConfigurationPannel/Services/PrintServerHostedService.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using Ninject;
|
||||
using Inspectron.Epson.PrintServer;
|
||||
using Inspectron.Epson.PrintServer.ConfigurationSources;
|
||||
using Inspectron.Epson.PrintServer.JobSources;
|
||||
using Inspectron.Epson.PrintServer.Printers;
|
||||
using Inspectron.Epson.PrintServer.PrintServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ConfigurationPannel.Services;
|
||||
|
||||
public class PrintServerHostedService : IHostedService
|
||||
{
|
||||
private readonly ILogger<PrintServerHostedService> _logger;
|
||||
private readonly ConfigurationManager _configManager;
|
||||
private PrintServer? _printServer;
|
||||
private PrintLoop? _printLoop;
|
||||
private StandardKernel? _kernel;
|
||||
|
||||
public PrintServerHostedService(
|
||||
ILogger<PrintServerHostedService> logger,
|
||||
ConfigurationManager configManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_configManager = configManager;
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Starting PrintServer background service");
|
||||
await InitializePrintServerAsync();
|
||||
}
|
||||
|
||||
private async Task InitializePrintServerAsync()
|
||||
{
|
||||
// Load configuration
|
||||
var config = await _configManager.LoadConfigurationAsync();
|
||||
|
||||
// Setup Ninject kernel (matching EpsonPrintService pattern)
|
||||
_kernel = new StandardKernel();
|
||||
_kernel.Bind<EpsonPrintServiceConfiguration>().ToConstant(config);
|
||||
_kernel.Bind<IPrintJobSource>().To<SignalRPrintJobSource>().InSingletonScope();
|
||||
_kernel.Bind<IPrintService>().To<Inspectron.Epson.PrintServer.PrintServices.EpsonPrintService>();
|
||||
_kernel.Bind<Microsoft.Extensions.Logging.ILogger>().ToConstant(_logger);
|
||||
_kernel.Bind<IAssignedPrinterRepository>().ToConstant(config);
|
||||
_kernel.Bind<IPrinterFactory>().To<PrinterFactory>().InSingletonScope();
|
||||
_kernel.Bind<IPrinterConfigurationSource>().ToConstant(config);
|
||||
_kernel.Bind<PrintServer>().ToSelf().InSingletonScope();
|
||||
|
||||
// Get instances
|
||||
_printServer = _kernel.Get<PrintServer>();
|
||||
_printLoop = _kernel.Get<PrintLoop>();
|
||||
|
||||
// Register printers from configuration
|
||||
foreach (var printerConfig in config.PrinterConfigurations.Values)
|
||||
{
|
||||
_printServer.RegisterPrinter(printerConfig.Address);
|
||||
}
|
||||
|
||||
// Start print loop
|
||||
await _printLoop.StartAsync();
|
||||
_logger.LogInformation("PrintServer background service started successfully");
|
||||
}
|
||||
|
||||
public async Task RestartAsync()
|
||||
{
|
||||
_logger.LogInformation("Restarting PrintServer with new configuration");
|
||||
|
||||
// Stop current print loop
|
||||
if (_printLoop != null)
|
||||
{
|
||||
await _printLoop.StopAsync();
|
||||
}
|
||||
|
||||
// Shutdown print server
|
||||
if (_printServer != null)
|
||||
{
|
||||
await _printServer.ShutdownAsync();
|
||||
}
|
||||
|
||||
// Dispose kernel
|
||||
_kernel?.Dispose();
|
||||
|
||||
// Reinitialize with new config
|
||||
await InitializePrintServerAsync();
|
||||
|
||||
_logger.LogInformation("PrintServer background service restarted successfully");
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Stopping PrintServer background service");
|
||||
|
||||
if (_printLoop != null)
|
||||
{
|
||||
await _printLoop.StopAsync();
|
||||
}
|
||||
|
||||
if (_printServer != null)
|
||||
{
|
||||
await _printServer.ShutdownAsync();
|
||||
}
|
||||
|
||||
_kernel?.Dispose();
|
||||
|
||||
_logger.LogInformation("PrintServer background service stopped");
|
||||
}
|
||||
|
||||
public async Task<(bool Success, string Message)> SubmitPrintJobAsync(string workAreaId, string content)
|
||||
{
|
||||
if (_printServer == null)
|
||||
return (false, "Print server not initialized");
|
||||
|
||||
var config = await _configManager.LoadConfigurationAsync();
|
||||
var printerIp = config.GetAssignedPrinter(workAreaId);
|
||||
|
||||
if (string.IsNullOrEmpty(printerIp))
|
||||
return (false, "No printer assigned to this work area");
|
||||
|
||||
var job = new PrintJob
|
||||
{
|
||||
AreaId = workAreaId,
|
||||
Document = content
|
||||
};
|
||||
|
||||
_printServer.SubmitJob(printerIp, job);
|
||||
_logger.LogInformation($"Test print job submitted to {printerIp} for work area {workAreaId}");
|
||||
|
||||
return (true, $"Print job submitted successfully to {printerIp}");
|
||||
}
|
||||
}
|
||||
39
ConfigurationPannel/Services/UserService.cs
Normal file
39
ConfigurationPannel/Services/UserService.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ConfigurationPannel.Services;
|
||||
|
||||
public class UserService
|
||||
{
|
||||
private readonly string _usersFilePath;
|
||||
|
||||
public UserService(IWebHostEnvironment env)
|
||||
{
|
||||
_usersFilePath = Path.Combine(env.ContentRootPath, "users.json");
|
||||
}
|
||||
|
||||
public async Task<bool> ValidateCredentialsAsync(string username, string password)
|
||||
{
|
||||
if (!File.Exists(_usersFilePath))
|
||||
return false;
|
||||
|
||||
var json = await File.ReadAllTextAsync(_usersFilePath);
|
||||
var userStore = JsonSerializer.Deserialize<UserStore>(json, new JsonSerializerOptions(){PropertyNameCaseInsensitive = true});
|
||||
var user = userStore?.Users.FirstOrDefault(u => u.Username == username);
|
||||
|
||||
if (user == null)
|
||||
return false;
|
||||
|
||||
return user.Password==password;
|
||||
}
|
||||
}
|
||||
|
||||
public class UserStore
|
||||
{
|
||||
public List<User> Users { get; set; } = new();
|
||||
}
|
||||
|
||||
public class User
|
||||
{
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
Reference in New Issue
Block a user