diff --git a/ScadaAdmin/OpenExtensions/ExtServerConfig/Code/ExtensionUtils.cs b/ScadaAdmin/OpenExtensions/ExtServerConfig/Code/ExtensionUtils.cs index b4f87ec02..3d49bc146 100644 --- a/ScadaAdmin/OpenExtensions/ExtServerConfig/Code/ExtensionUtils.cs +++ b/ScadaAdmin/OpenExtensions/ExtServerConfig/Code/ExtensionUtils.cs @@ -25,6 +25,7 @@ public static bool GetModuleView(IAdminContext adminContext, ServerApp serverApp { moduleView.ConfigDataset = adminContext.CurrentProject.ConfigDatabase; moduleView.AppDirs = adminContext.AppDirs.CreateDirsForView(serverApp.ConfigDir); + moduleView.AgentClient = adminContext.MainForm.GetAgentClient(false); moduleView.AppConfig = serverApp.AppConfig; moduleView.LoadDictionaries(); return true; diff --git a/ScadaAdmin/OpenExtensions/ExtServerConfig/ExtServerConfig.csproj b/ScadaAdmin/OpenExtensions/ExtServerConfig/ExtServerConfig.csproj index ce53622b2..5120fc2f4 100644 --- a/ScadaAdmin/OpenExtensions/ExtServerConfig/ExtServerConfig.csproj +++ b/ScadaAdmin/OpenExtensions/ExtServerConfig/ExtServerConfig.csproj @@ -12,7 +12,7 @@ Rapid SCADA Copyright © 2023 6.0.1 - 6.0.1.0 + 6.0.1.1 diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Deployment/FrmInstanceStatus.cs b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Deployment/FrmInstanceStatus.cs index d1a627007..433fd3ad4 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Deployment/FrmInstanceStatus.cs +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Deployment/FrmInstanceStatus.cs @@ -31,7 +31,6 @@ using Scada.Forms; using Scada.Lang; using System; -using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -43,10 +42,6 @@ namespace Scada.Admin.App.Forms.Deployment /// public partial class FrmInstanceStatus : Form, IDeploymentForm { - /// - /// The time period for disabling the button after pressing, ms. - /// - private const int ButtonWait = 1000; /// /// The services which status is displayed. /// @@ -86,6 +81,11 @@ public FrmInstanceStatus(AppData appData, ScadaProject project, ProjectInstance } + /// + /// Gets a value indicating whether the form is available to a user. + /// + private bool FormAvailable => Visible && !IsDisposed; + /// /// Gets a value indicating whether the selected profile changed. /// @@ -184,43 +184,34 @@ await Task.Run(() => }); } - /// - /// Displays the button in waiting state. - /// - private static void DisplayWait(Button button) - { - Task.Run(() => - { - button.Enabled = false; - Thread.Sleep(ButtonWait); - button.Enabled = true; - }); - } - /// /// Sends the command to the service. /// - private static void ControlService(IAgentClient client, ServiceApp serviceApp, ServiceCommand command) + private async Task ControlServiceAsync(IAgentClient client, ServiceApp serviceApp, ServiceCommand command) { if (client == null) return; - try + await Task.Run(() => { - bool result; + try + { + bool result; - lock (client) + lock (client) + { + result = client.ControlService(serviceApp, command, 0); + } + + if (!result && FormAvailable) + ScadaUiUtils.ShowError(AppPhrases.UnableControlService); + } + catch (Exception ex) { - result = client.ControlService(serviceApp, command, 0); + if (FormAvailable) + ScadaUiUtils.ShowError(ex.BuildErrorMessage(AppPhrases.ControlServiceError)); } - - if (!result) - ScadaUiUtils.ShowError(AppPhrases.UnableControlService); - } - catch (Exception ex) - { - ScadaUiUtils.ShowError(ex.BuildErrorMessage(AppPhrases.ControlServiceError)); - } + }); } @@ -276,7 +267,7 @@ private void btnDisconnect_Click(object sender, EventArgs e) Disconnect(); } - private void btnControlService_Click(object sender, EventArgs e) + private async void btnControlService_Click(object sender, EventArgs e) { Button button = (Button)sender; string buttonName = button.Name; @@ -302,8 +293,8 @@ private void btnControlService_Click(object sender, EventArgs e) // send command to application if (serviceApp != null && serviceCommand != null) { - DisplayWait(button); - ControlService(agentClient, serviceApp.Value, serviceCommand.Value); + button.DisplayWait(); + await ControlServiceAsync(agentClient, serviceApp.Value, serviceCommand.Value); } } diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.cs b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.cs index a69056b71..5481c0dff 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.cs +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.cs @@ -135,7 +135,8 @@ private bool ApplyChanges() if (!(int.TryParse(txtCnlNum.Text, out int cnlNum) && ConfigDatabase.MinID <= cnlNum && cnlNum <= ConfigDatabase.MaxID)) { - sbError.AppendError(lblCnlNum, CommonPhrases.IntegerInRangeRequired, ConfigDatabase.MinID, ConfigDatabase.MaxID); + sbError.AppendError(lblCnlNum, CommonPhrases.IntegerInRangeRequired, + ConfigDatabase.MinID, ConfigDatabase.MaxID); } int dataLen = -1; diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/ScadaAdmin.csproj b/ScadaAdmin/ScadaAdmin/ScadaAdmin/ScadaAdmin.csproj index f3d6cc1bc..d95fe7975 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/ScadaAdmin.csproj +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/ScadaAdmin.csproj @@ -12,7 +12,7 @@ Copyright © 2023 lamp.ico 6.1.0 - 6.1.0.1 + 6.1.0.2 diff --git a/ScadaComm/OpenDrivers/DrvDsOpcUaServer.Logic/DrvDsOpcUaServer.Logic.csproj b/ScadaComm/OpenDrivers/DrvDsOpcUaServer.Logic/DrvDsOpcUaServer.Logic.csproj index 6b86f325a..626196c2a 100644 --- a/ScadaComm/OpenDrivers/DrvDsOpcUaServer.Logic/DrvDsOpcUaServer.Logic.csproj +++ b/ScadaComm/OpenDrivers/DrvDsOpcUaServer.Logic/DrvDsOpcUaServer.Logic.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/ScadaComm/OpenDrivers/DrvModbus.Common/DrvModbus.Common.csproj b/ScadaComm/OpenDrivers/DrvModbus.Common/DrvModbus.Common.csproj index 7d2d53747..406c6001e 100644 --- a/ScadaComm/OpenDrivers/DrvModbus.Common/DrvModbus.Common.csproj +++ b/ScadaComm/OpenDrivers/DrvModbus.Common/DrvModbus.Common.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.2 + 6.0.0.3 diff --git a/ScadaComm/OpenDrivers/DrvModbus.Common/Protocol/ModbusUtils.cs b/ScadaComm/OpenDrivers/DrvModbus.Common/Protocol/ModbusUtils.cs index 2c8eb53c6..2ca4e4cbd 100644 --- a/ScadaComm/OpenDrivers/DrvModbus.Common/Protocol/ModbusUtils.cs +++ b/ScadaComm/OpenDrivers/DrvModbus.Common/Protocol/ModbusUtils.cs @@ -1,6 +1,8 @@ // Copyright (c) Rapid Software LLC. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; + namespace Scada.Comm.Drivers.DrvModbus.Protocol { /// @@ -183,7 +185,7 @@ public static string GetAddressRange(int address, int count, bool zeroAddr, bool } /// - /// Parses a byte order array from the string notation like '01234567'. + /// Parses a byte order array from the string notation like '0123456789ABCDEF'. /// public static int[] ParseByteOrder(string byteOrderStr) { @@ -198,7 +200,8 @@ public static int[] ParseByteOrder(string byteOrderStr) for (int i = 0; i < len; i++) { - byteOrder[i] = int.TryParse(byteOrderStr[i].ToString(), out int n) ? n : 0; + byteOrder[i] = int.TryParse(byteOrderStr[i].ToString(), + NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int n) ? n : 0; } return byteOrder; diff --git a/ScadaComm/OpenDrivers/DrvModbus.Logic/DrvModbus.Logic.csproj b/ScadaComm/OpenDrivers/DrvModbus.Logic/DrvModbus.Logic.csproj index 476f16ce9..32c767dac 100644 --- a/ScadaComm/OpenDrivers/DrvModbus.Logic/DrvModbus.Logic.csproj +++ b/ScadaComm/OpenDrivers/DrvModbus.Logic/DrvModbus.Logic.csproj @@ -8,7 +8,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.2 + 6.0.0.3 diff --git a/ScadaComm/OpenDrivers/DrvModbus.View/DrvModbus.View.csproj b/ScadaComm/OpenDrivers/DrvModbus.View/DrvModbus.View.csproj index ff005dec4..df1f72a7b 100644 --- a/ScadaComm/OpenDrivers/DrvModbus.View/DrvModbus.View.csproj +++ b/ScadaComm/OpenDrivers/DrvModbus.View/DrvModbus.View.csproj @@ -12,7 +12,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.2 + 6.0.0.3 diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.Common/DrvMqttClient.Common.csproj b/ScadaComm/OpenDrivers/DrvMqttClient.Common/DrvMqttClient.Common.csproj index a2c1ab4da..b2f03ae17 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.Common/DrvMqttClient.Common.csproj +++ b/ScadaComm/OpenDrivers/DrvMqttClient.Common/DrvMqttClient.Common.csproj @@ -10,7 +10,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.1 + 6.0.0.2 diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DevMqttClientLogic.cs b/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DevMqttClientLogic.cs index ae10eaf7d..701169002 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DevMqttClientLogic.cs +++ b/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DevMqttClientLogic.cs @@ -192,12 +192,7 @@ private void ExecuteJavaScript(ReceivedMessage message, SubscriptionTag subscrip { int tagIndex = subscriptionTag.TagIndex + i; double tagValue = subscriptionTag.JsValues[i]; - - if (double.IsNaN(tagValue)) - DeviceData.Invalidate(tagIndex); - else - DeviceData.Set(tagIndex, tagValue); - + DeviceData.Set(tagIndex, tagValue); updateTimestamps[tagIndex] = LastSessionTime; } } diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DrvMqttClient.Logic.csproj b/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DrvMqttClient.Logic.csproj index ad7717511..3f34b7884 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DrvMqttClient.Logic.csproj +++ b/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DrvMqttClient.Logic.csproj @@ -11,7 +11,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.1 + 6.0.0.2 diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.View/DrvMqttClient.View.csproj b/ScadaComm/OpenDrivers/DrvMqttClient.View/DrvMqttClient.View.csproj index 0e1d92a59..97dbe3c34 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.View/DrvMqttClient.View.csproj +++ b/ScadaComm/OpenDrivers/DrvMqttClient.View/DrvMqttClient.View.csproj @@ -12,7 +12,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.1 + 6.0.0.2 diff --git a/ScadaComm/OpenDrivers/DrvOpcUa.Common/DrvOpcUa.Common.csproj b/ScadaComm/OpenDrivers/DrvOpcUa.Common/DrvOpcUa.Common.csproj index c855e70e7..33a4c10c8 100644 --- a/ScadaComm/OpenDrivers/DrvOpcUa.Common/DrvOpcUa.Common.csproj +++ b/ScadaComm/OpenDrivers/DrvOpcUa.Common/DrvOpcUa.Common.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/ScadaComm/ScadaComm/ScadaCommApp/ScadaCommApp.csproj b/ScadaComm/ScadaComm/ScadaCommApp/ScadaCommApp.csproj index bb1483492..9a3eec68f 100644 --- a/ScadaComm/ScadaComm/ScadaCommApp/ScadaCommApp.csproj +++ b/ScadaComm/ScadaComm/ScadaCommApp/ScadaCommApp.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1 diff --git a/ScadaComm/ScadaComm/ScadaCommEngine/CoreLogic.cs b/ScadaComm/ScadaComm/ScadaCommEngine/CoreLogic.cs index 45479271c..e95e6ead4 100644 --- a/ScadaComm/ScadaComm/ScadaCommEngine/CoreLogic.cs +++ b/ScadaComm/ScadaComm/ScadaCommEngine/CoreLogic.cs @@ -893,7 +893,7 @@ public void StopProcessing() terminated = true; serviceStatus = ServiceStatus.Terminating; - if (thread.Join(AppConfig.GeneralOptions.StopWait)) + if (thread.Join(TimeSpan.FromSeconds(AppConfig.GeneralOptions.StopWait))) Log.WriteAction(CommonPhrases.LogicStopped); else Log.WriteAction(CommonPhrases.UnableToStopLogic); diff --git a/ScadaComm/ScadaComm/ScadaCommEngine/ScadaCommEngine.csproj b/ScadaComm/ScadaComm/ScadaCommEngine/ScadaCommEngine.csproj index b59ae4118..cabf159c6 100644 --- a/ScadaComm/ScadaComm/ScadaCommEngine/ScadaCommEngine.csproj +++ b/ScadaComm/ScadaComm/ScadaCommEngine/ScadaCommEngine.csproj @@ -8,7 +8,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1 diff --git a/ScadaComm/ScadaComm/ScadaCommWkr/ScadaCommWkr.csproj b/ScadaComm/ScadaComm/ScadaCommWkr/ScadaCommWkr.csproj index b5ab7d05b..7c04cef5c 100644 --- a/ScadaComm/ScadaComm/ScadaCommWkr/ScadaCommWkr.csproj +++ b/ScadaComm/ScadaComm/ScadaCommWkr/ScadaCommWkr.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1 diff --git a/ScadaCommon/ScadaCommon.Forms/ListViewExtensions.cs b/ScadaCommon/ScadaCommon.Forms/ListViewExtensions.cs index ae0f50878..c44a52732 100644 --- a/ScadaCommon/ScadaCommon.Forms/ListViewExtensions.cs +++ b/ScadaCommon/ScadaCommon.Forms/ListViewExtensions.cs @@ -50,6 +50,14 @@ public static ListViewItem GetSelectedItem(this ListView listView) return listView.SelectedItems.Count > 0 ? listView.SelectedItems[0] : null; } + /// + /// Gets an object associated with the first selected list item. + /// + public static object GetSelectedObject(this ListView listView) + { + return listView.GetSelectedItem()?.Tag; + } + /// /// Moves up the selected list item. /// diff --git a/ScadaCommon/ScadaCommon.Forms/ScadaUiUtils.cs b/ScadaCommon/ScadaCommon.Forms/ScadaUiUtils.cs index 434406c75..d7f503ed6 100644 --- a/ScadaCommon/ScadaCommon.Forms/ScadaUiUtils.cs +++ b/ScadaCommon/ScadaCommon.Forms/ScadaUiUtils.cs @@ -9,6 +9,8 @@ using System.IO; using System.Linq; using System.Text; +using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; namespace Scada.Forms @@ -27,7 +29,11 @@ public static class ScadaUiUtils /// The maximum column width in DataGridView in pixels. /// private const int MaxColumnWidth = 500; - + /// + /// The time period for disabling the button after pressing, ms. + /// + private const int ButtonWait = 1000; + /// /// The log refresh interval for local access, ms. /// @@ -115,8 +121,7 @@ public static void SetValue(this NumericUpDown numericUpDown, decimal val) /// public static void SetTime(this DateTimePicker dateTimePicker, DateTime time) { - DateTime date = dateTimePicker.MinDate; - dateTimePicker.Value = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second); + dateTimePicker.Value = dateTimePicker.MinDate + time.TimeOfDay; } /// @@ -124,8 +129,7 @@ public static void SetTime(this DateTimePicker dateTimePicker, DateTime time) /// public static void SetTime(this DateTimePicker dateTimePicker, TimeSpan timeSpan) { - DateTime date = dateTimePicker.MinDate; - dateTimePicker.Value = new DateTime(date.Year, date.Month, date.Day).Add(timeSpan); + dateTimePicker.Value = dateTimePicker.MinDate + timeSpan; } /// @@ -174,6 +178,19 @@ public static void DrawTabItem(this ListBox listBox, DrawItemEventArgs e) e.DrawFocusRectangle(); } + /// + /// Displays the button in waiting state. + /// + public static void DisplayWait(this Button button) + { + Task.Run(() => + { + button.Enabled = false; + Thread.Sleep(ButtonWait); + button.Enabled = true; + }); + } + /// /// Tests whether the specified area is visible on any of the available screens. /// diff --git a/ScadaCommon/ScadaCommon.Log/ScadaCommon.Log.csproj b/ScadaCommon/ScadaCommon.Log/ScadaCommon.Log.csproj index 6104b75ad..ff31e3cfb 100644 --- a/ScadaCommon/ScadaCommon.Log/ScadaCommon.Log.csproj +++ b/ScadaCommon/ScadaCommon.Log/ScadaCommon.Log.csproj @@ -4,7 +4,7 @@ netstandard2.0 Scada.Log True - 6.1.0 + 6.0.0 Rapid SCADA Rapid Software LLC Mikhail Shiryaev diff --git a/ScadaCommon/ScadaCommon.MultiDb/ScadaCommon.MultiDb.csproj b/ScadaCommon/ScadaCommon.MultiDb/ScadaCommon.MultiDb.csproj index 2410afded..54b43379a 100644 --- a/ScadaCommon/ScadaCommon.MultiDb/ScadaCommon.MultiDb.csproj +++ b/ScadaCommon/ScadaCommon.MultiDb/ScadaCommon.MultiDb.csproj @@ -17,7 +17,7 @@ - + diff --git a/ScadaCommon/ScadaCommon/Data/Models/RightMatrix.cs b/ScadaCommon/ScadaCommon/Data/Models/RightMatrix.cs index 608812d50..ed44d7d2c 100644 --- a/ScadaCommon/ScadaCommon/Data/Models/RightMatrix.cs +++ b/ScadaCommon/ScadaCommon/Data/Models/RightMatrix.cs @@ -20,7 +20,7 @@ * * Author : Mikhail Shiryaev * Created : 2020 - * Modified : 2022 + * Modified : 2023 */ using Scada.Data.Entities; @@ -75,14 +75,14 @@ protected IEnumerable EnumerateParentRoleIDs(ITableIndex roleRef_childRoleI if (protectionSet == null) protectionSet = new HashSet { childRoleID }; - foreach (int parentRoleID in roleRef_childRoleIndex.SelectItems(childRoleID)) + foreach (RoleRef roleRef in roleRef_childRoleIndex.SelectItems(childRoleID)) { - if (protectionSet.Add(parentRoleID)) + if (protectionSet.Add(roleRef.ParentRoleID)) { - yield return parentRoleID; + yield return roleRef.ParentRoleID; foreach (int grandparentRoleID in - EnumerateParentRoleIDs(roleRef_childRoleIndex, parentRoleID, protectionSet)) + EnumerateParentRoleIDs(roleRef_childRoleIndex, roleRef.ParentRoleID, protectionSet)) { yield return grandparentRoleID; } @@ -105,7 +105,8 @@ protected IEnumerable EnumerateChildObjects(ITableIndex obj_parentObjIndex, { yield return childObj; - foreach (Obj grandchildObj in EnumerateChildObjects(obj_parentObjIndex, childObj.ObjNum)) + foreach (Obj grandchildObj in + EnumerateChildObjects(obj_parentObjIndex, childObj.ObjNum, protectionSet)) { yield return grandchildObj; } diff --git a/ScadaCommon/ScadaCommon/ScadaUtils.Collections.cs b/ScadaCommon/ScadaCommon/ScadaUtils.Collections.cs index 9dd16719d..34382377a 100644 --- a/ScadaCommon/ScadaCommon/ScadaUtils.Collections.cs +++ b/ScadaCommon/ScadaCommon/ScadaUtils.Collections.cs @@ -315,7 +315,7 @@ public static bool ParseRange(string s, bool allowEmpty, bool distinct, out ILis public static string ToRangeString(this IEnumerable collection) { if (collection == null) - throw new ArgumentNullException(nameof(collection)); + return ""; List list = new List(collection); list.Sort(); diff --git a/ScadaCommon/ScadaCommon/ScadaUtils.Converter.cs b/ScadaCommon/ScadaCommon/ScadaUtils.Converter.cs index c4d7db20c..ea6124f58 100644 --- a/ScadaCommon/ScadaCommon/ScadaUtils.Converter.cs +++ b/ScadaCommon/ScadaCommon/ScadaUtils.Converter.cs @@ -296,13 +296,29 @@ public static string ToLocalizedString(this DateTime dateTime, CultureInfo cultu /// public static string ToLocalizedDateString(this DateTime dateTime) { - return dateTime.ToString("d", Locale.Culture); + return dateTime.ToLocalizedDateString(Locale.Culture); + } + + /// + /// Converts the specified value to a string representation of the date using the specified culture. + /// + public static string ToLocalizedDateString(this DateTime dateTime, CultureInfo culture) + { + return dateTime.ToString("d", culture); } /// /// Converts the specified value to a string representation of the time using the selected culture. /// public static string ToLocalizedTimeString(this DateTime dateTime) + { + return dateTime.ToLocalizedTimeString(Locale.Culture); + } + + /// + /// Converts the specified value to a string representation of the time using the specified culture. + /// + public static string ToLocalizedTimeString(this DateTime dateTime, CultureInfo culture) { return dateTime.ToString("T", Locale.Culture); } diff --git a/ScadaCommon/ScadaCommon/ScadaUtils.cs b/ScadaCommon/ScadaCommon/ScadaUtils.cs index bf851b2f4..a1515168c 100644 --- a/ScadaCommon/ScadaCommon/ScadaUtils.cs +++ b/ScadaCommon/ScadaCommon/ScadaUtils.cs @@ -20,7 +20,7 @@ * * Author : Mikhail Shiryaev * Created : 2007 - * Modified : 2022 + * Modified : 2023 */ using Scada.Lang; @@ -429,6 +429,23 @@ public static uint CRC32(byte[] buffer, int offset, int length) return crc ^ 0xFFFFFFFF; } + /// + /// Gets the start date of the month for the specified timestamp. + /// + public static DateTime GetMonthStart(this DateTime dateTime) + { + return new DateTime(dateTime.Year, dateTime.Month, 1, 0, 0, 0, dateTime.Kind); + } + + /// + /// Gets the end date of the month for the specified timestamp. + /// + public static DateTime GetMonthEnd(this DateTime dateTime) + { + return new DateTime(dateTime.Year, dateTime.Month, + DateTime.DaysInMonth(dateTime.Year, dateTime.Month), 0, 0, 0, dateTime.Kind); + } + /// /// Returns the larger of two timestamps. /// @@ -487,7 +504,15 @@ public static string BuildErrorMessage(this Exception ex, string text = "", para /// public static string FirstNonEmpty(params string[] args) { - return args.FirstOrDefault(s => !string.IsNullOrEmpty(s)); + return args?.FirstOrDefault(s => !string.IsNullOrEmpty(s)); + } + + /// + /// Returns the first non-empty string result returned by the specified functions. + /// + public static string FirstNonEmpty(params Func[] args) + { + return args?.Select(f => f()).FirstOrDefault(s => !string.IsNullOrEmpty(s)); } /// @@ -508,7 +533,7 @@ public static string GetPreview(this string s, int maxLength) /// public static void RestoreHierarchy(this ITreeNode treeNode) { - if (treeNode.Children != null) + if (treeNode?.Children != null) { foreach (object child in treeNode.Children) { diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AdministratorHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AdministratorHistory.cshtml index 58e4c05e1..aa6cd3b28 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AdministratorHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AdministratorHistory.cshtml @@ -23,6 +23,11 @@

Administrator History

Administrator Application

+
ScadaAdmin 6.1.0.2 (May 15, 2023)
+
    +
  • Instance status form remains responsive if Agent is not available
  • +
+
ScadaAdmin 6.1.0.1 (April 02, 2023)
  • UI fixes
  • @@ -90,6 +95,11 @@

Server Configurator

+
ExtServerConfig 6.0.1.1 (May 15, 2023)
+
    +
  • Fixed module interface initialization
  • +
+
ExtServerConfig 6.0.1.0 (March 21, 2023)
  • Added new application options
  • diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/CommunicatorHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/CommunicatorHistory.cshtml index dae5d6474..cbc384ac1 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/CommunicatorHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/CommunicatorHistory.cshtml @@ -35,6 +35,11 @@

    Communicator History

    Communicator Application

    +
    ScadaComm 6.1.0.1 (May 15, 2023)
    +
      +
    • Fixed waiting for service stop
    • +
    +
    ScadaComm 6.1.0.0 (March 21, 2023)
    • Uses new configuration database and application protocol
    • @@ -171,6 +176,11 @@ @**** DrvModbus ****@

      Modbus

      +
      DrvModbus 6.0.0.3 (May 15, 2023)
      +
        +
      • Supports A...F digits in byte order
      • +
      +
      DrvModbus 6.0.0.2 (March 21, 2023)
      • Fixed channel generation
      • @@ -200,6 +210,11 @@ @**** DrvMqttClient ****@

        MQTT Client

        +
        DrvMqttClient 6.0.0.2 (May 15, 2023)
        +
          +
        • JavaScript execution refactoring
        • +
        +
        DrvMqttClient 6.0.0.1 (January 17, 2023)
        • Updated MQTTnet dependency
        • @@ -268,8 +283,13 @@
        • Porting the driver to the new version
        - @**** Drv ****@ + @**** DrvTelegram ****@

        Telegram

        +
        DrvTelegram 6.0.0.1 (May 15, 2023)
        +
          +
        • Fixed chat ID input
        • +
        +
        DrvTelegram 6.0.0.0 (December 03, 2022)
        • Bot token is stored encrypted
        • diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ScadaHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ScadaHistory.cshtml index 846f4ed02..254963d3e 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ScadaHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ScadaHistory.cshtml @@ -6,6 +6,33 @@

          History of Rapid SCADA

          +
          Rapid SCADA 6.1.2 (May 15, 2023)
          +
            +
          • Server 6.1.0.2
          • +
          • + Communicator 6.1.0.1 +
              +
            • DrvModbus 6.0.0.3
            • +
            • DrvMqttClient 6.0.0.2
            • +
            +
          • +
          • + Webstation 6.1.0.1 +
              +
            • PlgMain 6.0.1.1
            • +
            • PlgScheme 6.0.0.1
            • +
            +
          • +
          • Agent 6.1.0.0
          • +
          • + Administrator 6.1.0.2 +
              +
            • ExtServerConfig 6.0.1.1
            • +
            +
          • +
          • Scheme Editor 5.3.1.1
          • +
          +
          Rapid SCADA 6.1.1 (April 02, 2023)
          • Server 6.1.0.1
          • diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ServerHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ServerHistory.cshtml index 915b5de16..f90d7fcad 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ServerHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ServerHistory.cshtml @@ -24,6 +24,11 @@

            Server History

            Server Application

            +
            ScadaServer 6.1.0.2 (May 15, 2023)
            +
              +
            • Fixed waiting for service stop
            • +
            +
            ScadaServer 6.1.0.1 (April 02, 2023)
            • Fixed reading configuration database
            • @@ -115,6 +120,11 @@ @**** ModAutoControl ****@

              Automatic Control Module

              +
              ModAutoControl 6.0.0.1 (May 15, 2023)
              +
                +
              • Fixed formatting of variable values in commands
              • +
              +
              ModAutoControl 6.0.0.0 (December 03, 2022)
              • Added new variables available in command text
              • diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/WebstationHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/WebstationHistory.cshtml index 0f3ff5b38..cba4b0270 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/WebstationHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/WebstationHistory.cshtml @@ -23,6 +23,11 @@

                Webstation History

                Webstation Application

                +
                ScadaWeb 6.1.0.1 (May 15, 2023)
                +
                  +
                • Autofocus support for modal forms
                • +
                +
                ScadaWeb 6.1.0.0 (March 21, 2023)
                • Support for external users
                • @@ -56,6 +61,11 @@

                Chart Pro

                +
                PlgChartPro 6.0.0.3 (April 27, 2023)
                +
                  +
                • Fixed loading chart for the past period
                • +
                +
                PlgChartPro 6.0.0.2 (April 02, 2023)
                • Fixed zoom button color
                • @@ -82,6 +92,12 @@

                Main Plugin

                +
                PlgMain 6.0.1.1 (May 15, 2023)
                +
                  +
                • Table view styles changed
                • +
                • Autofocus on the command form
                • +
                +
                PlgMain 6.0.1.0 (March 21, 2023)
                • Uses channel command format
                • @@ -98,6 +114,11 @@

                Schemes

                +
                PlgScheme 6.0.0.1 (May 15, 2023)
                +
                  +
                • Fixed scheme component style
                • +
                +
                PlgScheme 6.0.0.0 (December 03, 2022)
                • Scheme is horizontally centered
                • diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/AdministratorHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/AdministratorHistory.cshtml index a16b2559a..5f8f44f29 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/AdministratorHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/AdministratorHistory.cshtml @@ -23,6 +23,11 @@

                  История Администратора

                  Приложение Администратор

                  +
                  ScadaAdmin 6.1.0.2 (15.05.2023)
                  +
                    +
                  • Форма статуса экземпляра сохраняет отзывчивость, если Агент не доступен
                  • +
                  +
                  ScadaAdmin 6.1.0.1 (02.04.2023)
                  • Исправления в пользовательском интерфейсе
                  • @@ -90,6 +95,11 @@

                  Конфигуратор Сервера

                  +
                  ExtServerConfig 6.0.1.1 (15.05.2023)
                  +
                    +
                  • Исправлена инициализация интерфейса модуля
                  • +
                  +
                  ExtServerConfig 6.0.1.0 (21.03.2023)
                  • Добавлены новые параметры приложения
                  • diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/CommunicatorHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/CommunicatorHistory.cshtml index 0672719ec..f20687afd 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/CommunicatorHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/CommunicatorHistory.cshtml @@ -36,6 +36,11 @@

                    История Коммуникатора

                    Приложение Коммуникатор

                    +
                    ScadaComm 6.1.0.1 (15.05.2023)
                    +
                      +
                    • Исправлено ожидание остановки сервиса
                    • +
                    +
                    ScadaComm 6.1.0.0 (21.03.2023)
                    • Использует новую базу конфигурации и протокол приложений
                    • @@ -184,6 +189,11 @@ @**** DrvModbus ****@

                      Modbus

                      +
                      DrvModbus 6.0.0.3 (15.05.2023)
                      +
                        +
                      • Поддержка цифр A...F в порядке байт
                      • +
                      +
                      DrvModbus 6.0.0.2 (21.03.2023)
                      • Исправлена генерация каналов
                      • @@ -213,6 +223,11 @@ @**** DrvMqttClient ****@

                        MQTT-клиент

                        +
                        DrvMqttClient 6.0.0.2 (15.05.2023)
                        +
                          +
                        • Рефакторинг выполнения JavaScript
                        • +
                        +
                        DrvMqttClient 6.0.0.1 (17.01.2023)
                        • Обновлена зависимость MQTTnet
                        • @@ -281,8 +296,13 @@
                        • Портирование драйвера на новую версию
                        - @**** Drv ****@ + @**** DrvTelegram ****@

                        Telegram

                        +
                        DrvTelegram 6.0.0.1 (15.05.2023)
                        +
                          +
                        • Исправлен ввод идентификатора чата
                        • +
                        +
                        DrvTelegram 6.0.0.0 (03.12.2022)
                        • Токен бота сохраняется в зашифрованном виде
                        • diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/ScadaHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/ScadaHistory.cshtml index 3871ba0f8..27395f804 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/ScadaHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/ScadaHistory.cshtml @@ -6,6 +6,33 @@

                          История Rapid SCADA

                          +
                          Rapid SCADA 6.1.2 (15.05.2023)
                          +
                            +
                          • Сервер 6.1.0.2
                          • +
                          • + Коммуникатор 6.1.0.1 +
                              +
                            • DrvModbus 6.0.0.3
                            • +
                            • DrvMqttClient 6.0.0.2
                            • +
                            +
                          • +
                          • + Вебстанция 6.1.0.1 +
                              +
                            • PlgMain 6.0.1.1
                            • +
                            • PlgScheme 6.0.0.1
                            • +
                            +
                          • +
                          • Агент 6.1.0.0
                          • +
                          • + Администратор 6.1.0.2 +
                              +
                            • ExtServerConfig 6.0.1.1
                            • +
                            +
                          • +
                          • Редактор схем 5.3.1.1
                          • +
                          +
                          Rapid SCADA 6.1.1 (02.04.2023)
                          • Сервер 6.1.0.1
                          • diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/ServerHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/ServerHistory.cshtml index 3010d7102..e34d124df 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/ServerHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/ServerHistory.cshtml @@ -24,6 +24,11 @@

                            История Сервера

                            Приложение Сервер

                            +
                            ScadaServer 6.1.0.2 (15.05.2023)
                            +
                              +
                            • Исправлено ожидание остановки сервиса
                            • +
                            +
                            ScadaServer 6.1.0.1 (02.04.2023)
                            • Исправлено считывание базы конфигурации
                            • @@ -115,6 +120,11 @@ @**** ModAutoControl ****@

                              Модуль автоматического управления

                              +
                              ModAutoControl 6.0.0.1 (15.05.2023)
                              +
                                +
                              • Исправлено форматирование значений переменных в командах
                              • +
                              +
                              ModAutoControl 6.0.0.0 (03.12.2022)
                              • Добавлены новые переменные, доступные в тексте команд
                              • diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/WebstationHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/WebstationHistory.cshtml index ad6faf9f2..128078a5f 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/WebstationHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/WebstationHistory.cshtml @@ -23,6 +23,11 @@

                                История Вебстанции

                                Приложение Вебстанция

                                +
                                ScadaWeb 6.1.0.1 (15.05.2023)
                                +
                                  +
                                • Поддержка автофокуса для модальных форм
                                • +
                                +
                                ScadaWeb 6.1.0.0 (21.03.2023)
                                • Поддержка внешних пользователей
                                • @@ -56,6 +61,11 @@

                                Графики Про

                                +
                                PlgChartPro 6.0.0.3 (27.04.2023)
                                +
                                  +
                                • Исправлена загрузка графика за прошедший период
                                • +
                                +
                                PlgChartPro 6.0.0.2 (02.04.2023)
                                • Исправлен цвет кнопки масштаба
                                • @@ -82,6 +92,12 @@

                                Основной плагин

                                +
                                PlgMain 6.0.1.1 (15.05.2023)
                                +
                                  +
                                • Изменены стили табличного представления
                                • +
                                • Автофокус на форме команды
                                • +
                                +
                                PlgMain 6.0.1.0 (21.03.2023)
                                • Использует формат команды канала
                                • @@ -98,6 +114,11 @@

                                Схемы

                                +
                                PlgScheme 6.0.0.1 (15.05.2023)
                                +
                                  +
                                • Исправлен стиль компонентов схемы
                                • +
                                +
                                PlgScheme 6.0.0.0 (03.12.2022)
                                • Схема располагается горизонтально по центру
                                • diff --git a/ScadaReport/ScadaReport/IReportContext.cs b/ScadaReport/ScadaReport/IReportContext.cs index 93211fe4c..75b7beb52 100644 --- a/ScadaReport/ScadaReport/IReportContext.cs +++ b/ScadaReport/ScadaReport/IReportContext.cs @@ -2,7 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Scada.Client; +using Scada.Data.Entities; using Scada.Data.Models; +using Scada.Data.Tables; +using Scada.Lang; using System.Globalization; namespace Scada.Report @@ -38,6 +41,11 @@ public interface IReportContext /// string TemplateDir { get; } + /// + /// Get the path to CSS files for HTML reports. + /// + string CssPath { get; } + /// /// Converts a universal time (UTC) to the time in the report's time zone. @@ -46,5 +54,44 @@ DateTime ConvertTimeFromUtc(DateTime dateTime) { return TimeZoneInfo.ConvertTimeFromUtc(dateTime, TimeZone); } + + /// + /// Finds an archive entity by the first non-empty archive code. + /// Raises an exception if not found. + /// + Archive FindArchive(params string[] archiveCodes) + { + string archiveCode = ScadaUtils.FirstNonEmpty(archiveCodes); + return ConfigDatabase.ArchiveTable.SelectFirst(new TableFilter("Code", archiveCode)) ?? + throw new ScadaException(Locale.IsRussian ? + "Архив не найдён в базе конфигурации." : + "Archive not found in the configuration database.") + { MessageIsPublic = true }; + } + + /// + /// Finds channel entities by the specified channel numbers. + /// If some channel does not exists, adds an empty channel. + /// + List FindChannels(IList cnlNums) + { + if (cnlNums == null) + { + return new List(); + } + else + { + List cnls = new(cnlNums.Count); + + foreach (int cnlNum in cnlNums) + { + cnls.Add( + ConfigDatabase.CnlTable.GetItem(cnlNum) ?? + new Cnl { CnlNum = cnlNum, Name = "" }); + } + + return cnls; + } + } } } diff --git a/ScadaReport/ScadaReport/OutputFormat.cs b/ScadaReport/ScadaReport/OutputFormat.cs index 2df748981..4acbfd66d 100644 --- a/ScadaReport/ScadaReport/OutputFormat.cs +++ b/ScadaReport/ScadaReport/OutputFormat.cs @@ -14,6 +14,7 @@ public enum OutputFormat Default, Pdf, Xml2003, - OpenXml + Xlsx, + Html } } diff --git a/ScadaReport/ScadaReport/RelativeDate.cs b/ScadaReport/ScadaReport/RelativeDate.cs deleted file mode 100644 index c01fc6bc6..000000000 --- a/ScadaReport/ScadaReport/RelativeDate.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Rapid Software LLC. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#pragma warning disable 1591 // Missing XML comment for publicly visible type or member - -namespace Scada.Report -{ - /// - /// Specifies the relative report dates. - /// Задает относительные даты отчёта. - /// - public enum RelativeDate - { - Today, - Yesterday - } -} diff --git a/ScadaReport/ScadaReport/ReportArgs.cs b/ScadaReport/ScadaReport/ReportArgs.cs index fa893a1d9..f44efd732 100644 --- a/ScadaReport/ScadaReport/ReportArgs.cs +++ b/ScadaReport/ScadaReport/ReportArgs.cs @@ -18,6 +18,7 @@ public ReportArgs() { StartTime = DateTime.MinValue; EndTime = DateTime.MinValue; + ArchiveCode = ""; Format = OutputFormat.Default; CustomArgs = new Dictionary(); } @@ -33,6 +34,11 @@ public ReportArgs() /// public DateTime EndTime { get; set; } + /// + /// Gets or sets the archive code. + /// + public string ArchiveCode { get; set; } + /// /// Gets or sets the output format. /// @@ -53,7 +59,8 @@ public virtual void Validate() { throw new ScadaException(Locale.IsRussian ? "Некорректный диапазон времени." : - "Invalid time range.") { MessageIsPublic = true }; + "Invalid time range.") + { MessageIsPublic = true }; } } } diff --git a/ScadaReport/ScadaReport/ReportContext.cs b/ScadaReport/ScadaReport/ReportContext.cs index a3397be92..11d016a78 100644 --- a/ScadaReport/ScadaReport/ReportContext.cs +++ b/ScadaReport/ScadaReport/ReportContext.cs @@ -37,5 +37,10 @@ public class ReportContext : IReportContext /// Gets the directory of templates. /// public string TemplateDir { get; init; } + + /// + /// Get the path to CSS files for HTML reports. + /// + public string CssPath { get; init; } } } diff --git a/ScadaReport/ScadaReport/ReportUtils.cs b/ScadaReport/ScadaReport/ReportUtils.cs index 075c90bcd..486b13127 100644 --- a/ScadaReport/ScadaReport/ReportUtils.cs +++ b/ScadaReport/ScadaReport/ReportUtils.cs @@ -10,45 +10,48 @@ namespace Scada.Report public static class ReportUtils { /// - /// Gets the actual report start date. + /// Gets the report start time as UTC if not specified by a user. /// - public static DateTime GetStartDate(RelativeDate startDate, DateTime currentDate) + public static DateTime GetUtcStartTime(DateTime utcNow, TimeZoneInfo timeZone, PeriodUnit unit) { - return startDate switch - { - RelativeDate.Yesterday => currentDate.AddDays(-1.0).Date, - _ => currentDate.Date, - }; + ArgumentNullException.ThrowIfNull(timeZone, nameof(timeZone)); + DateTime localStartTime = TimeZoneInfo.ConvertTimeFromUtc(utcNow, timeZone); + + localStartTime = unit == PeriodUnit.Month + ? new DateTime(localStartTime.Year, localStartTime.Month, 1, 0, 0, 0, DateTimeKind.Local) + : localStartTime.Date; + + return TimeZoneInfo.ConvertTimeToUtc(localStartTime, timeZone); } /// - /// Normalizes the time range. + /// Normalizes the report time range. /// /// - /// Makes the startDate a left point of the time range, and makes the period positive. + /// Makes the startTime a left point of the time range, and makes the period positive. /// - public static void NormalizeTimeRange(ref DateTime startDate, ref int period, - PeriodUnit unit = PeriodUnit.Day) + public static void NormalizeTimeRange(ref DateTime startTime, ref int period, PeriodUnit unit) { - startDate = startDate > DateTime.MinValue ? startDate.Date : DateTime.Today; + if (startTime == DateTime.MinValue) + throw new ArgumentException("Start time is not specified.", nameof(startTime)); if (unit == PeriodUnit.Month) { if (period < 0) { - startDate = startDate.AddMonths(period).Date; + startTime = startTime.AddMonths(period); period = -period; } } else { // Examples: - // If the period is -1, 0 or 1, it means the single day, the startDate. - // If the period is 2, it means 2 days starting from the startDate. - // If the period is -2, it means 2 days ending with the startDate and including it. + // If the period is -1, 0 or 1, it means the single day, the startTime. + // If the period is 2, it means 2 days starting from the startTime. + // If the period is -2, it means 2 days ending with the startTime and including it. if (period <= -2) { - startDate = startDate.AddDays(period + 1).Date; + startTime = startTime.AddDays(period + 1); period = -period; } else if (period < 1) @@ -59,42 +62,36 @@ public static void NormalizeTimeRange(ref DateTime startDate, ref int period, } /// - /// Normalizes the time range. + /// Normalizes the report time range. /// - public static void NormalizeTimeRange(ref DateTime startDate, ref DateTime endDate, ref int period, - PeriodUnit unit = PeriodUnit.Day) + public static void NormalizeTimeRange(ref DateTime startTime, ref DateTime endTime, ref int period, + PeriodUnit unit) { - bool periodInMonths = unit == PeriodUnit.Month; - - if (startDate > DateTime.MinValue && endDate > DateTime.MinValue) + if (startTime > DateTime.MinValue && endTime > DateTime.MinValue) { - if (endDate < startDate) - endDate = startDate; - period = periodInMonths ? - ((endDate.Year - startDate.Year) * 12) + endDate.Month - startDate.Month : - (int)(endDate - startDate).TotalDays + 1; + if (endTime < startTime) + endTime = startTime; + period = unit == PeriodUnit.Month + ? ((endTime.Year - startTime.Year) * 12) + endTime.Month - startTime.Month + : (int)(endTime - startTime).TotalDays; } - else if (startDate > DateTime.MinValue) + else if (startTime > DateTime.MinValue) { - NormalizeTimeRange(ref startDate, ref period, unit); - endDate = periodInMonths ? - startDate.AddMonths(period) : - startDate.AddDays(period - 1); + NormalizeTimeRange(ref startTime, ref period, unit); + endTime = unit == PeriodUnit.Month + ? startTime.AddMonths(period) + : startTime.AddDays(period); } - else if (endDate > DateTime.MinValue) + else if (endTime > DateTime.MinValue) { - period = Math.Abs(period); - NormalizeTimeRange(ref endDate, ref period, unit); - startDate = periodInMonths ? - endDate.AddMonths(-period) : - endDate.AddDays(-period + 1); + period = Math.Max(Math.Abs(period), 1); + startTime = unit == PeriodUnit.Month + ? endTime.AddMonths(-period) + : endTime.AddDays(-period); } else { - NormalizeTimeRange(ref startDate, ref period, unit); - endDate = periodInMonths ? - startDate.AddMonths(period) : - startDate.AddDays(period - 1); + throw new ArgumentException("Neither start time nor end time is not specified."); } } @@ -117,7 +114,8 @@ public static string GetExtension(this OutputFormat format) { OutputFormat.Pdf => ".pdf", OutputFormat.Xml2003 => ".xml", - OutputFormat.OpenXml => ".xlsx", + OutputFormat.Xlsx => ".xlsx", + OutputFormat.Html => ".html", _ => "" }; } diff --git a/ScadaReport/ScadaReport/ScadaReport.csproj b/ScadaReport/ScadaReport/ScadaReport.csproj index 2201d03b0..d0f541bc4 100644 --- a/ScadaReport/ScadaReport/ScadaReport.csproj +++ b/ScadaReport/ScadaReport/ScadaReport.csproj @@ -6,11 +6,11 @@ disable Scada.Report True - 6.0.0 + 6.1.0 Mikhail Shiryaev Rapid Software LLC Rapid SCADA - Copyright © 2022 + Copyright © 2023 diff --git a/ScadaReport/ScadaReport/Xml2003/Xml2003Renderer.cs b/ScadaReport/ScadaReport/Xml2003/Xml2003Renderer.cs index 424ee79a6..e51ab4c28 100644 --- a/ScadaReport/ScadaReport/Xml2003/Xml2003Renderer.cs +++ b/ScadaReport/ScadaReport/Xml2003/Xml2003Renderer.cs @@ -126,7 +126,7 @@ protected static bool FindDirective(string s, string name, out string val, out s /// - /// Renders a workbook to the output stream. + /// Renders a document to the output stream. /// public virtual void Render(string templateFileName, Stream outStream) { diff --git a/ScadaServer/ScadaServer/ScadaServerApp/ScadaServerApp.csproj b/ScadaServer/ScadaServer/ScadaServerApp/ScadaServerApp.csproj index 862e4599b..3a21cf938 100644 --- a/ScadaServer/ScadaServer/ScadaServerApp/ScadaServerApp.csproj +++ b/ScadaServer/ScadaServer/ScadaServerApp/ScadaServerApp.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.1 + 6.1.0.2 diff --git a/ScadaServer/ScadaServer/ScadaServerEngine/CoreLogic.cs b/ScadaServer/ScadaServer/ScadaServerEngine/CoreLogic.cs index 66fe35daa..5c0f7500f 100644 --- a/ScadaServer/ScadaServer/ScadaServerEngine/CoreLogic.cs +++ b/ScadaServer/ScadaServer/ScadaServerEngine/CoreLogic.cs @@ -1105,7 +1105,7 @@ public void StopProcessing() terminated = true; serviceStatus = ServiceStatus.Terminating; - if (thread.Join(AppConfig.GeneralOptions.StopWait)) + if (thread.Join(TimeSpan.FromSeconds(AppConfig.GeneralOptions.StopWait))) Log.WriteAction(CommonPhrases.LogicStopped); else Log.WriteAction(CommonPhrases.UnableToStopLogic); diff --git a/ScadaServer/ScadaServer/ScadaServerEngine/ScadaServerEngine.csproj b/ScadaServer/ScadaServer/ScadaServerEngine/ScadaServerEngine.csproj index 2c9f3a0e7..95ef1e74d 100644 --- a/ScadaServer/ScadaServer/ScadaServerEngine/ScadaServerEngine.csproj +++ b/ScadaServer/ScadaServer/ScadaServerEngine/ScadaServerEngine.csproj @@ -8,7 +8,7 @@ Mikhail Shiryaev Copyright © 2023 6.1.0 - 6.1.0.1 + 6.1.0.2 diff --git a/ScadaServer/ScadaServer/ScadaServerWkr/ScadaServerWkr.csproj b/ScadaServer/ScadaServer/ScadaServerWkr/ScadaServerWkr.csproj index d3f90ee81..6c3c3eab2 100644 --- a/ScadaServer/ScadaServer/ScadaServerWkr/ScadaServerWkr.csproj +++ b/ScadaServer/ScadaServer/ScadaServerWkr/ScadaServerWkr.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.1 + 6.1.0.2 diff --git a/ScadaWeb/OpenPlugins/PlgChart/PlgChart.csproj b/ScadaWeb/OpenPlugins/PlgChart/PlgChart.csproj index bf3eef9c4..18f593fcf 100644 --- a/ScadaWeb/OpenPlugins/PlgChart/PlgChart.csproj +++ b/ScadaWeb/OpenPlugins/PlgChart/PlgChart.csproj @@ -18,10 +18,6 @@ - - <_ContentIncludedByDefault Remove="wwwroot\plugins\Chart\css\chart.css" /> - - diff --git a/ScadaWeb/OpenPlugins/PlgMain.Common/PlgMain.Common.csproj b/ScadaWeb/OpenPlugins/PlgMain.Common/PlgMain.Common.csproj index 646083893..2cb72488c 100644 --- a/ScadaWeb/OpenPlugins/PlgMain.Common/PlgMain.Common.csproj +++ b/ScadaWeb/OpenPlugins/PlgMain.Common/PlgMain.Common.csproj @@ -10,7 +10,7 @@ Rapid SCADA Copyright © 2023 6.0.1 - 6.0.1.0 + 6.0.1.1 diff --git a/ScadaWeb/OpenPlugins/PlgMain.Report/EventReportArgs.cs b/ScadaWeb/OpenPlugins/PlgMain.Report/EventReportArgs.cs index 963d5beb3..a4436fe82 100644 --- a/ScadaWeb/OpenPlugins/PlgMain.Report/EventReportArgs.cs +++ b/ScadaWeb/OpenPlugins/PlgMain.Report/EventReportArgs.cs @@ -38,10 +38,10 @@ public EventReportArgs(ReportArgs reportArgs) ArgumentNullException.ThrowIfNull(reportArgs, nameof(reportArgs)); StartTime = reportArgs.StartTime; EndTime = reportArgs.EndTime; + ArchiveCode = reportArgs.ArchiveCode; Format = reportArgs.Format; CustomArgs = reportArgs.CustomArgs; - ArchiveCode = CustomArgs.GetValueAsString("ArchiveCode"); TailMode = CustomArgs.GetValueAsBool("TailMode"); EventCount = CustomArgs.GetValueAsInt("EventCount"); EventDepth = CustomArgs.GetValueAsInt("EventDepth"); @@ -54,11 +54,6 @@ public EventReportArgs(ReportArgs reportArgs) } - /// - /// Gets the archive code. - /// - public string ArchiveCode { get; init; } - /// /// Gets a value indicating whether to retrieve only the specified number of recent events. /// The start time and end time are ignored. diff --git a/ScadaWeb/OpenPlugins/PlgMain.Report/EventReportBuilder.cs b/ScadaWeb/OpenPlugins/PlgMain.Report/EventReportBuilder.cs index 371e0e57c..5686312dd 100644 --- a/ScadaWeb/OpenPlugins/PlgMain.Report/EventReportBuilder.cs +++ b/ScadaWeb/OpenPlugins/PlgMain.Report/EventReportBuilder.cs @@ -137,13 +137,7 @@ public void Generate(EventReportArgs args, Stream outStream) reportArgs.Validate(); ArgumentNullException.ThrowIfNull(outStream, nameof(outStream)); - // find archive - string archiveCode = ScadaUtils.FirstNonEmpty(args.ArchiveCode, DefaultArchiveCode); - archiveEntity = ReportContext.ConfigDatabase.ArchiveTable - .SelectFirst(new TableFilter("Code", archiveCode)) ?? - throw new ScadaException(reportDict.ArchiveNotFound); - - // render report + archiveEntity = ReportContext.FindArchive(args.ArchiveCode, DefaultArchiveCode); renderer.Render(templateFilePath, outStream); } diff --git a/ScadaWeb/OpenPlugins/PlgMain.Report/HistDataReportArgs.cs b/ScadaWeb/OpenPlugins/PlgMain.Report/HistDataReportArgs.cs index 240a8a551..cd97e1a8c 100644 --- a/ScadaWeb/OpenPlugins/PlgMain.Report/HistDataReportArgs.cs +++ b/ScadaWeb/OpenPlugins/PlgMain.Report/HistDataReportArgs.cs @@ -32,20 +32,15 @@ public HistDataReportArgs(ReportArgs reportArgs) ArgumentNullException.ThrowIfNull(reportArgs, nameof(reportArgs)); StartTime = reportArgs.StartTime; EndTime = reportArgs.EndTime; + ArchiveCode = reportArgs.ArchiveCode; Format = reportArgs.Format; CustomArgs = reportArgs.CustomArgs; - ArchiveCode = CustomArgs.GetValueAsString("ArchiveCode"); CnlNums = ScadaUtils.ParseRange(CustomArgs.GetValueAsString("CnlNums"), true, true); MaxPeriod = 0; } - /// - /// Gets the archive code. - /// - public string ArchiveCode { get; init; } - /// /// Gets the channel numbers. /// diff --git a/ScadaWeb/OpenPlugins/PlgMain.Report/HistDataReportBuilder.cs b/ScadaWeb/OpenPlugins/PlgMain.Report/HistDataReportBuilder.cs index 86d039008..6f309b01f 100644 --- a/ScadaWeb/OpenPlugins/PlgMain.Report/HistDataReportBuilder.cs +++ b/ScadaWeb/OpenPlugins/PlgMain.Report/HistDataReportBuilder.cs @@ -248,21 +248,9 @@ public void Generate(HistDataReportArgs args, Stream outStream) reportArgs.Validate(); ArgumentNullException.ThrowIfNull(outStream, nameof(outStream)); - // find archive - string archiveCode = ScadaUtils.FirstNonEmpty(args.ArchiveCode, DefaultArchiveCode); - archiveEntity = ReportContext.ConfigDatabase.ArchiveTable - .SelectFirst(new TableFilter("Code", archiveCode)) ?? - throw new ScadaException(reportDict.ArchiveNotFound); - - // find channels - cnls = new List(reportArgs.CnlNums.Count); - - foreach (int cnlNum in reportArgs.CnlNums) - { - cnls.Add( - ReportContext.ConfigDatabase.CnlTable.GetItem(cnlNum) ?? - new Cnl { CnlNum = cnlNum, Name = "" }); - } + // find entities + archiveEntity = ReportContext.FindArchive(args.ArchiveCode, DefaultArchiveCode); + cnls = ReportContext.FindChannels(reportArgs.CnlNums); // render report renderer.Render(templateFilePath, outStream); diff --git a/ScadaWeb/OpenPlugins/PlgMain.Report/PlgMain.Report.csproj b/ScadaWeb/OpenPlugins/PlgMain.Report/PlgMain.Report.csproj index 2726398c1..19e8b5099 100644 --- a/ScadaWeb/OpenPlugins/PlgMain.Report/PlgMain.Report.csproj +++ b/ScadaWeb/OpenPlugins/PlgMain.Report/PlgMain.Report.csproj @@ -10,7 +10,7 @@ Rapid SCADA Copyright © 2023 6.0.1 - 6.0.1.0 + 6.0.1.1 diff --git a/ScadaWeb/OpenPlugins/PlgMain.Report/TableViewReportBuilder.cs b/ScadaWeb/OpenPlugins/PlgMain.Report/TableViewReportBuilder.cs index ce6d617b7..e99648e55 100644 --- a/ScadaWeb/OpenPlugins/PlgMain.Report/TableViewReportBuilder.cs +++ b/ScadaWeb/OpenPlugins/PlgMain.Report/TableViewReportBuilder.cs @@ -170,12 +170,7 @@ public void Generate(TableViewReportArgs args, Stream outStream) reportArgs.Validate(); ArgumentNullException.ThrowIfNull(outStream, nameof(outStream)); - // find archive - archiveEntity = ReportContext.ConfigDatabase.ArchiveTable - .SelectFirst(new TableFilter("Code", args.TableOptions.ArchiveCode)) ?? - throw new ScadaException(reportDict.ArchiveNotFound); - - // render report + archiveEntity = ReportContext.FindArchive(args.TableOptions.ArchiveCode); renderer.Render(templateFilePath, outStream); } diff --git a/ScadaWeb/OpenPlugins/PlgMain.View/PlgMain.View.csproj b/ScadaWeb/OpenPlugins/PlgMain.View/PlgMain.View.csproj index 501fd54f3..0c2ec3887 100644 --- a/ScadaWeb/OpenPlugins/PlgMain.View/PlgMain.View.csproj +++ b/ScadaWeb/OpenPlugins/PlgMain.View/PlgMain.View.csproj @@ -10,7 +10,7 @@ Rapid SCADA Copyright © 2023 6.0.1 - 6.0.1.0 + 6.0.1.1 diff --git a/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/Command.cshtml b/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/Command.cshtml index a57e9be5e..79d1a7a02 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/Command.cshtml +++ b/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/Command.cshtml @@ -59,7 +59,7 @@ {
                                  - +
                                  } @@ -67,14 +67,14 @@ {
                                  - +
                                  } else if (Model.Input == CommandModel.InputType.Hex) {
                                  - +
                                  } else if (Model.Input == CommandModel.InputType.Enum) @@ -105,7 +105,7 @@
                                  - +
                                  } else if (Model.Input == CommandModel.InputType.Str) @@ -120,7 +120,7 @@
                                - +
                                @Model.Format.Descr
                            } diff --git a/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/HistDataReport.cshtml.cs b/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/HistDataReport.cshtml.cs index 342538d70..259d2f1f4 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/HistDataReport.cshtml.cs +++ b/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/HistDataReport.cshtml.cs @@ -27,7 +27,7 @@ public HistDataReportModel(IWebContext webContext, IUserContext userContext) public DateTime StartTime { get; private set; } public DateTime EndTime { get; private set; } - public List ArchiveList { get; private set; } = new(); + public List ArchiveList { get; } = new(); private void FillArchiveList() diff --git a/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/TableView.cshtml.cs b/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/TableView.cshtml.cs index 99be0aaef..38122842e 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/TableView.cshtml.cs +++ b/ScadaWeb/OpenPlugins/PlgMain/Areas/Main/Pages/TableView.cshtml.cs @@ -283,8 +283,9 @@ public HtmlString RenderTableView() AddTooltipHtml(sbHtml, tableItem.CnlNum, itemCnl); sbHtml - .Append("' />") - .Append("").Append(itemText).Append(""); + .Append("' />") + .Append(itemText).Append(""); if (enableCommands && itemCnl != null && itemCnl.IsOutput()) { @@ -295,7 +296,7 @@ public HtmlString RenderTableView() } else { - sbHtml.Append("").Append(itemText).Append(""); + sbHtml.Append("").Append(itemText).Append(""); } sbHtml.AppendLine("
                    "); // close first cell diff --git a/ScadaWeb/OpenPlugins/PlgMain/Controllers/MainApiController.cs b/ScadaWeb/OpenPlugins/PlgMain/Controllers/MainApiController.cs index 845220546..068474ac9 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/Controllers/MainApiController.cs +++ b/ScadaWeb/OpenPlugins/PlgMain/Controllers/MainApiController.cs @@ -63,9 +63,7 @@ private void CheckAccessRights(IntRange cnlNums) foreach (int cnlNum in cnlNums) { - Cnl cnl = webContext.ConfigDatabase.CnlTable.GetItem(cnlNum); - - if (cnl == null) + Cnl cnl = webContext.ConfigDatabase.CnlTable.GetItem(cnlNum) ?? throw new AccessDeniedException(); // no rights on undefined channel if (!userContext.Rights.GetRightByObj(cnl.ObjNum).View) diff --git a/ScadaWeb/OpenPlugins/PlgMain/Controllers/PrintController.cs b/ScadaWeb/OpenPlugins/PlgMain/Controllers/PrintController.cs index 77d299a7a..77e7224ea 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/Controllers/PrintController.cs +++ b/ScadaWeb/OpenPlugins/PlgMain/Controllers/PrintController.cs @@ -70,7 +70,7 @@ private IReportContext CreateReportContext() /// /// Generates an event report with the specified arguments. /// - private Stream GenerateEventReport(EventReportArgs args, out DateTime generateTime) + private Stream GenerateEventReport(EventReportArgs args, out string fileName) { MemoryStream stream = new(); @@ -78,7 +78,7 @@ private Stream GenerateEventReport(EventReportArgs args, out DateTime generateTi { EventReportBuilder builder = new(CreateReportContext()); builder.Generate(args, stream); - generateTime = builder.GenerateTime; + fileName = ReportUtils.BuildFileName(EventReportPrefix, builder.GenerateTime, OutputFormat.Xml2003); stream.Position = 0; } catch @@ -126,7 +126,7 @@ public IActionResult PrintTableView(int viewID, DateTime startTime, DateTime end throw new ScadaException(errMsg); MemoryStream stream = new(); - DateTime generateTime; + string fileName; try { @@ -140,7 +140,8 @@ public IActionResult PrintTableView(int viewID, DateTime startTime, DateTime end MaxPeriod = pluginContext.Options.MaxReportPeriod }, stream); - generateTime = builder.GenerateTime; + fileName = ReportUtils.BuildFileName(TableViewReportPrefix, + builder.GenerateTime, OutputFormat.Xml2003); stream.Position = 0; } catch @@ -149,10 +150,7 @@ public IActionResult PrintTableView(int viewID, DateTime startTime, DateTime end throw; } - return File( - stream, - MediaTypeNames.Application.Octet, - ReportUtils.BuildFileName(TableViewReportPrefix, generateTime, OutputFormat.Xml2003)); + return File(stream, MediaTypeNames.Application.Octet, fileName); } /// @@ -173,9 +171,9 @@ public IActionResult PrintEventsByView(int viewID) }; return File( - GenerateEventReport(args, out DateTime generateTime), + GenerateEventReport(args, out string fileName), MediaTypeNames.Application.Octet, - ReportUtils.BuildFileName(EventReportPrefix, generateTime, OutputFormat.Xml2003)); + fileName); } /// @@ -193,9 +191,9 @@ public IActionResult PrintAllEvents() }; return File( - GenerateEventReport(args, out DateTime generateTime), + GenerateEventReport(args, out string fileName), MediaTypeNames.Application.Octet, - ReportUtils.BuildFileName(EventReportPrefix, generateTime, OutputFormat.Xml2003)); + fileName); } /// @@ -234,9 +232,9 @@ public IActionResult PrintEventReport(DateTime startTime, DateTime endTime, }; return File( - GenerateEventReport(args, out DateTime generateTime), + GenerateEventReport(args, out string fileName), MediaTypeNames.Application.Octet, - ReportUtils.BuildFileName(EventReportPrefix, generateTime, OutputFormat.Xml2003)); + fileName); } /// @@ -246,7 +244,7 @@ public IActionResult PrintHistDataReport(DateTime startTime, DateTime endTime, string archive, IntRange cnlNums) { MemoryStream stream = new(); - DateTime generateTime; + string fileName; try { @@ -260,7 +258,7 @@ public IActionResult PrintHistDataReport(DateTime startTime, DateTime endTime, MaxPeriod = pluginContext.Options.MaxReportPeriod }, stream); - generateTime = builder.GenerateTime; + fileName = ReportUtils.BuildFileName(HistDataReportPrefix, builder.GenerateTime, OutputFormat.Xml2003); stream.Position = 0; } catch @@ -269,10 +267,7 @@ public IActionResult PrintHistDataReport(DateTime startTime, DateTime endTime, throw; } - return File( - stream, - MediaTypeNames.Application.Octet, - ReportUtils.BuildFileName(HistDataReportPrefix, generateTime, OutputFormat.Xml2003)); + return File(stream, MediaTypeNames.Application.Octet, fileName); } } } diff --git a/ScadaWeb/OpenPlugins/PlgMain/PlgMain.csproj b/ScadaWeb/OpenPlugins/PlgMain/PlgMain.csproj index 571ca202e..a529417f4 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/PlgMain.csproj +++ b/ScadaWeb/OpenPlugins/PlgMain/PlgMain.csproj @@ -11,22 +11,13 @@ Rapid SCADA Copyright © 2023 6.0.1 - 6.0.1.0 + 6.0.1.1 - - <_ContentIncludedByDefault Remove="wwwroot\plugins\Main\css\command.css" /> - - - - - - - diff --git a/ScadaWeb/OpenPlugins/PlgMain/lang/PlgMain.en-GB.xml b/ScadaWeb/OpenPlugins/PlgMain/lang/PlgMain.en-GB.xml index 4ec82fc37..b76ca1ce2 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/lang/PlgMain.en-GB.xml +++ b/ScadaWeb/OpenPlugins/PlgMain/lang/PlgMain.en-GB.xml @@ -99,7 +99,6 @@ Event report - Archive not found in the configuration database. Generated: Time zone: Archive: diff --git a/ScadaWeb/OpenPlugins/PlgMain/lang/PlgMain.ru-RU.xml b/ScadaWeb/OpenPlugins/PlgMain/lang/PlgMain.ru-RU.xml index 03a1caf88..a23f3cea0 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/lang/PlgMain.ru-RU.xml +++ b/ScadaWeb/OpenPlugins/PlgMain/lang/PlgMain.ru-RU.xml @@ -99,7 +99,6 @@ Отчёт по событиям - Архив не найдён в базе конфигурации. Получено: Часовой пояс: Архив: diff --git a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.css b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.css index ac14dff02..6a20e5bfd 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.css +++ b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.css @@ -14,8 +14,7 @@ .toolbar select { height: 24px; line-height: normal; - border: 1px solid #6c757d; - /*required for correct height*/ + border: 1px solid #6c757d; /*required for correct height*/ border-radius: 3px; } .toolbar .toolbar-group { @@ -50,8 +49,7 @@ } .table-main { - border-collapse: separate; - /*required for header stickiness*/ + border-collapse: separate; /*required for header stickiness*/ border-spacing: 0; border-left: 1px solid #6c757d; border-top: 1px solid #6c757d; @@ -80,8 +78,7 @@ font-weight: 600; padding: 2px 5px; position: sticky; - top: 0; - /*required for header stickiness*/ + top: 0; /*required for header stickiness*/ z-index: 1; } @@ -102,6 +99,10 @@ .table-main .item > span { display: table-cell; } +.table-main .item-hdr { + color: #495057; + font-weight: 600; +} .table-main .item-icon { width: 16px; min-width: 16px; @@ -113,10 +114,10 @@ top: -2px; } .table-main .item-text { + color: #0073aa; padding: 0 5px; } .table-main .item-link { - color: #0073aa; cursor: pointer; } .table-main .item-cmd { diff --git a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.min.css b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.min.css index fc1ba3a4a..32a0a5995 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.min.css +++ b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.min.css @@ -1 +1 @@ -body{background-color:#f8f9fa;color:#212529;}.toolbar{height:30px;line-height:30px;font-size:14px;padding:0 10px;white-space:nowrap;}.toolbar input,.toolbar select{height:24px;line-height:normal;border:1px solid #6c757d;border-radius:3px;}.toolbar .toolbar-group{margin-right:10px;}.toolbar .tool-btn{background-color:#fff;color:#495057;cursor:pointer;display:inline-block;margin-right:5px;padding:0 10px;white-space:nowrap;}.toolbar .tool-btn.selected{background-color:#0073aa;color:#fff;}.toolbar .tool-btn.selected:hover{color:#fff;}.toolbar .tool-btn:hover{color:#00b9eb;}.toolbar .badge{margin-right:5px;}.table-wrapper{padding:0 10px;overflow:auto;}.table-main{border-collapse:separate;border-spacing:0;border-left:1px solid #6c757d;border-top:1px solid #6c757d;}.table-main tr:nth-child(even){background-color:#f8f9fa;}.table-main tr:nth-child(odd){background-color:#fff;}.table-main tr:hover{background-color:#dee2e6;}.table-main th,.table-main td{border-bottom:1px solid #6c757d;border-right:1px solid #6c757d;font-size:.8rem;padding:2px 3px;text-align:center;vertical-align:middle;white-space:nowrap;}.table-main th{background-color:#ccc;font-weight:600;padding:2px 5px;position:sticky;top:0;z-index:1;}.table-main.hide-date span.hdr-date{display:none;}.table-main td:first-child{padding:2px 5px;text-align:left;}.table-main th.hid,.table-main td.hid{display:none;}.table-main .item{display:table;width:100%;}.table-main .item>span{display:table-cell;}.table-main .item-icon{width:16px;min-width:16px;}.table-main .item-icon img{width:16px;height:16px;position:relative;top:-2px;}.table-main .item-text{padding:0 5px;}.table-main .item-link{color:#0073aa;cursor:pointer;}.table-main .item-cmd{color:#a00;cursor:pointer;width:20px;min-width:20px;text-align:right;}.table-main .item-cmd:hover{color:#f00;}.tooltip-inner{max-width:500px;text-align:left;white-space:nowrap;} \ No newline at end of file +body{background-color:#f8f9fa;color:#212529;}.toolbar{height:30px;line-height:30px;font-size:14px;padding:0 10px;white-space:nowrap;}.toolbar input,.toolbar select{height:24px;line-height:normal;border:1px solid #6c757d;border-radius:3px;}.toolbar .toolbar-group{margin-right:10px;}.toolbar .tool-btn{background-color:#fff;color:#495057;cursor:pointer;display:inline-block;margin-right:5px;padding:0 10px;white-space:nowrap;}.toolbar .tool-btn.selected{background-color:#0073aa;color:#fff;}.toolbar .tool-btn.selected:hover{color:#fff;}.toolbar .tool-btn:hover{color:#00b9eb;}.toolbar .badge{margin-right:5px;}.table-wrapper{padding:0 10px;overflow:auto;}.table-main{border-collapse:separate;border-spacing:0;border-left:1px solid #6c757d;border-top:1px solid #6c757d;}.table-main tr:nth-child(even){background-color:#f8f9fa;}.table-main tr:nth-child(odd){background-color:#fff;}.table-main tr:hover{background-color:#dee2e6;}.table-main th,.table-main td{border-bottom:1px solid #6c757d;border-right:1px solid #6c757d;font-size:.8rem;padding:2px 3px;text-align:center;vertical-align:middle;white-space:nowrap;}.table-main th{background-color:#ccc;font-weight:600;padding:2px 5px;position:sticky;top:0;z-index:1;}.table-main.hide-date span.hdr-date{display:none;}.table-main td:first-child{padding:2px 5px;text-align:left;}.table-main th.hid,.table-main td.hid{display:none;}.table-main .item{display:table;width:100%;}.table-main .item>span{display:table-cell;}.table-main .item-hdr{color:#495057;font-weight:600;}.table-main .item-icon{width:16px;min-width:16px;}.table-main .item-icon img{width:16px;height:16px;position:relative;top:-2px;}.table-main .item-text{color:#0073aa;padding:0 5px;}.table-main .item-link{cursor:pointer;}.table-main .item-cmd{color:#a00;cursor:pointer;width:20px;min-width:20px;text-align:right;}.table-main .item-cmd:hover{color:#f00;}.tooltip-inner{max-width:500px;text-align:left;white-space:nowrap;} \ No newline at end of file diff --git a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.scss b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.scss index 6306f23f8..1775c157f 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.scss +++ b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/css/table-view.scss @@ -1,5 +1,6 @@ @import '_table-common'; +$item-hdr-color: $gray-700; $cmd-btn-color: #a00; $cmd-btn-hover-color: red; @@ -28,6 +29,11 @@ $cmd-btn-hover-color: red; } } + .item-hdr { + color: $item-hdr-color; + font-weight: 600; + } + .item-icon { width: 16px; min-width: 16px; @@ -41,11 +47,11 @@ $cmd-btn-hover-color: red; } .item-text { + color: $link-fore-color; padding: 0 5px; } .item-link { - color: $link-fore-color; cursor: pointer; } diff --git a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/js/events.js b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/js/events.js index 6b1620e08..411f326c0 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/js/events.js +++ b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/js/events.js @@ -29,6 +29,7 @@ class Severity { } const ALL_EVENTS_KEY = "Events.AllEvents"; +const START_DELAY = 550; // ms const POSTPONE_SCROLL_PERIOD = 10000; // ms var allEvents = false; @@ -303,5 +304,5 @@ $(document).ready(function () { bindEvents(); updateLayout(); showMessage(phrases.Loading); - startUpdatingEvents(); + setTimeout(startUpdatingEvents, START_DELAY); // wait for loading view in cache }); diff --git a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/js/table-view.js b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/js/table-view.js index 5f929c154..fa8849c9a 100644 --- a/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/js/table-view.js +++ b/ScadaWeb/OpenPlugins/PlgMain/wwwroot/plugins/Main/js/table-view.js @@ -29,7 +29,7 @@ const START_TIME_KEY = "TableView.StartTime"; const END_TIME_KEY = "TableView.EndTime"; const DEFAULT_CELL_COLOR = "Black"; const NEXT_TIME_SYMBOL = "*"; -const UPDATE_HIST_DATA_OFFSET = 500; //ms +const UPDATE_HIST_DATA_OFFSET = 500; // ms var localDate = ""; var timeRange = null; diff --git a/ScadaWeb/OpenPlugins/PlgScheme.Common/PlgScheme.Common.csproj b/ScadaWeb/OpenPlugins/PlgScheme.Common/PlgScheme.Common.csproj index 9eca7b6f5..ffee49da5 100644 --- a/ScadaWeb/OpenPlugins/PlgScheme.Common/PlgScheme.Common.csproj +++ b/ScadaWeb/OpenPlugins/PlgScheme.Common/PlgScheme.Common.csproj @@ -4,11 +4,12 @@ net6.0 Scada.Web.Plugins.PlgScheme True - 6.0.0 Mikhail Shiryaev Rapid Software LLC Rapid SCADA - Copyright © 2022 + Copyright © 2023 + 6.0.0 + 6.0.0.1 diff --git a/ScadaWeb/OpenPlugins/PlgScheme.View/PlgScheme.View.csproj b/ScadaWeb/OpenPlugins/PlgScheme.View/PlgScheme.View.csproj index 9d542805d..8a020e1b1 100644 --- a/ScadaWeb/OpenPlugins/PlgScheme.View/PlgScheme.View.csproj +++ b/ScadaWeb/OpenPlugins/PlgScheme.View/PlgScheme.View.csproj @@ -5,11 +5,12 @@ enable disable Scada.Web.Plugins.PlgScheme.View - 6.0.0 Mikhail Shiryaev Rapid Software LLC Rapid SCADA - Copyright © 2022 + Copyright © 2023 + 6.0.0 + 6.0.0.1 diff --git a/ScadaWeb/OpenPlugins/PlgScheme/PlgScheme.csproj b/ScadaWeb/OpenPlugins/PlgScheme/PlgScheme.csproj index a02bd67d6..1ad9c7254 100644 --- a/ScadaWeb/OpenPlugins/PlgScheme/PlgScheme.csproj +++ b/ScadaWeb/OpenPlugins/PlgScheme/PlgScheme.csproj @@ -4,11 +4,12 @@ net6.0 true Scada.Web.Plugins.PlgScheme - 6.0.0 Mikhail Shiryaev Rapid Software LLC Rapid SCADA - Copyright © 2022 + Copyright © 2023 + 6.0.0 + 6.0.0.1 diff --git a/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/_scheme.scss b/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/_scheme.scss index 2f02782af..817a20080 100644 --- a/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/_scheme.scss +++ b/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/_scheme.scss @@ -25,6 +25,7 @@ $cmd-frame-border-color: #999; .comp { box-sizing: border-box; + line-height: normal; position: absolute; &.action { diff --git a/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/scheme-view.css b/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/scheme-view.css index 1722a3265..9a0290eda 100644 --- a/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/scheme-view.css +++ b/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/scheme-view.css @@ -1,7 +1,6 @@ .scheme-wrapper { overflow: auto; - position: relative; - /*affects scrolling and scaling*/ + position: relative; /*affects scrolling and scaling*/ } .scheme-wrapper.loading { @@ -12,13 +11,12 @@ } .scheme { - position: absolute; - /*affects scaling*/ - transform-origin: left top; - /*affects scaling*/ + position: absolute; /*affects scaling*/ + transform-origin: left top; /*affects scaling*/ } .scheme .comp { box-sizing: border-box; + line-height: normal; position: absolute; } .scheme .comp.action { @@ -115,8 +113,7 @@ body { /* Debug tools */ #divDebugTools { padding: 0 10px; - display: none; - /*inline-block*/ + display: none; /*inline-block*/ font-size: 12px; vertical-align: top; } diff --git a/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/scheme-view.min.css b/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/scheme-view.min.css index f58f2eecd..138109bd5 100644 --- a/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/scheme-view.min.css +++ b/ScadaWeb/OpenPlugins/PlgScheme/wwwroot/plugins/Scheme/css/scheme-view.min.css @@ -1 +1 @@ -.scheme-wrapper{overflow:auto;position:relative;}.scheme-wrapper.loading{background-image:url("../images/loading.gif");background-position:center;background-repeat:no-repeat;background-attachment:fixed;}.scheme{position:absolute;transform-origin:left top;}.scheme .comp{box-sizing:border-box;position:absolute;}.scheme .comp.action{cursor:pointer;}.scheme .cmd-frame{background-image:url("../images/loading.gif");background-position:center;background-repeat:no-repeat;width:100px;height:50px;left:50%;top:50%;position:fixed;transform:translate(-50%,-50%);background-color:#fff;background-size:40px 40px;border:1px solid #999;border-radius:6px;}body{margin:0;padding:0;background-color:#f1f1f1;overflow:hidden;}#divNotif{position:fixed;top:0;left:0;max-height:100px;padding:10px;background-color:#fff;border-bottom:1px solid #ced4da;font-size:12px;overflow:auto;white-space:nowrap;}#divNotif .message{color:#0073aa;}#divNotif .message.error{color:#f00;}#divToolbar{position:fixed;height:30px;line-height:30px;font-size:14px;left:0;top:0;color:#9ca1a6;display:inline-block;font-size:14px;white-space:nowrap;}#divToolbar:hover span{opacity:1;}#divToolbar .tool-btn{height:30px;margin:0 5px 0 0;padding:0 10px;cursor:pointer;background-color:#fff;display:inline-block;line-height:30px;vertical-align:top;opacity:.5;}#divToolbar .tool-btn:hover{color:#00b9eb;}#spanCurScale{height:30px;margin:0 5px 0 0;padding:0 10px;cursor:pointer;background-color:#fff;display:inline-block;line-height:30px;vertical-align:top;opacity:.5;cursor:default;font-size:12px;}#divDebugTools{padding:0 10px;display:none;font-size:12px;vertical-align:top;}#divSchWrapper{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:12px;} \ No newline at end of file +.scheme-wrapper{overflow:auto;position:relative;}.scheme-wrapper.loading{background-image:url("../images/loading.gif");background-position:center;background-repeat:no-repeat;background-attachment:fixed;}.scheme{position:absolute;transform-origin:left top;}.scheme .comp{box-sizing:border-box;line-height:normal;position:absolute;}.scheme .comp.action{cursor:pointer;}.scheme .cmd-frame{background-image:url("../images/loading.gif");background-position:center;background-repeat:no-repeat;width:100px;height:50px;left:50%;top:50%;position:fixed;transform:translate(-50%,-50%);background-color:#fff;background-size:40px 40px;border:1px solid #999;border-radius:6px;}body{margin:0;padding:0;background-color:#f1f1f1;overflow:hidden;}#divNotif{position:fixed;top:0;left:0;max-height:100px;padding:10px;background-color:#fff;border-bottom:1px solid #ced4da;font-size:12px;overflow:auto;white-space:nowrap;}#divNotif .message{color:#0073aa;}#divNotif .message.error{color:#f00;}#divToolbar{position:fixed;height:30px;line-height:30px;font-size:14px;left:0;top:0;color:#9ca1a6;display:inline-block;font-size:14px;white-space:nowrap;}#divToolbar:hover span{opacity:1;}#divToolbar .tool-btn{height:30px;margin:0 5px 0 0;padding:0 10px;cursor:pointer;background-color:#fff;display:inline-block;line-height:30px;vertical-align:top;opacity:.5;}#divToolbar .tool-btn:hover{color:#00b9eb;}#spanCurScale{height:30px;margin:0 5px 0 0;padding:0 10px;cursor:pointer;background-color:#fff;display:inline-block;line-height:30px;vertical-align:top;opacity:.5;cursor:default;font-size:12px;}#divDebugTools{padding:0 10px;display:none;font-size:12px;vertical-align:top;}#divSchWrapper{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:12px;} \ No newline at end of file diff --git a/ScadaWeb/ScadaWeb/ScadaWeb/ScadaWeb.csproj b/ScadaWeb/ScadaWeb/ScadaWeb/ScadaWeb.csproj index 33d28b1d8..77e984df7 100644 --- a/ScadaWeb/ScadaWeb/ScadaWeb/ScadaWeb.csproj +++ b/ScadaWeb/ScadaWeb/ScadaWeb/ScadaWeb.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1 diff --git a/ScadaWeb/ScadaWeb/ScadaWeb/Startup.cs b/ScadaWeb/ScadaWeb/ScadaWeb/Startup.cs index 40c7cef0b..6005e968b 100644 --- a/ScadaWeb/ScadaWeb/ScadaWeb/Startup.cs +++ b/ScadaWeb/ScadaWeb/ScadaWeb/Startup.cs @@ -20,7 +20,7 @@ * * Author : Mikhail Shiryaev * Created : 2021 - * Modified : 2022 + * Modified : 2023 */ using Microsoft.AspNetCore.Authentication.Cookies; @@ -108,12 +108,13 @@ public void ConfigureServices(IServiceCollection services) services .AddRazorPages(options => { - options.Conventions.AuthorizeFolder(WebPath.Root); - options.Conventions.AllowAnonymousToPage(WebPath.ConfigReloadPage); - options.Conventions.AllowAnonymousToPage(WebPath.ErrorPage); - options.Conventions.AllowAnonymousToPage(WebPath.IndexPage); - options.Conventions.AllowAnonymousToPage(WebPath.LoginPage); - options.Conventions.AllowAnonymousToPage(WebPath.LogoutPage); + options.Conventions + .AuthorizeFolder(WebPath.Root) + .AllowAnonymousToPage(WebPath.ConfigReloadPage) + .AllowAnonymousToPage(WebPath.ErrorPage) + .AllowAnonymousToPage(WebPath.IndexPage) + .AllowAnonymousToPage(WebPath.LoginPage) + .AllowAnonymousToPage(WebPath.LogoutPage); }) .AddMvcOptions(options => { diff --git a/ScadaWeb/ScadaWeb/ScadaWeb/wwwroot/js/components/modal.js b/ScadaWeb/ScadaWeb/ScadaWeb/wwwroot/js/components/modal.js index be2e056ec..378dd7e21 100644 --- a/ScadaWeb/ScadaWeb/ScadaWeb/wwwroot/js/components/modal.js +++ b/ScadaWeb/ScadaWeb/ScadaWeb/wwwroot/js/components/modal.js @@ -221,15 +221,23 @@ class ModalManager { // bind events to the modal modalElem .on('shown.bs.modal', function () { - // update the modal height let frameWnd = ModalManager._getModalWnd(modalElem); - if (ScadaUtils.checkAccessToFrame(frameWnd, true) && !options.height) { + let frameAccessible = ScadaUtils.checkAccessToFrame(frameWnd, true); + + // update the modal height + if (frameAccessible && !options.height) { // html height can be greater than body height because of element margins modalFrame.css("height", frameWnd.$("html").height()); } + // set input focus + let autofocusElem = frameAccessible + ? frameWnd.$(frameWnd.document).find("[autofocus]").add(modalFrame).first() + : modalFrame; + autofocusElem.trigger("focus"); + + // remove overlay to allow user activity tempOverlay.remove(); - modalFrame.focus(); }) .on('hidden.bs.modal', function () { let callback = $(this).data("rs-callback"); diff --git a/ScadaWeb/ScadaWeb/ScadaWebCommon.Subset/ScadaWebCommon.Subset.csproj b/ScadaWeb/ScadaWeb/ScadaWebCommon.Subset/ScadaWebCommon.Subset.csproj index f92f9341e..2862b4e37 100644 --- a/ScadaWeb/ScadaWeb/ScadaWebCommon.Subset/ScadaWebCommon.Subset.csproj +++ b/ScadaWeb/ScadaWeb/ScadaWebCommon.Subset/ScadaWebCommon.Subset.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1 diff --git a/ScadaWeb/ScadaWeb/ScadaWebCommon/ScadaWebCommon.csproj b/ScadaWeb/ScadaWeb/ScadaWebCommon/ScadaWebCommon.csproj index 6f8a66f0e..93d854ff1 100644 --- a/ScadaWeb/ScadaWeb/ScadaWebCommon/ScadaWebCommon.csproj +++ b/ScadaWeb/ScadaWeb/ScadaWebCommon/ScadaWebCommon.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1