diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f71bc1..7ae2b3d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
## [Unreleased]
+## [0.5.1] - 2026-08-24
+
+### Added
+
+- Release packaging can resolve enabled plugin `*Secret` values from **MaksIT Vault** when `useVault` is set in `scriptSettings.json` (PowerShell module or HTTP API; `Shared` application fallback).
+
+### Changed
+
+- Copying resource-table rows includes column headers, so Ctrl+C pastes into Excel as a TSV table.
+
+### Fixed
+
+- Copying resource-table rows no longer pastes empty quoted cells after CPU/memory tooltips moved columns to templates.
+
## [0.5.0] - 2026-08-22
### Added
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 579c277..65576d6 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -3,7 +3,7 @@
latest
enable
enable
- 0.5.0
+ 0.5.1
MaksIT.ClusterConsole
MaksIT.ClusterConsole
diff --git a/src/MaksIT.ClusterConsole.UI/MainWindow.axaml b/src/MaksIT.ClusterConsole.UI/MainWindow.axaml
index 650e681..5fab99c 100644
--- a/src/MaksIT.ClusterConsole.UI/MainWindow.axaml
+++ b/src/MaksIT.ClusterConsole.UI/MainWindow.axaml
@@ -551,6 +551,8 @@
IsReadOnly="True"
CanUserResizeColumns="True"
CanUserSortColumns="True"
+ ClipboardCopyMode="IncludeHeader"
+ CopyingRowClipboardContent="OnResourceGridCopyingRowClipboardContent"
DoubleTapped="OnResourceGridDoubleTapped" />
diff --git a/src/MaksIT.ClusterConsole.UI/MainWindow.axaml.cs b/src/MaksIT.ClusterConsole.UI/MainWindow.axaml.cs
index 8542a2e..c20715b 100644
--- a/src/MaksIT.ClusterConsole.UI/MainWindow.axaml.cs
+++ b/src/MaksIT.ClusterConsole.UI/MainWindow.axaml.cs
@@ -97,6 +97,29 @@ public partial class MainWindow : Window {
page.BrowseFilesCommand.Execute(null);
}
+ private void OnResourceGridCopyingRowClipboardContent(object? sender, DataGridRowClipboardEventArgs e) {
+ if (!e.IsColumnHeadersRow)
+ return;
+
+ for (var i = 0; i < e.ClipboardRowContent.Count; i++) {
+ var cell = e.ClipboardRowContent[i];
+ e.ClipboardRowContent[i] = new DataGridClipboardCellContent(
+ cell.Item,
+ cell.Column,
+ ColumnHeaderText(cell.Column));
+ }
+ }
+
+ private static string ColumnHeaderText(DataGridColumn column) {
+ if (column.Tag is string tag && !string.IsNullOrWhiteSpace(tag))
+ return tag;
+ if (column.Header is string header)
+ return header;
+ if (column.Header is Control { DataContext: ColumnFilterViewModel filter })
+ return filter.Header;
+ return column.Header?.ToString() ?? "";
+ }
+
private void RebuildColumns(MainViewModel viewModel) {
var grid = this.FindControl("ResourceGrid");
if (grid is null)
@@ -129,6 +152,7 @@ public partial class MainWindow : Window {
CanUserSort = true,
CustomSortComparer = comparer,
CellTemplate = StatusCellTemplate(),
+ ClipboardContentBinding = new Binding(nameof(ResourceRow.Status)) { Mode = BindingMode.OneWay },
Width = new DataGridLength(1, DataGridLengthUnitType.Star),
MinWidth = 72
};
@@ -140,6 +164,7 @@ public partial class MainWindow : Window {
CanUserSort = true,
CustomSortComparer = comparer,
CellTemplate = TextCellTemplate(header),
+ ClipboardContentBinding = CellsBinding(header),
Width = new DataGridLength(1, DataGridLengthUnitType.Star),
MinWidth = 72
};
@@ -151,10 +176,7 @@ public partial class MainWindow : Window {
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(6, 0)
};
- text.Bind(TextBlock.TextProperty, new Binding(nameof(ResourceRow.Cells)) {
- Mode = BindingMode.OneWay,
- Converter = new DictionaryKeyConverter(header)
- });
+ text.Bind(TextBlock.TextProperty, CellsBinding(header));
text.Bind(ToolTip.TipProperty, new Binding(nameof(ResourceRow.CellTips)) {
Mode = BindingMode.OneWay,
Converter = new DictionaryKeyConverter(header)
@@ -176,6 +198,12 @@ public partial class MainWindow : Window {
return text;
}, true);
+ private static Binding CellsBinding(string header) =>
+ new(nameof(ResourceRow.Cells)) {
+ Mode = BindingMode.OneWay,
+ Converter = new DictionaryKeyConverter(header)
+ };
+
private sealed class DictionaryKeyConverter(string key) : IValueConverter {
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) {
if (value is IReadOnlyDictionary cells && cells.TryGetValue(key, out var text))
diff --git a/src/MaksIT.ClusterConsole.UI/Themes/Dark.axaml b/src/MaksIT.ClusterConsole.UI/Themes/Dark.axaml
index ffe1317..eb8d56d 100644
--- a/src/MaksIT.ClusterConsole.UI/Themes/Dark.axaml
+++ b/src/MaksIT.ClusterConsole.UI/Themes/Dark.axaml
@@ -205,6 +205,7 @@
+