import React, { useCallback } from 'react'; import { GenericPageData } from '../../pageInterface'; import { FaGoogle, FaMicrosoft, FaLink, FaSync, FaPlug } from 'react-icons/fa'; import { useConnections } from '../../../../hooks/useConnections'; // Helper function to convert attribute definitions to column config const attributesToColumns = (attributes: any[]) => { return attributes.map(attr => ({ key: attr.name, label: attr.label || attr.name, type: attr.type || 'string', width: attr.width || 200, minWidth: attr.minWidth || 100, maxWidth: attr.maxWidth || 400, sortable: attr.sortable !== false, filterable: attr.filterable !== false, searchable: attr.searchable !== false, filterOptions: attr.filterOptions })); }; // Hook factory function for connections data const createConnectionsHook = () => { return () => { const { connections, fetchConnections, deleteConnection, createGoogleConnectionAndAuth, createMicrosoftConnectionAndAuth, connectWithPopup, refreshMicrosoftToken, refreshGoogleToken, isConnecting, isLoading, error, attributes, permissions, pagination } = useConnections(); const generatedColumns = attributes && attributes.length > 0 ? attributesToColumns(attributes) : undefined; // Refetch function for pagination-aware refresh const refetch = useCallback(async (params?: any) => { await fetchConnections(params); }, [fetchConnections]); // Handle connection deletion const handleDelete = useCallback(async (connectionId: string) => { try { await deleteConnection(connectionId); // Refresh connections after deletion - FormGenerator will handle pagination // by calling refetch with current pagination params via its useEffect return true; } catch (error) { console.error('Failed to delete connection:', error); return false; } }, [deleteConnection]); // Handle single connection deletion for FormGenerator const handleDeleteSingle = useCallback(async (connection: any) => { const success = await handleDelete(connection.id); if (success) { refetch(); } }, [handleDelete, refetch]); // Handle multiple connection deletion for FormGenerator const handleDeleteMultiple = useCallback(async (selectedConnections: any[]) => { const connectionIds = selectedConnections.map(conn => conn.id); const results = await Promise.all( connectionIds.map(id => handleDelete(id)) ); const allSuccessful = results.every(result => result); if (allSuccessful) { refetch(); } }, [handleDelete, refetch]); return { data: connections, loading: isLoading, error: error, refetch, // Operations handleDelete, // FormGenerator specific handlers onDelete: handleDeleteSingle, onDeleteMultiple: handleDeleteMultiple, connectWithPopup, createGoogleConnectionAndAuth, createMicrosoftConnectionAndAuth, // Token refresh operations refreshMicrosoftToken, refreshGoogleToken, // Loading states isConnecting, deletingConnections: new Set(), // Placeholder for consistency with other pages refreshingConnections: new Set(), // Track which connections are refreshing // Attributes and permissions for dynamic column/button generation attributes, permissions, columns: generatedColumns, // Return generated columns pagination }; }; }; export const connectionsPageData: GenericPageData = { id: 'basedata-connections', path: 'basedata/connections', name: 'connections.title', description: 'connections.title', // Parent page parentPath: 'basedata', // Visual icon: FaLink, title: 'connections.title', subtitle: 'connections.subtitle', // Header buttons - Create Google and Microsoft connections headerButtons: [ { id: 'add-google-connection', label: 'connections.add_google_button', icon: FaGoogle, variant: 'primary', onClick: async (hookData: any) => { if (!hookData) { console.error('No hookData available for Google connection creation'); return; } if (!hookData.createGoogleConnectionAndAuth) { console.error('createGoogleConnectionAndAuth function not found in hookData', hookData); return; } try { await hookData.createGoogleConnectionAndAuth(); // Refresh connections after creation if (hookData?.refetch) { await hookData.refetch(); } } catch (error) { console.error('Failed to create Google connection:', error); } }, // Only show if user has create permission disabled: (hookData: any) => { if (!hookData?.permissions) return { disabled: false }; const hasCreate = hookData.permissions.create !== 'n' && hookData.permissions.view; return { disabled: !hasCreate, message: 'No permission to create connections' }; } }, { id: 'add-microsoft-connection', label: 'connections.add_microsoft_button', icon: FaMicrosoft, variant: 'primary', onClick: async (hookData: any) => { if (!hookData) { console.error('No hookData available for Microsoft connection creation'); return; } if (!hookData.createMicrosoftConnectionAndAuth) { console.error('createMicrosoftConnectionAndAuth function not found in hookData', hookData); return; } try { await hookData.createMicrosoftConnectionAndAuth(); // Refresh connections after creation if (hookData?.refetch) { await hookData.refetch(); } } catch (error) { console.error('Failed to create Microsoft connection:', error); } }, // Only show if user has create permission disabled: (hookData: any) => { if (!hookData?.permissions) return { disabled: false }; const hasCreate = hookData.permissions.create !== 'n' && hookData.permissions.view; return { disabled: !hasCreate, message: 'No permission to create connections' }; } } ], // Content sections - using generic table approach content: [ { id: 'connections-table', type: 'table', tableConfig: { hookFactory: createConnectionsHook, // Columns are generated dynamically from attributes via hookData.columns // Standard action buttons actionButtons: [ { type: 'delete', title: 'connections.action.delete', idField: 'id', operationName: 'handleDelete', loadingStateName: 'deletingConnections', disabled: (hookData: any) => { if (!hookData?.permissions) return { disabled: false }; const hasDelete = hookData.permissions.delete !== 'n' && hookData.permissions.view; return { disabled: !hasDelete, message: 'No permission to delete connections' }; } } ], // Custom action buttons (entity-specific) customActions: [ { id: 'connect', icon: React.createElement(FaPlug), title: 'connections.action.connect', onClick: async (row: any, hookData: any) => { if (hookData?.connectWithPopup) { await hookData.connectWithPopup(row.id); } }, // Only show connect button if status is not 'active' visible: (row: any) => row.status !== 'active', disabled: (_row: any, hookData: any) => { if (!hookData?.permissions) return { disabled: false, message: '' }; const hasUpdate = hookData.permissions.update !== 'n' && hookData.permissions.view; return { disabled: !hasUpdate, message: 'No permission to connect' }; }, loading: (_row: any, hookData: any) => hookData?.isConnecting || false }, { id: 'refresh', icon: React.createElement(FaSync), title: 'connections.action.refresh', onClick: async (row: any, hookData: any) => { // Determine which refresh function to use based on authority if (row.authority === 'msft' && hookData?.refreshMicrosoftToken) { await hookData.refreshMicrosoftToken(row.id); if (hookData?.refetch) await hookData.refetch(); } else if (row.authority === 'google' && hookData?.refreshGoogleToken) { await hookData.refreshGoogleToken(row.id); if (hookData?.refetch) await hookData.refetch(); } }, // Only show refresh button if status is 'active' (already connected) visible: (row: any) => row.status === 'active', disabled: (_row: any, hookData: any) => { if (!hookData?.permissions) return { disabled: false, message: '' }; const hasUpdate = hookData.permissions.update !== 'n' && hookData.permissions.view; return { disabled: !hasUpdate, message: 'No permission to refresh token' }; }, loading: (row: any, hookData: any) => hookData?.refreshingConnections?.has(row.id) || false } ], searchable: true, filterable: true, sortable: true, resizable: true, pagination: true, pageSize: 10, className: 'connections-table' } } ], // Page behavior persistent: false, preload: false, preserveState: true, // Keep page mounted and prevent refetching moduleEnabled: true, // Sidebar - will be shown as subpage under Administration // No drag and drop for connections dragDropConfig: { enabled: false }, // Lifecycle hooks onActivate: async () => { if (import.meta.env.DEV) console.log('Connections activated'); }, onLoad: async () => { if (import.meta.env.DEV) console.log('Connections loaded - can initialize connections list here'); }, onUnload: async () => { if (import.meta.env.DEV) console.log('Connections unloaded - cleanup connections references'); } };