Added normalization for date dimensions in SqlDashboardStorage to ensure consistent grouping for "AddedWhen" and "ChangedWhen" fields. Refactored CatalogsGrid.razor to use custom sort icons and default DxGrid filter row UI, simplifying markup and improving visual consistency. Updated related CSS for sortable headers and filter inputs.
133 lines
5.5 KiB
C#
133 lines
5.5 KiB
C#
using System.Data;
|
|
using System.Text;
|
|
using System.Xml.Linq;
|
|
using DevExpress.DashboardWeb;
|
|
using Microsoft.Data.SqlClient;
|
|
|
|
namespace DbFirst.API.Dashboards;
|
|
|
|
public sealed class SqlDashboardStorage : IEditableDashboardStorage
|
|
{
|
|
private readonly string _connectionString;
|
|
private readonly string _tableName;
|
|
private readonly Func<string?>? _userProvider;
|
|
|
|
public SqlDashboardStorage(string connectionString, string tableName = "TBDD_SMF_CONFIG", Func<string?>? userProvider = null)
|
|
{
|
|
_connectionString = connectionString;
|
|
_tableName = tableName;
|
|
_userProvider = userProvider;
|
|
}
|
|
|
|
public IEnumerable<DashboardInfo> GetAvailableDashboardsInfo()
|
|
{
|
|
var dashboards = new List<DashboardInfo>();
|
|
|
|
using var connection = new SqlConnection(_connectionString);
|
|
using var command = new SqlCommand($"SELECT DashboardId, DashboardName FROM dbo.[{_tableName}] WHERE ACTIVE = 1 ORDER BY DashboardName", connection);
|
|
|
|
connection.Open();
|
|
using var reader = command.ExecuteReader();
|
|
while (reader.Read())
|
|
{
|
|
var id = reader.GetString(0);
|
|
var name = reader.GetString(1);
|
|
dashboards.Add(new DashboardInfo { ID = id, Name = name });
|
|
}
|
|
|
|
return dashboards;
|
|
}
|
|
|
|
public XDocument LoadDashboard(string dashboardId)
|
|
{
|
|
using var connection = new SqlConnection(_connectionString);
|
|
using var command = new SqlCommand($"SELECT DashboardData FROM dbo.[{_tableName}] WHERE DashboardId = @Id AND ACTIVE = 1", connection);
|
|
command.Parameters.Add(new SqlParameter("@Id", SqlDbType.NVarChar, 128) { Value = dashboardId });
|
|
|
|
connection.Open();
|
|
var data = command.ExecuteScalar() as byte[];
|
|
if (data == null)
|
|
{
|
|
throw new ArgumentException($"Dashboard '{dashboardId}' not found.");
|
|
}
|
|
|
|
var xml = Encoding.UTF8.GetString(data);
|
|
var doc = XDocument.Parse(xml);
|
|
NormalizeCatalogDateDimensions(doc);
|
|
return doc;
|
|
}
|
|
|
|
private static void NormalizeCatalogDateDimensions(XDocument doc)
|
|
{
|
|
var dateMembers = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
"AddedWhen",
|
|
"ChangedWhen"
|
|
};
|
|
|
|
foreach (var dimension in doc.Descendants("Dimension"))
|
|
{
|
|
var member = dimension.Attribute("DataMember")?.Value;
|
|
if (member == null || !dateMembers.Contains(member))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var interval = dimension.Attribute("DateTimeGroupInterval")?.Value;
|
|
if (string.IsNullOrWhiteSpace(interval) || string.Equals(interval, "Year", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
dimension.SetAttributeValue("DateTimeGroupInterval", "DayMonthYear");
|
|
}
|
|
}
|
|
}
|
|
|
|
public string AddDashboard(XDocument dashboard, string dashboardName)
|
|
{
|
|
var id = string.IsNullOrWhiteSpace(dashboardName)
|
|
? Guid.NewGuid().ToString("N")
|
|
: dashboardName;
|
|
var payload = Encoding.UTF8.GetBytes(dashboard.ToString(SaveOptions.DisableFormatting));
|
|
var userName = _userProvider?.Invoke();
|
|
|
|
using var connection = new SqlConnection(_connectionString);
|
|
using var command = new SqlCommand($"INSERT INTO dbo.[{_tableName}] (ACTIVE, DashboardId, DashboardName, DashboardData, ADDED_WHO, ADDED_WHEN) VALUES (1, @Id, @Name, @Data, COALESCE(@User, SUSER_SNAME()), SYSUTCDATETIME())", connection);
|
|
command.Parameters.Add(new SqlParameter("@Id", SqlDbType.NVarChar, 128) { Value = id });
|
|
command.Parameters.Add(new SqlParameter("@Name", SqlDbType.NVarChar, 256) { Value = string.IsNullOrWhiteSpace(dashboardName) ? id : dashboardName });
|
|
command.Parameters.Add(new SqlParameter("@Data", SqlDbType.VarBinary, -1) { Value = payload });
|
|
command.Parameters.Add(new SqlParameter("@User", SqlDbType.NVarChar, 50) { Value = (object?)userName ?? DBNull.Value });
|
|
|
|
connection.Open();
|
|
command.ExecuteNonQuery();
|
|
return id;
|
|
}
|
|
|
|
public void SaveDashboard(string dashboardId, XDocument dashboard)
|
|
{
|
|
var payload = Encoding.UTF8.GetBytes(dashboard.ToString(SaveOptions.DisableFormatting));
|
|
var userName = _userProvider?.Invoke();
|
|
|
|
using var connection = new SqlConnection(_connectionString);
|
|
using var command = new SqlCommand($"UPDATE dbo.[{_tableName}] SET DashboardData = @Data, CHANGED_WHO = COALESCE(@User, SUSER_SNAME()), CHANGED_WHEN = SYSUTCDATETIME() WHERE DashboardId = @Id", connection);
|
|
command.Parameters.Add(new SqlParameter("@Id", SqlDbType.NVarChar, 128) { Value = dashboardId });
|
|
command.Parameters.Add(new SqlParameter("@Data", SqlDbType.VarBinary, -1) { Value = payload });
|
|
command.Parameters.Add(new SqlParameter("@User", SqlDbType.NVarChar, 50) { Value = (object?)userName ?? DBNull.Value });
|
|
|
|
connection.Open();
|
|
var rows = command.ExecuteNonQuery();
|
|
if (rows == 0)
|
|
{
|
|
throw new ArgumentException($"Dashboard '{dashboardId}' not found.");
|
|
}
|
|
}
|
|
|
|
public void DeleteDashboard(string dashboardId)
|
|
{
|
|
using var connection = new SqlConnection(_connectionString);
|
|
using var command = new SqlCommand($"DELETE FROM dbo.[{_tableName}] WHERE DashboardId = @Id", connection);
|
|
command.Parameters.Add(new SqlParameter("@Id", SqlDbType.NVarChar, 128) { Value = dashboardId });
|
|
|
|
connection.Open();
|
|
command.ExecuteNonQuery();
|
|
}
|
|
}
|