Public Access
Give the hosts board its vaults, and the Hetzner import a vault and a key
Six things, all of them answers to a question a screen was deciding on somebody's behalf. The board draws a heading per vault and sorts each vault's hosts by that vault's own groups. A group is an item of one vault, so drawing every group of every vault in one run flattened away containment that already exists: two vaults each holding a "production" were two headings with the same word on them, told apart by a small grey name beside each. Single- vault sessions are unchanged. There is now one "No group" heading per vault, so the folded set is keyed on SidebarGroupHeader.CollapseKey rather than on GroupId ?? Guid.Empty, which had one vault's unfiled hosts folding every other vault's away with them. A Ctrl-click starts its set with the card the board has lit. The board always has a selection — a fresh unlock lights the first host so CONNECT has something under it — so "one card lit, nothing ticked" is the state this screen opens in, and ticking a second card there produced a set of one: the machine the user was looking at was left out of the count and out of everything Delete, Move and Change group then ran over. The card tooltip says the host's name as well as its address. 214 pixels of card trims the name, and the tooltip was the one place it was not said in full. The card's floor drops from 120 to 104. A card with no tags measures about 87, so the mock's number was thirty pixels of air under every card on a board that is scrolled. "Move to another vault…" joins the board's context menu for one host. Moving one machine meant opening its pane and finding the menu inside it, while moving six was a right click away — the one-host case was the harder of the two. And the Hetzner import asks which vault and which key. A project belongs to a team more often than to a person, so forty servers landing wherever the session happens to be standing is the wrong default; ImportHostsAsync takes the target vault, and the ssh_config importer passes null and is unchanged. The key is the half Hetzner cannot supply and the keychain usually already holds — the public half went to Hetzner when the servers were made — so the import points every host at it rather than bringing one. It defaults to no key rather than guessing, and says so when the key it was given lives in a different vault from the hosts.
This commit is contained in:
1 parent
ed936380b3
commit
c859705b83
9 files changed
+926
-84
No files matched your search
@@ -457,11 +457,12 @@
|
||||
something that refuses it, leaving the window with nothing focused and the keystrokes going
|
||||
nowhere.
|
||||
|
||||
◆ EVERY GROUP, ONE AFTER ANOTHER, "No group" FIRST. Binds HostSections rather than VisibleHosts:
|
||||
the old grid held one level of a tree at a time, and this holds every group's cards at once, the
|
||||
way SidebarRows always has for the phone. A keychain nobody has filed anything in draws one
|
||||
section with no heading at all — see HostSectionViewModel.HasHeader — which is what makes the
|
||||
feature invisible until it is used.
|
||||
◆ EVERY VAULT, AND INSIDE EACH ONE EVERY GROUP, "No group" FIRST. Binds HostSections rather
|
||||
than VisibleHosts: the old grid held one level of a tree at a time, and this holds every group's
|
||||
cards at once, the way SidebarRows always has for the phone. A keychain nobody has filed
|
||||
anything in draws one section with no heading at all — see HostSectionViewModel.HasHeader —
|
||||
which is what makes the feature invisible until it is used. A session holding one vault draws no
|
||||
vault headings either, for the same reason and by the same rule.
|
||||
-->
|
||||
<ItemsControl x:Name="Board" Focusable="True" ItemsSource="{Binding HostSections}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
@@ -472,6 +473,27 @@
|
||||
<DataTemplate x:DataType="vm:HostSectionViewModel">
|
||||
<StackPanel Spacing="10">
|
||||
|
||||
<!--
|
||||
============ THE VAULT HEADING ============
|
||||
◆ THE BOARD'S OUTER LEVEL. A vault holds groups and a group holds hosts, and until this
|
||||
row existed the board drew only the inner two — every group of every vault in one run,
|
||||
told apart by a small grey vault name beside each heading. Two vaults each holding a
|
||||
"production" were two headings with the same word on them.
|
||||
|
||||
Drawn on the first section of each vault and nowhere else — see
|
||||
HostSectionViewModel.VaultHeading — and on no section at all where the board has one
|
||||
vault, which is what keeps a single-vault keychain looking exactly as it did. The rule
|
||||
to its right is the whole of the emphasis: this level is a divider with a name on it,
|
||||
not a heading competing with the group headings under it.
|
||||
-->
|
||||
<Grid ColumnDefinitions="Auto,*" IsVisible="{Binding StartsAVault}" Margin="0,2,0,2">
|
||||
<TextBlock Grid.Column="0" Text="{Binding VaultHeading}" FontSize="11.5"
|
||||
FontWeight="Bold" Foreground="{StaticResource Text}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
<Border Grid.Column="1" Height="1" Margin="10,0,0,0" VerticalAlignment="Center"
|
||||
Background="{StaticResource BorderSubtle}" />
|
||||
</Grid>
|
||||
|
||||
<!--
|
||||
============ THE SECTION HEADING ============
|
||||
"{label} · {count}", the vault name beside it when more than one vault is in play, a
|
||||
@@ -569,6 +591,18 @@
|
||||
Command="{Binding #Board.((vm:VaultViewModel)DataContext).OpenHostPaneCommand}" />
|
||||
<MenuItem Header="Edit…" IsVisible="{Binding !#Board.((vm:VaultViewModel)DataContext).IsChoosingHosts}"
|
||||
Command="{Binding #Board.((vm:VaultViewModel)DataContext).EditSelectedHostCommand}" />
|
||||
|
||||
<!--
|
||||
◆ THE SAME ENTRY THE DRAWER'S ⋯ MENU HAS, on the board where the host is. Moving
|
||||
one machine used to mean opening its pane first and then finding the menu inside
|
||||
it, while moving six was a right click away — the one-host case was the harder of
|
||||
the two, which is backwards. The command raises the drawer itself (see
|
||||
VaultViewModel.MoveHost); the picker it opens lives in that footer and nowhere
|
||||
else, and an entry that armed a panel nobody could see would be a menu item that
|
||||
did nothing.
|
||||
-->
|
||||
<MenuItem Header="Move to another vault…" IsVisible="{Binding !#Board.((vm:VaultViewModel)DataContext).IsChoosingHosts}"
|
||||
Command="{Binding #Board.((vm:VaultViewModel)DataContext).MoveHostCommand}" />
|
||||
<Separator IsVisible="{Binding !#Board.((vm:VaultViewModel)DataContext).IsChoosingHosts}" />
|
||||
<MenuItem Header="Delete…" IsVisible="{Binding !#Board.((vm:VaultViewModel)DataContext).IsChoosingHosts}"
|
||||
Command="{Binding #Board.((vm:VaultViewModel)DataContext).DeleteHostCommand}" />
|
||||
@@ -600,16 +634,26 @@
|
||||
The full address is on the tooltip and nowhere else on the card — the design's own
|
||||
rule, kept: a card read while scanning a section is read for its name and whether
|
||||
it is live, and an address is what somebody reads once they have found the machine,
|
||||
which the tooltip and the drawer both still say.
|
||||
which the tooltip and the drawer both still say. The name is on the tooltip too,
|
||||
and that is not duplication of the line six pixels above it: 214 pixels of card
|
||||
trims it, and the tooltip is where the untrimmed one lives. See
|
||||
HostRowViewModel.Tooltip.
|
||||
|
||||
MinHeight rather than a fixed Height, unlike the mock's own 120: this codebase's
|
||||
Border.tile is deliberately a fixed width and a free height (see App.axaml), so a
|
||||
card wearing four tags grows a second line rather than clipping the fourth one — a
|
||||
silent truncation is exactly the kind of thing the honesty rule in
|
||||
HANDOFF-hosts-v5.md exists to catch, and it costs nothing here to avoid.
|
||||
|
||||
◆ 104 RATHER THAN THE MOCK'S 120, and the floor is the only thing that moved. What
|
||||
a card with no tags actually needs is about 87 — 20 of padding, 43 of name and
|
||||
address, 24 for the row along the bottom — so 120 was thirty pixels of air below
|
||||
every card on a board that is scrolled. It is still a floor with room in it: the
|
||||
number is deliberately above what the content measures, so the common card is a
|
||||
uniform height rather than each one shrink-wrapping its own last line.
|
||||
-->
|
||||
<Border Classes="tile" Classes.chosen="{Binding IsChosen}" MinHeight="120"
|
||||
ToolTip.Tip="{Binding Address}">
|
||||
<Border Classes="tile" Classes.chosen="{Binding IsChosen}" MinHeight="104"
|
||||
ToolTip.Tip="{Binding Tooltip}">
|
||||
<Panel>
|
||||
<Grid RowDefinitions="Auto,*,Auto">
|
||||
|
||||
|
||||
Reference in new issue
Block a user