summary refs log tree commit diff
path: root/SystemdCtl.Client/Pages
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2024-01-20 08:34:32 +0100
committerRory& <root@rory.gay>2024-01-20 08:34:32 +0100
commit43e06f4b1b7ead9f8cc97fe547eb49d51f341486 (patch)
treeb700ba441320e0f3944c398080cadd296f03ef07 /SystemdCtl.Client/Pages
downloadSystemdCtl-43e06f4b1b7ead9f8cc97fe547eb49d51f341486.tar.xz
Initial commit
Diffstat (limited to 'SystemdCtl.Client/Pages')
-rw-r--r--SystemdCtl.Client/Pages/ServiceManage.razor66
-rw-r--r--SystemdCtl.Client/Pages/Services.razor154
2 files changed, 220 insertions, 0 deletions
diff --git a/SystemdCtl.Client/Pages/ServiceManage.razor b/SystemdCtl.Client/Pages/ServiceManage.razor
new file mode 100644
index 0000000..9a32087
--- /dev/null
+++ b/SystemdCtl.Client/Pages/ServiceManage.razor
@@ -0,0 +1,66 @@
+@page "/Service/{ServiceName}/Manage"

+@using LibSystemdCli.Models

+@using LibSystemdCli

+@using System.Text.RegularExpressions

+@using SystemdCtl.Client.Abstractions

+@* @attribute [StreamRendering] *@

+@rendermode InteractiveWebAssembly

+@inject NavigationManager NavigationManager

+

+

+<PageTitle>Manage @ServiceName</PageTitle>

+

+<h1>Manage @ServiceName</h1>

+

+@* //simple log view *@

+<div class="row">

+    <div class="col-12">

+        <h3>Logs</h3>

+        <div class="card">

+            <div class="card-body">

+                <pre>

+                    @foreach (var line in LogLines) {

+                        <span>@line</span><br/>

+                    }

+                </pre>

+            </div>

+        </div>

+    </div>

+</div>

+

+@code {

+

+    [Parameter]

+    public string ServiceName { get; set; } = "";

+

+    private static bool IsClient => !Environment.CommandLine.Contains("/");

+

+    private List<string> LogLines { get; set; } = new();

+

+    protected override async Task OnInitializedAsync() {

+        Console.WriteLine("OnInitializedAsync");

+        await Run();

+    }

+

+    private async Task Run() {

+        if (!IsClient) return;

+

+        LogLines.Clear();

+        var Http = new StreamingHttpClient() { BaseAddress = new Uri(NavigationManager.BaseUri) };

+        var _items = Http.GetAsyncEnumerableFromJsonAsync<string>($"/api/unit/{ServiceName}/logs");

+        await foreach (var item in _items) {

+            LogLines.Add(item);

+            if (LogLines.Count > 100) LogLines.RemoveAt(0);

+            StateHasChanged();

+        }

+    }

+

+    private string Capitalize(string input) {

+        return input switch {

+            null => throw new ArgumentNullException(nameof(input)),

+            "" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),

+            _ => input.First().ToString().ToUpper() + input[1..]

+        };

+    }

+

+}
\ No newline at end of file
diff --git a/SystemdCtl.Client/Pages/Services.razor b/SystemdCtl.Client/Pages/Services.razor
new file mode 100644
index 0000000..d0f67a7
--- /dev/null
+++ b/SystemdCtl.Client/Pages/Services.razor
@@ -0,0 +1,154 @@
+@page "/Services"

+@using LibSystemdCli.Models

+@using System.Text.RegularExpressions

+@using SystemdCtl.Client.Abstractions

+@using ArcaneLibs.Blazor.Components

+@* @attribute [StreamRendering] *@

+@rendermode InteractiveWebAssembly

+@inject NavigationManager NavigationManager

+

+

+<PageTitle>Services</PageTitle>

+

+<h1>Services</h1>

+

+<span>

+    <label>Type: </label>

+    <InputSelect @bind-Value="TypeFilter">

+        <option value="">All</option>

+        @foreach (var i in UnitTypes) {

+            <option value="@i">@Capitalize(i)</option>

+        }

+    </InputSelect>

+</span>

+<span>

