UNPKG

@dbs-portal/module-tenant-management

Version:

Tenant management and multi-tenancy support module

87 lines 7.48 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; /** * TenantSwitcher Component - Multi-tenant context switcher */ import React, { useState } from 'react'; import { Dropdown, Button, Space, Typography, Avatar, Input, List, Tag, Divider, Tooltip, Badge, Empty } from 'antd'; import { SwapOutlined, SearchOutlined, PlusOutlined, CheckOutlined, GlobalOutlined, DownOutlined } from '@ant-design/icons'; import { useTenantSwitcher } from '../hooks'; const { Text } = Typography; const { Search } = Input; export const TenantSwitcher = ({ placement = 'bottomLeft', showSearch = true, showCreateButton = true, onTenantCreate, className }) => { const [searchTerm, setSearchTerm] = useState(''); const [dropdownVisible, setDropdownVisible] = useState(false); const { switchTenant, availableTenants, currentTenant, isLoading, canSwitch } = useTenantSwitcher(); // Filter tenants based on search term const filteredTenants = availableTenants.filter(tenant => tenant.name.toLowerCase().includes(searchTerm.toLowerCase()) || tenant.displayName.toLowerCase().includes(searchTerm.toLowerCase())); const handleTenantSwitch = async (tenantId) => { try { await switchTenant(tenantId); setDropdownVisible(false); setSearchTerm(''); } catch (error) { console.error('Failed to switch tenant:', error); } }; const handleCreateTenant = () => { setDropdownVisible(false); onTenantCreate?.(); }; const renderTenantItem = (tenant) => { const isSelected = currentTenant?.id === tenant.id; return (_jsx(List.Item, { onClick: () => handleTenantSwitch(tenant.id), style: { cursor: 'pointer', padding: '8px 12px', backgroundColor: isSelected ? '#f0f0f0' : 'transparent' }, onMouseEnter: (e) => { if (!isSelected) { e.currentTarget.style.backgroundColor = '#fafafa'; } }, onMouseLeave: (e) => { if (!isSelected) { e.currentTarget.style.backgroundColor = 'transparent'; } }, children: _jsx(List.Item.Meta, { avatar: _jsx(Avatar, { size: "small", style: { backgroundColor: isSelected ? '#1890ff' : '#f56a00', fontSize: '12px' }, children: tenant.displayName.charAt(0).toUpperCase() }), title: _jsxs(Space, { children: [_jsx(Text, { strong: isSelected, children: tenant.displayName }), isSelected && (_jsx(CheckOutlined, { style: { color: '#52c41a', fontSize: '12px' } }))] }), description: _jsxs(Space, { children: [_jsx(Text, { type: "secondary", style: { fontSize: '12px' }, children: tenant.name }), _jsx(Tag, { color: tenant.isActive ? 'success' : 'default', style: { fontSize: '10px', padding: '0 4px', lineHeight: '16px' }, children: tenant.isActive ? 'Active' : 'Inactive' })] }) }) }, tenant.id)); }; const dropdownContent = (_jsxs("div", { style: { width: 300, maxHeight: 400, overflow: 'hidden' }, children: [_jsx("div", { style: { padding: '12px 16px', borderBottom: '1px solid #f0f0f0' }, children: _jsxs(Space, { children: [_jsx(GlobalOutlined, {}), _jsx(Text, { strong: true, children: "Switch Tenant" })] }) }), showSearch && (_jsx("div", { style: { padding: '12px 16px' }, children: _jsx(Search, { placeholder: "Search tenants...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), size: "small", allowClear: true }) })), _jsx("div", { style: { maxHeight: 250, overflowY: 'auto' }, children: filteredTenants.length > 0 ? (_jsx(List, { dataSource: filteredTenants, renderItem: renderTenantItem, size: "small", split: false })) : (_jsx("div", { style: { padding: '20px' }, children: _jsx(Empty, { image: Empty.PRESENTED_IMAGE_SIMPLE, description: searchTerm ? 'No tenants found' : 'No tenants available' }) })) }), showCreateButton && (_jsxs(_Fragment, { children: [_jsx(Divider, { style: { margin: 0 } }), _jsx("div", { style: { padding: '12px 16px' }, children: _jsx(Button, { type: "dashed", icon: _jsx(PlusOutlined, {}), onClick: handleCreateTenant, block: true, size: "small", children: "Create New Tenant" }) })] }))] })); // If no tenants available or loading if (isLoading) { return (_jsxs(Button, { className: className, loading: true, size: "small", children: [_jsx(GlobalOutlined, {}), " Loading..."] })); } if (availableTenants.length === 0) { return (_jsx(Button, { className: className, icon: _jsx(GlobalOutlined, {}), onClick: onTenantCreate, type: "dashed", size: "small", children: "Create Tenant" })); } // Single tenant - no switching needed if (!canSwitch) { return (_jsx(Tooltip, { title: `Current tenant: ${currentTenant?.displayName}`, children: _jsx(Button, { className: className, size: "small", disabled: true, children: _jsxs(Space, { children: [_jsx(Avatar, { size: 16, style: { backgroundColor: '#1890ff', fontSize: '10px' }, children: currentTenant?.displayName?.charAt(0).toUpperCase() }), _jsx(Text, { children: currentTenant?.displayName })] }) }) })); } // Multiple tenants - show switcher return (_jsx(Dropdown, { overlay: dropdownContent, trigger: ['click'], placement: placement, open: dropdownVisible, onOpenChange: setDropdownVisible, className: className, children: _jsx(Button, { size: "small", children: _jsxs(Space, { children: [_jsx(Avatar, { size: 16, style: { backgroundColor: '#1890ff', fontSize: '10px' }, children: currentTenant?.displayName?.charAt(0).toUpperCase() || 'T' }), _jsx(Text, { style: { maxWidth: 120 }, ellipsis: true, children: currentTenant?.displayName || 'Select Tenant' }), _jsx(Badge, { count: availableTenants.length, size: "small", style: { backgroundColor: '#52c41a' } }), _jsx(DownOutlined, { style: { fontSize: '10px' } })] }) }) })); }; /** * Compact version for headers/toolbars */ export const CompactTenantSwitcher = (props) => (_jsx(TenantSwitcher, { ...props, showSearch: false, showCreateButton: false })); /** * Full version for dashboards/main areas */ export const FullTenantSwitcher = (props) => (_jsx(TenantSwitcher, { ...props, showSearch: true, showCreateButton: true })); /** * Tenant indicator (read-only) */ export const TenantIndicator = ({ className }) => { const { currentTenant, isLoading } = useTenantSwitcher(); if (isLoading) { return (_jsx("div", { className: className, children: _jsxs(Space, { size: "small", children: [_jsx(Avatar, { size: 16 }), _jsx(Text, { type: "secondary", children: "Loading..." })] }) })); } if (!currentTenant) { return (_jsx("div", { className: className, children: _jsxs(Space, { size: "small", children: [_jsx(Avatar, { size: 16, icon: _jsx(GlobalOutlined, {}) }), _jsx(Text, { type: "secondary", children: "No tenant" })] }) })); } return (_jsx("div", { className: className, children: _jsxs(Space, { size: "small", children: [_jsx(Avatar, { size: 16, style: { backgroundColor: '#1890ff', fontSize: '10px' }, children: currentTenant.displayName.charAt(0).toUpperCase() }), _jsx(Text, { children: currentTenant.displayName }), _jsx(Tag, { color: currentTenant.isActive ? 'success' : 'default', style: { fontSize: '10px', padding: '0 4px', lineHeight: '16px' }, children: currentTenant.isActive ? 'Active' : 'Inactive' })] }) })); }; //# sourceMappingURL=TenantSwitcher.js.map