🔍 Code Extractor

class DocumentShareManager

Maturity: 56

A Panel-based UI component for managing document sharing permissions, displaying share URLs, and viewing user access information for controlled documents.

File:
/tf/active/vicechatdev/CDocs/ui/components/share_manager.py
Lines:
115 - 311
Complexity:
moderate

Purpose

DocumentShareManager provides a comprehensive user interface for document sharing management in a document control system. It displays document information, generates and displays shareable URLs, shows current user permissions in a table format, and allows refreshing of permission data. The component integrates with a document control backend to fetch and display real-time sharing information, making it easy for users to manage who has access to specific document versions.

Source Code

class DocumentShareManager(param.Parameterized):
    """
    UI Component for managing document sharing.
    
    This component provides a UI for viewing and managing document 
    sharing permissions, including:
    - Viewing current share URL
    - Viewing current users with access
    - Granting/revoking access
    """
    document_uid = param.String(default="")
    user_uid = param.String(default="")
    
    def __init__(self, **params):
        super().__init__(**params)
        
        # Create UI components
        self.title = pn.pane.Markdown("## Document Sharing")
        
        self.document_info = pn.pane.Markdown("Loading document information...")
        
        self.access_url_input = pn.widgets.TextInput(
            name="Document Access URL",
            value="",
            disabled=True,
            width=400
        )
        
        self.copy_url_button = pn.widgets.Button(
            name="Copy URL",
            button_type="primary",
            width=100,
            disabled=True
        )
        
        self.copy_url_button.on_click(self._copy_url_to_clipboard)
        
        self.update_button = pn.widgets.Button(
            name="Refresh Permissions",
            button_type="default",
            width=150
        )
        
        self.update_button.on_click(self._refresh_permissions)
        
        self.message_area = pn.pane.Markdown("")
        
        # Current access table
        self.access_table = pn.widgets.Tabulator(
            pd.DataFrame(columns=["User", "Role", "Access Type", "Last Updated"]),
            height=300,
            width=500
        )
        
        # Layout
        self.layout = pn.Column(
            self.title,
            self.document_info,
            pn.Row(
                self.access_url_input,
                self.copy_url_button
            ),
            pn.layout.Divider(),
            pn.pane.Markdown("### Current Access"),
            self.access_table,
            pn.Row(
                self.update_button,
                pn.layout.HSpacer(),
                self.message_area
            )
        )
        
        # Initialize
        self._update_display()
    
    def _update_display(self):
        """Update the display with current document sharing information."""
        if not self.document_uid:
            self.document_info.object = "No document selected."
            return
            
        try:
            # Get document and version
            document = ControlledDocument(uid=self.document_uid)
            
            if not document:
                self.document_info.object = "Document not found."
                return
                
            # Update document info
            self.document_info.object = f"""
            **Document**: {document.title}  
            **Document Number**: {document.doc_number}  
            **Status**: {document.get_status_name()}
            """
            
            # Get current version
            version = document.current_version
            
            if not version:
                self.access_url_input.value = "No current version available"
                self.copy_url_button.disabled = True
                return
                
            # Get access URL
            if self.user_uid:
                result = get_user_access_url(version, self.user_uid)
                if result.get('success', False) and result.get('share_url'):
                    self.access_url_input.value = result.get('share_url')
                    self.copy_url_button.disabled = False
                else:
                    self.access_url_input.value = f"Error: {result.get('message', 'Unable to get access URL')}"
                    self.copy_url_button.disabled = True
            else:
                # Just get a general share URL
                share_url = get_document_share_url(version)
                if share_url:
                    self.access_url_input.value = share_url
                    self.copy_url_button.disabled = False
                else:
                    self.access_url_input.value = "Unable to get access URL"
                    self.copy_url_button.disabled = True
            
            # Update access table
            # This would require fetching permission information from the share API
            # For the demo, we'll just show static data
            perm_result = manage_document_permissions(document)
            
            if perm_result.get('success', False) and 'details' in perm_result:
                access_data = []
                for user_perm in perm_result.get('details', []):
                    access_data.append({
                        "User": user_perm.get('user', 'Unknown'),
                        "Role": user_perm.get('role', 'User'),
                        "Access Type": "Edit" if user_perm.get('write_access', False) else "Read Only",
                        "Last Updated": datetime.now().strftime("%Y-%m-%d %H:%M")
                    })
                
                self.access_table.value = pd.DataFrame(access_data)
            else:
                self.access_table.value = pd.DataFrame([{
                    "User": "Error fetching permissions",
                    "Role": "",
                    "Access Type": "",
                    "Last Updated": ""
                }])
                
        except Exception as e:
            logger.error(f"Error updating share display: {e}")
            self.document_info.object = f"Error: {str(e)}"
    
    def _copy_url_to_clipboard(self, event):
        """Copy the access URL to clipboard."""
        if not self.access_url_input.value:
            return
            
        try:
            import pyperclip
            pyperclip.copy(self.access_url_input.value)
            self.message_area.object = "✅ URL copied to clipboard"
            self.message_area.style = {'color': 'green'}
        except ImportError:
            # If pyperclip is not available, show the message to manually copy
            self.message_area.object = "Please manually copy the URL"
            self.message_area.style = {'color': 'orange'}
    
    def _refresh_permissions(self, event):
        """Refresh document permissions."""
        if not self.document_uid:
            return
            
        try:
            document = ControlledDocument(uid=self.document_uid)
            if not document:
                self.message_area.object = "Document not found"
                self.message_area.style = {'color': 'red'}
                return
                
            result = manage_document_permissions(document)
            
            if result.get('success', False):
                self.message_area.object = "✅ Permissions updated successfully"
                self.message_area.style = {'color': 'green'}
                # Update the display
                self._update_display()
            else:
                self.message_area.object = f"❌ Error: {result.get('message', 'Unknown error')}"
                self.message_area.style = {'color': 'red'}
                
        except Exception as e:
            logger.error(f"Error refreshing permissions: {e}")
            self.message_area.object = f"❌ Error: {str(e)}"
            self.message_area.style = {'color': 'red'}
    
    def view(self):
        """Return the layout for display."""
        return self.layout

