339 lines
No EOL
9.6 KiB
TypeScript
339 lines
No EOL
9.6 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { IoIosLink, IoIosTrash } from 'react-icons/io';
|
|
import { MdModeEdit } from 'react-icons/md';
|
|
import { GoUnlink } from 'react-icons/go';
|
|
import React from 'react';
|
|
|
|
import { useConnections, useOAuthConnect, useDisconnect } from '../../hooks/useConnections';
|
|
import { useLanguage } from '../../contexts/LanguageContext';
|
|
import { ColumnConfig } from '../FormGenerator';
|
|
import { EditFieldConfig } from '../Popup';
|
|
import {
|
|
Connection,
|
|
CreateConnectionData,
|
|
ConnectionsLogicReturn,
|
|
TableAction
|
|
} from './interfaces';
|
|
|
|
export function useConnectionsLogic(): ConnectionsLogicReturn {
|
|
const { t } = useLanguage();
|
|
|
|
// Hooks
|
|
const {
|
|
connections,
|
|
fetchConnections,
|
|
createConnection,
|
|
updateConnection,
|
|
connectService,
|
|
disconnectService,
|
|
deleteConnection,
|
|
isLoading,
|
|
error
|
|
} = useConnections();
|
|
|
|
const {
|
|
connectWithPopup,
|
|
isConnecting,
|
|
error: connectError
|
|
} = useOAuthConnect();
|
|
|
|
const {
|
|
disconnect,
|
|
isDisconnecting,
|
|
error: disconnectError
|
|
} = useDisconnect();
|
|
|
|
// Local state
|
|
const [editPopupOpen, setEditPopupOpen] = useState(false);
|
|
const [editingConnection, setEditingConnection] = useState<Connection | null>(null);
|
|
|
|
// Define field configuration for editing connections
|
|
const connectionEditFields: EditFieldConfig[] = [
|
|
{
|
|
key: 'authority',
|
|
label: t('connections.field.service', 'Service'),
|
|
type: 'readonly',
|
|
editable: false,
|
|
formatter: (value: string) => {
|
|
if (!value) return t('connections.unknown', 'Unknown');
|
|
const labels = {
|
|
'google': t('connections.service.google', 'Google'),
|
|
'msft': t('connections.service.microsoft', 'Microsoft'),
|
|
'local': t('connections.service.local', 'Local')
|
|
};
|
|
return labels[value as keyof typeof labels] || value;
|
|
}
|
|
},
|
|
{
|
|
key: 'status',
|
|
label: t('connections.field.status', 'Status'),
|
|
type: 'readonly',
|
|
editable: false,
|
|
formatter: (value: string) => value ? value.charAt(0).toUpperCase() + value.slice(1) : t('connections.unknown', 'Unknown')
|
|
},
|
|
{
|
|
key: 'externalUsername',
|
|
label: t('connections.field.external_username', 'External Username'),
|
|
type: 'string',
|
|
editable: true,
|
|
required: false,
|
|
placeholder: t('connections.placeholder.external_username', 'Enter external username')
|
|
},
|
|
{
|
|
key: 'externalEmail',
|
|
label: t('connections.field.external_email', 'External Email'),
|
|
type: 'email',
|
|
editable: true,
|
|
required: false,
|
|
placeholder: t('connections.placeholder.external_email', 'Enter external email address')
|
|
},
|
|
{
|
|
key: 'connectedAt',
|
|
label: t('connections.field.connected_at', 'Connected At'),
|
|
type: 'readonly',
|
|
editable: false,
|
|
formatter: (value: string) => {
|
|
if (!value) return t('connections.not_available', 'N/A');
|
|
try {
|
|
return new Date(value).toLocaleString();
|
|
} catch {
|
|
return t('connections.invalid_date', 'Invalid Date');
|
|
}
|
|
}
|
|
},
|
|
{
|
|
key: 'lastChecked',
|
|
label: t('connections.field.last_checked', 'Last Checked'),
|
|
type: 'readonly',
|
|
editable: false,
|
|
formatter: (value: string) => {
|
|
if (!value) return t('connections.not_available', 'N/A');
|
|
try {
|
|
return new Date(value).toLocaleString();
|
|
} catch {
|
|
return t('connections.invalid_date', 'Invalid Date');
|
|
}
|
|
}
|
|
}
|
|
];
|
|
|
|
// Define custom columns for the connections table
|
|
const connectionColumns: ColumnConfig[] = [
|
|
{
|
|
key: 'authority',
|
|
label: t('connections.field.service', 'Service'),
|
|
type: 'enum',
|
|
filterOptions: ['google', 'msft', 'local'],
|
|
formatter: (value: string) => {
|
|
if (!value) return t('connections.unknown', 'Unknown');
|
|
const labels = {
|
|
'google': t('connections.service.google', 'Google'),
|
|
'msft': t('connections.service.microsoft', 'Microsoft'),
|
|
'local': t('connections.service.local', 'Local')
|
|
};
|
|
return labels[value as keyof typeof labels] || value;
|
|
},
|
|
width: 150,
|
|
sortable: true,
|
|
filterable: true
|
|
},
|
|
{
|
|
key: 'status',
|
|
label: t('connections.field.status', 'Status'),
|
|
type: 'enum',
|
|
filterOptions: ['active', 'pending', 'expired', 'revoked'],
|
|
formatter: (value: string) => {
|
|
return value?.charAt(0).toUpperCase() + value?.slice(1) || t('connections.unknown', 'Unknown');
|
|
},
|
|
width: 120,
|
|
sortable: true,
|
|
filterable: true
|
|
},
|
|
{
|
|
key: 'externalUsername',
|
|
label: t('connections.field.external_username', 'External Username'),
|
|
type: 'string',
|
|
width: 200,
|
|
sortable: true,
|
|
filterable: false,
|
|
searchable: true
|
|
},
|
|
{
|
|
key: 'externalEmail',
|
|
label: t('connections.field.external_email', 'External Email'),
|
|
type: 'string',
|
|
width: 250,
|
|
sortable: true,
|
|
filterable: false,
|
|
searchable: true
|
|
},
|
|
{
|
|
key: 'connectedAt',
|
|
label: t('connections.field.connected_at', 'Connected At'),
|
|
type: 'date',
|
|
width: 150,
|
|
sortable: true,
|
|
filterable: false,
|
|
searchable: true
|
|
},
|
|
{
|
|
key: 'lastChecked',
|
|
label: t('connections.field.last_checked', 'Last Checked'),
|
|
type: 'date',
|
|
width: 150,
|
|
sortable: true,
|
|
filterable: true,
|
|
searchable: true
|
|
},
|
|
{
|
|
key: 'expiresAt',
|
|
label: t('connections.field.expires_at', 'Expires At'),
|
|
type: 'date',
|
|
width: 150,
|
|
sortable: true,
|
|
filterable: true
|
|
}
|
|
];
|
|
|
|
// Fetch connections on mount
|
|
useEffect(() => {
|
|
fetchConnections();
|
|
}, []);
|
|
|
|
// Handler functions
|
|
const handleCreateConnection = async (type: 'msft' | 'google') => {
|
|
console.log('Creating connection for type:', type);
|
|
try {
|
|
const connectionData: CreateConnectionData = {
|
|
type: type,
|
|
status: 'pending',
|
|
connectedAt: new Date().toISOString(),
|
|
lastChecked: new Date().toISOString()
|
|
};
|
|
|
|
console.log('Sending connection data to backend:', connectionData);
|
|
const newConnection = await createConnection(connectionData);
|
|
console.log('Connection created successfully:', newConnection);
|
|
await fetchConnections();
|
|
} catch (error) {
|
|
console.error('Error creating connection:', error);
|
|
}
|
|
};
|
|
|
|
const handleConnect = async (connection: Connection) => {
|
|
console.log('Connecting to service:', connection);
|
|
try {
|
|
await connectWithPopup(connection.id);
|
|
await fetchConnections();
|
|
} catch (error) {
|
|
console.error('Error connecting to service:', error);
|
|
}
|
|
};
|
|
|
|
const handleDisconnect = async (connection: Connection) => {
|
|
console.log('Disconnecting from service:', connection);
|
|
try {
|
|
await disconnect(connection.id);
|
|
await fetchConnections();
|
|
} catch (error) {
|
|
console.error('Error disconnecting from service:', error);
|
|
}
|
|
};
|
|
|
|
const handleDelete = async (connection: Connection) => {
|
|
const serviceName = connection.authority?.charAt(0).toUpperCase() + connection.authority?.slice(1) || t('connections.unknown', 'Unknown');
|
|
const confirmMessage = t('connections.confirm_delete', 'Are you sure you want to delete the {service} connection?').replace('{service}', serviceName);
|
|
|
|
if (window.confirm(confirmMessage)) {
|
|
try {
|
|
await deleteConnection(connection.id);
|
|
await fetchConnections();
|
|
} catch (error) {
|
|
console.error('Error deleting connection:', error);
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleConnectOrDisconnect = async (connection: Connection) => {
|
|
if (connection.status === 'active') {
|
|
await handleDisconnect(connection);
|
|
} else {
|
|
await handleConnect(connection);
|
|
}
|
|
};
|
|
|
|
const handleEditConnection = async (connection: Connection) => {
|
|
console.log('Editing connection:', connection);
|
|
setEditingConnection(connection);
|
|
setEditPopupOpen(true);
|
|
};
|
|
|
|
const handleSaveConnection = async (updatedConnection: Connection) => {
|
|
if (!editingConnection) return;
|
|
|
|
try {
|
|
const updateData = {
|
|
externalUsername: updatedConnection.externalUsername,
|
|
externalEmail: updatedConnection.externalEmail
|
|
};
|
|
|
|
await updateConnection(editingConnection.id, updateData);
|
|
console.log('Connection updated successfully');
|
|
await fetchConnections();
|
|
setEditPopupOpen(false);
|
|
setEditingConnection(null);
|
|
} catch (error) {
|
|
console.error('Error updating connection:', error);
|
|
}
|
|
};
|
|
|
|
const handleCancelEdit = () => {
|
|
setEditPopupOpen(false);
|
|
setEditingConnection(null);
|
|
};
|
|
|
|
// Table actions
|
|
const tableActions: TableAction[] = [
|
|
{
|
|
label: t('connections.action.edit', 'Edit'),
|
|
onClick: handleEditConnection,
|
|
icon: <MdModeEdit />
|
|
},
|
|
{
|
|
label: t('connections.action.toggle_connection', 'Toggle Connection'),
|
|
onClick: handleConnectOrDisconnect,
|
|
icon: (connection: Connection) => connection.status === 'active' ? <GoUnlink /> : <IoIosLink />
|
|
},
|
|
{
|
|
label: t('connections.action.delete', 'Delete'),
|
|
onClick: handleDelete,
|
|
icon: <IoIosTrash />
|
|
}
|
|
];
|
|
|
|
return {
|
|
// Data
|
|
connections,
|
|
isLoading,
|
|
isConnecting,
|
|
isDisconnecting,
|
|
error,
|
|
connectError,
|
|
disconnectError,
|
|
editPopupOpen,
|
|
editingConnection,
|
|
connectionColumns,
|
|
connectionEditFields,
|
|
tableActions,
|
|
|
|
// Handlers
|
|
handleCreateConnection,
|
|
handleConnect,
|
|
handleDisconnect,
|
|
handleDelete,
|
|
handleConnectOrDisconnect,
|
|
handleEditConnection,
|
|
handleSaveConnection,
|
|
handleCancelEdit
|
|
};
|
|
}
|