(refactor): group client and UI sources by area and add Flathub and Store submission notes

This commit is contained in:
Maksym Sadovnychyy 2026-09-30 18:55:15 +02:00
parent 2423a433b6
commit d351df1d10
87 changed files with 365 additions and 134 deletions

View File

@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
## [Unreleased]
## [0.8.4] - 2026-09-30
### Added
- Flathub submission documents are in `packaging/flathub`.
- Microsoft Store text for the `runFullTrust` capability is in `packaging/microsoft-store/restricted-capabilities.md`.
### Changed
- Client and UI code is grouped by area: cluster session, kubeconfig, terminal, charts, editor, grid, and the shell, connection, and storage windows.
- AppStream includes screenshots, an age rating, and the kubeconfig step after install.
## [0.8.3] - 2026-09-29
### Added

View File

@ -57,6 +57,7 @@ Store listing copy:
| Product features (up to 20 bullets, 200 characters each) | [packaging/microsoft-store/product-features.md](packaging/microsoft-store/product-features.md) |
| Keywords (up to 7, 40 characters each, 21 words total) | [packaging/microsoft-store/keywords.md](packaging/microsoft-store/keywords.md) |
| Copyright, additional license terms, Developed by | [packaging/microsoft-store/additional-info.md](packaging/microsoft-store/additional-info.md) |
| Restricted capability `runFullTrust` | [packaging/microsoft-store/restricted-capabilities.md](packaging/microsoft-store/restricted-capabilities.md) |
| Store logos (9:16 poster, 1:1 box art, app tiles) | [packaging/microsoft-store/logos.md](packaging/microsoft-store/logos.md) |
### System requirements (Properties)
@ -85,6 +86,18 @@ The app is a win-x64 desktop console (tables, YAML, terminal). It does not use a
| Processor | x64 | Not specified |
| Graphics | Not specified | Not specified |
## Flathub
`FlatpakPack` writes the GitHub Release `.flatpak` from the linux-x64 publish. A Flathub submission builds a release tag from source. Open the pull request on [flathub/flathub](https://github.com/flathub/flathub) against `new-pr`.
| Field | Document |
|-------|----------|
| Pull request and local check | [packaging/flathub/submission.md](packaging/flathub/submission.md) |
| Upstream files and NuGet sources | [packaging/flathub/sources.md](packaging/flathub/sources.md) |
| Manifest values | [packaging/flathub/manifest.md](packaging/flathub/manifest.md) |
| Finish args | [packaging/flathub/permissions.md](packaging/flathub/permissions.md) |
| Verified app id | [packaging/flathub/verification.md](packaging/flathub/verification.md) |
## GitHub setup exe
The GitHub Windows installer stays the WiX Burn `setup.exe`. Its switches are `/quiet /norestart` (install), `/repair /quiet /norestart` (repair), and `/uninstall /quiet /norestart` (uninstall). Signing that exe for an EXE/MSI Store listing needs a Trusted Root Authenticode certificate and the Burn order: payload PEs, then the MSI, then `wix burn detach` / sign the engine / `wix burn reattach` / sign `setup.exe` ([WiX signing](https://docs.firegiant.com/wix/tools/signing/)).

View File

@ -9,6 +9,7 @@
<metadata_license>CC0-1.0</metadata_license>
<project_license>Apache-2.0</project_license>
<description>
<p>**After installation, point the app at a kubeconfig that can reach a running cluster (KUBECONFIG or ~/.kube/config).**</p>
<p>Browse a Kubernetes cluster from the desktop using your kubeconfig. Apply YAML, follow logs, exec into pods, and manage port-forwards without a browser.</p>
<p>Settings stay on this computer. Cluster access uses the network and files under the home folder (typically ~/.kube).</p>
<ul>
@ -32,7 +33,72 @@
<color type="primary" scheme_preference="light">#33A5CF</color>
<color type="primary" scheme_preference="dark">#003D7A</color>
</branding>
<content_rating type="oars-1.1"/>
<screenshots>
<screenshot type="default">
<image>https://raw.githubusercontent.com/MAKS-IT-COM/maksit-cluster-console/v0.8.3/assets/images/MaksIT.ClusterConsole.UI_jIJTQXS3pB.png</image>
<caption>Cluster overview</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/MAKS-IT-COM/maksit-cluster-console/v0.8.3/assets/images/MaksIT.ClusterConsole.UI_CmfgCLXO7x.png</image>
<caption>Applications table</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/MAKS-IT-COM/maksit-cluster-console/v0.8.3/assets/images/MaksIT.ClusterConsole.UI_FNf58xBr0a.png</image>
<caption>Pods table</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/MAKS-IT-COM/maksit-cluster-console/v0.8.3/assets/images/MaksIT.ClusterConsole.UI_k9oNwnqYrU.png</image>
<caption>Chat on a selected pod</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/MAKS-IT-COM/maksit-cluster-console/v0.8.3/assets/images/MaksIT.ClusterConsole.UI_VEkXUIQZ6N.png</image>
<caption>Volume files</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/MAKS-IT-COM/maksit-cluster-console/v0.8.3/assets/images/MaksIT.ClusterConsole.UI_zQePBIqSNT.png</image>
<caption>Dapr components</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/MAKS-IT-COM/maksit-cluster-console/v0.8.3/assets/images/MaksIT.ClusterConsole.UI_ktu7J3X0DP.png</image>
<caption>Port forwarding</caption>
</screenshot>
</screenshots>
<releases>
<release version="0.8.4" date="2026-09-30">
<url type="details">https://github.com/MAKS-IT-COM/maksit-cluster-console/blob/v0.8.4/CHANGELOG.md</url>
<description>
<p>Source folders follow the client and UI areas. Flathub and Store submission notes are in packaging.</p>
</description>
</release>
<release version="0.8.3" date="2026-09-29">
<url type="details">https://github.com/MAKS-IT-COM/maksit-cluster-console/blob/v0.8.3/CHANGELOG.md</url>
<description>
<p>Pod terminal, workload rollouts, storage and access actions, and YAML highlighting.</p>
</description>
</release>
</releases>
<content_rating type="oars-1.1">
<content_attribute id="violence-cartoon">none</content_attribute>
<content_attribute id="violence-fantasy">none</content_attribute>
<content_attribute id="violence-realistic">none</content_attribute>
<content_attribute id="violence-bloodshed">none</content_attribute>
<content_attribute id="violence-sexual">none</content_attribute>
<content_attribute id="drugs-alcohol">none</content_attribute>
<content_attribute id="drugs-narcotics">none</content_attribute>
<content_attribute id="drugs-tobacco">none</content_attribute>
<content_attribute id="sex-nudity">none</content_attribute>
<content_attribute id="sex-themes">none</content_attribute>
<content_attribute id="language-profanity">none</content_attribute>
<content_attribute id="language-humor">none</content_attribute>
<content_attribute id="language-discrimination">none</content_attribute>
<content_attribute id="social-chat">none</content_attribute>
<content_attribute id="social-info">none</content_attribute>
<content_attribute id="social-audio">none</content_attribute>
<content_attribute id="social-location">none</content_attribute>
<content_attribute id="social-contacts">none</content_attribute>
<content_attribute id="money-purchasing">none</content_attribute>
<content_attribute id="money-gambling">none</content_attribute>
</content_rating>
<requires>
<control>keyboard</control>
<control>pointing</control>

View File

@ -0,0 +1,28 @@
# Flathub manifest
Values for `com.maks_it.clusterconsole.yml` (or `.json`) at the top of the Flathub checkout.
| Item | Value |
|------|--------|
| Application id | `com.maks_it.clusterconsole` |
| Domain | `maks-it.com` |
| Homepage | [https://maks-it.com/](https://maks-it.com/) |
| Project | `src/MaksIT.ClusterConsole.UI/MaksIT.ClusterConsole.UI.csproj` |
| Target | `net10.0` |
| Source | Release tag on `https://github.com/MAKS-IT-COM/maksit-cluster-console` (currently `v0.8.4`) |
| Runtime | `org.freedesktop.Platform` |
| SDK | `org.freedesktop.Sdk` |
| SDK extension | `org.freedesktop.Sdk.Extension.dotnet10` |
| Runtimes | `linux-x64`, `linux-arm64`, self-contained |
| Command | `maksit-cluster-console` |
| Apphost | `MaksIT.ClusterConsole.UI` |
| Project license | `Apache-2.0` |
| Metadata license | `CC0-1.0` |
Publish the UI project. It references Shared. Tests stay out of the package. The Flatpak command matches the desktop `Exec`. The published apphost name is `MaksIT.ClusterConsole.UI`.
Use the newest Freedesktop branch that `org.freedesktop.Sdk.Extension.dotnet10` publishes, and the branch Flathub requires on the day of submission. Extension usage is in the [extension README](https://github.com/flathub/org.freedesktop.Sdk.Extension.dotnet10). Avalonia native libraries follow the runtime identifier.
`dotnet publish` uses `--source ./nuget-sources` before `--source /usr/lib/sdk/dotnet10/nuget/packages`.
The pull request steps are in [submission.md](submission.md). Source files are in [sources.md](sources.md). Finish args are in [permissions.md](permissions.md). Verification is in [verification.md](verification.md).

View File

@ -0,0 +1,19 @@
# Flathub permissions
Finish args for the manifest. The GitHub bundle uses this set. Keep the Flathub set to what the app uses.
```text
--share=ipc
--share=network
--socket=wayland
--socket=x11
--socket=pulseaudio
--device=dri
--filesystem=home
```
Network reaches the cluster API. Home covers `~/.kube`, a `KUBECONFIG` path under the home directory, settings under `~/.config`, and volume download and upload. X11 and Wayland are both present because Linux runs through X11/XWayland; Avalonia's native Wayland path hangs on GNOME. DRI is for GL rendering. The app has no audio feature; include pulseaudio only when a local run needs it.
A kubeconfig and a reachable cluster are required after install. The metainfo says so. The submission is from the project that maintains this repository.
The pull request steps are in [submission.md](submission.md). Manifest values are in [manifest.md](manifest.md). Verification is in [verification.md](verification.md).

View File

@ -0,0 +1,24 @@
# Flathub sources
Upstream files stay in this repository. The Flathub build installs them from the release tag.
| Path | Role |
|------|------|
| [data/com.maks_it.clusterconsole.metainfo.xml](../../data/com.maks_it.clusterconsole.metainfo.xml) | AppStream. Id `com.maks_it.clusterconsole`. |
| [data/com.maks_it.clusterconsole.desktop](../../data/com.maks_it.clusterconsole.desktop) | Launcher. `Exec=maksit-cluster-console`. `Terminal=false`. |
| [src/MaksIT.ClusterConsole.UI/Assets/icon.svg](../../src/MaksIT.ClusterConsole.UI/Assets/icon.svg) | Icon, installed as `share/icons/hicolor/scalable/apps/com.maks_it.clusterconsole.svg`. |
| [LICENSE.md](../../LICENSE.md) | Apache-2.0. Install to `$FLATPAK_DEST/share/licenses/com.maks_it.clusterconsole/` because the filename is `LICENSE.md`. |
Screenshot URLs in the metainfo use tag `v0.8.3`. The `0.8.4` release entry points at tag `v0.8.4`. On a newer release, point `<image>` and `<release>` at that tag or at a commit.
## Pull request
| File | Where |
|------|--------|
| `com.maks_it.clusterconsole.yml` or `.json` | Top of the Flathub checkout. Values are in [manifest.md](manifest.md). |
| NuGet sources | Generated, then committed in the pull request. The build has no network. |
| `flathub.json` | Only when one architecture is dropped. Both `x86_64` and `aarch64` stay in scope while both build. |
Generate the NuGet list with [flatpak-builder-tools/dotnet](https://github.com/flatpak/flatpak-builder-tools/tree/master/dotnet) or [Nickvision.FlatpakGenerator](https://github.com/nickvisionapps/flatpakgenerator).
The pull request steps are in [submission.md](submission.md). Finish args are in [permissions.md](permissions.md). Verification is in [verification.md](verification.md).

View File

@ -0,0 +1,21 @@
# Flathub submission
Open a pull request on [flathub/flathub](https://github.com/flathub/flathub) against the `new-pr` branch.
Title:
```text
Add com.maks_it.clusterconsole
```
Procedure: [Submission](https://docs.flathub.org/docs/for-app-authors/submission). Rules: [Requirements](https://docs.flathub.org/docs/for-app-authors/requirements). Metadata: [MetaInfo guidelines](https://docs.flathub.org/docs/for-app-authors/metainfo-guidelines). Runtimes: [Runtimes](https://docs.flathub.org/docs/for-app-authors/runtimes).
GitHub Releases keep the `FlatpakPack` bundle from the published `linux-x64` tree. Flathub compiles a release tag of this repository. Stable GitHub releases are the channel for the stable Flathub repository.
## Check
Build and install with `org.flatpak.Builder`, run `com.maks_it.clusterconsole`, and run `flatpak-builder-lint` on the manifest and on the local repo. Commands are on the submission page. AppStream warnings fail the linter.
Connect a kubeconfig, open a table, and confirm the window under X11/XWayland. Review comments stay on the same pull request. A test build is requested by commenting `bot, build`.
Sources are in [sources.md](sources.md). Manifest values are in [manifest.md](manifest.md). Finish args are in [permissions.md](permissions.md). Verification is in [verification.md](verification.md).

View File

@ -0,0 +1,9 @@
# Flathub verification
After the app is published, place this line in `https://maks-it.com/.well-known/org.flathub.VerifiedApps.txt`.
```text
com.maks_it.clusterconsole
```
The pull request steps are in [submission.md](submission.md). Manifest values are in [manifest.md](manifest.md). Finish args are in [permissions.md](permissions.md).

View File

@ -2,26 +2,24 @@
Paste into Partner Center → Store listings → **Product features**.
Short summaries of the product's key features. Displayed as a bulleted list. Up to 20 app features. Each feature is at most 200 characters.
Short summaries of the product's key features. The Store shows them as a bulleted list. Up to 20 app features. Each feature is at most 200 characters. Paste the sentence only; Partner Center adds the bullet.
```text
Set kubectl current-context from the catalog. The overview shows CPU, memory, and pod counts, and can patch container CPU and memory against node capacity.
Group applications by instance and namespace from standard labels. CPU is a percent of cluster allocatable. Memory is summed from owned pods when metrics are available.
Pod tables show ready, restarts, status, node, CPU, and memory. Follow logs, open a shell, and add an ephemeral debug container. Filters and sort stay per cluster.
Ask a local Ollama model about the selected resource. Chat can read issues, YAML, logs, and events only. It cannot apply, restart, or delete, and it does not call a cloud AI API.
Browse, edit, download, and upload files on a persistent volume or claim. Double-click a PV or PVC row to open the explorer.
Open Dapr from the navigator: components, configurations, subscriptions, resiliency, HTTP endpoints, sidecars, and the control plane.
Save port forwards, restore them on reconnect, and retarget a running pod. Double-click an active forward to open it in the browser. Rebind changes the local port.
Pick a cluster from the kubeconfig catalog. Access follows that identity's permissions.
Browse cluster, nodes, workloads, config, network, storage, namespaces, events, Helm, Dapr, access control, and custom resources, including CRDs installed in the cluster.
The open table watches the API. A label selector is sent with the list. Column filters and sort stay on this PC, per cluster.
View, apply, create, and delete resource YAML, including force delete. If the API server rejects an apply patch, apply falls back to create or replace.
Scale, restart, pause, resume, and undo workload rollouts. Trigger a CronJob. Cordon and drain nodes.
Resize a persistent volume claim. Change reclaim policy on a storage class and its volumes.
Approve or deny a certificate signing request. Create a ServiceAccount token and show it once.
Custom resource tables use extra columns from the CRD additionalPrinterColumns.
List Helm releases that are already installed in the cluster.
Show CPU and memory when the cluster has metrics-server.
```
- Set kubectl current-context from the catalog. The overview shows CPU, memory, and pod counts, and can patch container CPU and memory against node capacity.
- Group applications by instance and namespace from standard labels. CPU is a percent of cluster allocatable. Memory is summed from owned pods when metrics are available.
- Pod tables show ready, restarts, status, node, CPU, and memory. Follow logs, open a shell, and add an ephemeral debug container. Filters and sort stay per cluster.
- Ask a local Ollama model about the selected resource. Chat can read issues, YAML, logs, and events only. It cannot apply, restart, or delete, and it does not call a cloud AI API.
- Browse, edit, download, and upload files on a persistent volume or claim. Double-click a PV or PVC row to open the explorer.
- Open Dapr from the navigator: components, configurations, subscriptions, resiliency, HTTP endpoints, sidecars, and the control plane.
- Save port forwards, restore them on reconnect, and retarget a running pod. Double-click an active forward to open it in the browser. Rebind changes the local port.
- Pick a cluster from the kubeconfig catalog. Access follows that identity's permissions.
- Browse cluster, nodes, workloads, config, network, storage, namespaces, events, Helm, Dapr, access control, and custom resources, including CRDs installed in the cluster.
- The open table watches the API. A label selector is sent with the list. Column filters and sort stay on this PC, per cluster.
- View, apply, create, and delete resource YAML, including force delete. If the API server rejects an apply patch, apply falls back to create or replace.
- Scale, restart, pause, resume, and undo workload rollouts. Trigger a CronJob. Cordon and drain nodes.
- Resize a persistent volume claim. Change reclaim policy on a storage class and its volumes.
- Approve or deny a certificate signing request. Create a ServiceAccount token and show it once.
- Custom resource tables use extra columns from the CRD additionalPrinterColumns.
- List Helm releases that are already installed in the cluster.
- Show CPU and memory when the cluster has metrics-server.
The listing description and the other Store text fields are in [description.md](description.md).

View File

@ -0,0 +1,17 @@
# Microsoft Store restricted capabilities
Paste into Partner Center → Submission options. This product declares only `runFullTrust`.
The field holds 500 characters. [App capability declarations](https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations#special-and-restricted-capabilities) says a package with a full-trust app must declare `runFullTrust` or it cannot be installed. A full-trust app uses entry point `Windows.FullTrustApplication` and runs at medium integrity, outside an AppContainer.
## runFullTrust
Why do you need the `runFullTrust` capability, and how will it be used in your product?
```text
MaksIT Cluster Console is a full-trust Win32 app (.NET, Avalonia) packaged as MSIX. Windows.FullTrustApplication runs at medium integrity as the signed-in user, outside an AppContainer. runFullTrust is required for this package to install.
Used only for the user's kubeconfig (KUBECONFIG or %USERPROFILE%\.kube\config) and certificate files it names, local programs the kubeconfig already names, localhost port-forwards, and settings in %AppData%. No administrator rights or device capabilities.
```
Store listing text is in [description.md](description.md), [product-features.md](product-features.md), [keywords.md](keywords.md), and [additional-info.md](additional-info.md).

View File

@ -3,7 +3,7 @@
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>0.8.3</Version>
<Version>0.8.4</Version>
<Product>Cluster Console</Product>
<AssemblyTitle>Cluster Console</AssemblyTitle>
<Company>MaksIT</Company>

View File

@ -1,7 +1,7 @@
using k8s.Models;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public sealed record NodeUsage(
string Name,

View File

@ -1,7 +1,7 @@
using System.Text.Json.Nodes;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public sealed record ClusterSummary(
string GitVersion,

View File

@ -5,9 +5,10 @@ using System.Text.Json.Nodes;
using k8s;
using k8s.Models;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Internal;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public sealed partial class ClusterSession {
public const string FieldManager = "maksit-cluster-console";

View File

@ -3,9 +3,10 @@ using System.Text.Json.Nodes;
using k8s;
using k8s.Models;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Internal;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public sealed partial class ClusterSession {
private static readonly ResourceRef StorageClassRef = new("storage.k8s.io", "v1", "storageclasses", "StorageClass", false);

View File

@ -1,8 +1,10 @@
using k8s;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Internal;
using MaksIT.ClusterConsole.Client.Terminal;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public sealed partial class ClusterSession {
public async Task<Result<PodTerminalConnection>> OpenTerminalAsync(

View File

@ -7,9 +7,11 @@ using System.Runtime.CompilerServices;
using k8s;
using k8s.Models;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Internal;
using MaksIT.ClusterConsole.Client.KubeConfig;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public sealed partial class ClusterSession : IClusterSession {
private readonly Kubernetes _client;

View File

@ -1,7 +1,7 @@
using k8s.Models;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public sealed record WorkloadContainerLimit(
string Namespace,

View File

@ -1,9 +1,10 @@
using System.Text.Json.Nodes;
using k8s;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Terminal;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public interface IClusterSession : IDisposable {
string ContextName { get; }

View File

@ -2,7 +2,7 @@ using System.Globalization;
using System.Text.RegularExpressions;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public static class KubeQuantity {
private static readonly Regex Pattern = new(@"^\s*([+-]?\d+(?:\.\d+)?)([a-zA-Z]*)\s*$", RegexOptions.Compiled);

View File

@ -1,7 +1,7 @@
using System.Text.Json.Nodes;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public static class ReclaimPolicy {
public const string Delete = "Delete";

View File

@ -1,4 +1,4 @@
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public sealed record ResourceRef(
string Group,

View File

@ -1,7 +1,7 @@
using System.Text.Json.Nodes;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Cluster;
public static class RolloutHistory {
public const string RevisionAnnotation = "deployment.kubernetes.io/revision";

View File

@ -1,7 +1,7 @@
using System.Net;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Internal;
internal static class KubernetesApiRetry {
private const int MaxAttempts = 3;

View File

@ -3,7 +3,7 @@ using System.Text.Json.Nodes;
using MaksIT.Results;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Internal;
internal static class KubernetesResult {
public static Result Map(Exception ex) {

View File

@ -1,7 +1,7 @@
using System.Text.Json.Nodes;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Internal;
internal static class NamespaceListMerge {
public const string OrphanedPhase = "Orphaned";

View File

@ -2,7 +2,7 @@ using k8s;
using MaksIT.Results;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.KubeConfig;
public sealed record KubeContextInfo(
string Name,

View File

@ -2,7 +2,7 @@ using System.Diagnostics.CodeAnalysis;
using MaksIT.Core.Abstractions;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.KubeConfig;
public sealed class KubeAuthKind : Enumeration {
public static readonly KubeAuthKind Token = new(1, "token");

View File

@ -3,10 +3,11 @@ using System.Text.RegularExpressions;
using k8s;
using k8s.KubeConfigModels;
using YamlDotNet.Serialization;
using KubeCluster = k8s.KubeConfigModels.Cluster;
using YamlDotNet.Serialization.NamingConventions;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.KubeConfig;
internal static class KubeConfigEditor {
private static readonly Regex CurrentContextLine = new(
@ -109,12 +110,12 @@ internal static class KubeConfigEditor {
return request.ContextName.Trim();
}
public static Cluster UpsertCluster(K8SConfiguration config, KubeConnectionRequest request) {
public static KubeCluster UpsertCluster(K8SConfiguration config, KubeConnectionRequest request) {
var name = EffectiveClusterName(request, config);
var clusters = config.Clusters?.ToList() ?? [];
var cluster = clusters.FirstOrDefault(c => c.Name == name);
if (cluster is null) {
cluster = new Cluster { Name = name, ClusterEndpoint = new ClusterEndpoint() };
cluster = new KubeCluster { Name = name, ClusterEndpoint = new ClusterEndpoint() };
clusters.Add(cluster);
}

View File

@ -3,7 +3,7 @@ using k8s.Exceptions;
using MaksIT.Results;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.KubeConfig;
public sealed class KubeConfigService : IKubeConfigService {
public string GetWritablePath(string? kubeConfigPath = null) =>

View File

@ -1,4 +1,4 @@
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.KubeConfig;
public sealed record KubeContextDetails(
string Name,

View File

@ -3,7 +3,7 @@ using System.Text.Json;
using System.Text.Json.Nodes;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Terminal;
public static class PodShell {
public static string[] BuildCommand(string? shell) {

View File

@ -3,7 +3,7 @@ using System.Net.WebSockets;
using k8s;
namespace MaksIT.ClusterConsole.Client;
namespace MaksIT.ClusterConsole.Client.Terminal;
public sealed class PodTerminalConnection : IDisposable {
private readonly StreamDemuxer _demux;

View File

@ -1,6 +1,6 @@
using System.Globalization;
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,6 +1,6 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,6 +1,6 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,7 +1,7 @@
using System.Text;
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,6 +1,6 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,5 +1,5 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,5 +1,5 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,6 +1,6 @@
using System.Globalization;
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,7 +1,7 @@
using System.Net;
using System.Collections;
using System.Globalization;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -33,6 +33,6 @@ public sealed record ResourceDescriptor(
IReadOnlyList<ColumnSpec> Columns,
ResourceActions Actions,
IReadOnlyList<string> DetailTabs) {
public Client.ResourceRef ToRef() =>
public Client.Cluster.ResourceRef ToRef() =>
new(Group, Version, Plural, Kind, Namespaced);
}

View File

@ -1,6 +1,6 @@
using System.ComponentModel;
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Shared;

View File

@ -1,6 +1,6 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -2,9 +2,10 @@ using System.Text.Json;
using System.Text.Json.Nodes;
using k8s;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Shared.Chat;
using MaksIT.ClusterConsole.Client.Cluster;
using MaksIT.ClusterConsole.Client.Terminal;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,5 +1,5 @@
using k8s.Models;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,4 +1,4 @@
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.KubeConfig;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,5 +1,5 @@
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,5 +1,5 @@
using System.Net;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Internal;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,6 +1,6 @@
using System.Net;
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Internal;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,5 +1,5 @@
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Client.Internal;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,5 +1,5 @@
using System.Text;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,6 +1,6 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,5 +1,5 @@
using System.Text;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Terminal;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,5 +1,5 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -1,6 +1,6 @@
using System.Text.Json.Nodes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.Tests;

View File

@ -4,10 +4,12 @@ using Microsoft.Extensions.DependencyInjection;
using Avalonia;
using Avalonia.Markup.Xaml;
using Avalonia.Controls.ApplicationLifetimes;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.UI.ViewModels;
using MaksIT.ClusterConsole.UI.Windows;
using MaksIT.ClusterConsole.Client.Cluster;
using MaksIT.ClusterConsole.Client.Extensions;
using MaksIT.ClusterConsole.Client.KubeConfig;
using MaksIT.ClusterConsole.UI.ViewModels.Shell;
namespace MaksIT.ClusterConsole.UI;

View File

@ -3,7 +3,7 @@ using Avalonia.Controls;
using Avalonia.Media;
namespace MaksIT.ClusterConsole.UI.Controls;
namespace MaksIT.ClusterConsole.UI.Controls.Charts;
public sealed class ResourceBar : Control {
public static readonly StyledProperty<double> UsedProperty =

View File

@ -3,7 +3,7 @@ using Avalonia.Controls;
using Avalonia.Media;
namespace MaksIT.ClusterConsole.UI.Controls;
namespace MaksIT.ClusterConsole.UI.Controls.Charts;
public sealed class Sparkline : Control {
public static readonly StyledProperty<IReadOnlyList<double>?> ValuesProperty =

View File

@ -9,7 +9,7 @@ using MediaFontStyle = Avalonia.Media.FontStyle;
using ThemeFontStyle = TextMateSharp.Themes.FontStyle;
namespace MaksIT.ClusterConsole.UI.Controls;
namespace MaksIT.ClusterConsole.UI.Controls.Editor;
// TextMate's editor model tokenizes on a background thread, stops after 10_000
// characters on a line, and only repaints lines it still considers visible.

View File

@ -8,7 +8,7 @@ using MaksIT.ClusterConsole.Shared;
using TextMateSharp.Grammars;
namespace MaksIT.ClusterConsole.UI.Controls;
namespace MaksIT.ClusterConsole.UI.Controls.Editor;
public class SyntaxTextEditor : TextEditor {
public static readonly StyledProperty<string> TextProperty =

View File

@ -1,7 +1,7 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels"
x:Class="MaksIT.ClusterConsole.UI.Controls.ColumnFilterHeader"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels.Cluster"
x:Class="MaksIT.ClusterConsole.UI.Controls.Grid.ColumnFilterHeader"
x:DataType="vm:ColumnFilterViewModel">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Text="{Binding Header}"

View File

@ -1,9 +1,9 @@
using Avalonia.Controls;
using Avalonia.Input;
using MaksIT.ClusterConsole.UI.ViewModels;
using MaksIT.ClusterConsole.UI.ViewModels.Cluster;
namespace MaksIT.ClusterConsole.UI.Controls;
namespace MaksIT.ClusterConsole.UI.Controls.Grid;
public partial class ColumnFilterHeader : UserControl {
public ColumnFilterHeader() {

View File

@ -2,7 +2,7 @@ using Avalonia;
using Avalonia.Controls;
namespace MaksIT.ClusterConsole.UI.Controls;
namespace MaksIT.ClusterConsole.UI.Controls.Grid;
public static class DataGridColumns {
public static readonly AttachedProperty<bool> IndependentResizeProperty =

View File

@ -6,7 +6,7 @@ using Avalonia.VisualTree;
using MaksIT.ClusterConsole.Shared;
namespace MaksIT.ClusterConsole.UI;
namespace MaksIT.ClusterConsole.UI.Services;
internal sealed class LayoutPersistence {
private readonly Window _window;

View File

@ -1,6 +1,7 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:MaksIT.ClusterConsole.UI.Controls">
xmlns:editor="using:MaksIT.ClusterConsole.UI.Controls.Editor"
xmlns:grid="using:MaksIT.ClusterConsole.UI.Controls.Grid">
<Styles.Resources>
<Color x:Key="BrandHighlight">#33A5CF</Color>
<Color x:Key="BrandPrimary">#006199</Color>
@ -22,7 +23,7 @@
<Setter Property="FontFamily" Value="Segoe UI, Ubuntu, sans-serif" />
<Setter Property="FontSize" Value="13" />
</Style>
<Style Selector="controls|SyntaxTextEditor">
<Style Selector="editor|SyntaxTextEditor">
<Setter Property="FontFamily" Value="Cascadia Mono, Consolas, Ubuntu Mono, monospace" />
<Setter Property="FontSize" Value="12" />
<Setter Property="ShowLineNumbers" Value="True" />
@ -242,7 +243,7 @@
<Setter Property="VerticalGridLinesBrush" Value="#33383e" />
<Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ClipboardCopyMode" Value="IncludeHeader" />
<Setter Property="controls:DataGridColumns.IndependentResize" Value="True" />
<Setter Property="grid:DataGridColumns.IndependentResize" Value="True" />
</Style>
<Style Selector="DataGridRow:nth-child(even)">
<Setter Property="Background" Value="#22262a" />

View File

@ -7,7 +7,7 @@ using MaksIT.ClusterConsole.Shared.Chat;
using MaksIT.ClusterConsole.Client.Ollama;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Cluster;
public partial class ChatMessageViewModel : ObservableObject {
private TaskCompletionSource<bool>? _decision;

View File

@ -2,11 +2,11 @@ using System.Net.WebSockets;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MaksIT.ClusterConsole.Client;
using SvcSystems.UI.Terminal;
using MaksIT.ClusterConsole.Client.Terminal;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Cluster;
public partial class ClusterPageViewModel {
private PodTerminalConnection? _terminal;

View File

@ -6,13 +6,16 @@ using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MaksIT.Results;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Shared.Chat;
using MaksIT.ClusterConsole.Client.Ollama;
using MaksIT.ClusterConsole.Client.Cluster;
using MaksIT.ClusterConsole.Client.KubeConfig;
using MaksIT.ClusterConsole.UI.ViewModels.Shell;
using MaksIT.ClusterConsole.UI.ViewModels.Storage;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Cluster;
public partial class ClusterPageViewModel : ObservableObject, IDisposable {
private readonly ClusterWorkspace _workspace;

View File

@ -4,7 +4,7 @@ using CommunityToolkit.Mvvm.Input;
using MaksIT.ClusterConsole.Shared;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Cluster;
public partial class ColumnFilterValueViewModel : ObservableObject {
private readonly Action _changed;

View File

@ -1,8 +1,8 @@
using CommunityToolkit.Mvvm.ComponentModel;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Cluster;
public partial class LimitRowViewModel : ObservableObject {
public LimitRowViewModel(WorkloadContainerLimit source) {

View File

@ -1,9 +1,9 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.KubeConfig;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Connections;
public sealed record AuthKindChoice(string Id, string Title) {
public override string ToString() => Title;

View File

@ -1,10 +1,10 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Client.KubeConfig;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Connections;
public partial class ConnectionItemViewModel : ObservableObject {
public required KubeContextDetails Details { get; init; }

View File

@ -2,12 +2,17 @@ using System.Collections.ObjectModel;
using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Client.Ollama;
using MaksIT.ClusterConsole.UI.ViewModels;
using MaksIT.ClusterConsole.Client.Cluster;
using MaksIT.ClusterConsole.Client.KubeConfig;
using MaksIT.ClusterConsole.UI.ViewModels.Cluster;
using MaksIT.ClusterConsole.UI.ViewModels.Storage;
using MaksIT.ClusterConsole.UI.ViewModels.Connections;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Shell;
public partial class NavItemViewModel : ObservableObject {
public required NavigatorItem Item { get; init; }

View File

@ -1,10 +1,10 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MaksIT.ClusterConsole.Client;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.Client.Cluster;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Storage;
public partial class RetainReclaimViewModel : ObservableObject {
private readonly IClusterSession _session;

View File

@ -6,7 +6,7 @@ using CommunityToolkit.Mvvm.Input;
using MaksIT.ClusterConsole.Shared;
namespace MaksIT.ClusterConsole.UI.ViewModels;
namespace MaksIT.ClusterConsole.UI.ViewModels.Storage;
public sealed record LocalFilePick(string Name, byte[] Bytes);

View File

@ -1,6 +1,6 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels.Connections"
x:Class="MaksIT.ClusterConsole.UI.Windows.ConnectionWizardWindow"
x:DataType="vm:ConnectionWizardViewModel"
Title="Add connection"

View File

@ -1,7 +1,7 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using MaksIT.ClusterConsole.UI.ViewModels;
using MaksIT.ClusterConsole.UI.ViewModels.Connections;
namespace MaksIT.ClusterConsole.UI.Windows;
@ -67,4 +67,4 @@ public partial class ConnectionWizardWindow : Window {
];
}
public sealed record KubeConnectionRequestResult(MaksIT.ClusterConsole.Client.KubeConnectionRequest Request);
public sealed record KubeConnectionRequestResult(MaksIT.ClusterConsole.Client.KubeConfig.KubeConnectionRequest Request);

View File

@ -1,6 +1,6 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels.Connections"
x:Class="MaksIT.ClusterConsole.UI.Windows.ConnectionsWindow"
x:DataType="vm:ConnectionsViewModel"
Title="Connections"

View File

@ -1,5 +1,5 @@
using Avalonia.Controls;
using MaksIT.ClusterConsole.UI.ViewModels;
using MaksIT.ClusterConsole.UI.ViewModels.Connections;
namespace MaksIT.ClusterConsole.UI.Windows;

View File

@ -1,11 +1,13 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels"
xmlns:controls="using:MaksIT.ClusterConsole.UI.Controls"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels.Shell"
xmlns:cluster="using:MaksIT.ClusterConsole.UI.ViewModels.Cluster"
xmlns:charts="using:MaksIT.ClusterConsole.UI.Controls.Charts"
xmlns:editor="using:MaksIT.ClusterConsole.UI.Controls.Editor"
xmlns:shared="using:MaksIT.ClusterConsole.Shared"
xmlns:converters="using:MaksIT.ClusterConsole.UI.Converters"
xmlns:terminal="using:SvcSystems.UI.Terminal"
x:Class="MaksIT.ClusterConsole.UI.MainWindow"
x:Class="MaksIT.ClusterConsole.UI.Windows.MainWindow"
x:DataType="vm:MainViewModel"
Title="{x:Static shared:AppInfo.ProductName}"
Icon="/Assets/icon.ico"
@ -211,12 +213,12 @@
<TextBlock Grid.Column="1" Text="{Binding ActivePage.CpuCaption}" Classes="hint" />
</Grid>
<ProgressBar Grid.Row="1" Minimum="0" Maximum="100" Value="{Binding ActivePage.CpuPercent}" Height="8" Margin="0,8,0,8" />
<controls:Sparkline Grid.Row="2"
<charts:Sparkline Grid.Row="2"
Height="72"
HorizontalAlignment="Stretch"
Values="{Binding ActivePage.CpuHistory}"
LineBrush="#00a7a0" />
<controls:ResourceBar Grid.Row="3"
<charts:ResourceBar Grid.Row="3"
Height="20"
Margin="0,8,0,8"
HorizontalAlignment="Stretch"
@ -260,12 +262,12 @@
<TextBlock Grid.Column="1" Text="{Binding ActivePage.MemoryCaption}" Classes="hint" />
</Grid>
<ProgressBar Grid.Row="1" Minimum="0" Maximum="100" Value="{Binding ActivePage.MemoryPercent}" Height="8" Margin="0,8,0,8" />
<controls:Sparkline Grid.Row="2"
<charts:Sparkline Grid.Row="2"
Height="72"
HorizontalAlignment="Stretch"
Values="{Binding ActivePage.MemoryHistory}"
LineBrush="#C93DCE" />
<controls:ResourceBar Grid.Row="3"
<charts:ResourceBar Grid.Row="3"
Height="20"
Margin="0,8,0,8"
HorizontalAlignment="Stretch"
@ -309,7 +311,7 @@
<TextBlock Grid.Column="1" Text="{Binding ActivePage.PodCaption}" Classes="hint" />
</Grid>
<ProgressBar Grid.Row="1" Minimum="0" Maximum="100" Value="{Binding ActivePage.PodPercent}" Height="8" Margin="0,8,0,8" />
<controls:ResourceBar Grid.Row="2"
<charts:ResourceBar Grid.Row="2"
Height="20"
HorizontalAlignment="Stretch"
Used="{Binding ActivePage.PodSlice.Used}"
@ -350,8 +352,8 @@
<TextBlock Grid.Column="1" Text="{Binding Cpu.Caption}" Classes="hint" />
</Grid>
<ProgressBar Minimum="0" Maximum="100" Value="{Binding CpuPercent}" Height="8" />
<controls:Sparkline Height="72" HorizontalAlignment="Stretch" Values="{Binding CpuHistory}" LineBrush="#00a7a0" />
<controls:ResourceBar Height="16"
<charts:Sparkline Height="72" HorizontalAlignment="Stretch" Values="{Binding CpuHistory}" LineBrush="#00a7a0" />
<charts:ResourceBar Height="16"
HorizontalAlignment="Stretch"
Used="{Binding Cpu.Used}"
Requests="{Binding Cpu.Requests}"
@ -369,8 +371,8 @@
<TextBlock Grid.Column="1" Text="{Binding Memory.Caption}" Classes="hint" />
</Grid>
<ProgressBar Minimum="0" Maximum="100" Value="{Binding MemoryPercent}" Height="8" />
<controls:Sparkline Height="72" HorizontalAlignment="Stretch" Values="{Binding MemoryHistory}" LineBrush="#C93DCE" />
<controls:ResourceBar Height="16"
<charts:Sparkline Height="72" HorizontalAlignment="Stretch" Values="{Binding MemoryHistory}" LineBrush="#C93DCE" />
<charts:ResourceBar Height="16"
HorizontalAlignment="Stretch"
Used="{Binding Memory.Used}"
Requests="{Binding Memory.Requests}"
@ -388,7 +390,7 @@
<TextBlock Grid.Column="1" Text="{Binding Pods.Caption}" Classes="hint" />
</Grid>
<ProgressBar Minimum="0" Maximum="100" Value="{Binding PodPercent}" Height="8" />
<controls:ResourceBar Height="16"
<charts:ResourceBar Height="16"
HorizontalAlignment="Stretch"
Used="{Binding Pods.Used}"
Allocatable="{Binding Pods.Allocatable}"
@ -636,7 +638,7 @@
<Button Content="Apply YAML" Command="{Binding ActivePage.ApplyYamlCommand}" IsVisible="{Binding ActivePage.CanApplyYaml}" />
<TextBlock Text="Unsaved YAML" Classes="hint" IsVisible="{Binding ActivePage.IsDirty}" VerticalAlignment="Center" />
</StackPanel>
<controls:SyntaxTextEditor Text="{Binding ActivePage.YamlText}" PreferYaml="True" />
<editor:SyntaxTextEditor Text="{Binding ActivePage.YamlText}" PreferYaml="True" />
</DockPanel>
</TabItem>
<TabItem Header="Data" IsVisible="{Binding ActivePage.IsDataEditor}">
@ -651,7 +653,7 @@
Text="Value (multiline paste supported)"
Classes="hint"
Margin="0,0,0,4" />
<controls:SyntaxTextEditor Text="{Binding ActivePage.SelectedDataEntry.Value}"
<editor:SyntaxTextEditor Text="{Binding ActivePage.SelectedDataEntry.Value}"
FileName="{Binding ActivePage.SelectedDataEntry.Key}"
IsEnabled="{Binding ActivePage.HasSelectedDataEntry}" />
</DockPanel>
@ -788,7 +790,7 @@
<ScrollViewer>
<ItemsControl ItemsSource="{Binding ActivePage.ChatMessages}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:ChatMessageViewModel">
<DataTemplate x:DataType="cluster:ChatMessageViewModel">
<Border Classes="chat-bubble"
Classes.user="{Binding IsUser}"
Classes.assistant="{Binding IsAssistant}"

View File

@ -12,13 +12,15 @@ using Avalonia.Media;
using Avalonia.Threading;
using SvcSystems.UI.Terminal;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.UI.Controls;
using MaksIT.ClusterConsole.UI.Services;
using MaksIT.ClusterConsole.UI.Converters;
using MaksIT.ClusterConsole.UI.ViewModels;
using MaksIT.ClusterConsole.UI.Windows;
using MaksIT.ClusterConsole.UI.Controls.Grid;
using MaksIT.ClusterConsole.UI.ViewModels.Shell;
using MaksIT.ClusterConsole.UI.ViewModels.Cluster;
using MaksIT.ClusterConsole.UI.ViewModels.Storage;
namespace MaksIT.ClusterConsole.UI;
namespace MaksIT.ClusterConsole.UI.Windows;
public partial class MainWindow : Window {
private LayoutPersistence? _layout;

View File

@ -1,7 +1,7 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:client="using:MaksIT.ClusterConsole.Client"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels"
xmlns:client="using:MaksIT.ClusterConsole.Client.Cluster"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels.Storage"
x:Class="MaksIT.ClusterConsole.UI.Windows.RetainReclaimWindow"
x:DataType="vm:RetainReclaimViewModel"
Title="{Binding Title}"

View File

@ -1,5 +1,5 @@
using Avalonia.Controls;
using MaksIT.ClusterConsole.UI.ViewModels;
using MaksIT.ClusterConsole.UI.ViewModels.Storage;
namespace MaksIT.ClusterConsole.UI.Windows;

View File

@ -1,8 +1,8 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels"
xmlns:vm="using:MaksIT.ClusterConsole.UI.ViewModels.Storage"
xmlns:shared="using:MaksIT.ClusterConsole.Shared"
xmlns:controls="using:MaksIT.ClusterConsole.UI.Controls"
xmlns:editor="using:MaksIT.ClusterConsole.UI.Controls.Editor"
x:Class="MaksIT.ClusterConsole.UI.Windows.VolumeFilesWindow"
x:DataType="vm:VolumeFilesViewModel"
Title="{Binding WindowTitle}"
@ -61,7 +61,7 @@
Classes="hint"
Margin="0,0,0,8"
TextWrapping="Wrap" />
<controls:SyntaxTextEditor Text="{Binding EditorText}"
<editor:SyntaxTextEditor Text="{Binding EditorText}"
FileName="{Binding OpenFilePath}"
IsReadOnly="{Binding EditorReadOnly}" />
</DockPanel>

View File

@ -2,7 +2,7 @@ using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Platform.Storage;
using MaksIT.ClusterConsole.Shared;
using MaksIT.ClusterConsole.UI.ViewModels;
using MaksIT.ClusterConsole.UI.ViewModels.Storage;
namespace MaksIT.ClusterConsole.UI.Windows;