Fix modals

This commit is contained in:
myrmidex 2025-08-12 00:33:02 +02:00
parent 997646be35
commit 536dc3fcb8
2 changed files with 143 additions and 137 deletions

View file

@ -129,7 +129,7 @@ const Channels: React.FC = () => {
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2 flex-1 min-w-0">
<h3 className="text-lg font-medium text-gray-900 truncate">
!{channel.name}@{channel.platform_instance?.url?.replace(/^https?:\/\//, '')}
{channel.display_name || channel.name}
</h3>
<a
href={`https://${channel.platform_instance?.url?.replace(/^https?:\/\//, '')}/c/${channel.name}`}
@ -154,9 +154,9 @@ const Channels: React.FC = () => {
)}
</button>
</div>
{channel.display_name && (
<p className="text-sm text-gray-500">{channel.display_name}</p>
)}
<p className="text-sm text-gray-500">
!{channel.name}@{channel.platform_instance?.url?.replace(/^https?:\/\//, '')}
</p>
</div>
</div>
@ -229,79 +229,77 @@ const Channels: React.FC = () => {
{/* Account Management Modal */}
{showAccountModal && (
<div className="fixed inset-0 z-50 overflow-y-auto">
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" onClick={() => setShowAccountModal(null)}></div>
<div className="fixed inset-0" style={{ zIndex: 9999 }} onClick={() => setShowAccountModal(null)}>
<div
className="fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg shadow-xl p-6"
style={{ width: '500px', maxHeight: '80vh', overflowY: 'auto' }}
onClick={(e) => e.stopPropagation()}
>
<div className="flex items-center mb-4">
<div className="flex-shrink-0 flex items-center justify-center h-10 w-10 rounded-full bg-blue-100">
<Link2 className="h-6 w-6 text-blue-600" />
</div>
<div className="ml-4">
<h3 className="text-lg font-medium text-gray-900">
Manage Accounts for {showAccountModal.channelName}
</h3>
</div>
</div>
<span className="hidden sm:inline-block sm:align-middle sm:h-screen">&#8203;</span>
<div className="mb-4">
<p className="text-sm text-gray-500 mb-4">
Select a platform account to link to this channel:
</p>
<div className="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div className="sm:flex sm:items-start">
<div className="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<Link2 className="h-6 w-6 text-blue-600" />
</div>
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left flex-1">
<h3 className="text-lg leading-6 font-medium text-gray-900">
Manage Accounts for {showAccountModal.channelName}
</h3>
<div className="mt-4">
<p className="text-sm text-gray-500 mb-4">
Select a platform account to link to this channel:
</p>
{accounts && accounts.length > 0 ? (
<div className="space-y-2">
{accounts
.filter(account => !channels?.find(c => c.id === showAccountModal.channelId)?.platform_accounts?.some(pa => pa.id === account.id))
.map((account) => (
<button
key={account.id}
onClick={() => handleAttachAccount(showAccountModal.channelId, account.id)}
disabled={attachAccountMutation.isPending}
className="w-full text-left px-3 py-2 border border-gray-200 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:opacity-50"
>
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-900">@{account.username}</p>
{account.display_name && (
<p className="text-xs text-gray-500">{account.display_name}</p>
)}
</div>
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
account.is_active
? 'bg-green-100 text-green-800'
: 'bg-gray-100 text-gray-800'
}`}>
{account.is_active ? 'Active' : 'Inactive'}
</span>
</div>
</button>
))}
{accounts.filter(account => !channels?.find(c => c.id === showAccountModal.channelId)?.platform_accounts?.some(pa => pa.id === account.id)).length === 0 && (
<p className="text-sm text-gray-500 text-center py-4">
All available accounts are already linked to this channel.
</p>
{accounts && accounts.length > 0 ? (
<div className="space-y-2">
{accounts
.filter(account => !channels?.find(c => c.id === showAccountModal.channelId)?.platform_accounts?.some(pa => pa.id === account.id))
.map((account) => (
<button
key={account.id}
onClick={() => handleAttachAccount(showAccountModal.channelId, account.id)}
disabled={attachAccountMutation.isPending}
className="w-full text-left px-3 py-2 border border-gray-200 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:opacity-50"
>
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-900">@{account.username}</p>
{account.display_name && (
<p className="text-xs text-gray-500">{account.display_name}</p>
)}
</div>
) : (
<p className="text-sm text-gray-500 text-center py-4">
No platform accounts available. Create a platform account first.
</p>
)}
</div>
</div>
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
account.is_active
? 'bg-green-100 text-green-800'
: 'bg-gray-100 text-gray-800'
}`}>
{account.is_active ? 'Active' : 'Inactive'}
</span>
</div>
</button>
))}
{accounts.filter(account => !channels?.find(c => c.id === showAccountModal.channelId)?.platform_accounts?.some(pa => pa.id === account.id)).length === 0 && (
<p className="text-sm text-gray-500 text-center py-4">
All available accounts are already linked to this channel.
</p>
)}
</div>
</div>
<div className="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button
onClick={() => setShowAccountModal(null)}
className="w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
>
Close
</button>
</div>
) : (
<p className="text-sm text-gray-500 text-center py-4">
No platform accounts available. Create a platform account first.
</p>
)}
</div>
<div className="flex justify-end pt-4 border-t">
<button
onClick={() => setShowAccountModal(null)}
className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
Close
</button>
</div>
</div>
</div>

View file

@ -280,11 +280,16 @@ const CreateRouteModal: React.FC<CreateRouteModalProps> = ({ feeds, channels, on
};
return (
<div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
<div className="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white">
<div className="mt-3">
<h3 className="text-lg font-medium text-gray-900 mb-4">Create New Route</h3>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="fixed inset-0 overflow-y-auto" style={{ zIndex: 9999 }}>
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div className="fixed inset-0 transition-opacity" onClick={onClose}></div>
<span className="hidden sm:inline-block sm:align-middle sm:h-screen">&#8203;</span>
<div className="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" onClick={(e) => e.stopPropagation()}>
<div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 className="text-lg font-medium text-gray-900 mb-4">Create New Route</h3>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="feed_id" className="block text-sm font-medium text-gray-700 mb-1">
Feed
@ -356,7 +361,8 @@ const CreateRouteModal: React.FC<CreateRouteModalProps> = ({ feeds, channels, on
{isLoading ? 'Creating...' : 'Create Route'}
</button>
</div>
</form>
</form>
</div>
</div>
</div>
</div>
@ -379,63 +385,65 @@ const EditRouteModal: React.FC<EditRouteModalProps> = ({ route, onClose, onSubmi
};
return (
<div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
<div className="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white max-h-[80vh] overflow-y-auto">
<div className="mt-3">
<h3 className="text-lg font-medium text-gray-900 mb-4">Edit Route</h3>
<div className="mb-4 p-3 bg-gray-50 rounded-md">
<p className="text-sm text-gray-600">
<strong>Feed:</strong> {route.feed?.name}
</p>
<p className="text-sm text-gray-600">
<strong>Channel:</strong> {route.platform_channel?.display_name || route.platform_channel?.name}
</p>
</div>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="priority" className="block text-sm font-medium text-gray-700 mb-1">
Priority
</label>
<input
type="number"
id="priority"
min="0"
value={priority}
onChange={(e) => setPriority(parseInt(e.target.value))}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<p className="text-sm text-gray-500 mt-1">Higher priority routes are processed first</p>
</div>
<div className="border-t pt-4">
<KeywordManager
feedId={route.feed_id}
channelId={route.platform_channel_id}
keywords={route.keywords || []}
onKeywordChange={() => {
// Keywords will be refreshed via React Query invalidation
}}
/>
</div>
<div className="flex justify-end space-x-3 pt-4 border-t">
<button
type="button"
onClick={onClose}
className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Cancel
</button>
<button
type="submit"
disabled={isLoading}
className="px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
>
{isLoading ? 'Updating...' : 'Update Route'}
</button>
</div>
</form>
<div className="fixed inset-0" style={{ zIndex: 9999 }} onClick={onClose}>
<div
className="fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg shadow-xl p-6"
style={{ width: '500px', maxHeight: '80vh', overflowY: 'auto' }}
onClick={(e) => e.stopPropagation()}
>
<h3 className="text-lg font-medium text-gray-900 mb-4">Edit Route</h3>
<div className="mb-4 p-3 bg-gray-50 rounded-md">
<p className="text-sm text-gray-600">
<strong>Feed:</strong> {route.feed?.name}
</p>
<p className="text-sm text-gray-600">
<strong>Channel:</strong> {route.platform_channel?.display_name || route.platform_channel?.name}
</p>
</div>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="priority" className="block text-sm font-medium text-gray-700 mb-1">
Priority
</label>
<input
type="number"
id="priority"
min="0"
value={priority}
onChange={(e) => setPriority(parseInt(e.target.value))}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<p className="text-sm text-gray-500 mt-1">Higher priority routes are processed first</p>
</div>
<div className="border-t pt-4">
<KeywordManager
feedId={route.feed_id}
channelId={route.platform_channel_id}
keywords={route.keywords || []}
onKeywordChange={() => {
// Keywords will be refreshed via React Query invalidation
}}
/>
</div>
<div className="flex justify-end space-x-3 pt-4 border-t">
<button
type="button"
onClick={onClose}
className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Cancel
</button>
<button
type="submit"
disabled={isLoading}
className="px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
>
{isLoading ? 'Updating...' : 'Update Route'}
</button>
</div>
</form>
</div>
</div>
);