diff --git a/.gitignore b/.gitignore index f8dc71a..b864c70 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ EgwProxy/EgwProxy.dll # Doxygen generated docs docs/* +doxygen/* # Build results [Dd]ebug/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1c3a682..a943eaa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,11 +17,11 @@ variables: .DocReplica: &DocReplica - | - net use X: /delete - net use X: $env:NET_SHARE_X /u:$env:NET_USER_X $XDRIVE_PASSWD - ROBOCOPY docfx X:\$env:APP_NAME /MIR /XF .git* /XD .git + net use A: /delete + net use A: $env:NET_SHARE_X /u:$env:NET_USER_X $XDRIVE_PASSWD + ROBOCOPY doxygen A:\$env:APP_NAME /MIR /XF .git* /XD .git SLEEP 2 - net use X: /delete + net use A: /delete # helper x fix pacchetti nuget da repo locale nexus.steamware.net .nuget-fix: &nuget-fix @@ -191,7 +191,7 @@ variables: stages: - build - release - - docfx + - doxygen # -------------------------------- # BUILD @@ -239,10 +239,10 @@ IOB-MAN:release: - *SendToVersionsLog # -------------------------------- -# DocFx +# doxygen # -------------------------------- -IOB-MAN:docfx: - stage: docfx +IOB-MAN:doxygen: + stage: doxygen needs: ["IOB-MAN:build"] tags: - win @@ -257,6 +257,6 @@ IOB-MAN:docfx: - *nuget-fix - '& "$env:NUGET_PATH" restore "$env:APP_NAME.sln" -verbosity quiet' script: - - docfx $env:APP_NAME/docfx.json - - mv $env:APP_NAME/_site "docfx" + - doxygen Doxyfile +# - mv $env:APP_NAME/_site "doxygen" - *DocReplica \ No newline at end of file diff --git a/Doxyfile b/Doxyfile index c111d41..be66051 100644 --- a/Doxyfile +++ b/Doxyfile @@ -3,7 +3,7 @@ #--------------------------------------------------------------------------- PROJECT_NAME = "IOB-MAN" -OUTPUT_DIRECTORY = docs +OUTPUT_DIRECTORY = doxygen CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English EXTRACT_ALL = YES diff --git a/IOB-MAN/Components/Compo/ApplicationCheck.razor.cs b/IOB-MAN/Components/Compo/ApplicationCheck.razor.cs index ab5d1d2..58c8506 100644 --- a/IOB-MAN/Components/Compo/ApplicationCheck.razor.cs +++ b/IOB-MAN/Components/Compo/ApplicationCheck.razor.cs @@ -1,3 +1,17 @@ +/// +/// Component responsible for monitoring and managing IOB (Industrial Operation Block) services. +/// +/// This Blazor component displays real-time status of running processes, provides UI controls +/// for starting/stopping services, and manages auto-restart logic based on configuration and thresholds. +/// +/// Key Features: +/// - Displays live status of IOB services (running, stopped, ratio, color-coded indicators). +/// - Enables user to open process folders (config, logs, target paths). +/// - Supports dynamic filtering by IOB type. +/// - Implements auto-restart logic triggered when service health degrades. +/// - Integrates with external services (AppControlService, FluxLogManService) via DI. +/// - Handles UI state updates via parameterized events and background scanning. +/// using IOB_MAN.Core; using IOB_MAN.Core.Services; using Microsoft.AspNetCore.Components; @@ -13,6 +27,12 @@ namespace IOB_MAN.Components.Compo { #region Public Methods + /// + /// Cleans up event subscriptions and resources when the component is disposed. + /// + /// Specifically: + /// - Unsubscribes from ACService.StatusUpdated event. + /// public void Dispose() { ACService.EA_StatusUpdated -= ACService_EA_StatusUpdated; @@ -22,17 +42,37 @@ namespace IOB_MAN.Components.Compo #region Protected Fields + /// + /// Selected IOB type filter (e.g., "PLC", "SCADA", "HMI"). + /// Used to filter displayed records in the UI. + /// protected string iobTypeSel = ""; + /// + /// List of page sizes available for record pagination (e.g., 5, 10, 20 records per page). + /// Used in UI for user-controlled pagination. + /// protected List PageSizeDispl = new List() { 5, 10, 15, 20, 25, 50 }; #endregion Protected Fields #region Protected Properties + /// + /// Injected service for managing external applications and service states. + /// Responsible for opening, closing, and monitoring IOB processes. + /// [Inject] protected AppControlService ACService { get; set; } = null!; + /// + /// Gets or sets whether auto-restart is enabled. + /// + /// Behavior: + /// - When enabled, triggers automatic restart of closed services. + /// - When disabled, delays restart until a configurable threshold (VetoAutoCheck) is reached. + /// - On change, updates service state and forces UI reload. + /// protected bool AutoRestart { get => ACService.AutoRestartEnabled; @@ -41,7 +81,6 @@ namespace IOB_MAN.Components.Compo if (ACService.AutoRestartEnabled != value) { ACService.AutoRestartEnabled = value; - // eseguo check/riavvio... if (value) { ACService.DoReopenClosed(); @@ -57,11 +96,23 @@ namespace IOB_MAN.Components.Compo } } + /// + /// CSS style for context menu (positioned absolutely at mouse coordinates). + /// Dynamically set based on user right-click position. + /// protected string contextMenuStyle { get => $"position: absolute; top: {menuYpx}; left: {menuXpx}; z-index:999;"; } + /// + /// CSS class for process startup status indicator. + /// + /// Color logic: + /// - If fewer than configured processes are started ? "text-info" + /// - If <50% of processes are running ? "text-danger" + /// - If 50% to 100% running ? "text-warning" + /// protected string cssCheckProc { get @@ -87,6 +138,14 @@ namespace IOB_MAN.Components.Compo } } + /// + /// CSS class for "active processes" status. + /// + /// Color logic: + /// - If <50% of started processes are running ? "bg-danger" + /// - If 50% to 100% running ? "bg-warning" + /// - Otherwise ? "bg-success" + /// protected string cssProcAttivi { get @@ -105,6 +164,14 @@ namespace IOB_MAN.Components.Compo } } + /// + /// CSS class for "started processes" status. + /// + /// Color logic: + /// - If <50% of configured processes are started ? "bg-danger" + /// - If 50% to 100% started ? "bg-warning" + /// - Otherwise ? "bg-success" + /// protected string cssProcAvviati { get @@ -123,14 +190,26 @@ namespace IOB_MAN.Components.Compo } } + /// + /// Current list of IOB types (e.g., PLC, SCADA) available in the system. + /// Retrieved from ACService. + /// protected List CurrIobType { get => ACService.CurrIobType; } + /// + /// Injected service for managing flux log data and opening log views. + /// Used to open specific log files or view logs for a selected IOB. + /// [Inject] protected FluxLogManService FLMService { get; set; } = null!; + /// + /// Selected IOB type (user-filtered value). + /// Updates UI when changed and triggers a reload. + /// protected string IobTypeSel { get => iobTypeSel; @@ -144,11 +223,16 @@ namespace IOB_MAN.Components.Compo } } + /// + /// Injected JS runtime for interacting with browser APIs (e.g., confirm dialogs). + /// Used for user confirmation before reboot or restart actions. + /// [Inject] protected IJSRuntime JSRuntime { get; set; } = null!; /// - /// Livello Log impostato + /// Current logging level (e.g., Debug, Info, Warning). + /// Controls verbosity of logs in the application. /// protected LogLevelIob LogLevel { @@ -156,29 +240,52 @@ namespace IOB_MAN.Components.Compo set => ACService.LogLevel = value; } + /// + /// Navigation manager for routing to pages (e.g., About, Settings). + /// [Inject] protected NavigationManager NavMan { get; set; } = null!; + /// + /// Total number of configured IOB processes. + /// Used to calculate startup and running ratios. + /// protected int NumProcConfig { get => ACService.NumProcConfig; } + /// + /// Number of IOB processes currently running. + /// Used in status indicators and health checks. + /// protected int NumProcRunning { get => ACService.NumProcRunning; } + /// + /// Number of IOB processes that have been started (not necessarily running). + /// Used in status indicators and auto-restart logic. + /// protected int NumProcStarted { get => ACService.NumProcStarted; } + /// + /// Total number of configured IOB types. + /// Used for type-based filtering and UI display. + /// protected int NumTypeConfig { get => ACService.NumTypeConfig; } + /// + /// Round-trip time (in ms) for communication between components and services. + /// Used to measure responsiveness and performance. + /// protected double RoundTrip { get => ACService.RoundTrip; @@ -188,25 +295,54 @@ namespace IOB_MAN.Components.Compo #region Protected Methods + /// + /// Returns CSS class based on whether a specific IOB is running. + /// + /// Style: + /// - If not running ? "bg-danger bg-opacity-25" + /// - Otherwise ? empty (default background) + /// + /// The IOB record to evaluate. + /// Appropriate CSS class string. protected string CssClassIob(IobAdapt currRec) { string css = !currRec.isRunning ? "bg-danger bg-opacity-25" : ""; return css; } + /// + /// Delays a restart request by setting a countdown timer in the UI. + /// + /// Used when auto-restart is disabled to prevent immediate restarts. + /// protected void DelayRestart() { ACService.DelayRestart(false); } + /// + /// Closes all child IOB processes and refreshes the UI. + /// + /// Actions: + /// - Stops all running services. + /// - Triggers a full scan to update state. + /// - Optionally resets the list of services. + /// protected async Task DoCloseAll() { - // chiude tutto CloseAllChild(false); await ACService.DoScan(); - //ForceReload(); + // ForceReload(); // Optional: can be removed if UI refresh is handled elsewhere } + /// + /// Closes a specific child IOB process. + /// + /// Action: + /// - Sends a close command to the service. + /// - Hides the right-click menu. + /// + /// The IOB record to close. protected void DoCloseChild(IobAdapt currRec) { ACService.DoCloseChild(currRec); @@ -214,9 +350,13 @@ namespace IOB_MAN.Components.Compo } /// - /// Nasconde gli IOB + /// Minimizes all IOB process windows to the system tray. + /// + /// Behavior: + /// - Iterates over all CurrRecords. + /// - For each process, retrieves its MainWindowHandle and minimizes it. + /// - Logs any errors (e.g., process already closed). /// - /// protected void DoHideAll() { foreach (var item in CurrRecords) @@ -224,23 +364,29 @@ namespace IOB_MAN.Components.Compo try { Process p = Process.GetProcessById(item.pID); - // cerco e chiudo quelli che mi interessano... var windowsHandle = p.MainWindowHandle; ShowWindowAsync(windowsHandle, CoreEnum.SW_SHOWMINIMIZED); } catch (Exception exc) { - // errore era già chiuso.. Log.Error($"Errore in HIDE windows:{Environment.NewLine}{exc}"); } } } + /// + /// Reboots all IOB processes and optionally reloads configuration. + /// + /// Actions: + /// - Closes all services. + /// - If 'reloadConf' is true, re-scans configuration and reloads it. + /// - Reopens all services. + /// - Triggers a final scan to update UI. + /// + /// If true, re-reads configuration after restart. protected async Task DoRestartAll(bool reloadConf) { - // chiude tutto CloseAllChild(true); - // se richiesto rilettura conf riesegue anche quello... if (reloadConf) { await ACService.DoScan(); @@ -251,7 +397,12 @@ namespace IOB_MAN.Components.Compo } /// - /// Mostra in primo piano tutte le finestre IOB + /// Restores all IOB process windows to full screen. + /// + /// Behavior: + /// - Iterates over all CurrRecords. + /// - For each process, retrieves its MainWindowHandle and restores it. + /// - Logs any errors (e.g., process already closed). /// protected void DoShowAll() { @@ -260,43 +411,62 @@ namespace IOB_MAN.Components.Compo try { Process p = Process.GetProcessById(item.pID); - // cerco e chiudo quelli che mi interessano... var windowsHandle = p.MainWindowHandle; ShowWindowAsync(windowsHandle, CoreEnum.SW_SHOWNORMAL); } catch (Exception exc) { - // errore era già chiuso.. Log.Error($"Errore in SHOW windows:{Environment.NewLine}{exc}"); } } } /// - /// Mostra in primo piano tutte le finestre IOB + /// Restores a specific IOB process window. + /// + /// Action: + /// - Finds the process by ID and restores it to normal view. /// + /// The IOB record to restore. protected void DoShowChild(IobAdapt item) { try { Process p = Process.GetProcessById(item.pID); - // cerco e chiudo quelli che mi interessano... var windowsHandle = p.MainWindowHandle; ShowWindowAsync(windowsHandle, CoreEnum.SW_SHOWNORMAL); } catch (Exception exc) { - // errore era già chiuso.. Log.Error($"Errore in SHOW windows:{Environment.NewLine}{exc}"); } } + /// + /// Starts a specific IOB process. + /// + /// Action: + /// - Sends a command to ACService to open and start the selected IOB. + /// - Hides the right-click menu. + /// + /// The IOB record to start. protected void DoStartChild(IobAdapt currRec) { ACService.DoOpenChildSel(currRec); dxMenuVisible = false; } + /// + /// Forces a full scan of all IOB services and updates UI state. + /// + /// Actions: + /// - Sets isLoading to true. + /// - Clears current records. + /// - Calls DoScan() to refresh service list. + /// - Updates filtered list based on current filters (e.g., IOB type). + /// - Applies pagination. + /// - Sets isLoading to false and triggers UI update. + /// protected async Task ForceCheck() { isLoading = true; @@ -305,17 +475,37 @@ namespace IOB_MAN.Components.Compo isLoading = false; } + /// + /// Initializes the component. + /// + /// Action: + /// - Subscribes to ACService.StatusUpdated event to update UI on status changes. + /// protected override void OnInitialized() { ACService.EA_StatusUpdated += ACService_EA_StatusUpdated; } + /// + /// Called when parameters change (e.g., user selects a new IOB type). + /// + /// Actions: + /// - Triggers a full scan of services. + /// - Updates the UI with filtered records. + /// protected override async Task OnParametersSetAsync() { await ACService.DoScan(); ForceReload(); } + /// + /// Updates the number of records per page (e.g., from 10 to 20). + /// + /// Behavior: + /// - Updates the page count and triggers a reload to refresh the UI. + /// + /// New number of records per page. protected void SetNumRec(int newNum) { numRecord = newNum; @@ -323,6 +513,13 @@ namespace IOB_MAN.Components.Compo ForceReload(); } + /// + /// Updates the current page (e.g., page 2, 3, etc.). + /// + /// Behavior: + /// - Updates the page number and triggers a reload to refresh the UI. + /// + /// New page number. protected void SetPage(int newNum) { currPage = newNum; @@ -334,58 +531,116 @@ namespace IOB_MAN.Components.Compo #region Private Fields /// - /// Classe logger + /// Logger instance for structured logging within this component. /// private static Logger Log = LogManager.GetCurrentClassLogger(); + /// + /// Timestamp of last UI render to prevent rapid re-renders. + /// Prevents excessive updates when data changes quickly. + /// private DateTime _lastRender = DateTime.MinValue; + + /// + /// Auto-restart countdown (in seconds) displayed in UI. + /// Shows time remaining before auto-restart is triggered. + /// private string countAutoRestart = ""; + /// + /// Flag indicating whether the right-click menu is visible. + /// Used for UI state management. + /// private bool dxMenuVisible = false; + /// + /// Flag controlling whether task killing is allowed (e.g., for safety). + /// private bool enableKillTask = true; + /// + /// X-coordinate for context menu positioning (in pixels). + /// Set dynamically on right-click. + /// private string menuXpx = "0px"; + /// + /// Y-coordinate for context menu positioning (in pixels). + /// Set dynamically on right-click. + /// private string menuYpx = "0px"; + /// + /// Currently selected IOB record (used for actions like opening folders). + /// private IobAdapt? selIOB = null; #endregion Private Fields #region Private Properties + /// + /// Current computer name (e.g., "DESKTOP-ABC123"). + /// private string ComputerName { get => Environment.MachineName; } /// - /// Css e abilitazione chiusura (solo se c'è qualcosa da chiudere) + /// CSS class for "Close All" button. + /// + /// Behavior: + /// - Enabled only if at least one service is currently running. + /// - Disabled otherwise (grayed out). /// private string cssBtnCloseAll { get => NumProcStarted > 0 ? "" : "disabled opacity-50"; } + /// + /// Current page number (1-indexed). + /// private int currPage { get; set; } = 1; + /// + /// Current list of IOB service records (e.g., PLC, HMI). + /// Retrieved from ACService and used for UI display. + /// private List CurrRecords { get => ACService.ListIobAdapters; } + /// + /// User domain (e.g., "DOMAIN\\username"). + /// private string DomainName { get => Environment.UserDomainName; } + /// + /// Indicates whether the UI is loading (used for spinner or placeholder state). + /// private bool isLoading { get; set; } = false; + /// + /// Paginated list of records currently displayed in the UI. + /// Filtered and paginated based on IOB type and page size. + /// private List? ListRecords { get; set; } = null; + /// + /// Number of records per page (e.g., 10, 20). + /// private int numRecord { get; set; } = 10; + /// + /// Target path for a selected IOB (e.g., C:\IOB\PLC\001). + /// Built dynamically from CodIOB and ACService. + /// private string selIobTgtPath { get @@ -395,8 +650,14 @@ namespace IOB_MAN.Components.Compo } } + /// + /// Total number of records (used for pagination and UI display). + /// private int totalCount { get; set; } = 0; + /// + /// Current user name (e.g., "JohnDoe"). + /// private string UserName { get => Environment.UserName; @@ -406,17 +667,29 @@ namespace IOB_MAN.Components.Compo #region Private Methods + /// + /// Windows API: Shows a window with a specified style (e.g., minimized, normal). + /// Used to minimize or restore IOB process windows. + /// + /// Handle to the window. + /// Style (e.g., SW_SHOWMINIMIZED, SW_SHOWNORMAL). [DllImport("user32.dll")] private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); + /// + /// Handles status updates from ACService. + /// + /// Logic: + /// - If auto-restart is disabled, shows countdown until auto-restart is triggered. + /// - When countdown reaches zero, enables auto-restart. + /// - Forces UI reload to reflect new state. + /// private void ACService_EA_StatusUpdated() { - // verifico gestione atuorestart... if (!AutoRestart) { var remSec = (int)ACService.VetoAutoCheck.Subtract(DateTime.Now).TotalSeconds; countAutoRestart = remSec > 0 ? $"{remSec:N0}" : "!!!"; - // se va a zero... abilito riavvio! if (remSec <= 0) { AutoRestart = true; @@ -426,9 +699,12 @@ namespace IOB_MAN.Components.Compo } /// - /// Chiude tutti i child + /// Closes all child IOB processes. + /// + /// Parameters: + /// - doReset: if true, resets the internal list of services. /// - /// resetta elenco + /// Whether to reset the service list after closing. private void CloseAllChild(bool doReset) { enableKillTask = false; @@ -436,19 +712,35 @@ namespace IOB_MAN.Components.Compo enableKillTask = true; } + /// + /// Triggers a reboot request with user confirmation. + /// + /// Behavior: + /// - Uses JSRuntime to show a confirmation dialog. + /// - If confirmed, raises a reboot request to ACService. + /// + /// Mouse event arguments (used for context menu). private async Task ForceReboot(Microsoft.AspNetCore.Components.Web.MouseEventArgs args) { if (!await JSRuntime.InvokeAsync("confirm", "Sicuro di voler riavviare il programma?")) return; - // richiesta riavvio ACService.RaiseRebootReq(); } + /// + /// Forces a UI reload with current filters and pagination. + /// + /// Behavior: + /// - Skips if too soon (less than 1 second since last render). + /// - Updates filtered list based on IOB type. + /// - Applies pagination. + /// - Updates UI state and triggers re-render. + /// private void ForceReload() { if ((DateTime.Now - _lastRender).TotalSeconds < 1) - return; // skip if too soon + return; _lastRender = DateTime.Now; isLoading = true; @@ -457,7 +749,6 @@ namespace IOB_MAN.Components.Compo filtered = filtered.Where(x => x.TgtName == IobTypeSel).ToList(); totalCount = filtered.Count(); - // paginazione! ListRecords = filtered .OrderBy(x => x.CodIOB) .Skip(numRecord * (currPage - 1)) @@ -467,51 +758,71 @@ namespace IOB_MAN.Components.Compo _ = InvokeAsync(StateHasChanged); } + /// + /// Opens the target folder of the selected IOB (e.g., for configuration). + /// private void IobFolderOpenApp() { if (selIOB != null) Process.Start("explorer.exe", selIobTgtPath); - // chiudo e resetto selezione selIOB = null; dxMenuVisible = false; } + /// + /// Opens the configuration folder of the selected IOB. + /// private void IobFolderOpenConf() { if (selIOB != null) Process.Start("explorer.exe", Path.Combine(selIobTgtPath, "DATA", "CONF")); - // chiudo e resetto selezione selIOB = null; dxMenuVisible = false; } + /// + /// Opens the logs folder of the selected IOB. + /// private void IobFolderOpenLog() { if (selIOB != null) Process.Start("explorer.exe", Path.Combine(selIobTgtPath, "logs", selIOB.CodIOB)); - // chiudo e resetto selezione selIOB = null; dxMenuVisible = false; } + /// + /// Navigates to the "About" page. + /// private void NavAbout() { NavMan.NavigateTo("About"); } + /// + /// Opens a FluxLog view for the selected IOB. + /// private void OpenFLForm() { if (selIOB != null) FLMService.RequestLoadFLogData(selIOB.CodIOB); - // chiudo e resetto selezione selIOB = null; dxMenuVisible = false; } + /// + /// Handles right-click event on an IOB record. + /// + /// Behavior: + /// - Sets selected IOB. + /// - Shows context menu at mouse position. + /// + /// Mouse event arguments. + /// The IOB record being right-clicked. private void RightClick(Microsoft.AspNetCore.Components.Web.MouseEventArgs e, IobAdapt currRec) { selIOB = currRec; @@ -525,4 +836,4 @@ namespace IOB_MAN.Components.Compo #endregion Private Methods } -} \ No newline at end of file +} diff --git a/IOB-MAN/Components/Compo/CmpFooter.razor b/IOB-MAN/Components/Compo/CmpFooter.razor index d770729..d93a889 100644 --- a/IOB-MAN/Components/Compo/CmpFooter.razor +++ b/IOB-MAN/Components/Compo/CmpFooter.razor @@ -9,7 +9,3 @@ Egalware - - - - diff --git a/IOB-MAN/Components/Layout/MainLayout.razor.cs b/IOB-MAN/Components/Layout/MainLayout.razor.cs index dbf53b0..0523801 100644 --- a/IOB-MAN/Components/Layout/MainLayout.razor.cs +++ b/IOB-MAN/Components/Layout/MainLayout.razor.cs @@ -1,4 +1,4 @@ -namespace GPW.CORE.ADM.Components.Layout +namespace IOB_MAN.Components.Layout { public partial class MainLayout { diff --git a/IOB-MAN/IOB-MAN.csproj b/IOB-MAN/IOB-MAN.csproj index 07874d1..5b5f6ac 100644 --- a/IOB-MAN/IOB-MAN.csproj +++ b/IOB-MAN/IOB-MAN.csproj @@ -8,7 +8,7 @@ enable true enable - 4.0.2511.2808 + 4.0.2511.2809 Debug;Release;Remote_DEBUG false