Port the Azure scope tree to ElevateCore - #195
Merged
Merged
Conversation
ArmScope and ScopeTree, transliterated from the C# added for #186 along with their tests, so the macOS Azure tab has the same tree to draw from and the two Cores do not drift. PanelFilter now searches the whole ARM path on this side too, which is the one behaviour change here: a row shows only the scope's caption, but "prod" should find an eligibility whose subscription is named in the path alone. The Azure tab itself is unchanged and still lists flat. This is the logic layer only — see the follow-up issue for the SwiftUI work. NOT COMPILED. Written on a Windows machine with no Swift toolchain, so 'swift test' has never run against it. The tests mirror the C# suite case for case and are the fastest way to find whatever this got wrong. Refs #186 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The search box reaching an Azure role's whole scope path is live on macOS the moment this merges, so it belongs under Unreleased rather than waiting for the tab's tree. CI caught the omission. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
FrodeHus
marked this pull request as ready for review
September 19, 2026 00:17
FrodeHus
added a commit
that referenced
this pull request
Sep 19, 2026
The Azure tab listed its eligibilities flat, which does not scale: a platform engineer eligible for Contributor on sixty subscriptions read sixty sibling rows and clicked sixty times before the single activation Elevate promised. Windows and the CLI got the tree in #186; the logic and its tests came across to ElevateCore in #195. This is the SwiftUI layer that draws it. AppModel gains the Azure tab's tree and the state around it, mirroring AppModel.Panel.cs: azureTree(for:) builds from the already-filtered rows, so a search narrows the tree rather than sitting beside it; collapsedScopes is keyed per tenant, because two accounts can reach the same scope; and isScopeCollapsed answers false while filtering, so a match is never hidden behind a node closed earlier. The subtree checkbox carries its own canSelect, stricter than canActivate: the rule for "is this row's checkbox enabled" lived in the view, and without it a scope checkbox would select rows whose own checkbox is off. A partly chosen subtree fills up rather than emptying — the checkbox is offering the rest. TenantRoles walks ScopeTree.flatten on the Azure tab and emits a ScopeRow or a RoleRow per entry. The two foldings the Core already performs are what keep the tree from costing more rows than it saves, so the view only has to respect them: a scope that just passes through is drawn as a dimmed "Alpha /" ahead of the title it was folded into, and a scope leading to a single role gets no header at all. Indent is 12 pt a step and stops after three; the panel is 380 pt wide and a management group path is longer than that, and the header's own path says where you are. Management groups sit beside the subscriptions, not above them, for the reason ArmScope documents. Verified on a Mac: 444 ElevateCore tests and 158 ElevateApp tests pass, and the app builds with no new warnings. The twelve new AppModelScopeTreeTests mirror the C# suite case for case and were watched failing first. The panel was also rendered offscreen in light and dark, with and without select mode, to check the folding, the elision and the three-state checkbox against real scopes. Closes #194 Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #186; the SwiftUI work is tracked in #194.
Built and tested on a Mac.
swift buildandswift testare clean — 437 ElevateCore tests pass, including the newArmScopeTestsandScopeTreeTests— and the ElevateApp Xcode target builds and passes its tests on top of the changedPanelFilter(Swift 6.4 / Xcode 26).#193 has merged, so this now targets
mainand has been brought up to date with it; the diff is macOS-only.What is here
ArmScopeandScopeTreein ElevateCore, transliterated from the C# added in #193 together with their tests, so the two Cores do not drift.PanelFilternow searches the whole ARM path on this side too — the one behaviour change, and the only thing here a user could notice: a row shows only the scope's caption, but "prod" should find an eligibility whose subscription is named in the path alone.The Azure tab itself is untouched and still lists flat.
The tests mirror the C# suite case for case, including the two that pin the decisions worth not re-litigating: management groups sit beside subscriptions rather than above them, and a pass-through scope is folded into the node below it.
Not here
Everything in #194: the
AppModelstate and accessors, theScopeRowview,TenantRoleswalkingflatten, and the macOS docs. Landing this on its own keeps the logic and its tests reviewable separately from the view, and means whoever picks up the SwiftUI has a green Core underneath them.🤖 Generated with Claude Code