Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 1 addition & 65 deletions src/Controllers/ExportDataController.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
using System.IO;
using System.Net.Mime;
using System.Net.Mime;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Sqlbi.Bravo.Infrastructure.Extensions;
using Sqlbi.Bravo.Infrastructure.Helpers;
using Sqlbi.Bravo.Infrastructure.Windows;
using Sqlbi.Bravo.Models;
using Sqlbi.Bravo.Models.ExportData;
using Sqlbi.Bravo.Services;
Expand Down Expand Up @@ -47,12 +43,6 @@ public IActionResult ExportDelimitedTextFile(ExportDelimitedTextFromPBIReportReq
{
if (WindowDialogHelper.BrowseFolderDialog(out var path, cancellationToken))
{
if (request.Settings!.CreateSubfolder)
{
if (!GetExportSubfolderPath(ref path, name: request.Report!.ReportName))
return NoContent();
}

var job = _exportDataService.ExportDelimitedTextFile(request.Report!, request.Settings!, path, cancellationToken);
return Ok(job);
}
Expand Down Expand Up @@ -81,12 +71,6 @@ public async Task<IActionResult> ExportDelimitedTextFile(ExportDelimitedTextFrom

if (WindowDialogHelper.BrowseFolderDialog(out var path, cancellationToken))
{
if (request.Settings!.CreateSubfolder)
{
if (!GetExportSubfolderPath(ref path, name: request.Dataset!.DisplayName))
return NoContent();
}

var job = _exportDataService.ExportDelimitedTextFile(request.Dataset!, request.Settings!, path, session.AuthenticationResult.AccessToken, cancellationToken);
return Ok(job);
}
Expand Down Expand Up @@ -185,52 +169,4 @@ public IActionResult QueryExportJob(PBICloudDataset dataset)

return Ok(job);
}

private static bool GetExportSubfolderPath(ref string path, string? name)
{
if (name.IsNullOrWhiteSpace())
{
name = "New Folder";
}

var subfolderName = name.ReplaceInvalidPathChars();
var subfolderPath = Path.Combine(path, subfolderName);

if (Directory.Exists(subfolderPath))
{
var overwriteButton = new TaskDialogCommandLinkButton("&Overwrite", "Overwrite and replace files in the destination folder");
var keepbothButton = new TaskDialogCommandLinkButton("&Keep Both", "Files will be exported to a new folder");
var cancelButton = new TaskDialogCommandLinkButton("&Cancel", "Cancel export");
var heading = $"The destination folder you chose already contains a subfolder named '{subfolderName}'";
var text = "Choose an option to proceed";

var clickedButton = MessageDialog.ShowDialog(heading, text, footnoteText: null, allowCancel: true, overwriteButton, keepbothButton, cancelButton);

if (clickedButton == overwriteButton)
{
//
}
else if (clickedButton == keepbothButton)
{
for (var i = 1; /**/ ; i++)
{
var uniquePath = Path.Combine(path, $"{subfolderName} - {i}");

if (!Directory.Exists(uniquePath))
{
subfolderPath = uniquePath;
break;
}
}
}
else
{
path = string.Empty;
return false;
}
}

path = subfolderPath;
return true;
}
}
8 changes: 3 additions & 5 deletions src/Host/BravoApplicationInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@
namespace Sqlbi.Bravo.Host;

/// <summary>
/// Provides the initialization phase that precedes the application.
/// Initializes the application process, applying process-wide settings
/// and composing the necessary components before the host is created.
/// </summary>
internal static class BravoApplicationInitializer
{
/// <summary>
/// Initializes the process: applies the process-wide settings and composes what the process owns
/// before a host exists — as explicit objects in dependency order, no container — returning them
/// in the context. <see cref="BravoApplicationBuilder"/> later publishes them to the one real
/// service provider.
/// Initializes the application process, applying process-wide settings
/// </summary>
public static BravoApplicationInitializationContext Initialize()
{
Expand Down
40 changes: 1 addition & 39 deletions src/Infrastructure/AppEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.Json;
using Microsoft.Win32;
using Sqlbi.Bravo.Infrastructure.Configuration;
using Sqlbi.Bravo.Infrastructure.Configuration.Settings;
using Sqlbi.Bravo.Infrastructure.Diagnostics;
using Sqlbi.Bravo.Infrastructure.Extensions;
using Sqlbi.Bravo.Infrastructure.Helpers;
using Sqlbi.Bravo.Infrastructure.Security;
Expand Down Expand Up @@ -81,7 +79,6 @@ static AppEnvironment()

ProcessId = Environment.ProcessId;
SessionId = currentProcess.SessionId;
ProcessPath = Environment.ProcessPath!;

ApplicationDataPath = Path.Combine(Environment.GetFolderPath(DeploymentMode == AppDeploymentMode.Packaged ? Environment.SpecialFolder.UserProfile : Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.DoNotVerify), ApplicationName);
ApplicationTempPath = Path.Combine(ApplicationDataPath, ".temp");
Expand All @@ -91,8 +88,6 @@ static AppEnvironment()

Diagnostics = new ConcurrentDictionary<DiagnosticMessage, DiagnosticMessage>();
DefaultJsonOptions = new(JsonSerializerDefaults.Web) { MaxDepth = 32 }; // see Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions

AddEnvironmentDiagnosticInfo();
}

/// <summary>
Expand All @@ -103,8 +98,6 @@ static AppEnvironment()

public static int ProcessId { get; }

public static string ProcessPath { get; }

public static AppPublishMode PublishMode
{
get
Expand Down Expand Up @@ -168,37 +161,6 @@ public static void AddDiagnostics(DiagnosticMessageType type, string name, strin
_ = Diagnostics.TryAdd(message, message);
}

private static void AddEnvironmentDiagnosticInfo()
{
if (!IsDiagnosticLevelVerbose)
return;

var targetFramework = typeof(Program).Assembly.GetCustomAttributes(typeof(TargetFrameworkAttribute), inherit: false).OfType<TargetFrameworkAttribute>().FirstOrDefault();

var info = new
{
SystemOSVersion = Environment.OSVersion.VersionString,
SystemProcessorCount = Environment.ProcessorCount,
ProcessId,
ProcessPath,
ProcessSessionId = SessionId,
RuntimeOSDescription = RuntimeInformation.OSDescription.ToString(),
RuntimeOSVersion = RuntimeInformation.RuntimeIdentifier,
RuntimeFrameworkDescription = RuntimeInformation.FrameworkDescription,
TargetFrameworkName = targetFramework?.FrameworkName ?? "n/a",
WebView2VersionInfo,
//
ApplicationPublishMode = PublishMode.ToString(),
ApplicationDeploymentMode = DeploymentMode.ToString(),
ApplicationVersion = AppVersion.InformationalVersion,
ApplicationDataPath,
ApplicationTempPath,
ApplicationUserSettingsFilePath = UserSettingsFilePath,
};

AddDiagnostics(DiagnosticMessageType.Json, name: $"{nameof(AppEnvironment)}.EnvironmentInfo", content: JsonSerializer.Serialize(info));
}

private static AppDeploymentMode GetDeploymentMode()
{
if (DesktopBridgeHelper.IsRunningAsMsixPackage())
Expand Down
7 changes: 7 additions & 0 deletions src/Infrastructure/AppWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Sqlbi.Bravo.Host;
using Sqlbi.Bravo.Infrastructure.Configuration;
using Sqlbi.Bravo.Infrastructure.Configuration.Settings;
using Sqlbi.Bravo.Infrastructure.Diagnostics;
using Sqlbi.Bravo.Infrastructure.Extensions;
using Sqlbi.Bravo.Infrastructure.Helpers;
using Sqlbi.Bravo.Infrastructure.Messages;
Expand Down Expand Up @@ -183,6 +184,12 @@ private void OnFormLoad(object? sender, EventArgs e)
CenterToScreen();

_instanceActivationEvents.ActivationRequested += OnActivationRequestedRestoreWindowToForeground;

if (AppEnvironment.IsDiagnosticLevelVerbose)
{
var content = EnvironmentInfo.Collect().ToDictionary();
AppEnvironment.AddDiagnostics(DiagnosticMessageType.Json, name: $"{nameof(AppWindow)}.{nameof(EnvironmentInfo)}", content: JsonSerializer.Serialize(content));
}
}

private void OnFormClosed(object? sender, FormClosedEventArgs e)
Expand Down
93 changes: 93 additions & 0 deletions src/Infrastructure/Diagnostics/EnvironmentInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using Sqlbi.Bravo.Infrastructure.Telemetry;

namespace Sqlbi.Bravo.Infrastructure.Diagnostics;

/// <summary>
/// Provides diagnostic information about the environment in which the application is running.
/// </summary>
internal sealed class EnvironmentInfo
{
private readonly IReadOnlyList<KeyValuePair<string, string>> _entries;

/// <summary>
/// Collects the environment information and returns an instance of <see cref="EnvironmentInfo"/>.
/// </summary>
public static EnvironmentInfo Collect()
{
var entries = new KeyValuePair<string, string>[]
{
new("TimestampUtc", DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)),
new("TimestampLocal", DateTime.Now.ToString("O", CultureInfo.InvariantCulture)),
// Application
new("ApplicationSessionId", SafeRead(() => TelemetrySessionInfo.SessionId)),
new("ApplicationVersion", SafeRead(() => AppVersion.InformationalVersion)),
new("ApplicationPublishMode", SafeRead(() => AppEnvironment.PublishMode.ToString())),
new("ApplicationDeploymentMode", SafeRead(() => AppEnvironment.DeploymentMode.ToString())),
new("ApplicationDataPath", SafeRead(() => AppEnvironment.ApplicationDataPath)),
// Process
new("ProcessId", SafeRead(() => Environment.ProcessId.ToString(CultureInfo.InvariantCulture))),
new("ProcessPath", SafeRead(() => Environment.ProcessPath)),
new("ProcessSessionId", SafeRead(() => AppEnvironment.SessionId.ToString(CultureInfo.InvariantCulture))),
new("ProcessArchitecture", SafeRead(() => RuntimeInformation.ProcessArchitecture.ToString())),
new("ProcessProcessorCount", SafeRead(() => Environment.ProcessorCount.ToString(CultureInfo.InvariantCulture))),
// Machine
new("OSDescription", SafeRead(() => RuntimeInformation.OSDescription)),
new("OSArchitecture", SafeRead(() => RuntimeInformation.OSArchitecture.ToString())),
// Runtime
new("RuntimeDescription", SafeRead(() => RuntimeInformation.FrameworkDescription)),
new("RuntimeIdentifier", SafeRead(() => RuntimeInformation.RuntimeIdentifier)),
// Components
new("WebView2Version", SafeRead(() => AppEnvironment.WebView2VersionInfo)),
};

return new EnvironmentInfo(entries);
}

private EnvironmentInfo(IReadOnlyList<KeyValuePair<string, string>> entries)
{
_entries = entries;
}

/// <summary>
/// Returns the environment information as a text block.
/// </summary>
public string ToText()
{
var builder = new StringBuilder();

builder.AppendLine("# Environment Information");
builder.AppendLine();

foreach (var (name, value) in _entries)
builder.Append($"- {name}: ").AppendLine(value);

return builder.ToString();
}

/// <summary>
/// Returns the environment information as dictionary.
/// </summary>
public Dictionary<string, string> ToDictionary()
{
return _entries.ToDictionary((entry) => entry.Key, (entry) => entry.Value);
}

internal static string SafeRead(Func<string?> read, string fallback = "n/a")
{
try
{
return read() ?? fallback;
}
catch (Exception ex)
{
return $"unavailable ({ex.GetType().Name})";
}
}
}
Loading
Loading