Skip to content

Commit e36ca43

Browse files
feat: Refactor Game Server Edit functionality with tabbed configuration
- Introduced GameServerEditViewModel to encapsulate game server data and configuration settings. - Updated GameServersController to handle new view model and fetch configuration namespaces. - Enhanced Edit.cshtml to support tabbed navigation for different configuration sections (General, FTP, RCON, Agent, Ban File Sync, Server List). - Created partial views for each configuration section to improve code organization and maintainability. - Implemented feature toggles for displaying relevant configuration tabs based on user permissions. - Added error handling for configuration saving processes and improved user feedback on updates.
1 parent ac9056f commit e36ca43

12 files changed

Lines changed: 651 additions & 222 deletions

src/XtremeIdiots.Portal.Web.Tests/XtremeIdiots.Portal.Web.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Nullable>enable</Nullable>
88
<IsPackable>false</IsPackable>
99
<!-- Suppress CA1707: Underscores in test method names are acceptable for readability -->
10-
<NoWarn>$(NoWarn);CA1707</NoWarn>
10+
<NoWarn>$(NoWarn);CA1707;CS0618</NoWarn>
1111
</PropertyGroup>
1212

1313
<ItemGroup>

src/XtremeIdiots.Portal.Web/Controllers/GameServersController.cs

Lines changed: 265 additions & 43 deletions
Large diffs are not rendered by default.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System.ComponentModel;
2+
using System.ComponentModel.DataAnnotations;
3+
4+
namespace XtremeIdiots.Portal.Web.ViewModels;
5+
6+
/// <summary>
7+
/// Composite view model for the game server edit page with tabbed configuration
8+
/// </summary>
9+
public class GameServerEditViewModel
10+
{
11+
/// <summary>
12+
/// Core game server data
13+
/// </summary>
14+
public GameServerViewModel GameServer { get; set; } = new();
15+
16+
// FTP configuration (parsed from "ftp" config namespace)
17+
18+
[DisplayName("FTP Hostname")]
19+
public string? FtpConfigHostname { get; set; }
20+
21+
[DisplayName("FTP Port")]
22+
public int FtpConfigPort { get; set; } = 21;
23+
24+
[DisplayName("FTP Username")]
25+
public string? FtpConfigUsername { get; set; }
26+
27+
[DisplayName("FTP Password")]
28+
[DataType(DataType.Password)]
29+
public string? FtpConfigPassword { get; set; }
30+
31+
// RCON configuration (parsed from "rcon" config namespace)
32+
33+
[DisplayName("RCON Password")]
34+
[DataType(DataType.Password)]
35+
public string? RconConfigPassword { get; set; }
36+
37+
// Agent configuration (parsed from "agent" config namespace)
38+
39+
[DisplayName("Log File Path")]
40+
public string? AgentConfigLogFilePath { get; set; }
41+
42+
[DisplayName("RCON Sync Enabled")]
43+
public bool AgentConfigRconSyncEnabled { get; set; } = true;
44+
45+
// Ban File Sync configuration (parsed from "banfiles" config namespace)
46+
47+
[DisplayName("Check Interval (seconds)")]
48+
[Range(10, 86400)]
49+
public int BanFileSyncConfigCheckIntervalSeconds { get; set; } = 60;
50+
51+
// Server List configuration (parsed from "serverlist" config namespace)
52+
53+
[DisplayName("Position")]
54+
public int ServerListConfigPosition { get; set; }
55+
56+
[DisplayName("HTML Banner")]
57+
[DataType(DataType.MultilineText)]
58+
public string? ServerListConfigHtmlBanner { get; set; }
59+
60+
// Auth flags for tab visibility
61+
62+
public bool CanEditFtp { get; set; }
63+
public bool CanEditRcon { get; set; }
64+
}

src/XtremeIdiots.Portal.Web/ViewModels/GameServerViewModel.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,37 +75,43 @@ public class GameServerViewModel
7575
/// Gets or sets whether live player tracking is enabled for this server
7676
/// </summary>
7777
[DisplayName("Live Tracking")]
78+
[Obsolete("Will be reviewed in a future version.")]
7879
public bool LiveTrackingEnabled { get; set; }
7980