+    <InputCheckbox @bind-Value="@ShowSystem"></InputCheckbox>

+    <label>Show system services</label>

+</span>

+

+@if (filteredItems is not { Count: > 0 }) {

+    <p>

+        <em>Loading...</em>

+    </p>

+}

+else {

+    <table class="table">

+        <thead>

+            <tr>

+                <th>Service</th>

+                <th>Description</th>

+                <th>Status</th>

+                <th></th>

+            </tr>

+        </thead>

+        <tbody>

+            @foreach (var unit in filteredItems) {

+                <tr>

+                    <td>@unit.Unit</td>

+                    <td>@unit.Description</td>

+                    <td>@unit.Active</td>

+                    <td><LinkButton href="@($"/Service/{unit.Unit}/Manage")">Manage</LinkButton></td>

+                </tr>

+                @foreach (var frag in unit.FragmentPaths) {

+                    <tr>

+                        <td/>

+                        <td>@frag</td>

+                        <td/>

+                    </tr>

+                }

+            }

+        </tbody>

+    </table>

+}

+

+@code {

+

+    private static Regex[] AlwaysHidden = new Regex[] {

+        //services

+        new Regex(@"^systemd-fsck@.*\.service$"),

+        new Regex(@"^modprobe@.*\.service$"),

+        new Regex(@"^xen.*\.service$"),

+        new Regex(@"^virt.*\.service$"),

+        new Regex(@"^libvirt.*\.service$"),

+        new Regex(@"^systemd-.*\.service$"),

+        //sockets

+        new Regex(@"^virt.*\.socket$"),

+        new Regex(@"^systemd.*\.socket$"),

+        new Regex(@"^libvirt.*\.socket$"),

+        //device

+        new(@"^dev-disk-by.*\.device$"),

+        new(@"^sys-device.*\.device$"),

+        new(@".*-by\\x2d.*\.device$"),

+        //mount

+        new(@"^run-credentials.*\.mount"),

+        //target

+        new(@"^blockdev@dev-disk-by.*\.target$")

+    };

+

+    private static bool IsClient => !Environment.CommandLine.Contains("/");

+    private List<SystemdUnitListItem>? items = new();

+    private List<SystemdUnitListItem>? filteredItems = new();

+    private List<string> UnitTypes = new();

+    private string _typeFilter = "";

+    private bool _showSystem;

+

+    public string TypeFilter {

+        get => _typeFilter;

+        set {

+            _typeFilter = value;

+            FilterItems();

+        }

+    }

+

+    public bool ShowSystem {

+        get => _showSystem;

+        set {

+            _showSystem = value;

+            FilterItems();

+        }

+    }

+

+    protected override async Task OnInitializedAsync() {

+        // await Task.Delay(500);

+

+        // items = await SystemdExecutor.GetUnits();

+        Console.WriteLine("OnInitializedAsync");

+        await ReloadItems();

+    }

+

+    private async Task ReloadItems() {

+        if (!IsClient) return;

+

+        items.Clear();

+        var Http = new StreamingHttpClient() { BaseAddress = new Uri(NavigationManager.BaseUri) };

+        var _items = Http.GetAsyncEnumerableFromJsonAsync<SystemdUnitListItem>("/api/listUnits");

+        await foreach (var item in _items) {

+            items.Add(item);

+            if (items.Count % 10 == 0)

+                await FilterItems();

+        }

+

+        await FilterItems();

+    }

+

+    private async Task FilterItems() {

+        var filter = items.Where(x => true);//!AlwaysHidden.Any(y => y.IsMatch(x.Unit)));

+        if (!_showSystem)

+            filter = filter.Where(x => !x.IsSystem);

+

+        UnitTypes = filter.Select(x => x.UnitType).Distinct().ToList();

+        filter = filter.Where(x => x.Unit.EndsWith(TypeFilter)).ToList();

+

+        filteredItems = filter.ToList();

+        StateHasChanged();

+    }

+

+    private string Capitalize(string input) {

+        return input switch {

+            null => throw new ArgumentNullException(nameof(input)),

+            "" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),

+            _ => input.First().ToString().ToUpper() + input[1..]

+        };

+    }

+

+}
\ No newline at end of file