Add User Manager panel for sys::UserService components
New user_service_view.py with table of sys::User children, add/edit/delete dialogs, SHA-1 credential hashing, 32-bit permission bitmask (4 groups x 7 flags), 8-bit provisioning byte, and undo support. Wired into main.py with context menu entry, panel management, history navigation, and live-mode DOM resolution for correct display on connected devices. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import properties
|
||||
import sax_file
|
||||
import schema
|
||||
import undo
|
||||
import user_service_view
|
||||
import wiresheet
|
||||
from sax_dom import (find_component_by_path, find_parent_element, get_component_path,
|
||||
read_meta_property, update_meta_property)
|
||||
@@ -78,6 +79,7 @@ HISTORY_LIMIT = 50
|
||||
VIEW_SHEET = "sheet"
|
||||
VIEW_PROPERTIES = "properties"
|
||||
VIEW_LINKS = "links"
|
||||
VIEW_USERS = "users"
|
||||
|
||||
# Tk class names of the widgets that own the keyboard while they have focus. Del and
|
||||
# Backspace mean "edit this text" in each of them, never "delete the selected component".
|
||||
@@ -122,6 +124,7 @@ show_left_column_var = None
|
||||
properties_panel = None
|
||||
link_panel = None
|
||||
kits_panel = None
|
||||
user_service_panel = None
|
||||
|
||||
# The sheet to put the tree back on when a sheet change is refused because of unsaved
|
||||
# edits, and the flag that stops the restoring selection from being read as a fresh
|
||||
@@ -189,6 +192,12 @@ def refresh_all_views():
|
||||
else:
|
||||
close_editor_panel(force=True)
|
||||
|
||||
if user_service_panel is not None:
|
||||
if _component_in_document(user_service_panel.comp):
|
||||
user_service_panel.refresh()
|
||||
else:
|
||||
close_editor_panel(force=True)
|
||||
|
||||
|
||||
def _component_in_document(comp):
|
||||
root = app_state.xml_root_element
|
||||
@@ -210,7 +219,7 @@ def delete_component(comp):
|
||||
than going through refresh_all_views, so the panel would otherwise be left describing
|
||||
a component the document no longer has.
|
||||
"""
|
||||
panel = properties_panel or link_panel
|
||||
panel = properties_panel or link_panel or user_service_panel
|
||||
showing = panel is not None and panel.comp is comp
|
||||
if sax_file.execute_cascading_deletion(comp) and showing:
|
||||
close_editor_panel(force=True)
|
||||
@@ -218,7 +227,8 @@ def delete_component(comp):
|
||||
|
||||
def editor_panel_showing():
|
||||
"""Whether something other than the wiresheet has the editor pane."""
|
||||
return properties_panel is not None or link_panel is not None or kits_panel is not None
|
||||
return (properties_panel is not None or link_panel is not None
|
||||
or kits_panel is not None or user_service_panel is not None)
|
||||
|
||||
|
||||
def _take_editor_pane():
|
||||
@@ -330,6 +340,38 @@ def dismiss_link_view(restore_canvas=True):
|
||||
_give_editor_pane_back()
|
||||
|
||||
|
||||
def show_user_service(comp):
|
||||
"""Puts the User Manager for a sys::UserService in the editor pane."""
|
||||
global user_service_panel
|
||||
if comp is None:
|
||||
return
|
||||
|
||||
if not close_editor_panel():
|
||||
return
|
||||
|
||||
_take_editor_pane()
|
||||
user_service_panel = user_service_view.build_user_service_panel(
|
||||
frame_editor, comp, on_change=refresh_all_views,
|
||||
on_close=dismiss_user_service,
|
||||
)
|
||||
user_service_panel.frame.pack(fill=tk.BOTH, expand=True)
|
||||
record_visit(VIEW_USERS, comp)
|
||||
app_state.set_status(f"User Manager: {comp.get('name', '?')}")
|
||||
|
||||
|
||||
def dismiss_user_service(restore_canvas=True):
|
||||
"""Takes the User Manager down and gives the pane back."""
|
||||
global user_service_panel
|
||||
if user_service_panel is None:
|
||||
return
|
||||
|
||||
user_service_panel.destroy()
|
||||
user_service_panel = None
|
||||
|
||||
if restore_canvas:
|
||||
_give_editor_pane_back()
|
||||
|
||||
|
||||
def show_kits():
|
||||
"""Puts the kit table in the editor pane, in place of the wiresheet."""
|
||||
global kits_panel
|
||||
@@ -378,6 +420,9 @@ def close_editor_panel(force=False):
|
||||
if kits_panel is not None:
|
||||
dismiss_kits()
|
||||
return True
|
||||
if user_service_panel is not None:
|
||||
dismiss_user_service()
|
||||
return True
|
||||
if properties_panel is None:
|
||||
return True
|
||||
if force:
|
||||
@@ -1207,6 +1252,11 @@ def fill_component_popup(menu, comp):
|
||||
label="Link View",
|
||||
command=lambda: show_link_view(comp),
|
||||
)
|
||||
if user_service_view.is_user_service(comp):
|
||||
menu.add_command(
|
||||
label="User Manager",
|
||||
command=lambda: show_user_service(comp),
|
||||
)
|
||||
menu.add_separator()
|
||||
menu.add_command(
|
||||
label="Delete Component",
|
||||
@@ -1644,6 +1694,8 @@ def _show_history_entry(position):
|
||||
_show_sheet_entry(element)
|
||||
elif kind == VIEW_PROPERTIES:
|
||||
show_properties(element)
|
||||
elif kind == VIEW_USERS:
|
||||
show_user_service(element)
|
||||
else:
|
||||
show_link_view(element)
|
||||
finally:
|
||||
@@ -1707,7 +1759,7 @@ def on_tree_filled():
|
||||
|
||||
# A different file has no such component, and a rebuild after a delete may have taken
|
||||
# it. Neither is a moment to ask about edits that now have nowhere to go.
|
||||
panel = properties_panel or link_panel
|
||||
panel = properties_panel or link_panel or user_service_panel
|
||||
if panel is not None and not _component_in_document(panel.comp):
|
||||
close_editor_panel(force=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user