from streamlit.delta_generator import DeltaGenerator from utility_classes.base_report_page import Renderable class NeoserraExportLinkGrabber(Renderable): """ Reusable UI component for capturing paired API endpoint URLs. This class encapsulates the state and presentation logic for modifying external data endpoints. By grouping the current and previous fiscal period URLs into a single renderable object, it standardizes the visual layout across the Admin Panel and isolates the input-capture logic from the parent page's batch validation pipeline. :param grabber_title: The unique display name for this URL grouping (e.g., 'Client List'). :type grabber_title: str :param prev_fy_initial_value: The existing configuration URL for the previous fiscal period. :type prev_fy_initial_value: str :param current_fy_initial_value: The existing configuration URL for the current fiscal period. :type current_fy_initial_value: str """ def __init__(self, grabber_title:str, prev_fy_initial_value:str, current_fy_initial_value:str): """ Initializes the component's state with existing configuration values. Pre-populates the internal state with the currently loaded external data endpoints. This ensures that when the component is rendered, administrators can audit or slightly modify the existing configuration rather than re-entering complex URLs from scratch. :param grabber_title: The unique title acting as the instance ID. :type grabber_title: str :param prev_fy_initial_value: The starting string value for the previous fiscal period input. :type prev_fy_initial_value: str :param current_fy_initial_value: The starting string value for the current fiscal period input. :type current_fy_initial_value: str """ super().__init__(grabber_title) self.prev_fy_url = prev_fy_initial_value self.current_fy_url = current_fy_initial_value self.title = grabber_title def render(self, container: DeltaGenerator): """ Maps the URL capture inputs to the provided Streamlit layout container. Constructs a visually distinct, bordered container to group the paired fiscal period endpoints together. It binds the text input widgets to the component's internal state, allowing the parent orchestrator to extract the modified strings during the form submission phase. :param container: The Streamlit layout container (typically a form) to draw the widgets onto. :type container: DeltaGenerator """ selector_container = container.container(border=True, key=self.get_widget_key("neoserra_export_url_selector_container")) selector_container.caption(self.title) prev_fy_url = selector_container.text_input("Previous Fiscal Year Export Module URL", key=self.get_widget_key("prev_fy_url_text_input"), value=self.prev_fy_url) current_fy_url = selector_container.text_input("Current Fiscal Year Export Module URL", key=self.get_widget_key("current_fy_url_text_input"), value=self.current_fy_url) self.prev_fy_url = prev_fy_url self.current_fy_url = current_fy_url def get_widget_key(self, widget_unique_id: str) -> str: """ Generates globally unique identifiers for the component's internal Streamlit widgets. Because the Admin Panel renders multiple instances of this exact class on the same page, this method prevents Streamlit `DuplicateWidgetID` execution crashes by prefixing the local widget ID (e.g., 'prev_fy_url_text_input') with the instance's unique title. :param widget_unique_id: The local identifier for the specific text input widget. :type widget_unique_id: str :return: A concatenated, globally unique string key. :rtype: str """ return f'{self.instance_id}_{widget_unique_id}'