8081
/// <summary>
8182
/// Gets or sets whether this server appears in the banner server list
8283
/// </summary>
8384
[DisplayName("Banner Server List")]
85+
[Obsolete("Replaced by ServerListEnabled. Will be removed in a future version.")]
8486
public bool BannerServerListEnabled { get; set; }
8587

8688
/// <summary>
8789
/// Gets or sets the display position in server lists
8890
/// </summary>
8991
[DisplayName("Position")]
92+
[Obsolete("Replaced by position in serverlist config namespace. Will be removed in a future version.")]
9093
public int ServerListPosition { get; set; }
9194

9295
/// <summary>
9396
/// Gets or sets the custom HTML banner content for this server
9497
/// </summary>
9598
[DataType(DataType.MultilineText)]
9699
[DisplayName("HTML Banner")]
100+
[Obsolete("Replaced by htmlBanner in serverlist config namespace. Will be removed in a future version.")]
97101
public string? HtmlBanner { get; set; }
98102

99103
/// <summary>
100104
/// Gets or sets whether this server appears in the portal server list
101105
/// </summary>
102106
[DisplayName("Portal Server List")]
107+
[Obsolete("Will be reviewed in a future version.")]
103108
public bool PortalServerListEnabled { get; set; }
104109

105110
/// <summary>
106111
/// Gets or sets whether bot functionality is enabled for this server
107112
/// </summary>
108113
[DisplayName("Bot")]
114+
[Obsolete("Legacy feature. Will be removed in a future version.")]
109115
public bool BotEnabled { get; set; }
110116

