mirror of
https://github.com/langbot-app/LangBot.git
synced 2025-11-25 03:15:06 +08:00
Compare commits
3 Commits
c3c51b0fbf
...
763c1a885c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
763c1a885c | ||
|
|
dbc09f46f4 | ||
|
|
cf43f09aff |
@@ -289,12 +289,16 @@ export default function ApiIntegrationDialog({
|
||||
{t('common.noApiKeys')}
|
||||
</div>
|
||||
) : (
|
||||
<div className="border rounded-md">
|
||||
<div className="border rounded-md overflow-x-auto">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>{t('common.name')}</TableHead>
|
||||
<TableHead>{t('common.apiKeyValue')}</TableHead>
|
||||
<TableHead className="min-w-[120px]">
|
||||
{t('common.name')}
|
||||
</TableHead>
|
||||
<TableHead className="min-w-[200px]">
|
||||
{t('common.apiKeyValue')}
|
||||
</TableHead>
|
||||
<TableHead className="w-[100px]">
|
||||
{t('common.actions')}
|
||||
</TableHead>
|
||||
@@ -372,16 +376,20 @@ export default function ApiIntegrationDialog({
|
||||
{t('common.noWebhooks')}
|
||||
</div>
|
||||
) : (
|
||||
<div className="border rounded-md">
|
||||
<Table>
|
||||
<div className="border rounded-md overflow-x-auto max-w-full">
|
||||
<Table className="table-fixed w-full">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>{t('common.name')}</TableHead>
|
||||
<TableHead>{t('common.webhookUrl')}</TableHead>
|
||||
<TableHead className="w-[150px]">
|
||||
{t('common.name')}
|
||||
</TableHead>
|
||||
<TableHead className="w-[380px]">
|
||||
{t('common.webhookUrl')}
|
||||
</TableHead>
|
||||
<TableHead className="w-[80px]">
|
||||
{t('common.webhookEnabled')}
|
||||
</TableHead>
|
||||
<TableHead className="w-[100px]">
|
||||
<TableHead className="w-[80px]">
|
||||
{t('common.actions')}
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
@@ -389,20 +397,30 @@ export default function ApiIntegrationDialog({
|
||||
<TableBody>
|
||||
{webhooks.map((webhook) => (
|
||||
<TableRow key={webhook.id}>
|
||||
<TableCell>
|
||||
<div>
|
||||
<div className="font-medium">{webhook.name}</div>
|
||||
<TableCell className="truncate">
|
||||
<div className="truncate">
|
||||
<div
|
||||
className="font-medium truncate"
|
||||
title={webhook.name}
|
||||
>
|
||||
{webhook.name}
|
||||
</div>
|
||||
{webhook.description && (
|
||||
<div className="text-sm text-muted-foreground">
|
||||
<div
|
||||
className="text-sm text-muted-foreground truncate"
|
||||
title={webhook.description}
|
||||
>
|
||||
{webhook.description}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<code className="text-sm bg-muted px-2 py-1 rounded break-all">
|
||||
{webhook.url}
|
||||
</code>
|
||||
<div className="overflow-x-auto max-w-[380px]">
|
||||
<code className="text-sm bg-muted px-2 py-1 rounded whitespace-nowrap inline-block">
|
||||
{webhook.url}
|
||||
</code>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Switch
|
||||
|
||||
@@ -240,7 +240,7 @@ export default function DynamicFormItemComponent({
|
||||
model.requester,
|
||||
)}
|
||||
alt="icon"
|
||||
className="w-8 h-8 rounded-full"
|
||||
className="w-8 h-8 rounded-[8%]"
|
||||
/>
|
||||
<h4 className="font-medium">{model.name}</h4>
|
||||
</div>
|
||||
|
||||
@@ -235,7 +235,7 @@ export default function KBForm({
|
||||
model.requester,
|
||||
)}
|
||||
alt="icon"
|
||||
className="w-8 h-8 rounded-full"
|
||||
className="w-8 h-8 rounded-[8%]"
|
||||
/>
|
||||
<h4 className="font-medium">
|
||||
{model.name}
|
||||
|
||||
@@ -263,6 +263,18 @@ function MarketPageContent({
|
||||
}
|
||||
}, [currentPage, isLoadingMore, hasMore, fetchPlugins, searchQuery]);
|
||||
|
||||
// Check if content fills the viewport and load more if needed
|
||||
const checkAndLoadMore = useCallback(() => {
|
||||
const scrollContainer = scrollContainerRef.current;
|
||||
if (!scrollContainer || isLoading || isLoadingMore || !hasMore) return;
|
||||
|
||||
const { scrollHeight, clientHeight } = scrollContainer;
|
||||
// If content doesn't fill the viewport (no scrollbar), load more
|
||||
if (scrollHeight <= clientHeight) {
|
||||
loadMore();
|
||||
}
|
||||
}, [loadMore, isLoading, isLoadingMore, hasMore]);
|
||||
|
||||
// Listen to scroll events on the scroll container
|
||||
useEffect(() => {
|
||||
const scrollContainer = scrollContainerRef.current;
|
||||
@@ -280,6 +292,25 @@ function MarketPageContent({
|
||||
return () => scrollContainer.removeEventListener('scroll', handleScroll);
|
||||
}, [loadMore]);
|
||||
|
||||
// Check if we need to load more after content changes or initial load
|
||||
useEffect(() => {
|
||||
// Small delay to ensure DOM has updated
|
||||
const timer = setTimeout(() => {
|
||||
checkAndLoadMore();
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
}, [plugins, checkAndLoadMore]);
|
||||
|
||||
// Also check on window resize
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
checkAndLoadMore();
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, [checkAndLoadMore]);
|
||||
|
||||
// 安装插件
|
||||
// const handleInstallPlugin = (plugin: PluginV4) => {
|
||||
// console.log('install plugin', plugin);
|
||||
@@ -360,7 +391,7 @@ function MarketPageContent({
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-6 pb-6">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-6 pb-6 pt-4">
|
||||
{plugins.map((plugin) => (
|
||||
<PluginMarketCardComponent
|
||||
key={plugin.pluginId}
|
||||
|
||||
Reference in New Issue
Block a user