@dbs-portal/module-tenant-management
Version:
Tenant management and multi-tenancy support module
87 lines • 7.48 kB
JavaScript
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