111117
/// <summary>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@using XtremeIdiots.Portal.Web.ViewModels
2+
@model GameServerEditViewModel
3+
4+
<div class="ibox">
5+
<div class="ibox-title">
6+
Agent Configuration
7+
</div>
8+
<div class="ibox-content">
9+
<div class="mb-3">
10+
<label asp-for="AgentConfigLogFilePath" class="control-label"></label>
11+
<input asp-for="AgentConfigLogFilePath" class="form-control" />
12+
<span asp-validation-for="AgentConfigLogFilePath" class="text-danger"></span>
13+
<small class="form-text text-muted">The file system path to the game server log file that the agent monitors.</small>
14+
</div>
15+
<div class="form-check mb-3">
16+
<label class="form-check-label">
17+
<input class="form-check-input" asp-for="AgentConfigRconSyncEnabled" />
18+
@Html.DisplayNameFor(m => m.AgentConfigRconSyncEnabled)
19+
</label>
20+
<small class="form-text text-muted d-block">When enabled, the agent will synchronize RCON commands with the game server.</small>
21+
</div>
22+
</div>
23+
</div>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
@using XtremeIdiots.Portal.Web.ViewModels
2+
@model GameServerEditViewModel
3+
4+
<div class="ibox">
5+
<div class="ibox-title">
6+
Ban File Sync Configuration
7+
</div>
8+
<div class="ibox-content">
9+
<div class="mb-3">
10+
<label asp-for="BanFileSyncConfigCheckIntervalSeconds" class="control-label"></label>
11+
<input asp-for="BanFileSyncConfigCheckIntervalSeconds" class="form-control" type="number" min="10" max="86400" />
12+
<span asp-validation-for="BanFileSyncConfigCheckIntervalSeconds" class="text-danger"></span>
13+
<small class="form-text text-muted">How often (in seconds) to check for ban file updates. Valid range: 10–86400 (default: 60).</small>
14+
</div>
15+
</div>
16+
</div>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
@using XtremeIdiots.Portal.Web.ViewModels
2+
@model GameServerEditViewModel
3+
4+
<div class="ibox">
5+
<div class="ibox-title">
6+
FTP Configuration
7+
</div>
8+
<div class="ibox-content">
9+
<div class="mb-3">
10+
<label asp-for="FtpConfigHostname" class="control-label"></label>
11+
<input asp-for="FtpConfigHostname" class="form-control" />
12+
<span asp-validation-for="FtpConfigHostname" class="text-danger"></span>
13+
<small class="form-text text-muted">The hostname or IP address of the FTP server for file transfers.</small>
14+
</div>
15+
<div class="mb-3">
16+
<label asp-for="FtpConfigPort" class="control-label"></label>
17+
<input asp-for="FtpConfigPort" class="form-control" type="number" />
18+
<span asp-validation-for="FtpConfigPort" class="text-danger"></span>
19+
<small class="form-text text-muted">FTP port number (default: 21).</small>
20+
</div>
21+
<div class="mb-3">
22+
<label asp-for="FtpConfigUsername" class="control-label"></label>
23+
<input asp-for="FtpConfigUsername" class="form-control" />
24+
<span asp-validation-for="FtpConfigUsername" class="text-danger"></span>
25+
<small class="form-text text-muted">Username for FTP authentication.</small>
26+
</div>
27+
<div class="mb-3">
28+
<label asp-for="FtpConfigPassword" class="control-label"></label>
29+
<input asp-for="FtpConfigPassword" class="form-control" type="password" />
30+
<span asp-validation-for="FtpConfigPassword" class="text-danger"></span>
31+
<small class="form-text text-muted">Password for FTP authentication.</small>
32+
</div>
33+
</div>
34+
</div>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
@using XtremeIdiots.Portal.Web.ViewModels
2+
@model GameServerEditViewModel
3+
4+
<div class="ibox">
5+
<div class="ibox-title">
6+
General
7+
</div>
8+
<div class="ibox-content">
9+
<div class="mb-3">
10+
<label asp-for="GameServer.GameType" class="control-label"></label>
11+
<select asp-for="GameServer.GameType" class="form-control" asp-items="ViewBag.GameType"
12+
disabled="disabled"></select>
13+
<input type="hidden" asp-for="GameServer.GameType" />
14+
<span asp-validation-for="GameServer.GameType" class="text-danger"></span>
15+
</div>
16+
<div class="mb-3">
17+
<label asp-for="GameServer.Title" class="control-label"></label>
18+
<input asp-for="GameServer.Title" class="form-control" />
19+
<span asp-validation-for="GameServer.Title" class="text-danger"></span>
20+
</div>
21+
<div class="mb-3">
22+
<label asp-for="GameServer.Hostname" class="control-label"></label>
23+
<input asp-for="GameServer.Hostname" class="form-control" />
24+
<span asp-validation-for="GameServer.Hostname" class="text-danger"></span>
25+
</div>
26+
<div class="mb-3">
27+
<label asp-for="GameServer.QueryPort" class="control-label"></label>
28+
<input asp-for="GameServer.QueryPort" class="form-control" />
29+
<span asp-validation-for="GameServer.QueryPort" class="text-danger"></span>
30+
</div>
31+
32+
<hr />
33+
<h6 class="text-muted">Legacy Toggles</h6>
34+
35+
<div class="form-check mb-3">
36+
<label class="form-check-label">
37+
<input class="form-check-input feature-toggle" asp-for="GameServer.PortalServerListEnabled" />
38+
@Html.DisplayNameFor(m => m.GameServer.PortalServerListEnabled)
39+
<span class="badge bg-warning text-dark">Legacy</span>
40+
</label>
41+
</div>
42+
<div class="form-check mb-3">
43+
<label class="form-check-label">
44+
<input class="form-check-input feature-toggle" asp-for="GameServer.LiveTrackingEnabled" />
45+
@Html.DisplayNameFor(m => m.GameServer.LiveTrackingEnabled)
46+
<span class="badge bg-warning text-dark">Legacy</span>
47+
</label>
48+
</div>
49+
<div class="form-check mb-3">
50+
<label class="form-check-label">
51+
<input class="form-check-input feature-toggle" asp-for="GameServer.BannerServerListEnabled" />
52+
@Html.DisplayNameFor(m => m.GameServer.BannerServerListEnabled)
53+
<span class="badge bg-warning text-dark">Legacy</span>
54+
</label>
55+
</div>
56+
<div class="form-check mb-3">
57+
<label class="form-check-label">
58+
<input class="form-check-input feature-toggle" asp-for="GameServer.BotEnabled" />
59+
@Html.DisplayNameFor(m => m.GameServer.BotEnabled)
60+
<span class="badge bg-warning text-dark">Legacy</span>
61+
</label>
62+
</div>
63+
64+
<hr />
65+
<h6 class="text-muted">Integration Toggles</h6>
66+
67+
<div class="form-check mb-3">
68+
<label class="form-check-label">
69+
<input class="form-check-input feature-toggle" asp-for="GameServer.FtpEnabled"
70+
data-toggle-tab="ftp-tab-btn" />
71+
@Html.DisplayNameFor(m => m.GameServer.FtpEnabled)
72+
</label>
73+
</div>
74+
<div class="form-check mb-3">
75+
<label class="form-check-label">
76+
<input class="form-check-input feature-toggle" asp-for="GameServer.RconEnabled"
77+
data-toggle-tab="rcon-tab-btn" />
78+
@Html.DisplayNameFor(m => m.GameServer.RconEnabled)
79+
</label>
80+
</div>
81+
<div class="form-check mb-3">
82+
<label class="form-check-label">
83+
<input class="form-check-input feature-toggle" asp-for="GameServer.AgentEnabled"
84+
data-toggle-tab="agent-tab-btn" />
85+
@Html.DisplayNameFor(m => m.GameServer.AgentEnabled)
86+
</label>
87+
</div>
88+
<div class="form-check mb-3">
89+
<label class="form-check-label">
90+
<input class="form-check-input feature-toggle" asp-for="GameServer.BanFileSyncEnabled"
91+
data-toggle-tab="banfilesync-tab-btn" />
92+
@Html.DisplayNameFor(m => m.GameServer.BanFileSyncEnabled)
93+
</label>
94+
</div>
95+
<div class="form-check mb-3">
96+
<label class="form-check-label">
97+
<input class="form-check-input feature-toggle" asp-for="GameServer.ServerListEnabled"
98+
data-toggle-tab="serverlist-tab-btn" />
99+
@Html.DisplayNameFor(m => m.GameServer.ServerListEnabled)
100+
</label>
101+
</div>
102+
</div>
103+
</div>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
@using XtremeIdiots.Portal.Web.ViewModels
2+
@model GameServerEditViewModel
3+
4+
<div class="ibox">
5+
<div class="ibox-title">
6+
RCON Configuration
7+
</div>
8+
<div class="ibox-content">
9+
<div class="mb-3">
10+
<label asp-for="RconConfigPassword" class="control-label"></label>
11+
<input asp-for="RconConfigPassword" class="form-control" type="password" />
12+
<span asp-validation-for="RconConfigPassword" class="text-danger"></span>
13+
<small class="form-text text-muted">The RCON password used for remote server administration.</small>
14+
</div>
15+
</div>
16+
</div>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@using XtremeIdiots.Portal.Web.ViewModels
2+
@model GameServerEditViewModel
3+
4+
<div class="ibox">
5+
<div class="ibox-title">
6+
Server List Configuration
7+
</div>
8+
<div class="ibox-content">
9+
<div class="mb-3">
10+
<label asp-for="ServerListConfigPosition" class="control-label"></label>
11+
<input asp-for="ServerListConfigPosition" class="form-control" type="number" />
12+
<span asp-validation-for="ServerListConfigPosition" class="text-danger"></span>
13+
<small class="form-text text-muted">Display order position in the server list. Lower values appear first.</small>
14+
</div>
15+
<div class="mb-3">
16+
<label asp-for="ServerListConfigHtmlBanner" class="control-label"></label>
17+
<textarea asp-for="ServerListConfigHtmlBanner" class="form-control" style="height: 200px"></textarea>
18+
<span asp-validation-for="ServerListConfigHtmlBanner" class="text-danger"></span>
19+
<small class="form-text text-muted">Custom HTML banner content displayed for this server in the server list.</small>
20+
</div>
21+
</div>
22+
</div>

0 commit comments

Comments
 (0)