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
17 changes: 15 additions & 2 deletions Intersect.Editor/Forms/FrmUploadToServer.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

99 changes: 97 additions & 2 deletions Intersect.Editor/Forms/FrmUploadToServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,17 @@ private void UpdateAuthenticationStatus()
if (_tokenResponse != null)
{
lblStatus.Text = "✓ Authenticated";
btnLogin.Visible = false;
btnLogin.Text = "Re-Login";
}
else
{
lblStatus.Text = "⚠ Not authenticated - click Login to authenticate";
btnLogin.Visible = true;
btnLogin.Text = "Login";
}

// Login button is always visible now
btnLogin.Visible = true;

// Force UI refresh
btnLogin.Refresh();
lblStatus.Refresh();
Expand Down Expand Up @@ -796,6 +799,98 @@ private async Task PerformUpload()
);
}

private async void btnTestUrl_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txtServerUrl.Text))
{
DarkMessageBox.ShowError(
"Please enter a server URL to test.",
"Server URL Required",
DarkDialogButton.Ok,
Icon
);
return;
}

btnTestUrl.Enabled = false;
var originalStatus = lblStatus.Text;
lblStatus.Text = "Testing server URL...";

try
{
var serverUrl = txtServerUrl.Text.TrimEnd('/');
using var httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};

// Try to reach the server's API endpoint
var testEndpoint = $"{serverUrl}/api/v1/info";
var response = await httpClient.GetAsync(testEndpoint);

if (response.IsSuccessStatusCode)
{
lblStatus.Text = "✓ Server URL is reachable";
DarkMessageBox.ShowInformation(
"The server URL is valid and reachable!",
"Test Successful",
DarkDialogButton.Ok,
Icon
);
}
else
{
lblStatus.Text = $"⚠ Server responded with status: {response.StatusCode}";
DarkMessageBox.ShowWarning(
$"The server responded but returned status code: {response.StatusCode}\n\n" +
"The URL may still work for uploading if the API is configured correctly.",
"Server Response",
DarkDialogButton.Ok,
Icon
);
}
}
catch (HttpRequestException ex)
{
lblStatus.Text = "✗ Failed to reach server";
DarkMessageBox.ShowError(
$"Could not connect to the server:\n\n{ex.Message}\n\n" +
"Please check the URL and ensure the server is running.",
"Connection Failed",
DarkDialogButton.Ok,
Icon
);
}
catch (TaskCanceledException)
{
lblStatus.Text = "✗ Connection timed out";
DarkMessageBox.ShowError(
"The connection to the server timed out.\n\n" +
"Please check the URL and ensure the server is running.",
"Connection Timeout",
DarkDialogButton.Ok,
Icon
);
}
catch (Exception ex)
{
lblStatus.Text = "✗ Test failed";
DarkMessageBox.ShowError(
$"An error occurred while testing the URL:\n\n{ex.Message}",
"Test Error",
DarkDialogButton.Ok,
Icon
);
}
finally
{
btnTestUrl.Enabled = true;
// Restore authentication status after a delay
await Task.Delay(3000);
UpdateAuthenticationStatus();
}
}

private void btnClose_Click(object sender, EventArgs e)
{
Close();
Expand Down
58 changes: 58 additions & 0 deletions Intersect.Server/Web/ApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,9 @@ private async Task StartAsync(CancellationToken cancellationToken = default)
return;
}

// Ensure assets folder exists
EnsureAssetDirectoriesExist(app);

_app = app;
await app.StartAsync(cancellationToken);
}
Expand All @@ -725,6 +728,61 @@ private async Task StartAsync(CancellationToken cancellationToken = default)
}
}

private void EnsureAssetDirectoriesExist(WebApplication app)
{
try
{
var updateServerSection = app.Configuration.GetSection(GetOptionsName<UpdateServerOptions>());
var updateServerOptions = updateServerSection.Get<UpdateServerOptions>();

if (updateServerOptions?.Enabled != true)
{
return;
}

var assetRoot = updateServerOptions.AssetRoot ?? "assets";
var assetRootPath = Path.Combine(app.Environment.ContentRootPath, assetRoot);

// Create the main assets directory if it doesn't exist
if (!Directory.Exists(assetRootPath))
{
Directory.CreateDirectory(assetRootPath);
ApplicationContext.Context.Value?.Logger.LogInformation(
"Created assets directory at: {AssetRootPath}",
assetRootPath
);
}

// Create client and editor subdirectories
var clientAssetsPath = Path.Combine(assetRootPath, "client");
if (!Directory.Exists(clientAssetsPath))
{
Directory.CreateDirectory(clientAssetsPath);
ApplicationContext.Context.Value?.Logger.LogInformation(
"Created client assets directory at: {ClientAssetsPath}",
clientAssetsPath
);
}

var editorAssetsPath = Path.Combine(assetRootPath, "editor");
if (!Directory.Exists(editorAssetsPath))
{
Directory.CreateDirectory(editorAssetsPath);
ApplicationContext.Context.Value?.Logger.LogInformation(
"Created editor assets directory at: {EditorAssetsPath}",
editorAssetsPath
);
}
}
catch (Exception exception)
{
ApplicationContext.Context.Value?.Logger.LogWarning(
exception,
"Failed to create assets directories"
);
}
}

private async Task StopAsync(CancellationToken cancellationToken = default)
{
if (_app != default)
Expand Down
Loading