feat(configmanager): add ConnectionStrings editor with test connection support
Adds a new ConnectionStrings section to ConfigManager allowing users to manage database connection strings with provider selection, connection testing, and visual feedback for connection state.
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
# ConnectionStrings Editor - Design Plan
|
||||
|
||||
## Overview
|
||||
|
||||
Add a ConnectionStrings section under Settings in the ConfigManager tree view. This section provides a master-detail editor for managing database connection strings with provider-specific field editing.
|
||||
|
||||
## Design Decisions
|
||||
|
||||
| Decision | Choice | Rationale |
|
||||
|----------|--------|-----------|
|
||||
| Storage location | appsettings.json | Consistent with existing settings pattern |
|
||||
| Field editing | Provider-specific parsed fields | Better UX than raw connection string editing |
|
||||
| Supported providers | Generic, Oracle, SqlServer | Covers existing JDE/CMS/MSSQL needs |
|
||||
| SQL Server auth | SQL Authentication only | Windows auth not needed for this use case |
|
||||
| Password display | Masked with reveal toggle | Security + usability balance |
|
||||
| Edit workflow | Inline panel editing | Matches existing form patterns |
|
||||
| Delete behavior | Confirmation dialog, immediate | Prevents accidents, clear feedback |
|
||||
|
||||
## Architecture
|
||||
|
||||
### Tree Structure
|
||||
|
||||
```
|
||||
Settings/
|
||||
├── DataSync
|
||||
├── DataAccess
|
||||
├── Auth
|
||||
├── Ldap
|
||||
├── Search
|
||||
├── ExcelExport
|
||||
└── ConnectionStrings <-- NEW
|
||||
```
|
||||
|
||||
### Data Model
|
||||
|
||||
**ConnectionStringEntry** - represents a single connection string:
|
||||
|
||||
```csharp
|
||||
public class ConnectionStringEntry
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public ConnectionProvider Provider { get; set; } = ConnectionProvider.Generic;
|
||||
|
||||
// SqlServer fields
|
||||
public string? Server { get; set; }
|
||||
public string? Database { get; set; }
|
||||
public string? UserId { get; set; }
|
||||
public string? Password { get; set; }
|
||||
public string Encrypt { get; set; } = "True";
|
||||
public bool TrustServerCertificate { get; set; }
|
||||
public int ConnectionTimeout { get; set; } = 30;
|
||||
public string? ApplicationName { get; set; }
|
||||
|
||||
// Oracle fields
|
||||
public string? Host { get; set; }
|
||||
public int Port { get; set; } = 1521;
|
||||
public string? ServiceName { get; set; }
|
||||
|
||||
// Generic fields
|
||||
public string? RawConnectionString { get; set; }
|
||||
|
||||
// Generates the final connection string based on Provider
|
||||
public string GenerateConnectionString() { ... }
|
||||
}
|
||||
|
||||
public enum ConnectionProvider
|
||||
{
|
||||
Generic,
|
||||
SqlServer,
|
||||
Oracle
|
||||
}
|
||||
```
|
||||
|
||||
**ConnectionStringsSection** - the config model section:
|
||||
|
||||
```csharp
|
||||
public class ConnectionStringsSection
|
||||
{
|
||||
public List<ConnectionStringEntry> Entries { get; set; } = new();
|
||||
}
|
||||
```
|
||||
|
||||
### ViewModel Structure
|
||||
|
||||
```
|
||||
ConnectionStringsFormViewModel
|
||||
├── Connections : ObservableCollection<ConnectionStringEntryViewModel>
|
||||
├── SelectedConnection : ConnectionStringEntryViewModel?
|
||||
├── HasSelection : bool
|
||||
├── AvailableProviders : IReadOnlyList<ConnectionProvider>
|
||||
├── AddConnectionCommand
|
||||
├── DeleteConnectionCommand
|
||||
├── ValidateConnectionCommand
|
||||
├── TestConnectionCommand
|
||||
```
|
||||
|
||||
**ConnectionStringEntryViewModel** - wraps each entry for editing:
|
||||
|
||||
```csharp
|
||||
public class ConnectionStringEntryViewModel : ViewModelBase
|
||||
{
|
||||
// All fields from ConnectionStringEntry exposed as properties
|
||||
// Provider property triggers template switching
|
||||
// GeneratedConnectionString property for preview
|
||||
// IsPasswordVisible for password reveal toggle
|
||||
}
|
||||
```
|
||||
|
||||
### Connection String Formats
|
||||
|
||||
**SqlServer:**
|
||||
```
|
||||
Server={server};Database={database};User Id={userId};Password={password};Encrypt={encrypt};TrustServerCertificate={trust};Connection Timeout={timeout};Application Name={appName};
|
||||
```
|
||||
|
||||
**Oracle (EZConnect):**
|
||||
```
|
||||
Data Source=//{host}:{port}/{serviceName};User Id={userId};Password={password};Connection Timeout={timeout};
|
||||
```
|
||||
|
||||
**Generic:**
|
||||
Raw connection string as entered by user.
|
||||
|
||||
## UI Design
|
||||
|
||||
### Layout Structure
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Connection Strings │
|
||||
│ ──────────────────────────────────────────────────────── │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Connections (3) │ │
|
||||
│ │ ┌────────────┬──────────┬─────────────────────────┐ │ │
|
||||
│ │ │ Name │ Provider │ Server │ │ │
|
||||
│ │ ├────────────┼──────────┼─────────────────────────┤ │ │
|
||||
│ │ │ jde │ Oracle │ jdeserver.company.com │ │ │
|
||||
│ │ │ mssql │ SqlServer│ localhost\SQLEXPRESS │ │ │
|
||||
│ │ │ cms │ Generic │ - │ │ │
|
||||
│ │ └────────────┴──────────┴─────────────────────────┘ │ │
|
||||
│ │ [+ Add] [Delete] │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Edit Connection: mssql │ │
|
||||
│ │ │ │
|
||||
│ │ Name * Provider * │ │
|
||||
│ │ [mssql ] [SqlServer ▼] │ │
|
||||
│ │ ──────────────────────────────────────────────────── │ │
|
||||
│ │ Server * Database * │ │
|
||||
│ │ [localhost\SQLEXPRESS] [ScopingTool ] │ │
|
||||
│ │ │ │
|
||||
│ │ User Id Password │ │
|
||||
│ │ [sa ] [•••••••• ] [👁] │ │
|
||||
│ │ │ │
|
||||
│ │ Encrypt ☐ Trust Server Certificate │ │
|
||||
│ │ [True ▼] (Skip cert validation) │ │
|
||||
│ │ │ │
|
||||
│ │ Connection Timeout Application Name │ │
|
||||
│ │ [30 ] [JdeScopingTool ] │ │
|
||||
│ │ ──────────────────────────────────────────────────── │ │
|
||||
│ │ CONNECTION STRING PREVIEW │ │
|
||||
│ │ Server=localhost\SQLEXPRESS;Database=ScopingTool;... │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ [Validate] [Test Connection] │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Provider-Specific Forms
|
||||
|
||||
**SqlServer fields:**
|
||||
- Server (text, required)
|
||||
- Database (text, required)
|
||||
- User Id (text)
|
||||
- Password (password with reveal toggle)
|
||||
- Encrypt (dropdown: True/False/Strict)
|
||||
- TrustServerCertificate (checkbox)
|
||||
- Connection Timeout (numeric, default 30)
|
||||
- Application Name (text)
|
||||
|
||||
**Oracle fields:**
|
||||
- Host (text, required)
|
||||
- Port (numeric, default 1521)
|
||||
- Service Name (text, required)
|
||||
- User Id (text, required)
|
||||
- Password (password with reveal toggle, required)
|
||||
- Connection Timeout (numeric)
|
||||
|
||||
**Generic fields:**
|
||||
- Connection String (multiline text, required)
|
||||
|
||||
### Button Behaviors
|
||||
|
||||
| Button | Action |
|
||||
|--------|--------|
|
||||
| Add | Creates new entry with default values, selects it |
|
||||
| Delete | Shows confirmation dialog, removes entry on confirm |
|
||||
| Validate | Validates connection string syntax (no network call) |
|
||||
| Test | Attempts actual database connection, shows modal with result |
|
||||
|
||||
### State Transitions
|
||||
|
||||
```
|
||||
No connections → Empty state with "Add First Connection" button
|
||||
Connections exist, none selected → Table visible, placeholder in edit area
|
||||
Connection selected → Edit form visible with provider-specific fields
|
||||
Field changed → Entry marked dirty, generates preview string
|
||||
Save (via main Save) → All changes persisted to appsettings.json
|
||||
```
|
||||
|
||||
## Integration Points
|
||||
|
||||
### ConfigModel Integration
|
||||
|
||||
Add `ConnectionStrings` property to `ConfigModel`:
|
||||
|
||||
```csharp
|
||||
public class ConfigModel
|
||||
{
|
||||
// Existing properties...
|
||||
public ConnectionStringsSection ConnectionStrings { get; set; } = new();
|
||||
}
|
||||
```
|
||||
|
||||
### MainWindowViewModel Integration
|
||||
|
||||
- Add ConnectionStrings node to tree under Settings folder
|
||||
- Handle node selection to load `ConnectionStringsFormViewModel`
|
||||
- Mark node as modified when connection strings change
|
||||
|
||||
### Serialization
|
||||
|
||||
Connection strings serialize to appsettings.json as:
|
||||
|
||||
```json
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"Entries": [
|
||||
{
|
||||
"Name": "mssql",
|
||||
"Provider": "SqlServer",
|
||||
"Server": "localhost\\SQLEXPRESS",
|
||||
"Database": "ScopingTool",
|
||||
"UserId": "sa",
|
||||
"Password": "secretpassword",
|
||||
"Encrypt": "True",
|
||||
"TrustServerCertificate": true,
|
||||
"ConnectionTimeout": 30,
|
||||
"ApplicationName": "JdeScopingTool"
|
||||
},
|
||||
{
|
||||
"Name": "jde",
|
||||
"Provider": "Oracle",
|
||||
"Host": "jdeserver.company.com",
|
||||
"Port": 1521,
|
||||
"ServiceName": "JDEPROD",
|
||||
"UserId": "jde_readonly",
|
||||
"Password": "oraclepassword",
|
||||
"ConnectionTimeout": 60
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
|
||||
1. **ConnectionStringEntry tests:**
|
||||
- GenerateConnectionString produces correct format per provider
|
||||
- Default values are correct
|
||||
- Required field validation
|
||||
|
||||
2. **ConnectionStringEntryViewModel tests:**
|
||||
- Property changes raise PropertyChanged
|
||||
- Provider change clears irrelevant fields
|
||||
- Password visibility toggle works
|
||||
|
||||
3. **ConnectionStringsFormViewModel tests:**
|
||||
- Add creates new entry and selects it
|
||||
- Delete removes selected entry
|
||||
- Selection change updates form
|
||||
- HasSelection reflects state correctly
|
||||
|
||||
### Integration Tests
|
||||
|
||||
1. **Serialization round-trip:**
|
||||
- Save and reload preserves all fields
|
||||
- Provider enum serializes correctly
|
||||
|
||||
2. **Connection testing:**
|
||||
- SqlServer test connection works
|
||||
- Oracle test connection works
|
||||
- Error messages displayed correctly
|
||||
@@ -0,0 +1,421 @@
|
||||
# ConnectionStrings Editor - Implementation Plan
|
||||
|
||||
## Overview
|
||||
|
||||
Step-by-step implementation guide for adding ConnectionStrings editor to ConfigManager.
|
||||
|
||||
**Estimated tasks:** 12 tasks in 4 batches
|
||||
|
||||
---
|
||||
|
||||
## Batch 1: Data Models
|
||||
|
||||
### Task 1: Create ConnectionProvider enum
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/Models/ConnectionProvider.cs`
|
||||
|
||||
```csharp
|
||||
namespace JdeScoping.ConfigManager.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Database provider types supported by the ConnectionStrings editor.
|
||||
/// </summary>
|
||||
public enum ConnectionProvider
|
||||
{
|
||||
Generic,
|
||||
SqlServer,
|
||||
Oracle
|
||||
}
|
||||
```
|
||||
|
||||
**Verification:** Build succeeds.
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Create ConnectionStringEntry model
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/Models/ConnectionStringEntry.cs`
|
||||
|
||||
```csharp
|
||||
namespace JdeScoping.ConfigManager.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single connection string entry with provider-specific fields.
|
||||
/// </summary>
|
||||
public class ConnectionStringEntry
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public ConnectionProvider Provider { get; set; } = ConnectionProvider.Generic;
|
||||
|
||||
// SqlServer fields
|
||||
public string? Server { get; set; }
|
||||
public string? Database { get; set; }
|
||||
public string? UserId { get; set; }
|
||||
public string? Password { get; set; }
|
||||
public string Encrypt { get; set; } = "True";
|
||||
public bool TrustServerCertificate { get; set; }
|
||||
public int ConnectionTimeout { get; set; } = 30;
|
||||
public string? ApplicationName { get; set; }
|
||||
|
||||
// Oracle fields
|
||||
public string? Host { get; set; }
|
||||
public int Port { get; set; } = 1521;
|
||||
public string? ServiceName { get; set; }
|
||||
|
||||
// Generic fields
|
||||
public string? RawConnectionString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates the connection string based on the Provider type.
|
||||
/// </summary>
|
||||
public string GenerateConnectionString()
|
||||
{
|
||||
return Provider switch
|
||||
{
|
||||
ConnectionProvider.SqlServer => GenerateSqlServerConnectionString(),
|
||||
ConnectionProvider.Oracle => GenerateOracleConnectionString(),
|
||||
ConnectionProvider.Generic => RawConnectionString ?? string.Empty,
|
||||
_ => string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
private string GenerateSqlServerConnectionString()
|
||||
{
|
||||
var parts = new List<string>();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Server))
|
||||
parts.Add($"Server={Server}");
|
||||
if (!string.IsNullOrWhiteSpace(Database))
|
||||
parts.Add($"Database={Database}");
|
||||
if (!string.IsNullOrWhiteSpace(UserId))
|
||||
parts.Add($"User Id={UserId}");
|
||||
if (!string.IsNullOrWhiteSpace(Password))
|
||||
parts.Add($"Password={Password}");
|
||||
if (!string.IsNullOrWhiteSpace(Encrypt))
|
||||
parts.Add($"Encrypt={Encrypt}");
|
||||
if (TrustServerCertificate)
|
||||
parts.Add("TrustServerCertificate=True");
|
||||
if (ConnectionTimeout != 30)
|
||||
parts.Add($"Connection Timeout={ConnectionTimeout}");
|
||||
if (!string.IsNullOrWhiteSpace(ApplicationName))
|
||||
parts.Add($"Application Name={ApplicationName}");
|
||||
|
||||
return string.Join(";", parts);
|
||||
}
|
||||
|
||||
private string GenerateOracleConnectionString()
|
||||
{
|
||||
var parts = new List<string>();
|
||||
|
||||
var host = Host ?? "localhost";
|
||||
var port = Port > 0 ? Port : 1521;
|
||||
var service = ServiceName ?? "";
|
||||
|
||||
parts.Add($"Data Source=//{host}:{port}/{service}");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(UserId))
|
||||
parts.Add($"User Id={UserId}");
|
||||
if (!string.IsNullOrWhiteSpace(Password))
|
||||
parts.Add($"Password={Password}");
|
||||
if (ConnectionTimeout > 0 && ConnectionTimeout != 30)
|
||||
parts.Add($"Connection Timeout={ConnectionTimeout}");
|
||||
|
||||
return string.Join(";", parts);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Verification:** Build succeeds.
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Create ConnectionStringsSection model
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/Models/ConnectionStringsSection.cs`
|
||||
|
||||
```csharp
|
||||
namespace JdeScoping.ConfigManager.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration section for connection strings.
|
||||
/// </summary>
|
||||
public class ConnectionStringsSection
|
||||
{
|
||||
public List<ConnectionStringEntry> Entries { get; set; } = new();
|
||||
}
|
||||
```
|
||||
|
||||
**Verification:** Build succeeds.
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Add ConnectionStrings to ConfigModel
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/Models/ConfigModel.cs`
|
||||
|
||||
Add property to existing ConfigModel class:
|
||||
|
||||
```csharp
|
||||
public ConnectionStringsSection ConnectionStrings { get; set; } = new();
|
||||
```
|
||||
|
||||
**Verification:** Build succeeds.
|
||||
|
||||
---
|
||||
|
||||
## Batch 2: ViewModels
|
||||
|
||||
### Task 5: Create ConnectionStringEntryViewModel
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/Forms/ConnectionStringEntryViewModel.cs`
|
||||
|
||||
Create ViewModel that wraps ConnectionStringEntry with:
|
||||
- All properties exposed with change notification
|
||||
- `GeneratedConnectionString` computed property
|
||||
- `IsPasswordVisible` toggle property
|
||||
- `TogglePasswordVisibilityCommand`
|
||||
- `ProviderDisplay` and `ServerDisplay` for table columns
|
||||
|
||||
Key implementation details:
|
||||
- Constructor takes `ConnectionStringEntry model` and `Action onChanged`
|
||||
- All setters call `OnPropertyChanged()` and `_onChanged()`
|
||||
- When Provider changes, also notify `GeneratedConnectionString`
|
||||
- ServerDisplay returns Server (SqlServer), Host (Oracle), or "-" (Generic)
|
||||
|
||||
**Verification:** Build succeeds.
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Create ConnectionStringsFormViewModel
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/Forms/ConnectionStringsFormViewModel.cs`
|
||||
|
||||
Create main ViewModel with:
|
||||
- `Connections : ObservableCollection<ConnectionStringEntryViewModel>`
|
||||
- `SelectedConnection : ConnectionStringEntryViewModel?`
|
||||
- `HasSelection : bool` (computed from SelectedConnection != null)
|
||||
- `ConnectionCount : int` (computed from Connections.Count)
|
||||
- `AvailableProviders : IReadOnlyList<ConnectionProvider>`
|
||||
- `EncryptOptions : IReadOnlyList<string>` = ["True", "False", "Strict"]
|
||||
|
||||
Commands:
|
||||
- `AddConnectionCommand` - creates new entry with default name "NewConnection", selects it
|
||||
- `DeleteConnectionCommand` - requires confirmation via IDialogService, removes selected
|
||||
- `ValidateConnectionCommand` - validates syntax, shows result via IDialogService
|
||||
- `TestConnectionCommand` - tests actual connection, shows modal result
|
||||
|
||||
Constructor takes:
|
||||
- `ConnectionStringsSection model`
|
||||
- `Action onChanged`
|
||||
- `IDialogService dialogService`
|
||||
|
||||
**Verification:** Build succeeds.
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Create IConnectionTestService interface and implementation
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/Services/IConnectionTestService.cs`
|
||||
|
||||
```csharp
|
||||
namespace JdeScoping.ConfigManager.Services;
|
||||
|
||||
public interface IConnectionTestService
|
||||
{
|
||||
Task<ConnectionTestResult> TestConnectionAsync(string connectionString, ConnectionProvider provider);
|
||||
}
|
||||
|
||||
public class ConnectionTestResult
|
||||
{
|
||||
public bool Success { get; init; }
|
||||
public string Message { get; init; } = string.Empty;
|
||||
public TimeSpan? Duration { get; init; }
|
||||
}
|
||||
```
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/Services/ConnectionTestService.cs`
|
||||
|
||||
Implementation that:
|
||||
- Uses `Microsoft.Data.SqlClient` for SqlServer
|
||||
- Uses `Oracle.ManagedDataAccess.Client` for Oracle (or stub if not available)
|
||||
- Returns success/failure with timing and error message
|
||||
|
||||
**Verification:** Build succeeds.
|
||||
|
||||
---
|
||||
|
||||
## Batch 3: Views (AXAML)
|
||||
|
||||
### Task 8: Create ConnectionStringsFormView.axaml
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/Views/Forms/ConnectionStringsFormView.axaml`
|
||||
|
||||
Create view with:
|
||||
1. Header section ("Connection Strings" with separator)
|
||||
2. Connections list section:
|
||||
- DataGrid with Name, Provider, Server columns
|
||||
- Height="200", selection mode single
|
||||
- Toolbar with Add, Delete buttons
|
||||
3. Placeholder section (when no selection):
|
||||
- "Select a connection string to edit" text
|
||||
4. Edit form section (when selection exists):
|
||||
- Name + Provider fields (always visible)
|
||||
- ContentControl with DataTemplates for provider-specific fields
|
||||
5. Action buttons section:
|
||||
- Validate, Test Connection buttons
|
||||
|
||||
Use existing form styling:
|
||||
- Background="#0D0F12", BorderBrush="#2D3540"
|
||||
- Input Background="#232A35"
|
||||
- FontFamily="JetBrains Mono" for values
|
||||
- MaxWidth="800" (wider than other forms for table)
|
||||
|
||||
**Verification:** Build succeeds and view renders.
|
||||
|
||||
---
|
||||
|
||||
### Task 9: Create provider-specific DataTemplates
|
||||
|
||||
Within ConnectionStringsFormView.axaml, create DataTemplates in UserControl.Resources:
|
||||
|
||||
**SqlServerTemplate:**
|
||||
- Server, Database fields (row)
|
||||
- UserId, Password fields (row, password with reveal button)
|
||||
- Encrypt dropdown, TrustServerCertificate checkbox (row)
|
||||
- ConnectionTimeout, ApplicationName fields (row)
|
||||
- Connection string preview box
|
||||
|
||||
**OracleTemplate:**
|
||||
- Host, Port fields (row)
|
||||
- ServiceName field
|
||||
- UserId, Password fields (row, password with reveal button)
|
||||
- ConnectionTimeout field
|
||||
- Connection string preview box
|
||||
|
||||
**GenericTemplate:**
|
||||
- Info banner explaining generic usage
|
||||
- Connection String multiline TextBox
|
||||
|
||||
Use ContentControl with binding to switch templates based on Provider.
|
||||
|
||||
**Verification:** Build succeeds, templates render correctly.
|
||||
|
||||
---
|
||||
|
||||
### Task 10: Create ConnectionStringsFormView.axaml.cs code-behind
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/Views/Forms/ConnectionStringsFormView.axaml.cs`
|
||||
|
||||
Standard Avalonia code-behind:
|
||||
|
||||
```csharp
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace JdeScoping.ConfigManager.Views.Forms;
|
||||
|
||||
public partial class ConnectionStringsFormView : UserControl
|
||||
{
|
||||
public ConnectionStringsFormView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Verification:** Build succeeds.
|
||||
|
||||
---
|
||||
|
||||
## Batch 4: Integration & Tests
|
||||
|
||||
### Task 11: Integrate into MainWindowViewModel
|
||||
|
||||
**File:** `NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/MainWindowViewModel.cs`
|
||||
|
||||
Updates needed:
|
||||
|
||||
1. In `BuildSettingsNodes()` method, add ConnectionStrings node:
|
||||
```csharp
|
||||
new TreeNodeViewModel("ConnectionStrings", "🔗", TreeNodeType.SettingsSection)
|
||||
{
|
||||
SectionKey = "ConnectionStrings"
|
||||
}
|
||||
```
|
||||
|
||||
2. In `LoadFormViewModelForNode()` method, add case for ConnectionStrings:
|
||||
```csharp
|
||||
"ConnectionStrings" => new ConnectionStringsFormViewModel(
|
||||
_appSettingsConfig!.ConnectionStrings,
|
||||
MarkCurrentNodeModified,
|
||||
_dialogService,
|
||||
_connectionTestService),
|
||||
```
|
||||
|
||||
3. Register `IConnectionTestService` in DI (App.axaml.cs or Program.cs)
|
||||
|
||||
**Verification:**
|
||||
- Build succeeds
|
||||
- ConnectionStrings appears in Settings tree
|
||||
- Clicking node shows form
|
||||
|
||||
---
|
||||
|
||||
### Task 12: Add unit tests
|
||||
|
||||
**File:** `NEW/tests/JdeScoping.ConfigManager.Tests/Models/ConnectionStringEntryTests.cs`
|
||||
|
||||
Test cases:
|
||||
- `GenerateConnectionString_SqlServer_ProducesCorrectFormat`
|
||||
- `GenerateConnectionString_SqlServer_OmitsDefaultTimeout`
|
||||
- `GenerateConnectionString_Oracle_ProducesEZConnectFormat`
|
||||
- `GenerateConnectionString_Generic_ReturnsRawString`
|
||||
- `DefaultValues_AreCorrect`
|
||||
|
||||
**File:** `NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/ConnectionStringEntryViewModelTests.cs`
|
||||
|
||||
Test cases:
|
||||
- `Constructor_InitializesFromModel`
|
||||
- `PropertyChange_UpdatesModel`
|
||||
- `PropertyChange_InvokesOnChanged`
|
||||
- `TogglePasswordVisibility_TogglesIsPasswordVisible`
|
||||
- `ProviderDisplay_ReturnsCorrectString`
|
||||
- `ServerDisplay_ReturnsServerForSqlServer`
|
||||
- `ServerDisplay_ReturnsHostForOracle`
|
||||
- `ServerDisplay_ReturnsDashForGeneric`
|
||||
|
||||
**File:** `NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/ConnectionStringsFormViewModelTests.cs`
|
||||
|
||||
Test cases:
|
||||
- `Constructor_InitializesFromModel`
|
||||
- `AddConnection_CreatesNewEntryAndSelectsIt`
|
||||
- `DeleteConnection_RemovesSelectedEntry`
|
||||
- `SelectedConnection_UpdatesHasSelection`
|
||||
- `HasSelection_IsFalseWhenNothingSelected`
|
||||
- `ConnectionCount_ReflectsCollectionSize`
|
||||
|
||||
**Verification:** All tests pass.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Batch | Tasks | Description |
|
||||
|-------|-------|-------------|
|
||||
| 1 | 1-4 | Data models (ConnectionProvider, ConnectionStringEntry, ConnectionStringsSection, ConfigModel update) |
|
||||
| 2 | 5-7 | ViewModels (ConnectionStringEntryViewModel, ConnectionStringsFormViewModel, IConnectionTestService) |
|
||||
| 3 | 8-10 | Views (ConnectionStringsFormView, DataTemplates, code-behind) |
|
||||
| 4 | 11-12 | Integration (MainWindowViewModel, DI registration) and unit tests |
|
||||
|
||||
## Post-Implementation Verification
|
||||
|
||||
After all tasks complete:
|
||||
|
||||
1. `dotnet build NEW/JdeScoping.slnx` - should succeed
|
||||
2. `dotnet test NEW/JdeScoping.slnx` - all tests should pass
|
||||
3. Run ConfigManager app:
|
||||
- Open a config folder
|
||||
- Navigate to Settings → ConnectionStrings
|
||||
- Add a new SqlServer connection
|
||||
- Fill in fields, verify preview updates
|
||||
- Test connection works
|
||||
- Save config, verify appsettings.json updated
|
||||
Reference in New Issue
Block a user