Parameters

Name Type Default Kind
bases param.Parameterized -

Parameter Details

document_uid: String parameter representing the unique identifier of the document to manage. Must be a valid UID from the ControlledDocument system. When empty, the component displays a 'No document selected' message.

user_uid: String parameter representing the unique identifier of the user for whom to generate a personalized access URL. When provided, generates a user-specific share URL; when empty, generates a general document share URL.

Return Value

The class constructor returns a DocumentShareManager instance with initialized UI components and layout. The view() method returns a Panel Column layout object containing all UI elements (title, document info, URL input, buttons, access table) ready for display in a Panel application. Internal methods return None (event handlers) or update component state.

Class Interface

Methods

__init__(self, **params) -> None

Purpose: Initialize the DocumentShareManager with UI components, layout, and event handlers

Parameters:

  • params: Keyword arguments passed to param.Parameterized parent class, typically document_uid and user_uid

Returns: None - initializes instance with all UI components and triggers initial display update

_update_display(self) -> None

Purpose: Update all UI components with current document sharing information, including document details, share URL, and permissions table

Returns: None - updates instance attributes (document_info, access_url_input, access_table) with current data

_copy_url_to_clipboard(self, event) -> None

Purpose: Event handler to copy the document access URL to the system clipboard using pyperclip

Parameters:

  • event: Panel button click event object (automatically passed by Panel framework)

Returns: None - copies URL to clipboard and updates message_area with success/error message

_refresh_permissions(self, event) -> None

Purpose: Event handler to refresh document permissions from the backend and update the display

Parameters:

  • event: Panel button click event object (automatically passed by Panel framework)

Returns: None - fetches fresh permission data and updates UI components with results

view(self) -> pn.Column

Purpose: Return the complete Panel layout for rendering in a Panel application

Returns: Panel Column object containing all UI components arranged in the defined layout structure

Attributes

Name Type Description Scope
document_uid param.String Parameter storing the unique identifier of the document being managed, defaults to empty string instance
user_uid param.String Parameter storing the unique identifier of the user for personalized access URLs, defaults to empty string instance
title pn.pane.Markdown Markdown pane displaying the component title '## Document Sharing' instance
document_info pn.pane.Markdown Markdown pane displaying document details (title, number, status) or loading/error messages instance
access_url_input pn.widgets.TextInput Disabled text input widget displaying the generated document access URL (400px wide) instance
copy_url_button pn.widgets.Button Primary button to copy the access URL to clipboard, disabled when no valid URL is available (100px wide) instance
update_button pn.widgets.Button Default button to manually refresh permissions data from the backend (150px wide) instance
message_area pn.pane.Markdown Markdown pane for displaying status messages with color-coded styling (success, error, warning) instance
access_table pn.widgets.Tabulator Tabulator widget displaying current user permissions with columns: User, Role, Access Type, Last Updated (300px height, 500px width) instance
layout pn.Column Main Panel Column layout containing all UI components arranged vertically with rows and dividers instance

