Replaced file-based dashboard storage with SQL Server-backed storage using the new SqlDashboardStorage class and TBDD_SMF_CONFIG table. Updated Program.cs to use the new storage and ensure default dashboards are loaded into the database. Simplified DefaultDashboard.xml to remove old items. Added SQL script for the dashboard storage table. Cleaned up unused folder references in the project file. This centralizes dashboard management and supports multi-instance scenarios.
174 lines
6.6 KiB
C#
174 lines
6.6 KiB
C#
using DbFirst.API.Middleware;
|
|
using DbFirst.API.Dashboards;
|
|
using DbFirst.Application;
|
|
using DbFirst.Application.Repositories;
|
|
using DbFirst.Domain;
|
|
using DbFirst.Domain.Entities;
|
|
using DbFirst.Infrastructure;
|
|
using DbFirst.Infrastructure.Repositories;
|
|
using DevExpress.AspNetCore;
|
|
using DevExpress.DashboardAspNetCore;
|
|
using DevExpress.DashboardCommon;
|
|
using DevExpress.DashboardWeb;
|
|
using DevExpress.DataAccess.Json;
|
|
using System.Xml.Linq;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Add services to the container.
|
|
builder.Services.AddControllers();
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerGen();
|
|
|
|
// TODO: allow listed origins configured in appsettings.json
|
|
// In any case, dont let them to free to use without cors. if there is no origin specified, block all.
|
|
// In development you can keep it easy.
|
|
builder.Services.AddCors(options =>
|
|
{
|
|
options.AddDefaultPolicy(policy =>
|
|
{
|
|
if (builder.Environment.IsDevelopment())
|
|
{
|
|
policy.AllowAnyOrigin()
|
|
.AllowAnyHeader()
|
|
.AllowAnyMethod();
|
|
}
|
|
else
|
|
{
|
|
var origins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>() ?? Array.Empty<string>();
|
|
if (origins.Length > 0)
|
|
{
|
|
policy.WithOrigins(origins)
|
|
.AllowAnyHeader()
|
|
.AllowAnyMethod();
|
|
}
|
|
// if no origins configured, deny all by leaving policy without allowances
|
|
}
|
|
});
|
|
});
|
|
|
|
builder.Services.AddInfrastructure(builder.Configuration);
|
|
builder.Services.AddApplication();
|
|
|
|
builder.Services.AddScoped<ICatalogRepository, CatalogRepository>();
|
|
|
|
builder.Services.AddDevExpressControls();
|
|
builder.Services.AddScoped<DashboardConfigurator>((IServiceProvider serviceProvider) => {
|
|
var dashboardsPath = Path.Combine(builder.Environment.ContentRootPath, "Data", "Dashboards");
|
|
Directory.CreateDirectory(dashboardsPath);
|
|
|
|
var defaultDashboardPath = Path.Combine(dashboardsPath, "DefaultDashboard.xml");
|
|
if (!File.Exists(defaultDashboardPath))
|
|
{
|
|
var defaultDashboard = new Dashboard();
|
|
defaultDashboard.Title.Text = "Default Dashboard";
|
|
defaultDashboard.SaveToXml(defaultDashboardPath);
|
|
}
|
|
|
|
var dashboardBaseUrl = builder.Configuration["Dashboard:BaseUrl"]
|
|
?? builder.Configuration["ApiBaseUrl"]
|
|
?? builder.Configuration["ASPNETCORE_URLS"]?.Split(';', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault()
|
|
?? "https://localhost:7204";
|
|
|
|
dashboardBaseUrl = dashboardBaseUrl.TrimEnd('/');
|
|
|
|
var catalogsGridDashboardPath = Path.Combine(dashboardsPath, "CatalogsGrid.xml");
|
|
if (!File.Exists(catalogsGridDashboardPath))
|
|
{
|
|
var dashboard = new Dashboard();
|
|
dashboard.Title.Text = "Catalogs (Dashboard Grid)";
|
|
|
|
var catalogDataSource = new DashboardJsonDataSource("Catalogs (API)")
|
|
{
|
|
ComponentName = "catalogsDataSource",
|
|
JsonSource = new UriJsonSource(new Uri($"{dashboardBaseUrl}/api/catalogs"))
|
|
};
|
|
|
|
dashboard.DataSources.Add(catalogDataSource);
|
|
|
|
var grid = new GridDashboardItem
|
|
{
|
|
DataSource = catalogDataSource,
|
|
Name = "Catalogs"
|
|
};
|
|
|
|
grid.Columns.Add(new GridDimensionColumn(new Dimension(nameof(VwmyCatalog.Guid))) { Name = "Id" });
|
|
grid.Columns.Add(new GridDimensionColumn(new Dimension(nameof(VwmyCatalog.CatTitle))) { Name = "Titel" });
|
|
grid.Columns.Add(new GridDimensionColumn(new Dimension(nameof(VwmyCatalog.CatString))) { Name = "String" });
|
|
grid.Columns.Add(new GridDimensionColumn(new Dimension(nameof(VwmyCatalog.AddedWho))) { Name = "Angelegt von" });
|
|
grid.Columns.Add(new GridDimensionColumn(new Dimension(nameof(VwmyCatalog.AddedWhen))) { Name = "Angelegt am" });
|
|
grid.Columns.Add(new GridDimensionColumn(new Dimension(nameof(VwmyCatalog.ChangedWho))) { Name = "Geändert von" });
|
|
grid.Columns.Add(new GridDimensionColumn(new Dimension(nameof(VwmyCatalog.ChangedWhen))) { Name = "Geändert am" });
|
|
|
|
dashboard.Items.Add(grid);
|
|
|
|
var layoutGroup = new DashboardLayoutGroup { Orientation = DashboardLayoutGroupOrientation.Vertical };
|
|
layoutGroup.ChildNodes.Add(new DashboardLayoutItem(grid));
|
|
dashboard.LayoutRoot = layoutGroup;
|
|
|
|
dashboard.SaveToXml(catalogsGridDashboardPath);
|
|
}
|
|
|
|
DashboardConfigurator configurator = new DashboardConfigurator();
|
|
|
|
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? string.Empty;
|
|
var dashboardStorage = new SqlDashboardStorage(connectionString, "TBDD_SMF_CONFIG");
|
|
configurator.SetDashboardStorage(dashboardStorage);
|
|
|
|
DataSourceInMemoryStorage dataSourceStorage = new DataSourceInMemoryStorage();
|
|
DashboardJsonDataSource jsonDataSourceUrl = new DashboardJsonDataSource("JSON Data Source (URL)");
|
|
jsonDataSourceUrl.JsonSource = new UriJsonSource(
|
|
new Uri("https://raw.githubusercontent.com/DevExpress-Examples/DataSources/master/JSON/customers.json"));
|
|
jsonDataSourceUrl.RootElement = "Customers";
|
|
dataSourceStorage.RegisterDataSource("jsonDataSourceUrl", jsonDataSourceUrl.SaveToXml());
|
|
|
|
var catalogsJsonDataSource = new DashboardJsonDataSource("Catalogs (API)")
|
|
{
|
|
ComponentName = "catalogsDataSource",
|
|
JsonSource = new UriJsonSource(new Uri($"{dashboardBaseUrl}/api/catalogs"))
|
|
};
|
|
dataSourceStorage.RegisterDataSource(catalogsJsonDataSource.ComponentName, catalogsJsonDataSource.SaveToXml());
|
|
dataSourceStorage.RegisterDataSource(catalogsJsonDataSource.Name, catalogsJsonDataSource.SaveToXml());
|
|
|
|
configurator.SetDataSourceStorage(dataSourceStorage);
|
|
|
|
EnsureDashboardInStorage(dashboardStorage, "DefaultDashboard", defaultDashboardPath);
|
|
EnsureDashboardInStorage(dashboardStorage, "CatalogsGrid", catalogsGridDashboardPath);
|
|
|
|
return configurator;
|
|
});
|
|
|
|
var app = builder.Build();
|
|
|
|
// Configure the HTTP request pipeline.
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.UseSwagger();
|
|
app.UseSwaggerUI();
|
|
}
|
|
|
|
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
|
|
|
app.UseDevExpressControls();
|
|
app.UseHttpsRedirection();
|
|
app.UseCors();
|
|
app.UseAuthorization();
|
|
|
|
app.MapDashboardRoute("api/dashboard", "DefaultDashboard");
|
|
|
|
app.MapControllers();
|
|
|
|
app.Run();
|
|
|
|
static void EnsureDashboardInStorage(IEditableDashboardStorage storage, string id, string filePath)
|
|
{
|
|
var exists = storage.GetAvailableDashboardsInfo().Any(info => string.Equals(info.ID, id, StringComparison.OrdinalIgnoreCase));
|
|
if (exists || !File.Exists(filePath))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var doc = XDocument.Load(filePath);
|
|
storage.AddDashboard(doc, id);
|
|
}
|