nextjs-chatbot-ui 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,7 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
13
13
  const [currentStep, setCurrentStep] = useState<'connection' | 'columns'>('connection');
14
14
  const [isConnecting, setIsConnecting] = useState(false);
15
15
  const [connectionError, setConnectionError] = useState<string | null>(null);
16
+ const [connectionSuccess, setConnectionSuccess] = useState(false);
16
17
  const [availableColumns, setAvailableColumns] = useState<string[]>([]);
17
18
  const [isLoadingColumns, setIsLoadingColumns] = useState(false);
18
19
 
@@ -52,52 +53,69 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
52
53
  setConnectionError(null);
53
54
  };
54
55
 
55
- const handleTestConnection = async () => {
56
+ const handleTestConnection = async (): Promise<boolean> => {
56
57
  if (!onTestConnection) {
57
58
  // Default test - just validate fields
58
59
  if (!connection.host || !connection.database) {
59
60
  setConnectionError('Please fill in all required fields');
60
- return;
61
+ setConnectionSuccess(false);
62
+ return false;
61
63
  }
62
64
  setConnectionError(null);
63
- return;
65
+ setConnectionSuccess(true);
66
+ return true;
64
67
  }
65
68
 
66
69
  setIsConnecting(true);
67
70
  setConnectionError(null);
71
+ setConnectionSuccess(false);
68
72
 
69
73
  try {
70
74
  const isValid = await onTestConnection(connection);
71
75
  if (isValid) {
72
76
  setConnectionError(null);
73
- // Fetch columns after successful connection
74
- await handleFetchColumns();
77
+ setConnectionSuccess(true);
78
+ return true;
75
79
  } else {
76
80
  setConnectionError('Connection failed. Please check your credentials.');
81
+ setConnectionSuccess(false);
82
+ return false;
77
83
  }
78
84
  } catch (error: any) {
79
85
  setConnectionError(error.message || 'Connection failed. Please try again.');
86
+ setConnectionSuccess(false);
87
+ return false;
80
88
  } finally {
81
89
  setIsConnecting(false);
82
90
  }
83
91
  };
84
92
 
85
- const handleFetchColumns = async () => {
93
+ const handleFetchColumns = async (): Promise<string[]> => {
86
94
  if (!onFetchColumns) {
87
95
  // Mock columns for demo
88
- setAvailableColumns(['id', 'title', 'content', 'description', 'category', 'tags', 'created_at', 'updated_at']);
96
+ const mockColumns = ['id', 'title', 'content', 'description', 'category', 'tags', 'created_at', 'updated_at'];
97
+ setAvailableColumns(mockColumns);
89
98
  setIsLoadingColumns(false);
90
- return;
99
+ return mockColumns;
91
100
  }
92
101
 
93
102
  setIsLoadingColumns(true);
103
+ setConnectionError(null);
94
104
  try {
95
105
  const columns = await onFetchColumns(connection);
96
- setAvailableColumns(columns);
106
+ if (columns && columns.length > 0) {
107
+ setAvailableColumns(columns);
108
+ setIsLoadingColumns(false);
109
+ return columns;
110
+ } else {
111
+ setConnectionError('No columns found in the database.');
112
+ setIsLoadingColumns(false);
113
+ return [];
114
+ }
97
115
  } catch (error: any) {
98
116
  setConnectionError(error.message || 'Failed to fetch columns');
99
- } finally {
100
117
  setIsLoadingColumns(false);
118
+ return [];
101
119
  }
102
120
  };
103
121
 
@@ -106,21 +124,39 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
106
124
  if (dbType === 'mongodb') {
107
125
  if (!connection.connectionString && (!connection.host || !connection.database)) {
108
126
  setConnectionError('Please provide connection string or host and database');
127
+ setConnectionSuccess(false);
109
128
  return;
110
129
  }
111
130
  } else {
112
131
  if (!connection.host || !connection.database || !connection.username || !connection.password) {
113
132
  setConnectionError('Please fill in all required fields');
133
+ setConnectionSuccess(false);
114
134
  return;
115
135
  }
116
136
  }
117
137
 
118
- // Test connection
119
- await handleTestConnection();
138
+ // Clear previous errors
139
+ setConnectionError(null);
140
+ setConnectionSuccess(false);
141
+
142
+ // Test connection first
143
+ const connectionSuccess = await handleTestConnection();
120
144
 
121
- // If no error, move to next step
122
- if (!connectionError) {
145
+ if (!connectionSuccess) {
146
+ // Connection failed, don't proceed
147
+ return;
148
+ }
149
+
150
+ // If connection successful, fetch columns
151
+ const fetchedColumns = await handleFetchColumns();
152
+
153
+ if (fetchedColumns && fetchedColumns.length > 0) {
154
+ // Successfully fetched columns, move to next step
123
155
  setCurrentStep('columns');
156
+ setConnectionError(null);
157
+ } else {
158
+ // Column fetching failed, show error but keep connection success
159
+ // Error is already set in handleFetchColumns
124
160
  }
125
161
  };
126
162
 
@@ -158,6 +194,8 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
158
194
  setIsModalOpen(false);
159
195
  setCurrentStep('connection');
160
196
  setConnectionError(null);
197
+ setConnectionSuccess(false);
198
+ setAvailableColumns([]);
161
199
  setColumnSelection({
162
200
  embeddingColumns: [],
163
201
  llmColumns: [],
@@ -435,88 +473,131 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
435
473
  <p className="text-sm text-red-800">{connectionError}</p>
436
474
  </div>
437
475
  )}
476
+ {connectionSuccess && !connectionError && !isConnecting && (
477
+ <div className="bg-green-50 border border-green-200 rounded-lg p-4">
478
+ <p className="text-sm text-green-800">✓ Connection successful!</p>
479
+ </div>
480
+ )}
438
481
  </div>
439
482
  ) : (
440
483
  <div className="space-y-6">
441
484
  {isLoadingColumns ? (
442
- <div className="flex items-center justify-center py-8">
443
- <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
485
+ <div className="flex flex-col items-center justify-center py-8">
486
+ <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mb-3"></div>
487
+ <p className="text-sm text-gray-600">Loading columns...</p>
488
+ </div>
489
+ ) : availableColumns.length === 0 ? (
490
+ <div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
491
+ <p className="text-sm text-yellow-800">No columns available. Please go back and check your connection.</p>
444
492
  </div>
445
493
  ) : (
446
494
  <>
447
495
  <div>
448
- <p className="text-sm text-gray-600 mb-4">
449
- Select which columns to use for embedding, LLM processing, and ChromaDB storage.
496
+ <p className="text-sm text-gray-600 mb-2">
497
+ Select which columns to use for <strong>Embeddings</strong>, <strong>LLM processing</strong>, and <strong>ChromaDB storage</strong>.
498
+ </p>
499
+ <p className="text-xs text-gray-500 mb-4">
500
+ Found {availableColumns.length} column{availableColumns.length !== 1 ? 's' : ''} in your database.
450
501
  </p>
451
502
  </div>
452
503
 
453
504
  {/* Embedding Columns */}
454
505
  <div>
455
- <label className="block text-sm font-medium text-gray-700 mb-3">
456
- Embedding Columns
506
+ <label className="block text-sm font-medium text-gray-700 mb-2">
507
+ Works with Embeddings
457
508
  </label>
458
- <div className="grid grid-cols-2 gap-2 max-h-32 overflow-y-auto border border-gray-200 rounded-lg p-3">
459
- {availableColumns.map((column) => (
460
- <label
461
- key={`embedding-${column}`}
462
- className="flex items-center gap-2 cursor-pointer hover:bg-gray-50 p-2 rounded"
463
- >
464
- <input
465
- type="checkbox"
466
- checked={columnSelection.embeddingColumns.includes(column)}
467
- onChange={() => handleColumnToggle(column, 'embeddingColumns')}
468
- className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
469
- />
470
- <span className="text-sm text-gray-700">{column}</span>
471
- </label>
472
- ))}
509
+ <p className="text-xs text-gray-500 mb-3">Select columns that will be used for embedding generation</p>
510
+ <div className="grid grid-cols-2 gap-2 max-h-40 overflow-y-auto border border-gray-200 rounded-lg p-3 bg-gray-50">
511
+ {availableColumns.length === 0 ? (
512
+ <p className="text-sm text-gray-500 col-span-2 text-center py-2">No columns available</p>
513
+ ) : (
514
+ availableColumns.map((column) => (
515
+ <label
516
+ key={`embedding-${column}`}
517
+ className="flex items-center gap-2 cursor-pointer hover:bg-white p-2 rounded transition-colors"
518
+ >
519
+ <input
520
+ type="checkbox"
521
+ checked={columnSelection.embeddingColumns.includes(column)}
522
+ onChange={() => handleColumnToggle(column, 'embeddingColumns')}
523
+ className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
524
+ />
525
+ <span className="text-sm text-gray-700">{column}</span>
526
+ </label>
527
+ ))
528
+ )}
473
529
  </div>
530
+ {columnSelection.embeddingColumns.length > 0 && (
531
+ <p className="text-xs text-green-600 mt-1">
532
+ {columnSelection.embeddingColumns.length} column{columnSelection.embeddingColumns.length !== 1 ? 's' : ''} selected
533
+ </p>
534
+ )}
474
535
  </div>
475
536
 
476
537
  {/* LLM Columns */}
477
538
  <div>
478
- <label className="block text-sm font-medium text-gray-700 mb-3">
479
- LLM Columns
539
+ <label className="block text-sm font-medium text-gray-700 mb-2">
540
+ Works with LLM
480
541
  </label>
481
- <div className="grid grid-cols-2 gap-2 max-h-32 overflow-y-auto border border-gray-200 rounded-lg p-3">
482
- {availableColumns.map((column) => (
483
- <label
484
- key={`llm-${column}`}
485
- className="flex items-center gap-2 cursor-pointer hover:bg-gray-50 p-2 rounded"
486
- >
487
- <input
488
- type="checkbox"
489
- checked={columnSelection.llmColumns.includes(column)}
490
- onChange={() => handleColumnToggle(column, 'llmColumns')}
491
- className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
492
- />
493
- <span className="text-sm text-gray-700">{column}</span>
494
- </label>
495
- ))}
542
+ <p className="text-xs text-gray-500 mb-3">Select columns that will be processed by the LLM</p>
543
+ <div className="grid grid-cols-2 gap-2 max-h-40 overflow-y-auto border border-gray-200 rounded-lg p-3 bg-gray-50">
544
+ {availableColumns.length === 0 ? (
545
+ <p className="text-sm text-gray-500 col-span-2 text-center py-2">No columns available</p>
546
+ ) : (
547
+ availableColumns.map((column) => (
548
+ <label
549
+ key={`llm-${column}`}
550
+ className="flex items-center gap-2 cursor-pointer hover:bg-white p-2 rounded transition-colors"
551
+ >
552
+ <input
553
+ type="checkbox"
554
+ checked={columnSelection.llmColumns.includes(column)}
555
+ onChange={() => handleColumnToggle(column, 'llmColumns')}
556
+ className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
557
+ />
558
+ <span className="text-sm text-gray-700">{column}</span>
559
+ </label>
560
+ ))
561
+ )}
496
562
  </div>
563
+ {columnSelection.llmColumns.length > 0 && (
564
+ <p className="text-xs text-green-600 mt-1">
565
+ {columnSelection.llmColumns.length} column{columnSelection.llmColumns.length !== 1 ? 's' : ''} selected
566
+ </p>
567
+ )}
497
568
  </div>
498
569
 
499
570
  {/* ChromaDB Columns */}
500
571
  <div>
501
- <label className="block text-sm font-medium text-gray-700 mb-3">
502
- ChromaDB Columns
572
+ <label className="block text-sm font-medium text-gray-700 mb-2">
573
+ Works with ChromaDB
503
574
  </label>
504
- <div className="grid grid-cols-2 gap-2 max-h-32 overflow-y-auto border border-gray-200 rounded-lg p-3">
505
- {availableColumns.map((column) => (
506
- <label
507
- key={`chroma-${column}`}
508
- className="flex items-center gap-2 cursor-pointer hover:bg-gray-50 p-2 rounded"
509
- >
510
- <input
511
- type="checkbox"
512
- checked={columnSelection.chromaColumns.includes(column)}
513
- onChange={() => handleColumnToggle(column, 'chromaColumns')}
514
- className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
515
- />
516
- <span className="text-sm text-gray-700">{column}</span>
517
- </label>
518
- ))}
575
+ <p className="text-xs text-gray-500 mb-3">Select columns that will be stored in ChromaDB</p>
576
+ <div className="grid grid-cols-2 gap-2 max-h-40 overflow-y-auto border border-gray-200 rounded-lg p-3 bg-gray-50">
577
+ {availableColumns.length === 0 ? (
578
+ <p className="text-sm text-gray-500 col-span-2 text-center py-2">No columns available</p>
579
+ ) : (
580
+ availableColumns.map((column) => (
581
+ <label
582
+ key={`chroma-${column}`}
583
+ className="flex items-center gap-2 cursor-pointer hover:bg-white p-2 rounded transition-colors"
584
+ >
585
+ <input
586
+ type="checkbox"
587
+ checked={columnSelection.chromaColumns.includes(column)}
588
+ onChange={() => handleColumnToggle(column, 'chromaColumns')}
589
+ className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
590
+ />
591
+ <span className="text-sm text-gray-700">{column}</span>
592
+ </label>
593
+ ))
594
+ )}
519
595
  </div>
596
+ {columnSelection.chromaColumns.length > 0 && (
597
+ <p className="text-xs text-green-600 mt-1">
598
+ {columnSelection.chromaColumns.length} column{columnSelection.chromaColumns.length !== 1 ? 's' : ''} selected
599
+ </p>
600
+ )}
520
601
  </div>
521
602
  </>
522
603
  )}
@@ -537,9 +618,12 @@ const AdminSetup: React.FC<AdminSetupProps> = ({
537
618
  <button
538
619
  onClick={handleConnectAndNext}
539
620
  disabled={isConnecting || isLoadingColumns}
540
- className="px-6 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
621
+ className="px-6 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center gap-2"
541
622
  >
542
- {isConnecting ? 'Connecting...' : 'Connect & Next'}
623
+ {isConnecting && (
624
+ <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
625
+ )}
626
+ {isLoadingColumns ? 'Loading Columns...' : isConnecting ? 'Connecting...' : 'Connect & Next'}
543
627
  </button>
544
628
  ) : (
545
629
  <button
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nextjs-chatbot-ui",
3
3
 
4
- "version": "1.1.0",
4
+ "version": "1.1.1",
5
5
  "description": "A configurable chatbot UI component for Next.js with Tailwind CSS",
6
6
  "main": "./index.tsx",
7
7
  "module": "./index.tsx",