Dependencies

  • panel
  • param
  • pandas
  • logging
  • datetime
  • pyperclip
  • CDocs.models.document
  • CDocs.models.user_extensions
  • CDocs.controllers.share_controller

Required Imports

import panel as pn
import param
import pandas as pd
from typing import Dict, List, Any, Optional, Callable
import logging
from datetime import datetime
from CDocs.models.document import ControlledDocument, DocumentVersion
from CDocs.models.user_extensions import DocUser
from CDocs.controllers.share_controller import get_document_share_url, get_user_access_url, manage_document_permissions

Conditional/Optional Imports

These imports are only needed under specific conditions:

import pyperclip

Condition: only needed when copying URL to clipboard via the Copy URL button; gracefully degrades if not available

Optional

Usage Example

import panel as pn
from document_share_manager import DocumentShareManager

# Initialize Panel extension
pn.extension('tabulator')

# Create manager instance with document and user UIDs
share_manager = DocumentShareManager(
    document_uid='doc-12345-abcde',
    user_uid='user-67890-fghij'
)

# Display the UI in a Panel application
share_manager.view().servable()

# Or update document dynamically
share_manager.document_uid = 'doc-new-uid'
share_manager._update_display()

# Access UI components directly if needed
share_manager.message_area.object = 'Custom message'

# Serve in a Panel app
app = pn.template.FastListTemplate(
    title='Document Sharing',
    main=[share_manager.view()]
)
app.servable()

Best Practices

  • Always set document_uid before displaying the component to avoid 'No document selected' state
  • Call _update_display() after changing document_uid or user_uid to refresh the UI with new data
  • Handle the optional pyperclip dependency gracefully - the component will show a manual copy message if unavailable
  • The component automatically initializes and updates on instantiation, no manual initialization needed
  • Use the view() method to get the renderable layout for Panel applications
  • The access_table uses Tabulator widget which requires Panel's tabulator extension to be loaded
  • Error messages are displayed in the message_area with color-coded styling (green for success, red for errors, orange for warnings)
  • The component maintains its own state through Panel widgets - avoid directly modifying widget values outside the class methods
  • Refresh permissions periodically using the Refresh Permissions button or programmatically calling _refresh_permissions()
  • The component expects a logger instance to be available in the module scope for error logging

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class SharePermissionIndicator 75.4% similar

    A Panel-based visual indicator component that displays document sharing permissions, showing whether a user has write access or read-only access to a document with color-coded status indicators.

    From: /tf/active/vicechatdev/CDocs/ui/components/share_manager.py
  • class DocumentAccessControls 71.0% similar

    A Panel-based UI component that manages document access controls, providing view and edit buttons with role-based permissions and status indicators.

    From: /tf/active/vicechatdev/CDocs/ui/components/document_access_controls.py
  • class ControlledDocApp 61.6% similar

    A standalone Panel web application class that provides a complete controlled document management system with user authentication, navigation, and document lifecycle management features.

    From: /tf/active/vicechatdev/panel_app.py
  • class CDocsApp 59.1% similar

    Panel-based web application class for the CDocs Controlled Document System that provides a complete UI with navigation, authentication, and document management features.

    From: /tf/active/vicechatdev/cdocs_panel_app.py
  • function manage_document_permissions 58.6% similar

    Comprehensive function to manage document sharing and user permissions. This function: 1. Creates a share only if needed for active users 2. Adds/updates users with appropriate permissions based on their roles 3. Removes users who shouldn't have access anymore 4. Cleans up shares that are no longer needed 5. Manages ACL entries for write permissions on the document's folder Args: document: The document to manage permissions for Returns: Dict: Result of permission updates with detailed information

    From: /tf/active/vicechatdev/CDocs/controllers/share_controller.py
← Back to Browse